mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
moved metis into src/other; moved decomposition libraries into src/
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
/* -g -DFULLDEBUG -O0 */ \
|
/* -g -DFULLDEBUG -O0 */ \
|
||||||
-I$(FOAM_UTILITIES)/parallelProcessing/decompositionMethods/decompositionMethods/lnInclude \
|
-I$(LIB_SRC)/decompositionAgglomeration/decompositionMethods/lnInclude \
|
||||||
-I$(LIB_SRC)/autoMesh/lnInclude \
|
-I$(LIB_SRC)/autoMesh/lnInclude \
|
||||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/triSurface/lnInclude \
|
-I$(LIB_SRC)/triSurface/lnInclude \
|
||||||
|
|||||||
@ -2,8 +2,7 @@ EXE_INC = \
|
|||||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
-I$(FOAM_UTILITIES)/parallelProcessing/decompositionMethods/decompositionMethods/lnInclude
|
-I$(LIB_SRC)/decompositionAgglomeration/decompositionMethods/lnInclude
|
||||||
|
|
||||||
|
|
||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lmeshTools \
|
-lmeshTools \
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -x
|
|
||||||
|
|
||||||
(cd decompositionMethods; ./Allwmake)
|
|
||||||
wmake decomposePar
|
|
||||||
wmake reconstructPar
|
|
||||||
wmake reconstructParMesh
|
|
||||||
wmake redistributeMeshPar
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I../decompositionMethods/decompositionMethods/lnInclude \
|
-I$(LIB_SRC)/decompositionAgglomeration/decompositionMethods/lnInclude \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -x
|
|
||||||
|
|
||||||
wmake libso metis-5.0pre2/GKlib
|
|
||||||
wmake libso metis-5.0pre2/libmetis
|
|
||||||
|
|
||||||
wmake libso decompositionMethods
|
|
||||||
(cd parMetisDecomp; ./Allwmake)
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
METIS 4.0.2, 3/10/04
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
- Fixed a problem with weighted graphs and ometis.c
|
|
||||||
|
|
||||||
|
|
||||||
METIS 4.0.1, 11/29/98
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
This is mostly a bug-fix release
|
|
||||||
|
|
||||||
- Fixed some bugs in the multi-constraint partitioning routines
|
|
||||||
- Fixed some bugs in the volume-minimization routines
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
METIS 4.0.0, 9/20/98
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
METIS 4.0 contains a number of changes over the previous major release (ver
|
|
||||||
3.0.x). Most of these changes are concentrated on the graph and mesh
|
|
||||||
partitioning routines and they do not affect the sparse matrix re-ordering
|
|
||||||
routines. Here is a list of the major changes:
|
|
||||||
|
|
||||||
Multi-Constraint Partitioning
|
|
||||||
-----------------------------
|
|
||||||
METIS now includes partitioning routines that can be used to a partition
|
|
||||||
a graph in the presence of multiple balancing constraints.
|
|
||||||
|
|
||||||
Minimizing the Total Communication Volume
|
|
||||||
-----------------------------------------
|
|
||||||
METIS now includes partitioning routines whose objective is to minimize
|
|
||||||
the total communication volume (as opposed to minimizing the edge-cut).
|
|
||||||
|
|
||||||
Minimizing the Maximum Connectivity of the Subdomains
|
|
||||||
-----------------------------------------------------
|
|
||||||
The k-way partitioning routines in METIS can now directly minimize the number
|
|
||||||
of adjacent subdomains. For most graphs corresponding to finite element
|
|
||||||
meshes, METIS is able to significantly reduce the maximum (and total) number of
|
|
||||||
adjacent subdomains.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
METIS 3.0.6, 1/28/98
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
- Fixed some problems when too many partitions were asked, and each partition
|
|
||||||
end up having 0 vertices
|
|
||||||
- Fixed some bugs in the I/O routines
|
|
||||||
- Added support for the g77 compiler under Linux
|
|
||||||
|
|
||||||
|
|
||||||
METIS 3.0.5, 12/22/97
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
- Fixed problems on 64-bit architectures (eg., -64 option on SGIs).
|
|
||||||
- Added some options in Makefile.in
|
|
||||||
|
|
||||||
|
|
||||||
METIS 3.0.4, 12/1/97
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Fixed a memory leak in the ordering code.
|
|
||||||
|
|
||||||
|
|
||||||
METIS 3.0.3, 11/5/97
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
This is mostly a bug-fix release with just a few additions
|
|
||||||
|
|
||||||
Added functionality
|
|
||||||
- Added support for quadrilateral elements.
|
|
||||||
- Added a routine METIS_EstimateMemory that estimates the amount of
|
|
||||||
memory that will be allocated by METIS. This is useful in determining
|
|
||||||
if a problem can run on your system.
|
|
||||||
- Added hooks to allow PARMETIS to use the orderings produced by METIS.
|
|
||||||
This is hidden from the user but it will be used in the next release
|
|
||||||
of PARMETIS.
|
|
||||||
|
|
||||||
Bug-fixes
|
|
||||||
- Fixed a bug related to memory allocation. This should somewhat reduce the
|
|
||||||
overall memory used by METIS.
|
|
||||||
- Fixed some bugs in the 'graphchk' program in the case of weighted graphs.
|
|
||||||
- Removed some code corresponding to unused options.
|
|
||||||
- Fixed some minor bugs in the node-refinement code
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
METIS 3.0 contains a number of changes over METIS 2.0.
|
|
||||||
The major changes are the following:
|
|
||||||
|
|
||||||
General Changes
|
|
||||||
---------------
|
|
||||||
1. Added code to directly partition finite element meshes.
|
|
||||||
|
|
||||||
2. Added code to convert finite element meshes into graphs so they
|
|
||||||
can be used by METIS.
|
|
||||||
|
|
||||||
1. The names, calling sequences, and options of the routines in
|
|
||||||
METISlib have been changed.
|
|
||||||
|
|
||||||
2. Better support has been added for Fortran programs.
|
|
||||||
|
|
||||||
3. Eliminated the 'metis' program. The only way to tune METIS's
|
|
||||||
behavior is to use METISlib.
|
|
||||||
|
|
||||||
4. Improved memory management. METIS should now only abort if truly
|
|
||||||
there is no more memory left in the system.
|
|
||||||
|
|
||||||
|
|
||||||
Graph Partitioning
|
|
||||||
------------------
|
|
||||||
1. Added partitioning routines that can be used to compute a partition
|
|
||||||
with prescribed partition weights. For example, they can be used to
|
|
||||||
compute a 3-way partition such that partition 1 has 50% of the weight,
|
|
||||||
partition 2 has 20% of the way, and partition 3 has 30% of the weight.
|
|
||||||
|
|
||||||
2. Improved the speed of the k-way partitioning algorithm (kmetis). The
|
|
||||||
new code has better cache locality which dramatically improves the
|
|
||||||
speed for large graphs. A factor of 4 speedup can be obtained for
|
|
||||||
certain graphs. METIS can now partition a 4 million node graph
|
|
||||||
in well under a minute on a MIPS R10000.
|
|
||||||
|
|
||||||
3. Eliminated some of the options that were seldom used.
|
|
||||||
|
|
||||||
|
|
||||||
Fill-Reducing Orderings
|
|
||||||
----------------------
|
|
||||||
1. Added a node based ordering code `onmetis' that greatly improves
|
|
||||||
ordering quality.
|
|
||||||
|
|
||||||
2. Improved the quality of the orderings produced by the original
|
|
||||||
edge-based ordering code (it is now called 'oemetis').
|
|
||||||
|
|
||||||
3. METIS can now analyze the graph and try to compress together
|
|
||||||
nodes with identical sparsity pattern. For some problems, this
|
|
||||||
significantly reduces ordering time
|
|
||||||
|
|
||||||
4. METIS can now prune dense columns prior to ordering. This can be
|
|
||||||
helpful for LP matrices.
|
|
||||||
|
|
||||||
|
|
||||||
Mesh Partitioning
|
|
||||||
-----------------
|
|
||||||
1. METIS can now directly partition the element node array of finite
|
|
||||||
element meshes. It produces two partitioning vectors. One for the
|
|
||||||
elements and one for the nodes. METIS supports the following
|
|
||||||
elements: triangles, tetrahedra, hexahedra
|
|
||||||
|
|
||||||
|
|
||||||
Mesh-To-Graph Conversion Routines
|
|
||||||
---------------------------------
|
|
||||||
1. METIS now includes a number of mesh conversion functions that can
|
|
||||||
be used to create the dual and nodal graphs directly from the
|
|
||||||
element connectivity arrays. These are highly optimized routines.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
metis-5.0pre2
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
r1437 | karypis | 2007-04-07 23:16:16 -0500 (Sat, 07 Apr 2007) | 3 lines
|
|
||||||
|
|
||||||
- Added installation instructions and change-logs.
|
|
||||||
- Tested 32bit & 64bit on 64bit architectures and passed tests.
|
|
||||||
- Tested 32bit on 32bit architectures and passed tests.
|
|
||||||
- strtoidx() addition for portable input file parsing
|
|
||||||
- Restructured the internal memory allocation schemes for graph and
|
|
||||||
refinement data. This should enhance portability and make the code
|
|
||||||
easier to maintain.
|
|
||||||
- Fixed some bad memory allocation calls (i.e., sizeof(x)/sizeof(idxtype).
|
|
||||||
However, there are tons of those and need to be corrected once and for
|
|
||||||
all by eliminating workspace and the associated mallocs.
|
|
||||||
- Added mprint/mscanf family of functions for portable formated I/O
|
|
||||||
of the idxtype datatype. The specifier for this datatype is %D.
|
|
||||||
All library routines use this function for printing.
|
|
||||||
The implementation of these routines is not very efficient, but
|
|
||||||
that should do for now (in principle these routines should not be
|
|
||||||
used unless debugging).
|
|
||||||
- Incorporated GKlib into METIS, which replaced many of its internal
|
|
||||||
functions. GKlib's malloc interface will enable graceful and clean
|
|
||||||
aborts (i.e., free all internally allocated memory) on fatal errors.
|
|
||||||
This will probably be available in the next pre-release.
|
|
||||||
- Fixed the problems associated with metis.h that were identified by
|
|
||||||
David (flyspray Issue #9).
|
|
||||||
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
trunk/b64.c
|
|
||||||
trunk/blas.c
|
|
||||||
trunk/dfkvkselect.c
|
|
||||||
trunk/dlmalloc.c
|
|
||||||
trunk/error.c
|
|
||||||
trunk/fs.c
|
|
||||||
trunk/getopt.c
|
|
||||||
trunk/htable.c
|
|
||||||
trunk/io.c
|
|
||||||
trunk/memory.c
|
|
||||||
trunk/omp.c
|
|
||||||
trunk/pdb.c
|
|
||||||
trunk/pqueue.c
|
|
||||||
trunk/seq.c
|
|
||||||
trunk/sort.c
|
|
||||||
trunk/string.c
|
|
||||||
trunk/timers.c
|
|
||||||
trunk/tokenizer.c
|
|
||||||
trunk/util.c
|
|
||||||
|
|
||||||
LIB = $(FOAM_LIBBIN)/libGKlib
|
|
||||||
@ -1 +0,0 @@
|
|||||||
/*EXE_INC = -Wno-unused-variables*/
|
|
||||||
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* GKlib.h
|
|
||||||
*
|
|
||||||
* George's library of most frequently used routines
|
|
||||||
*
|
|
||||||
* $Id: GKlib.h 1430 2007-04-07 17:53:07Z karypis $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GKLIB_H_
|
|
||||||
#define _GKLIB_H_ 1
|
|
||||||
|
|
||||||
#define GKMSPACE
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define __MSC__
|
|
||||||
#endif
|
|
||||||
#if defined(__ICC)
|
|
||||||
#define __ICC__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <gk_arch.h> /*!< This should be here, prior to the includes */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Header file inclusion section
|
|
||||||
**************************************************************************/
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <float.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <setjmp.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#if defined(__WITHPCRE__)
|
|
||||||
#include <pcreposix.h>
|
|
||||||
#else
|
|
||||||
#include <regex.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__OPENMP__)
|
|
||||||
#include <omp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <gk_dlmalloc.h>
|
|
||||||
#include <gk_types.h>
|
|
||||||
#include <gk_struct.h>
|
|
||||||
#include <gk_externs.h>
|
|
||||||
#include <gk_defs.h>
|
|
||||||
#include <gk_macros.h>
|
|
||||||
#include <gk_getopt.h>
|
|
||||||
|
|
||||||
#include <gk_sort.h>
|
|
||||||
#include <gk_blas.h>
|
|
||||||
#include <gk_memory.h>
|
|
||||||
|
|
||||||
#include <gk_proto.h>
|
|
||||||
|
|
||||||
#endif /* GKlib.h */
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,212 +0,0 @@
|
|||||||
#*************************************************************************
|
|
||||||
# Global flags
|
|
||||||
#*************************************************************************
|
|
||||||
gdb = yes
|
|
||||||
debug = no
|
|
||||||
memdbg = no
|
|
||||||
openmp = no
|
|
||||||
pcre = no
|
|
||||||
x86compiler = gcc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#*************************************************************************
|
|
||||||
# System-specific compilation flags
|
|
||||||
#*************************************************************************
|
|
||||||
# Get some basic information about the system that you are working on
|
|
||||||
cputype = $(shell uname -m | sed "s/\\ /_/g")
|
|
||||||
systype = $(shell uname)
|
|
||||||
ifeq ($(findstring CYGWIN, $(systype)),CYGWIN)
|
|
||||||
systype = MSWIN
|
|
||||||
# systype = CYGWIN
|
|
||||||
cputype = x86
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(systype),MSWIN)
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
# These defs are very much Visual Studio Specific
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
#Compiler information
|
|
||||||
CC = cl
|
|
||||||
OPTFLAGS = /Ox
|
|
||||||
COPTIONS = -DWIN32 -DMSC -D_CRT_SECURE_NO_DEPRECATE
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = /cygdrive/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/VC/BIN/link
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = lib /NODEFAULTLIB:LIBC /OUT:$@
|
|
||||||
RANLIB =
|
|
||||||
|
|
||||||
ifeq ($(openmp),yes)
|
|
||||||
COPTIONS += -D__OPENMP__ /openmp
|
|
||||||
LDOPTIONS += /openmp
|
|
||||||
endif
|
|
||||||
|
|
||||||
#Compile input/output file specification
|
|
||||||
SOURCEFILE = /c $<
|
|
||||||
OUTPUTFILE = /Fo$@
|
|
||||||
|
|
||||||
# Standard file extensions
|
|
||||||
OBJEXT = .obj
|
|
||||||
LIBEXT = .lib
|
|
||||||
EXEEXT = .exe
|
|
||||||
else
|
|
||||||
ifeq ($(systype),Linux)
|
|
||||||
ifeq ($(x86compiler),gcc)
|
|
||||||
#Compiler information
|
|
||||||
CC = gcc
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS = -DLINUX -D_FILE_OFFSET_BITS=64 -Wall -std=c99 -pedantic
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = gcc
|
|
||||||
else
|
|
||||||
#Compiler information
|
|
||||||
CC = icc
|
|
||||||
OPTFLAGS = -O3
|
|
||||||
COPTIONS = -DLINUX -D_FILE_OFFSET_BITS=64 -std=c99
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = icc
|
|
||||||
|
|
||||||
ifeq ($(openmp),yes)
|
|
||||||
COPTIONS += -D__OPENMP__ -openmp -openmp-report2
|
|
||||||
LDOPTIONS += -openmp
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(systype),Darwin)
|
|
||||||
#Compiler information
|
|
||||||
CC = gcc
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS = -DDARWIN -D_FILE_OFFSET_BITS=64 -Wall -std=c99 -pedantic
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = gcc
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = gcc
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(systype),SunOS)
|
|
||||||
#Compiler information
|
|
||||||
CC = /opt/SUNWspro/bin/cc
|
|
||||||
OPTFLAGS = -xO4
|
|
||||||
COPTIONS = -DSUNOS
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = /opt/SUNWspro/bin/cc
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(systype),CYGWIN)
|
|
||||||
#Compiler information
|
|
||||||
CC = gcc
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS = -DCYGWIN -DWIN32 -D_FILE_OFFSET_BITS=64 -Wall -std=c99 -pedantic -mno-cygwin
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS = -mno-cygwin
|
|
||||||
LD = gcc
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
# These defs are common among the GNU/GCC based systems
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
#Library creation information
|
|
||||||
AR = ar crv $@
|
|
||||||
RANLIB = ar -ts $@
|
|
||||||
|
|
||||||
#Compile input/output file specification
|
|
||||||
SOURCEFILE = -c $<
|
|
||||||
OUTPUTFILE = -o $@
|
|
||||||
|
|
||||||
# Standard file extensions
|
|
||||||
OBJEXT = .o
|
|
||||||
LIBEXT = .a
|
|
||||||
EXEEXT =
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
#**************************************************************************
|
|
||||||
DMALLOCINC =
|
|
||||||
DMALLOCFLAGS =
|
|
||||||
DEBUGFLAGS =
|
|
||||||
XTRAFLAGS =
|
|
||||||
|
|
||||||
ifeq ($(dmalloc),yes)
|
|
||||||
DMALLOCINC = -I$(HOME)/local/include
|
|
||||||
DMALLOCFLAGS = -DDMALLOC
|
|
||||||
OPTFLAGS = -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(debug),yes)
|
|
||||||
DEBUGFLAGS = -DDEBUG
|
|
||||||
OPTFLAGS = -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(gdb),yes)
|
|
||||||
OPTFLAGS += -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(pcre),yes)
|
|
||||||
XTRAFLAGS += -D__WITHPCRE__
|
|
||||||
endif
|
|
||||||
#**************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#**************************************************************************
|
|
||||||
INCLUDES = -I./ $(INCDIR) $(DMALLOCINC)
|
|
||||||
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(XTRAFLAGS) $(DMALLOCFLAGS) $(DEBUGFLAGS) $(INCLUDES)
|
|
||||||
#**************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#**************************************************************************
|
|
||||||
# Create the build directory if it does not exist
|
|
||||||
#**************************************************************************
|
|
||||||
BUILDDIR = ../builds/$(systype)-$(cputype)
|
|
||||||
$(shell mkdir -p $(BUILDDIR))
|
|
||||||
|
|
||||||
OBJS = $(patsubst %.c, $(BUILDDIR)/%$(OBJEXT), $(wildcard *.c))
|
|
||||||
HEADERS = $(wildcard *.h) Makefile
|
|
||||||
|
|
||||||
|
|
||||||
$(BUILDDIR)/libGKlib$(LIBEXT): $(OBJS)
|
|
||||||
$(AR) $(OBJS)
|
|
||||||
$(RANLIB)
|
|
||||||
|
|
||||||
doc:
|
|
||||||
doxygen ../doxygen/Doxyfile
|
|
||||||
|
|
||||||
pubdoc:
|
|
||||||
doxygen ../doxygen/Doxyfile
|
|
||||||
scp -r ../doxygen/html/* dminers.dtc.umn.edu:/var/www/wwwroot/dminers/files/doxy/GKlib
|
|
||||||
ssh dminers.dtc.umn.edu "chmod -R a+rX /var/www/wwwroot/dminers/files/doxy/GKlib"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJS)
|
|
||||||
|
|
||||||
realclean:
|
|
||||||
rm -f $(OBJS) ; rm -f $(BUILDDIR)/libGKlib$(LIBEXT)
|
|
||||||
|
|
||||||
|
|
||||||
$(OBJS) : $(HEADERS) Makefile
|
|
||||||
|
|
||||||
|
|
||||||
$(BUILDDIR)/%$(OBJEXT) : %.c
|
|
||||||
$(CC) $(CFLAGS) $(SOURCEFILE) $(OUTPUTFILE)
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file b64.c
|
|
||||||
\brief This file contains some simple 8bit-to-6bit encoding/deconding routines
|
|
||||||
|
|
||||||
Most of these routines are outdated and should be converted using glibc's equivalent
|
|
||||||
routines.
|
|
||||||
|
|
||||||
\date Started 2/22/05
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: b64.c 1421 2007-04-06 14:37:41Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
#define B64OFFSET 48 /* This is the '0' number */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Encode 3 '8-bit' binary bytes as 4 '6-bit' characters
|
|
||||||
*******************************************************************************/
|
|
||||||
void encodeblock(unsigned char *in, unsigned char *out)
|
|
||||||
{
|
|
||||||
out[0] = (in[0] >> 2);
|
|
||||||
out[1] = (((in[0] & 0x03) << 4) | (in[1] >> 4));
|
|
||||||
out[2] = (((in[1] & 0x0f) << 2) | (in[2] >> 6));
|
|
||||||
out[3] = (in[2] & 0x3f);
|
|
||||||
|
|
||||||
out[0] += B64OFFSET;
|
|
||||||
out[1] += B64OFFSET;
|
|
||||||
out[2] += B64OFFSET;
|
|
||||||
out[3] += B64OFFSET;
|
|
||||||
|
|
||||||
// printf("%c %c %c %c %2x %2x %2x %2x %2x %2x %2x\n", out[0], out[1], out[2], out[3], out[0], out[1], out[2], out[3], in[0], in[1], in[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Decode 4 '6-bit' characters into 3 '8-bit' binary bytes
|
|
||||||
*******************************************************************************/
|
|
||||||
void decodeblock(unsigned char *in, unsigned char *out)
|
|
||||||
{
|
|
||||||
in[0] -= B64OFFSET;
|
|
||||||
in[1] -= B64OFFSET;
|
|
||||||
in[2] -= B64OFFSET;
|
|
||||||
in[3] -= B64OFFSET;
|
|
||||||
|
|
||||||
out[0] = (in[0] << 2 | in[1] >> 4);
|
|
||||||
out[1] = (in[1] << 4 | in[2] >> 2);
|
|
||||||
out[2] = (in[2] << 6 | in[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function encodes an input array of bytes into a base64 encoding. Memory
|
|
||||||
* for the output array is assumed to have been allocated by the calling program
|
|
||||||
* and be sufficiently large. The output string is NULL terminated.
|
|
||||||
*******************************************************************************/
|
|
||||||
void GKEncodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if (nbytes%3 != 0)
|
|
||||||
gk_errexit(SIGERR, "GKEncodeBase64: Input buffer size should be a multiple of 3! (%d)\n", nbytes);
|
|
||||||
|
|
||||||
for (j=0, i=0; i<nbytes; i+=3, j+=4)
|
|
||||||
encodeblock(inbuffer+i, outbuffer+j);
|
|
||||||
|
|
||||||
//printf("%d %d\n", nbytes, j);
|
|
||||||
outbuffer[j] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function decodes an input array of base64 characters into their actual
|
|
||||||
* 8-bit codes. Memory * for the output array is assumed to have been allocated
|
|
||||||
* by the calling program and be sufficiently large. The padding is discarded.
|
|
||||||
*******************************************************************************/
|
|
||||||
void GKDecodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if (nbytes%4 != 0)
|
|
||||||
gk_errexit(SIGERR, "GKDecodeBase64: Input buffer size should be a multiple of 4! (%d)\n", nbytes);
|
|
||||||
|
|
||||||
for (j=0, i=0; i<nbytes; i+=4, j+=3)
|
|
||||||
decodeblock(inbuffer+i, outbuffer+j);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,129 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file blas.c
|
|
||||||
\brief This file contains GKlib's implementation of BLAS-like routines
|
|
||||||
|
|
||||||
The BLAS routines that are currently implemented are mostly level-one.
|
|
||||||
They follow a naming convention of the type gk_[type][name], where
|
|
||||||
[type] is one of c, i, f, and d, based on C's four standard scalar
|
|
||||||
datatypes of characters, integers, floats, and doubles.
|
|
||||||
|
|
||||||
These routines are implemented using a generic macro template,
|
|
||||||
which is used for code generation.
|
|
||||||
|
|
||||||
\date Started 9/28/95
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: blas.c 1421 2007-04-06 14:37:41Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Set the elements of an array to a specified value */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_SET(gk_cset, char)
|
|
||||||
GK_SET(gk_iset, int)
|
|
||||||
GK_SET(gk_fset, float)
|
|
||||||
GK_SET(gk_dset, double)
|
|
||||||
GK_SET(gk_idxset, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Set the elements of an array in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_INCSET(gk_cincset, char)
|
|
||||||
GK_INCSET(gk_iincset, int)
|
|
||||||
GK_INCSET(gk_fincset, float)
|
|
||||||
GK_INCSET(gk_dincset, double)
|
|
||||||
GK_INCSET(gk_idxincset, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Return the index of the maximum element in a vector */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_ARGMAX(gk_cargmax, char)
|
|
||||||
GK_ARGMAX(gk_iargmax, int)
|
|
||||||
GK_ARGMAX(gk_fargmax, float)
|
|
||||||
GK_ARGMAX(gk_dargmax, double)
|
|
||||||
GK_ARGMAX(gk_idxargmax, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Return the index of the minimum element in a vector */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_ARGMIN(gk_cargmin, char)
|
|
||||||
GK_ARGMIN(gk_iargmin, int)
|
|
||||||
GK_ARGMIN(gk_fargmin, float)
|
|
||||||
GK_ARGMIN(gk_dargmin, double)
|
|
||||||
GK_ARGMIN(gk_idxargmin, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Return the index of the Kth largest element in a vector */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_ARGMAX_N(gk_cargmax_n, char, gk_ckv_t, gk_ckvmalloc, gk_dckvsort)
|
|
||||||
GK_ARGMAX_N(gk_iargmax_n, int, gk_ikv_t, gk_ikvmalloc, gk_dikvsort)
|
|
||||||
GK_ARGMAX_N(gk_fargmax_n, float, gk_fkv_t, gk_fkvmalloc, gk_dfkvsort)
|
|
||||||
GK_ARGMAX_N(gk_dargmax_n, double, gk_dkv_t, gk_dkvmalloc, gk_ddkvsort)
|
|
||||||
GK_ARGMAX_N(gk_idxargmax_n, gk_idx_t, gk_idxkv_t, gk_idxkvmalloc, gk_didxkvsort)
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sums the entries of an array */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_SUM(gk_csum, char, intmax_t)
|
|
||||||
GK_SUM(gk_isum, int, intmax_t)
|
|
||||||
GK_SUM(gk_fsum, float, float)
|
|
||||||
GK_SUM(gk_dsum, double, double)
|
|
||||||
GK_SUM(gk_idxsum, gk_idx_t, intmax_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Scales the elements of a vector by a constant */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_SCALE(gk_cscale, char)
|
|
||||||
GK_SCALE(gk_iscale, int)
|
|
||||||
GK_SCALE(gk_fscale, float)
|
|
||||||
GK_SCALE(gk_dscale, double)
|
|
||||||
GK_SCALE(gk_idxscale, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Computes the 2-norm of a vector */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_NORM2(gk_cnorm2, char, intmax_t)
|
|
||||||
GK_NORM2(gk_inorm2, int, intmax_t)
|
|
||||||
GK_NORM2(gk_fnorm2, float, float)
|
|
||||||
GK_NORM2(gk_dnorm2, double, double)
|
|
||||||
GK_NORM2(gk_idxnorm2, gk_idx_t, intmax_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Computes the dot-product of two vectors */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_DOT(gk_cdot, char, intmax_t)
|
|
||||||
GK_DOT(gk_idot, int, intmax_t)
|
|
||||||
GK_DOT(gk_fdot, float, float)
|
|
||||||
GK_DOT(gk_ddot, double, double)
|
|
||||||
GK_DOT(gk_idxdot, gk_idx_t, intmax_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Computes y = ax+y */
|
|
||||||
/*************************************************************************/
|
|
||||||
GK_AXPY(gk_caxpy, char)
|
|
||||||
GK_AXPY(gk_iaxpy, int)
|
|
||||||
GK_AXPY(gk_faxpy, float)
|
|
||||||
GK_AXPY(gk_daxpy, double)
|
|
||||||
GK_AXPY(gk_idxaxpy, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file dfkvkselect.c
|
|
||||||
\brief Sorts only the largest k values
|
|
||||||
|
|
||||||
\date Started 7/14/00
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: dfkvkselect.c 1421 2007-04-06 14:37:41Z karypis $\endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
/* Byte-wise swap two items of size SIZE. */
|
|
||||||
#define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0)
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function puts the 'topk' largest values in the beginning of the array
|
|
||||||
*******************************************************************************/
|
|
||||||
int gk_dfkvkselect(int n, int topk, gk_fkv_t *cand)
|
|
||||||
{
|
|
||||||
int i, j, lo, hi, mid;
|
|
||||||
gk_fkv_t pivot, stmp;
|
|
||||||
|
|
||||||
if (n <= topk)
|
|
||||||
return n; /* return if the array has fewer elements than we want */
|
|
||||||
|
|
||||||
for (lo=0, hi=n-1; hi-lo > 2;) {
|
|
||||||
mid = lo + ((hi-lo) >> 1);
|
|
||||||
|
|
||||||
/* select the pivot */
|
|
||||||
if (cand[mid].key > cand[lo].key)
|
|
||||||
QSSWAP(cand[mid], cand[lo], stmp);
|
|
||||||
if (cand[hi].key > cand[mid].key)
|
|
||||||
QSSWAP(cand[mid], cand[hi], stmp);
|
|
||||||
else
|
|
||||||
goto jump_over;
|
|
||||||
if (cand[mid].key > cand[lo].key)
|
|
||||||
QSSWAP(cand[mid], cand[lo], stmp);
|
|
||||||
|
|
||||||
jump_over:;
|
|
||||||
pivot = cand[mid];
|
|
||||||
|
|
||||||
/* Here's the famous ``collapse the walls'' section of quicksort. */
|
|
||||||
for (i=lo+1, j=hi-1; i<=j;) {
|
|
||||||
for (; cand[i].key > pivot.key; i++);
|
|
||||||
for (; pivot.key > cand[j].key; j--);
|
|
||||||
|
|
||||||
if (i < j) {
|
|
||||||
QSSWAP (cand[i], cand[j], stmp);
|
|
||||||
i++;
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
else if (i == j) {
|
|
||||||
i++;
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > topk)
|
|
||||||
hi = i;
|
|
||||||
else if (i < topk)
|
|
||||||
lo = i;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hi-lo == 2) {
|
|
||||||
if (cand[lo].key < cand[lo+1].key)
|
|
||||||
QSSWAP(cand[lo], cand[lo+1], stmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (cand[lo].key < cand[hi].key)
|
|
||||||
printf("Hmm Error: %d %d %d %f %f\n", i, lo, hi, cand[lo].key, cand[hi].key);
|
|
||||||
|
|
||||||
|
|
||||||
for (i=topk; i<n; i++) {
|
|
||||||
for (j=0; j<topk; j++)
|
|
||||||
if (cand[i].key > cand[j].key)
|
|
||||||
printf("Hmm Error: %d %d %f %f %d %d\n", i, j, cand[i].key, cand[j].key, lo, hi);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return topk;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,157 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file error.c
|
|
||||||
\brief Various error-handling functions
|
|
||||||
|
|
||||||
This file contains functions dealing with error reporting and termination
|
|
||||||
|
|
||||||
\author George
|
|
||||||
\date 1/1/2007
|
|
||||||
\version\verbatim $Id: error.c 1065 2007-03-06 23:11:52Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#define _GK_ERROR_C_ /* this is needed to properly declare the gk_return_to_entry
|
|
||||||
as an extern function in GKlib.h */
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* This is the jmp_buf for the graceful exit in case of severy error */
|
|
||||||
__thread jmp_buf gk_return_to_entry;
|
|
||||||
|
|
||||||
/* These are the holders of the old singal handlers for the trapped signals */
|
|
||||||
typedef void (*sighandler_t)(int); /* this should be in signals.h, but is not there */
|
|
||||||
static __thread sighandler_t old_SIGFPE_handler;
|
|
||||||
static __thread sighandler_t old_SIGILL_handler;
|
|
||||||
static __thread sighandler_t old_SIGSEGV_handler;
|
|
||||||
#ifndef WIN32
|
|
||||||
static __thread sighandler_t old_SIGBUS_handler;
|
|
||||||
#endif
|
|
||||||
static __thread sighandler_t old_SIGABRT_handler;
|
|
||||||
static __thread sighandler_t old_SIGMEM_handler; /* Custom signal */
|
|
||||||
static __thread sighandler_t old_SIGERR_handler; /* Custom signal */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function prints an error message and exits
|
|
||||||
**************************************************************************/
|
|
||||||
void errexit(char *f_str,...)
|
|
||||||
{
|
|
||||||
va_list argp;
|
|
||||||
|
|
||||||
va_start(argp, f_str);
|
|
||||||
vfprintf(stderr, f_str, argp);
|
|
||||||
va_end(argp);
|
|
||||||
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
exit(-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function prints an error message and raises a signum signal
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_errexit(int signum, char *f_str,...)
|
|
||||||
{
|
|
||||||
va_list argp;
|
|
||||||
|
|
||||||
va_start(argp, f_str);
|
|
||||||
vfprintf(stderr, f_str, argp);
|
|
||||||
va_end(argp);
|
|
||||||
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
raise(signum);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* This function sets a number of signal handlers and sets the return point
|
|
||||||
* of a longjmp
|
|
||||||
****************************************************************************/
|
|
||||||
void gk_SetSignalHandlers()
|
|
||||||
{
|
|
||||||
old_SIGFPE_handler = signal(SIGFPE, gk_NonLocalExit_Handler);
|
|
||||||
old_SIGILL_handler = signal(SIGILL, gk_NonLocalExit_Handler);
|
|
||||||
old_SIGSEGV_handler = signal(SIGSEGV, gk_NonLocalExit_Handler);
|
|
||||||
#ifndef WIN32
|
|
||||||
old_SIGBUS_handler = signal(SIGBUS, gk_NonLocalExit_Handler);
|
|
||||||
#endif
|
|
||||||
old_SIGABRT_handler = signal(SIGABRT, gk_NonLocalExit_Handler);
|
|
||||||
if (SIGMEM != SIGABRT)
|
|
||||||
old_SIGMEM_handler = signal(SIGMEM, gk_NonLocalExit_Handler);
|
|
||||||
if (SIGERR != SIGABRT)
|
|
||||||
old_SIGERR_handler = signal(SIGERR, gk_NonLocalExit_Handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* This function sets the handlers for the signals to their default handlers
|
|
||||||
****************************************************************************/
|
|
||||||
void gk_UnsetSignalHandlers()
|
|
||||||
{
|
|
||||||
signal(SIGFPE, old_SIGFPE_handler);
|
|
||||||
signal(SIGILL, old_SIGILL_handler);
|
|
||||||
signal(SIGSEGV, old_SIGSEGV_handler);
|
|
||||||
#ifndef WIN32
|
|
||||||
signal(SIGBUS, old_SIGBUS_handler);
|
|
||||||
#endif
|
|
||||||
signal(SIGABRT, old_SIGABRT_handler);
|
|
||||||
if (SIGMEM != SIGABRT)
|
|
||||||
signal(SIGMEM, old_SIGMEM_handler);
|
|
||||||
if (SIGERR != SIGABRT)
|
|
||||||
signal(SIGERR, old_SIGERR_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the handler for SIGUSR1 that implements the cleaning up
|
|
||||||
* process prior to a non-local exit.
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_NonLocalExit_Handler(int signum)
|
|
||||||
{
|
|
||||||
gk_malloc_cleanup();
|
|
||||||
|
|
||||||
//printf("Calling longjmp...\n");
|
|
||||||
longjmp(gk_return_to_entry, signum);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief Thread-safe implementation of strerror() */
|
|
||||||
/**************************************************************************/
|
|
||||||
char *gk_strerror(int errnum)
|
|
||||||
{
|
|
||||||
static __thread char buf[1024];
|
|
||||||
|
|
||||||
strerror_r(errnum, buf, 1024);
|
|
||||||
|
|
||||||
buf[1023] = '\0';
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function prints a backtrace of callinf functions
|
|
||||||
**************************************************************************/
|
|
||||||
void PrintBackTrace()
|
|
||||||
{
|
|
||||||
#ifdef LINUX
|
|
||||||
void *array[10];
|
|
||||||
int i, size;
|
|
||||||
char **strings;
|
|
||||||
|
|
||||||
size = backtrace(array, 10);
|
|
||||||
strings = backtrace_symbols(array, size);
|
|
||||||
|
|
||||||
printf("Obtained %d stack frames.\n", size);
|
|
||||||
for (i=0; i<size; i++) {
|
|
||||||
printf("%s\n", strings[i]);
|
|
||||||
}
|
|
||||||
free(strings);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@ -1,197 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file fs.c
|
|
||||||
\brief Various file-system functions.
|
|
||||||
|
|
||||||
This file contains various functions that deal with interfacing with
|
|
||||||
the filesystem in a portable way.
|
|
||||||
|
|
||||||
\date Started 4/10/95
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: fs.c 986 2007-02-27 19:04:21Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks if a file exists
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_fexists(char *fname)
|
|
||||||
{
|
|
||||||
struct stat status;
|
|
||||||
|
|
||||||
if (stat(fname, &status) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return S_ISREG(status.st_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks if a directory exists
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_dexists(char *dirname)
|
|
||||||
{
|
|
||||||
struct stat status;
|
|
||||||
|
|
||||||
if (stat(dirname, &status) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return S_ISDIR(status.st_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief Returns the size of the file in bytes
|
|
||||||
|
|
||||||
This function returns the size of a file as a 64 bit integer. If there
|
|
||||||
were any errors in stat'ing the file, -1 is returned.
|
|
||||||
\note That due to the -1 return code, the maximum file size is limited to
|
|
||||||
63 bits (which I guess is okay for now).
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
intmax_t gk_getfsize(char *filename)
|
|
||||||
{
|
|
||||||
struct stat status;
|
|
||||||
|
|
||||||
if (stat(filename, &status) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return (intmax_t)(status.st_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function gets some basic statistics about the file
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_getfilestats(char *fname, int *r_nlines, int *r_ntokens, int *r_nbytes)
|
|
||||||
{
|
|
||||||
int nlines, ntokens, nbytes;
|
|
||||||
size_t lnlen;
|
|
||||||
FILE *fpin;
|
|
||||||
char *line=NULL, delim[] = " \t", *token;
|
|
||||||
|
|
||||||
fpin = gk_fopen(fname, "r", "gk_GetFileStats");
|
|
||||||
|
|
||||||
nlines = ntokens = nbytes = 0;
|
|
||||||
|
|
||||||
while (gk_getline(&line, &lnlen, fpin)) {
|
|
||||||
nlines++;
|
|
||||||
nbytes += strlen(line);
|
|
||||||
|
|
||||||
token = strtok(line, delim);
|
|
||||||
while (token) {
|
|
||||||
ntokens++;
|
|
||||||
token = strtok(NULL, delim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_fclose(fpin);
|
|
||||||
|
|
||||||
*r_nlines = nlines;
|
|
||||||
*r_ntokens = ntokens;
|
|
||||||
*r_nbytes = nbytes;
|
|
||||||
|
|
||||||
gk_free((void *)&line, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes in a potentially full path specification of a file
|
|
||||||
* and just returns a string containing just the basename of the file.
|
|
||||||
* The basename is derived from the actual filename by stripping the last
|
|
||||||
* .ext part.
|
|
||||||
**************************************************************************/
|
|
||||||
char *gk_getbasename(char *path)
|
|
||||||
{
|
|
||||||
char *startptr, *endptr;
|
|
||||||
char *basename;
|
|
||||||
|
|
||||||
if ((startptr = strrchr(path, '/')) == NULL)
|
|
||||||
startptr = path;
|
|
||||||
else
|
|
||||||
startptr = startptr+1;
|
|
||||||
|
|
||||||
basename = gk_strdup(startptr);
|
|
||||||
|
|
||||||
if ((endptr = strrchr(basename, '.')) != NULL)
|
|
||||||
*endptr = '\0';
|
|
||||||
|
|
||||||
return basename;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes in a potentially full path specification of a file
|
|
||||||
* and just returns a string corresponding to its file extension. The
|
|
||||||
* extension of a file is considered to be the string right after the
|
|
||||||
* last '.' character.
|
|
||||||
**************************************************************************/
|
|
||||||
char *gk_getextname(char *path)
|
|
||||||
{
|
|
||||||
char *startptr;
|
|
||||||
|
|
||||||
if ((startptr = strrchr(path, '.')) == NULL)
|
|
||||||
return gk_strdup(path);
|
|
||||||
else
|
|
||||||
return gk_strdup(startptr+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes in a potentially full path specification of a file
|
|
||||||
* and just returns a string containing just the filename.
|
|
||||||
**************************************************************************/
|
|
||||||
char *gk_getfilename(char *path)
|
|
||||||
{
|
|
||||||
char *startptr;
|
|
||||||
|
|
||||||
if ((startptr = strrchr(path, '/')) == NULL)
|
|
||||||
return gk_strdup(path);
|
|
||||||
else
|
|
||||||
return gk_strdup(startptr+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes in a potentially full path specification of a file
|
|
||||||
* and extracts the directory path component if it exists, otherwise it
|
|
||||||
* returns "./" as the path. The memory for it is dynamically allocated.
|
|
||||||
**************************************************************************/
|
|
||||||
char *getpathname(char *path)
|
|
||||||
{
|
|
||||||
char *endptr, *tmp;
|
|
||||||
|
|
||||||
if ((endptr = strrchr(path, '/')) == NULL) {
|
|
||||||
return gk_strdup(".");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tmp = gk_strdup(path);
|
|
||||||
*(strrchr(tmp, '/')) = '\0';
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function creates a path
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_mkpath(char *pathname)
|
|
||||||
{
|
|
||||||
char tmp[2048];
|
|
||||||
|
|
||||||
sprintf(tmp, "mkdir -p %s", pathname);
|
|
||||||
return system(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function deletes a directory tree and all of its contents
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_rmpath(char *pathname)
|
|
||||||
{
|
|
||||||
char tmp[2048];
|
|
||||||
|
|
||||||
sprintf(tmp, "rm -r %s", pathname);
|
|
||||||
return system(tmp);
|
|
||||||
}
|
|
||||||
@ -1,858 +0,0 @@
|
|||||||
/*************************************************************************/
|
|
||||||
/*! \file getopt.c
|
|
||||||
\brief Command line parsing
|
|
||||||
|
|
||||||
This file contains a implementation of GNU's Getopt facility. The purpose
|
|
||||||
for including it here is to ensure portability across different unix- and
|
|
||||||
windows-based systems.
|
|
||||||
|
|
||||||
\warning
|
|
||||||
The implementation provided here uses the \c gk_ prefix for all variables
|
|
||||||
used by the standard Getopt facility to communicate with the program.
|
|
||||||
So, do read the documentation here.
|
|
||||||
|
|
||||||
\verbatim
|
|
||||||
Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001
|
|
||||||
Free Software Foundation, Inc. This file is part of the GNU C Library.
|
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with the GNU C Library; if not, write to the Free
|
|
||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
02111-1307 USA.
|
|
||||||
\endverbatim
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Local function prototypes */
|
|
||||||
/*************************************************************************/
|
|
||||||
static void exchange (char **);
|
|
||||||
static const char *gk_getopt_initialize (int, char *const *, const char *);
|
|
||||||
static int gk_getopt_internal(int argc, char *const *argv, const char *optstring,
|
|
||||||
const struct gk_option *longopts, int *longind, int long_only);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief For communication arguments to the caller.
|
|
||||||
|
|
||||||
This variable is set by getopt to point at the value of the option argument,
|
|
||||||
for those options that accept arguments.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
char *gk_optarg;
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief Index in ARGV of the next element to be scanned.
|
|
||||||
|
|
||||||
This variable is set by getopt to the index of the next element of the argv
|
|
||||||
array to be processed. Once getopt has found all of the option arguments,
|
|
||||||
you can use this variable to determine where the remaining non-option arguments
|
|
||||||
begin.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
int gk_optind = 1;
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief Controls error reporting for unrecognized options.
|
|
||||||
|
|
||||||
If the value of this variable is nonzero, then getopt prints an error
|
|
||||||
message to the standard error stream if it encounters an unknown option
|
|
||||||
character or an option with a missing required argument. This is the default
|
|
||||||
behavior. If you set this variable to zero, getopt does not print any messages,
|
|
||||||
but it still returns the character ? to indicate an error.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
int gk_opterr = 1;
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief Stores unknown option characters
|
|
||||||
|
|
||||||
When getopt encounters an unknown option character or an option with a
|
|
||||||
missing required argument, it stores that option character in this
|
|
||||||
variable. You can use this for providing your own diagnostic messages.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
int gk_optopt = '?';
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
Records that the getopt facility has been initialized.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
int gk_getopt_initialized;
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
The next char to be scanned in the option-element in which the last option
|
|
||||||
character we returned was found. This allows us to pick up the scan where
|
|
||||||
we left off.
|
|
||||||
|
|
||||||
If this is zero, or a null string, it means resume the scan by advancing
|
|
||||||
to the next ARGV-element.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
static char *nextchar;
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
Value of POSIXLY_CORRECT environment variable.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
static char *posixly_correct;
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
Describe how to deal with options that follow non-option ARGV-elements.
|
|
||||||
|
|
||||||
If the caller did not specify anything, the default is REQUIRE_ORDER if
|
|
||||||
the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise.
|
|
||||||
|
|
||||||
REQUIRE_ORDER means don't recognize them as options; stop option processing
|
|
||||||
when the first non-option is seen. This is what Unix does. This mode of
|
|
||||||
operation is selected by either setting the environment variable
|
|
||||||
POSIXLY_CORRECT, or using `+' as the first character of the list of
|
|
||||||
option characters.
|
|
||||||
|
|
||||||
PERMUTE is the default. We permute the contents of ARGV as we scan, so
|
|
||||||
that eventually all the non-options are at the end. This allows options
|
|
||||||
to be given in any order, even with programs that were not written to
|
|
||||||
expect this.
|
|
||||||
|
|
||||||
RETURN_IN_ORDER is an option available to programs that were written
|
|
||||||
to expect options and other ARGV-elements in any order and that care
|
|
||||||
about the ordering of the two. We describe each non-option ARGV-element
|
|
||||||
as if it were the argument of an option with character code 1.
|
|
||||||
Using `-' as the first character of the list of option characters
|
|
||||||
selects this mode of operation.
|
|
||||||
|
|
||||||
The special argument `--' forces an end of option-scanning regardless
|
|
||||||
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
|
||||||
`--' can cause `getopt' to return -1 with `gk_optind' != ARGC.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
static enum
|
|
||||||
{
|
|
||||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
|
||||||
} ordering;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
Describe the part of ARGV that contains non-options that have
|
|
||||||
been skipped. `first_nonopt' is the index in ARGV of the first of them;
|
|
||||||
`last_nonopt' is the index after the last of them.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
static int first_nonopt;
|
|
||||||
static int last_nonopt;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
Handle permutation of arguments.
|
|
||||||
|
|
||||||
Exchange two adjacent subsequences of ARGV.
|
|
||||||
One subsequence is elements [first_nonopt,last_nonopt)
|
|
||||||
which contains all the non-options that have been skipped so far.
|
|
||||||
The other is elements [last_nonopt,gk_optind), which contains all
|
|
||||||
the options processed since those non-options were skipped.
|
|
||||||
|
|
||||||
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
|
||||||
the new indices of the non-options in ARGV after they are moved.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
static void exchange (char **argv)
|
|
||||||
{
|
|
||||||
int bottom = first_nonopt;
|
|
||||||
int middle = last_nonopt;
|
|
||||||
int top = gk_optind;
|
|
||||||
char *tem;
|
|
||||||
|
|
||||||
/* Exchange the shorter segment with the far end of the longer segment.
|
|
||||||
That puts the shorter segment into the right place.
|
|
||||||
It leaves the longer segment in the right place overall,
|
|
||||||
but it consists of two parts that need to be swapped next. */
|
|
||||||
|
|
||||||
while (top > middle && middle > bottom) {
|
|
||||||
if (top - middle > middle - bottom) {
|
|
||||||
/* Bottom segment is the short one. */
|
|
||||||
int len = middle - bottom;
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
/* Swap it with the top part of the top segment. */
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
tem = argv[bottom + i];
|
|
||||||
argv[bottom + i] = argv[top - (middle - bottom) + i];
|
|
||||||
argv[top - (middle - bottom) + i] = tem;
|
|
||||||
}
|
|
||||||
/* Exclude the moved bottom segment from further swapping. */
|
|
||||||
top -= len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Top segment is the short one. */
|
|
||||||
int len = top - middle;
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
/* Swap it with the bottom part of the bottom segment. */
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
tem = argv[bottom + i];
|
|
||||||
argv[bottom + i] = argv[middle + i];
|
|
||||||
argv[middle + i] = tem;
|
|
||||||
}
|
|
||||||
/* Exclude the moved top segment from further swapping. */
|
|
||||||
bottom += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update records for the slots the non-options now occupy. */
|
|
||||||
|
|
||||||
first_nonopt += (gk_optind - last_nonopt);
|
|
||||||
last_nonopt = gk_optind;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
Initialize the internal data when the first call is made.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
static const char *gk_getopt_initialize (int argc, char *const *argv, const char *optstring)
|
|
||||||
{
|
|
||||||
/* Start processing options with ARGV-element 1 (since ARGV-element 0
|
|
||||||
is the program name); the sequence of previously skipped
|
|
||||||
non-option ARGV-elements is empty. */
|
|
||||||
|
|
||||||
first_nonopt = last_nonopt = gk_optind;
|
|
||||||
|
|
||||||
nextchar = NULL;
|
|
||||||
|
|
||||||
posixly_correct = getenv("POSIXLY_CORRECT");
|
|
||||||
|
|
||||||
/* Determine how to handle the ordering of options and nonoptions. */
|
|
||||||
if (optstring[0] == '-') {
|
|
||||||
ordering = RETURN_IN_ORDER;
|
|
||||||
++optstring;
|
|
||||||
}
|
|
||||||
else if (optstring[0] == '+') {
|
|
||||||
ordering = REQUIRE_ORDER;
|
|
||||||
++optstring;
|
|
||||||
}
|
|
||||||
else if (posixly_correct != NULL)
|
|
||||||
ordering = REQUIRE_ORDER;
|
|
||||||
else
|
|
||||||
ordering = PERMUTE;
|
|
||||||
|
|
||||||
return optstring;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*
|
|
||||||
Scan elements of ARGV (whose length is ARGC) for option characters
|
|
||||||
given in OPTSTRING.
|
|
||||||
|
|
||||||
If an element of ARGV starts with '-', and is not exactly "-" or "--",
|
|
||||||
then it is an option element. The characters of this element
|
|
||||||
(aside from the initial '-') are option characters. If `getopt'
|
|
||||||
is called repeatedly, it returns successively each of the option characters
|
|
||||||
from each of the option elements.
|
|
||||||
|
|
||||||
If `getopt' finds another option character, it returns that character,
|
|
||||||
updating `gk_optind' and `nextchar' so that the next call to `getopt' can
|
|
||||||
resume the scan with the following option character or ARGV-element.
|
|
||||||
|
|
||||||
If there are no more option characters, `getopt' returns -1.
|
|
||||||
Then `gk_optind' is the index in ARGV of the first ARGV-element
|
|
||||||
that is not an option. (The ARGV-elements have been permuted
|
|
||||||
so that those that are not options now come last.)
|
|
||||||
|
|
||||||
OPTSTRING is a string containing the legitimate option characters.
|
|
||||||
If an option character is seen that is not listed in OPTSTRING,
|
|
||||||
return '?' after printing an error message. If you set `gk_opterr' to
|
|
||||||
zero, the error message is suppressed but we still return '?'.
|
|
||||||
|
|
||||||
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
|
|
||||||
so the following text in the same ARGV-element, or the text of the following
|
|
||||||
ARGV-element, is returned in `gk_optarg'. Two colons mean an option that
|
|
||||||
wants an optional arg; if there is text in the current ARGV-element,
|
|
||||||
it is returned in `gk_optarg', otherwise `gk_optarg' is set to zero.
|
|
||||||
|
|
||||||
If OPTSTRING starts with `-' or `+', it requests different methods of
|
|
||||||
handling the non-option ARGV-elements.
|
|
||||||
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
|
|
||||||
|
|
||||||
Long-named options begin with `--' instead of `-'.
|
|
||||||
Their names may be abbreviated as long as the abbreviation is unique
|
|
||||||
or is an exact match for some defined option. If they have an
|
|
||||||
argument, it follows the option name in the same ARGV-element, separated
|
|
||||||
from the option name by a `=', or else the in next ARGV-element.
|
|
||||||
When `getopt' finds a long-named option, it returns 0 if that option's
|
|
||||||
`flag' field is nonzero, the value of the option's `val' field
|
|
||||||
if the `flag' field is zero.
|
|
||||||
|
|
||||||
The elements of ARGV aren't really const, because we permute them.
|
|
||||||
But we pretend they're const in the prototype to be compatible
|
|
||||||
with other systems.
|
|
||||||
|
|
||||||
LONGOPTS is a vector of `struct gk_option' terminated by an
|
|
||||||
element containing a name which is zero.
|
|
||||||
|
|
||||||
LONGIND returns the index in LONGOPT of the long-named option found.
|
|
||||||
It is only valid when a long-named option has been found by the most
|
|
||||||
recent call.
|
|
||||||
|
|
||||||
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
|
|
||||||
long-named options.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
static int gk_getopt_internal(int argc, char *const *argv, const char *optstring,
|
|
||||||
const struct gk_option *longopts, int *longind, int long_only)
|
|
||||||
{
|
|
||||||
int print_errors = gk_opterr;
|
|
||||||
if (optstring[0] == ':')
|
|
||||||
print_errors = 0;
|
|
||||||
|
|
||||||
if (argc < 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
gk_optarg = NULL;
|
|
||||||
|
|
||||||
if (gk_optind == 0 || !gk_getopt_initialized) {
|
|
||||||
if (gk_optind == 0)
|
|
||||||
gk_optind = 1; /* Don't scan ARGV[0], the program name. */
|
|
||||||
optstring = gk_getopt_initialize (argc, argv, optstring);
|
|
||||||
gk_getopt_initialized = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Test whether ARGV[gk_optind] points to a non-option argument.
|
|
||||||
Either it does not have option syntax, or there is an environment flag
|
|
||||||
from the shell indicating it is not an option. The later information
|
|
||||||
is only used when the used in the GNU libc. */
|
|
||||||
# define NONOPTION_P (argv[gk_optind][0] != '-' || argv[gk_optind][1] == '\0')
|
|
||||||
|
|
||||||
if (nextchar == NULL || *nextchar == '\0') {
|
|
||||||
/* Advance to the next ARGV-element. */
|
|
||||||
|
|
||||||
/* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
|
|
||||||
moved back by the user (who may also have changed the arguments). */
|
|
||||||
if (last_nonopt > gk_optind)
|
|
||||||
last_nonopt = gk_optind;
|
|
||||||
if (first_nonopt > gk_optind)
|
|
||||||
first_nonopt = gk_optind;
|
|
||||||
|
|
||||||
if (ordering == PERMUTE) {
|
|
||||||
/* If we have just processed some options following some non-options,
|
|
||||||
exchange them so that the options come first. */
|
|
||||||
|
|
||||||
if (first_nonopt != last_nonopt && last_nonopt != gk_optind)
|
|
||||||
exchange ((char **) argv);
|
|
||||||
else if (last_nonopt != gk_optind)
|
|
||||||
first_nonopt = gk_optind;
|
|
||||||
|
|
||||||
/* Skip any additional non-options
|
|
||||||
and extend the range of non-options previously skipped. */
|
|
||||||
|
|
||||||
while (gk_optind < argc && NONOPTION_P)
|
|
||||||
gk_optind++;
|
|
||||||
|
|
||||||
last_nonopt = gk_optind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The special ARGV-element `--' means premature end of options.
|
|
||||||
Skip it like a null option,
|
|
||||||
then exchange with previous non-options as if it were an option,
|
|
||||||
then skip everything else like a non-option. */
|
|
||||||
|
|
||||||
if (gk_optind != argc && !strcmp (argv[gk_optind], "--")) {
|
|
||||||
gk_optind++;
|
|
||||||
|
|
||||||
if (first_nonopt != last_nonopt && last_nonopt != gk_optind)
|
|
||||||
exchange ((char **) argv);
|
|
||||||
else if (first_nonopt == last_nonopt)
|
|
||||||
first_nonopt = gk_optind;
|
|
||||||
last_nonopt = argc;
|
|
||||||
|
|
||||||
gk_optind = argc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have done all the ARGV-elements, stop the scan
|
|
||||||
and back over any non-options that we skipped and permuted. */
|
|
||||||
|
|
||||||
if (gk_optind == argc) {
|
|
||||||
/* Set the next-arg-index to point at the non-options
|
|
||||||
that we previously skipped, so the caller will digest them. */
|
|
||||||
if (first_nonopt != last_nonopt)
|
|
||||||
gk_optind = first_nonopt;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have come to a non-option and did not permute it,
|
|
||||||
either stop the scan or describe it to the caller and pass it by. */
|
|
||||||
|
|
||||||
if (NONOPTION_P) {
|
|
||||||
if (ordering == REQUIRE_ORDER)
|
|
||||||
return -1;
|
|
||||||
gk_optarg = argv[gk_optind++];
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have found another option-ARGV-element.
|
|
||||||
Skip the initial punctuation. */
|
|
||||||
|
|
||||||
nextchar = (argv[gk_optind] + 1 + (longopts != NULL && argv[gk_optind][1] == '-'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode the current option-ARGV-element. */
|
|
||||||
|
|
||||||
/* Check whether the ARGV-element is a long option.
|
|
||||||
|
|
||||||
If long_only and the ARGV-element has the form "-f", where f is
|
|
||||||
a valid short option, don't consider it an abbreviated form of
|
|
||||||
a long option that starts with f. Otherwise there would be no
|
|
||||||
way to give the -f short option.
|
|
||||||
|
|
||||||
On the other hand, if there's a long option "fubar" and
|
|
||||||
the ARGV-element is "-fu", do consider that an abbreviation of
|
|
||||||
the long option, just like "--fu", and not "-f" with arg "u".
|
|
||||||
|
|
||||||
This distinction seems to be the most useful approach. */
|
|
||||||
|
|
||||||
if (longopts != NULL && (argv[gk_optind][1] == '-' || (long_only && (argv[gk_optind][2] || !strchr(optstring, argv[gk_optind][1]))))) {
|
|
||||||
char *nameend;
|
|
||||||
const struct gk_option *p;
|
|
||||||
const struct gk_option *pfound = NULL;
|
|
||||||
int exact = 0;
|
|
||||||
int ambig = 0;
|
|
||||||
int indfound = -1;
|
|
||||||
int option_index;
|
|
||||||
|
|
||||||
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
|
|
||||||
/* Do nothing. */ ;
|
|
||||||
|
|
||||||
/* Test all long options for either exact match or abbreviated matches. */
|
|
||||||
for (p = longopts, option_index = 0; p->name; p++, option_index++) {
|
|
||||||
if (!strncmp (p->name, nextchar, nameend - nextchar)) {
|
|
||||||
if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) {
|
|
||||||
/* Exact match found. */
|
|
||||||
pfound = p;
|
|
||||||
indfound = option_index;
|
|
||||||
exact = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (pfound == NULL) {
|
|
||||||
/* First nonexact match found. */
|
|
||||||
pfound = p;
|
|
||||||
indfound = option_index;
|
|
||||||
}
|
|
||||||
else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
|
|
||||||
/* Second or later nonexact match found. */
|
|
||||||
ambig = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ambig && !exact) {
|
|
||||||
if (print_errors)
|
|
||||||
fprintf(stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[gk_optind]);
|
|
||||||
|
|
||||||
nextchar += strlen (nextchar);
|
|
||||||
gk_optind++;
|
|
||||||
gk_optopt = 0;
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfound != NULL) {
|
|
||||||
option_index = indfound;
|
|
||||||
gk_optind++;
|
|
||||||
if (*nameend) {
|
|
||||||
/* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */
|
|
||||||
if (pfound->has_arg)
|
|
||||||
gk_optarg = nameend + 1;
|
|
||||||
else {
|
|
||||||
if (print_errors) {
|
|
||||||
if (argv[gk_optind - 1][1] == '-')
|
|
||||||
/* --option */
|
|
||||||
fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name);
|
|
||||||
else
|
|
||||||
/* +option or -option */
|
|
||||||
fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[gk_optind - 1][0], pfound->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
nextchar += strlen (nextchar);
|
|
||||||
|
|
||||||
gk_optopt = pfound->val;
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pfound->has_arg == 1) {
|
|
||||||
if (gk_optind < argc)
|
|
||||||
gk_optarg = argv[gk_optind++];
|
|
||||||
else {
|
|
||||||
if (print_errors)
|
|
||||||
fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[gk_optind - 1]);
|
|
||||||
nextchar += strlen (nextchar);
|
|
||||||
gk_optopt = pfound->val;
|
|
||||||
return optstring[0] == ':' ? ':' : '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextchar += strlen (nextchar);
|
|
||||||
if (longind != NULL)
|
|
||||||
*longind = option_index;
|
|
||||||
if (pfound->flag) {
|
|
||||||
*(pfound->flag) = pfound->val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return pfound->val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Can't find it as a long option. If this is not getopt_long_only,
|
|
||||||
or the option starts with '--' or is not a valid short
|
|
||||||
option, then it's an error. Otherwise interpret it as a short option. */
|
|
||||||
if (!long_only || argv[gk_optind][1] == '-' || strchr(optstring, *nextchar) == NULL) {
|
|
||||||
if (print_errors) {
|
|
||||||
if (argv[gk_optind][1] == '-')
|
|
||||||
/* --option */
|
|
||||||
fprintf(stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar);
|
|
||||||
else
|
|
||||||
/* +option or -option */
|
|
||||||
fprintf(stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[gk_optind][0], nextchar);
|
|
||||||
}
|
|
||||||
nextchar = (char *) "";
|
|
||||||
gk_optind++;
|
|
||||||
gk_optopt = 0;
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look at and handle the next short option-character. */
|
|
||||||
{
|
|
||||||
char c = *nextchar++;
|
|
||||||
char *temp = strchr(optstring, c);
|
|
||||||
|
|
||||||
/* Increment `gk_optind' when we start to process its last character. */
|
|
||||||
if (*nextchar == '\0')
|
|
||||||
++gk_optind;
|
|
||||||
|
|
||||||
if (temp == NULL || c == ':') {
|
|
||||||
if (print_errors) {
|
|
||||||
if (posixly_correct)
|
|
||||||
/* 1003.2 specifies the format of this message. */
|
|
||||||
fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c);
|
|
||||||
else
|
|
||||||
fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
|
|
||||||
}
|
|
||||||
gk_optopt = c;
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convenience. Treat POSIX -W foo same as long option --foo */
|
|
||||||
if (temp[0] == 'W' && temp[1] == ';') {
|
|
||||||
char *nameend;
|
|
||||||
const struct gk_option *p;
|
|
||||||
const struct gk_option *pfound = NULL;
|
|
||||||
int exact = 0;
|
|
||||||
int ambig = 0;
|
|
||||||
int indfound = 0;
|
|
||||||
int option_index;
|
|
||||||
|
|
||||||
/* This is an option that requires an argument. */
|
|
||||||
if (*nextchar != '\0') {
|
|
||||||
gk_optarg = nextchar;
|
|
||||||
/* If we end this ARGV-element by taking the rest as an arg,
|
|
||||||
we must advance to the next element now. */
|
|
||||||
gk_optind++;
|
|
||||||
}
|
|
||||||
else if (gk_optind == argc) {
|
|
||||||
if (print_errors) {
|
|
||||||
/* 1003.2 specifies the format of this message. */
|
|
||||||
fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c);
|
|
||||||
}
|
|
||||||
gk_optopt = c;
|
|
||||||
if (optstring[0] == ':')
|
|
||||||
c = ':';
|
|
||||||
else
|
|
||||||
c = '?';
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* We already incremented `gk_optind' once; increment it again when taking next ARGV-elt as argument. */
|
|
||||||
gk_optarg = argv[gk_optind++];
|
|
||||||
|
|
||||||
/* gk_optarg is now the argument, see if it's in the table of longopts. */
|
|
||||||
|
|
||||||
for (nextchar = nameend = gk_optarg; *nameend && *nameend != '='; nameend++)
|
|
||||||
/* Do nothing. */ ;
|
|
||||||
|
|
||||||
/* Test all long options for either exact match or abbreviated matches. */
|
|
||||||
for (p = longopts, option_index = 0; p->name; p++, option_index++) {
|
|
||||||
if (!strncmp (p->name, nextchar, nameend - nextchar)) {
|
|
||||||
if ((unsigned int) (nameend - nextchar) == strlen (p->name)) {
|
|
||||||
/* Exact match found. */
|
|
||||||
pfound = p;
|
|
||||||
indfound = option_index;
|
|
||||||
exact = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (pfound == NULL) {
|
|
||||||
/* First nonexact match found. */
|
|
||||||
pfound = p;
|
|
||||||
indfound = option_index;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* Second or later nonexact match found. */
|
|
||||||
ambig = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ambig && !exact) {
|
|
||||||
if (print_errors)
|
|
||||||
fprintf(stderr, "%s: option `-W %s' is ambiguous\n", argv[0], argv[gk_optind]);
|
|
||||||
nextchar += strlen (nextchar);
|
|
||||||
gk_optind++;
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
if (pfound != NULL) {
|
|
||||||
option_index = indfound;
|
|
||||||
if (*nameend) {
|
|
||||||
/* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */
|
|
||||||
if (pfound->has_arg)
|
|
||||||
gk_optarg = nameend + 1;
|
|
||||||
else {
|
|
||||||
if (print_errors)
|
|
||||||
fprintf(stderr, "%s: option `-W %s' doesn't allow an argument\n", argv[0], pfound->name);
|
|
||||||
|
|
||||||
nextchar += strlen (nextchar);
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pfound->has_arg == 1) {
|
|
||||||
if (gk_optind < argc)
|
|
||||||
gk_optarg = argv[gk_optind++];
|
|
||||||
else {
|
|
||||||
if (print_errors)
|
|
||||||
fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[gk_optind - 1]);
|
|
||||||
nextchar += strlen (nextchar);
|
|
||||||
return optstring[0] == ':' ? ':' : '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextchar += strlen (nextchar);
|
|
||||||
if (longind != NULL)
|
|
||||||
*longind = option_index;
|
|
||||||
if (pfound->flag) {
|
|
||||||
*(pfound->flag) = pfound->val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return pfound->val;
|
|
||||||
}
|
|
||||||
nextchar = NULL;
|
|
||||||
return 'W'; /* Let the application handle it. */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (temp[1] == ':') {
|
|
||||||
if (temp[2] == ':') {
|
|
||||||
/* This is an option that accepts an argument optionally. */
|
|
||||||
if (*nextchar != '\0') {
|
|
||||||
gk_optarg = nextchar;
|
|
||||||
gk_optind++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
gk_optarg = NULL;
|
|
||||||
nextchar = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* This is an option that requires an argument. */
|
|
||||||
if (*nextchar != '\0') {
|
|
||||||
gk_optarg = nextchar;
|
|
||||||
/* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */
|
|
||||||
gk_optind++;
|
|
||||||
}
|
|
||||||
else if (gk_optind == argc) {
|
|
||||||
if (print_errors) {
|
|
||||||
/* 1003.2 specifies the format of this message. */
|
|
||||||
fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c);
|
|
||||||
}
|
|
||||||
gk_optopt = c;
|
|
||||||
if (optstring[0] == ':')
|
|
||||||
c = ':';
|
|
||||||
else
|
|
||||||
c = '?';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* We already incremented `gk_optind' once; increment it again when taking next ARGV-elt as argument. */
|
|
||||||
gk_optarg = argv[gk_optind++];
|
|
||||||
nextchar = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief Parse command-line arguments
|
|
||||||
|
|
||||||
The gk_getopt() function gets the next option argument from the argument
|
|
||||||
list specified by the \c argv and \c argc arguments. Normally these values
|
|
||||||
come directly from the arguments received by main().
|
|
||||||
|
|
||||||
\param argc is the number of command line arguments passed to main().
|
|
||||||
\param argv is an array of strings storing the above command line
|
|
||||||
arguments.
|
|
||||||
\param options is a string that specifies the option characters that
|
|
||||||
are valid for this program. An option character in this string
|
|
||||||
can be followed by a colon (`:') to indicate that it takes a
|
|
||||||
required argument. If an option character is followed by two
|
|
||||||
colons (`::'), its argument is optional; this is a GNU extension.
|
|
||||||
|
|
||||||
\return
|
|
||||||
It returns the option character for the next command line option. When no
|
|
||||||
more option arguments are available, it returns -1. There may still be
|
|
||||||
more non-option arguments; you must compare the external variable
|
|
||||||
#gk_optind against the \c argc parameter to check this.
|
|
||||||
|
|
||||||
\return
|
|
||||||
If the option has an argument, gk_getopt() returns the argument by storing
|
|
||||||
it in the variable #gk_optarg. You don't ordinarily need to copy the
|
|
||||||
#gk_optarg string, since it is a pointer into the original \c argv array,
|
|
||||||
not into a static area that might be overwritten.
|
|
||||||
|
|
||||||
\return
|
|
||||||
If gk_getopt() finds an option character in \c argv that was not included
|
|
||||||
in options, or a missing option argument, it returns `?' and sets the
|
|
||||||
external variable #gk_optopt to the actual option character.
|
|
||||||
If the first character of options is a colon (`:'), then gk_getopt()
|
|
||||||
returns `:' instead of `?' to indicate a missing option argument.
|
|
||||||
In addition, if the external variable #gk_opterr is nonzero (which is
|
|
||||||
the default), gk_getopt() prints an error message. This variable is
|
|
||||||
set by gk_getopt() to point at the value of the option argument,
|
|
||||||
for those options that accept arguments.
|
|
||||||
|
|
||||||
|
|
||||||
gk_getopt() has three ways to deal with options that follow non-options
|
|
||||||
\c argv elements. The special argument <tt>`--'</tt> forces in all cases
|
|
||||||
the end of option scanning.
|
|
||||||
- The default is to permute the contents of \c argv while scanning it
|
|
||||||
so that eventually all the non-options are at the end. This allows
|
|
||||||
options to be given in any order, even with programs that were not
|
|
||||||
written to expect this.
|
|
||||||
- If the options argument string begins with a hyphen (`-'), this is
|
|
||||||
treated specially. It permits arguments that are not options to be
|
|
||||||
returned as if they were associated with option character `\\1'.
|
|
||||||
- POSIX demands the following behavior: The first non-option stops
|
|
||||||
option processing. This mode is selected by either setting the
|
|
||||||
environment variable POSIXLY_CORRECT or beginning the options
|
|
||||||
argument string with a plus sign (`+').
|
|
||||||
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
int gk_getopt(int argc, char **argv, const char *options)
|
|
||||||
{
|
|
||||||
return gk_getopt_internal(argc, argv, options, NULL, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief Parse command-line arguments with long options
|
|
||||||
|
|
||||||
This function accepts GNU-style long options as well as single-character
|
|
||||||
options.
|
|
||||||
|
|
||||||
\param argc is the number of command line arguments passed to main().
|
|
||||||
\param argv is an array of strings storing the above command line
|
|
||||||
arguments.
|
|
||||||
\param options describes the short options to accept, just as it does
|
|
||||||
in gk_getopt().
|
|
||||||
\param long_options describes the long options to accept. See the
|
|
||||||
defintion of ::gk_option for more information.
|
|
||||||
\param opt_index this is a returned variable. For any long option,
|
|
||||||
gk_getopt_long() tells you the index in the array \c long_options
|
|
||||||
of the options definition, by storing it into <tt>*opt_index</tt>.
|
|
||||||
You can get the name of the option with <tt>longopts[*opt_index].name</tt>.
|
|
||||||
So you can distinguish among long options either by the values
|
|
||||||
in their val fields or by their indices. You can also distinguish
|
|
||||||
in this way among long options that set flags.
|
|
||||||
|
|
||||||
|
|
||||||
\return
|
|
||||||
When gk_getopt_long() encounters a short option, it does the same thing
|
|
||||||
that gk_getopt() would do: it returns the character code for the option,
|
|
||||||
and stores the options argument (if it has one) in #gk_optarg.
|
|
||||||
|
|
||||||
\return
|
|
||||||
When gk_getopt_long() encounters a long option, it takes actions based
|
|
||||||
on the flag and val fields of the definition of that option.
|
|
||||||
|
|
||||||
\return
|
|
||||||
If flag is a null pointer, then gk_getopt_long() returns the contents
|
|
||||||
of val to indicate which option it found. You should arrange distinct
|
|
||||||
values in the val field for options with different meanings, so you
|
|
||||||
can decode these values after gk_getopt_long() returns. If the long
|
|
||||||
option is equivalent to a short option, you can use the short option's
|
|
||||||
character code in val.
|
|
||||||
|
|
||||||
\return
|
|
||||||
If flag is not a null pointer, that means this option should just set
|
|
||||||
a flag in the program. The flag is a variable of type int that you
|
|
||||||
define. Put the address of the flag in the flag field. Put in the
|
|
||||||
val field the value you would like this option to store in the flag.
|
|
||||||
In this case, gk_getopt_long() returns 0.
|
|
||||||
|
|
||||||
\return
|
|
||||||
When a long option has an argument, gk_getopt_long() puts the argument
|
|
||||||
value in the variable #gk_optarg before returning. When the option has
|
|
||||||
no argument, the value in #gk_optarg is a null pointer. This is
|
|
||||||
how you can tell whether an optional argument was supplied.
|
|
||||||
|
|
||||||
\return
|
|
||||||
When gk_getopt_long() has no more options to handle, it returns -1,
|
|
||||||
and leaves in the variable #gk_optind the index in argv of the next
|
|
||||||
remaining argument.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
int gk_getopt_long( int argc, char *const *argv, const char *options,
|
|
||||||
const struct gk_option *long_options, int *opt_index)
|
|
||||||
{
|
|
||||||
return gk_getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! \brief Parse command-line arguments with only long options
|
|
||||||
|
|
||||||
Like gk_getopt_long(), but '-' as well as '--' can indicate a long option.
|
|
||||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
|
||||||
but does match a short option, it is parsed as a short option instead.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
int gk_getopt_long_only(int argc, char *const *argv, const char *options,
|
|
||||||
const struct gk_option *long_options, int *opt_index)
|
|
||||||
{
|
|
||||||
return gk_getopt_internal(argc, argv, options, long_options, opt_index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_arch.h
|
|
||||||
\brief This file contains various architecture-specific declerations
|
|
||||||
|
|
||||||
\date Started 3/27/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_arch.h 1430 2007-04-07 17:53:07Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_ARCH_H_
|
|
||||||
#define _GK_ARCH_H_
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Architecture-specific differences in header files
|
|
||||||
**************************************************************************/
|
|
||||||
#ifdef LINUX
|
|
||||||
#if !defined(__USE_XOPEN)
|
|
||||||
#define __USE_XOPEN
|
|
||||||
#endif
|
|
||||||
#if !defined(_XOPEN_SOURCE)
|
|
||||||
#define _XOPEN_SOURCE 600
|
|
||||||
#endif
|
|
||||||
#if !defined(__USE_XOPEN2K)
|
|
||||||
#define __USE_XOPEN2K
|
|
||||||
#endif
|
|
||||||
#include <execinfo.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __MSC__
|
|
||||||
#include <crtdefs.h>
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Architecture-specific modifications
|
|
||||||
**************************************************************************/
|
|
||||||
#ifdef WIN32
|
|
||||||
#define __thread __declspec( thread )
|
|
||||||
|
|
||||||
typedef __int32 int32_t;
|
|
||||||
typedef __int64 int64_t;
|
|
||||||
typedef unsigned __int32 uint32_t;
|
|
||||||
typedef unsigned __int64 uint64_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUNOS
|
|
||||||
#define __thread
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DARWIN
|
|
||||||
#define __thread
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __MSC__
|
|
||||||
#define rint(x) ((int)((x)+0.5)) /* MSC does not have rint() function */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#if !defined(strdup)
|
|
||||||
extern char* strdup (const char *);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,224 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_blas.h
|
|
||||||
\brief This file contains GKlib's code generators for BLAS-like routines
|
|
||||||
|
|
||||||
\date Started 3/28/07
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_blas.h 1421 2007-04-06 14:37:41Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_BLAS_H_
|
|
||||||
#define _GK_BLAS_H_
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?set()-class of routines */
|
|
||||||
/*************************************************************************/
|
|
||||||
#define GK_SET(NAME, TYPE) \
|
|
||||||
TYPE *NAME(size_t n, TYPE val, TYPE *x)\
|
|
||||||
{\
|
|
||||||
size_t i;\
|
|
||||||
\
|
|
||||||
for (i=0; i<n; i++)\
|
|
||||||
x[i] = val;\
|
|
||||||
\
|
|
||||||
return x;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_SET_PROTO(NAME, TYPE) \
|
|
||||||
TYPE *NAME(size_t n, TYPE val, TYPE *x);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?incset()-class of routines */
|
|
||||||
/*************************************************************************/
|
|
||||||
#define GK_INCSET(NAME, TYPE)\
|
|
||||||
TYPE *NAME(size_t n, TYPE baseval, TYPE *x)\
|
|
||||||
{\
|
|
||||||
size_t i;\
|
|
||||||
\
|
|
||||||
for (i=0; i<n; i++)\
|
|
||||||
x[i] = baseval+i;\
|
|
||||||
\
|
|
||||||
return x;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_INCSET_PROTO(NAME, TYPE) \
|
|
||||||
TYPE *NAME(size_t n, TYPE baseval, TYPE *x);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?argmax()-class of routines */
|
|
||||||
/*************************************************************************/
|
|
||||||
#define GK_ARGMAX(NAME, TYPE) \
|
|
||||||
size_t NAME(size_t n, TYPE *x)\
|
|
||||||
{\
|
|
||||||
size_t i, max=0;\
|
|
||||||
\
|
|
||||||
for (i=1; i<n; i++)\
|
|
||||||
max = (x[i] > x[max] ? i : max);\
|
|
||||||
\
|
|
||||||
return max;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_ARGMAX_PROTO(NAME, TYPE) \
|
|
||||||
size_t NAME(size_t n, TYPE *x);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?argmin()-class of routines */
|
|
||||||
/*************************************************************************/
|
|
||||||
#define GK_ARGMIN(NAME, TYPE) \
|
|
||||||
size_t NAME(size_t n, TYPE *x)\
|
|
||||||
{\
|
|
||||||
size_t i, min=0;\
|
|
||||||
\
|
|
||||||
for (i=1; i<n; i++)\
|
|
||||||
min = (x[i] < x[min] ? i : min);\
|
|
||||||
\
|
|
||||||
return min;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_ARGMIN_PROTO(NAME, TYPE) \
|
|
||||||
size_t NAME(size_t n, TYPE *x);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?argmax_n()-class of routines */
|
|
||||||
/*************************************************************************/
|
|
||||||
#define GK_ARGMAX_N(NAME, TYPE, KEYVAL_T, KEYVALMALLOC, KEYVALSORT) \
|
|
||||||
size_t NAME(size_t n, TYPE *x, size_t k)\
|
|
||||||
{\
|
|
||||||
size_t i, max_n;\
|
|
||||||
KEYVAL_T *cand;\
|
|
||||||
\
|
|
||||||
cand = KEYVALMALLOC(n, "GK_ARGMAX_N: cand");\
|
|
||||||
\
|
|
||||||
for (i=0; i<n; i++) {\
|
|
||||||
cand[i].val = i;\
|
|
||||||
cand[i].key = x[i];\
|
|
||||||
}\
|
|
||||||
KEYVALSORT(n, cand);\
|
|
||||||
\
|
|
||||||
max_n = cand[k-1].val;\
|
|
||||||
\
|
|
||||||
gk_free((void *)&cand, LTERM);\
|
|
||||||
\
|
|
||||||
return max_n;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_ARGMAX_N_PROTO(NAME, TYPE) \
|
|
||||||
size_t NAME(size_t n, TYPE *x, size_t k);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?sum()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_SUM(NAME, INTYPE, OUTTYPE) \
|
|
||||||
OUTTYPE NAME(size_t n, INTYPE *x, size_t incx)\
|
|
||||||
{\
|
|
||||||
size_t i;\
|
|
||||||
OUTTYPE sum = 0;\
|
|
||||||
\
|
|
||||||
for (i=0; i<n; i++, x+=incx)\
|
|
||||||
sum += (*x);\
|
|
||||||
\
|
|
||||||
return sum;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_SUM_PROTO(NAME, INTYPE, OUTTYPE) \
|
|
||||||
OUTTYPE NAME(size_t n, INTYPE *x, size_t incx);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?scale()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_SCALE(NAME, TYPE) \
|
|
||||||
TYPE *NAME(size_t n, TYPE alpha, TYPE *x, size_t incx)\
|
|
||||||
{\
|
|
||||||
size_t i;\
|
|
||||||
\
|
|
||||||
for (i=0; i<n; i++, x+=incx)\
|
|
||||||
(*x) *= alpha;\
|
|
||||||
\
|
|
||||||
return x;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_SCALE_PROTO(NAME, TYPE) \
|
|
||||||
TYPE *NAME(size_t n, TYPE alpha, TYPE *x, size_t incx);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?norm2()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_NORM2(NAME, INTYPE, OUTTYPE) \
|
|
||||||
OUTTYPE NAME(size_t n, INTYPE *x, size_t incx)\
|
|
||||||
{\
|
|
||||||
size_t i;\
|
|
||||||
OUTTYPE partial = 0;\
|
|
||||||
\
|
|
||||||
for (i=0; i<n; i++, x+=incx)\
|
|
||||||
partial += (*x) * (*x);\
|
|
||||||
\
|
|
||||||
return (partial > 0 ? (OUTTYPE)sqrt((double)partial) : 0.0);\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_NORM2_PROTO(NAME, INTYPE, OUTTYPE) \
|
|
||||||
OUTTYPE NAME(size_t n, INTYPE *x, size_t incx);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?dot()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_DOT(NAME, INTYPE, OUTTYPE) \
|
|
||||||
OUTTYPE NAME(size_t n, INTYPE *x, size_t incx, INTYPE *y, size_t incy)\
|
|
||||||
{\
|
|
||||||
size_t i;\
|
|
||||||
OUTTYPE partial = 0.0;\
|
|
||||||
\
|
|
||||||
for (i=0; i<n; i++, x+=incx, y+=incy)\
|
|
||||||
partial += (*x) * (*y);\
|
|
||||||
\
|
|
||||||
return partial;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_DOT_PROTO(NAME, INTYPE, OUTTYPE) \
|
|
||||||
OUTTYPE NAME(size_t n, INTYPE *x, size_t incx, INTYPE *y, size_t incy);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?axpy()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_AXPY(NAME, TYPE) \
|
|
||||||
TYPE *NAME(size_t n, TYPE alpha, TYPE *x, size_t incx, TYPE *y, size_t incy)\
|
|
||||||
{\
|
|
||||||
size_t i;\
|
|
||||||
TYPE *y_in = y;\
|
|
||||||
\
|
|
||||||
for (i=0; i<n; i++, x+=incx, y+=incy)\
|
|
||||||
*y += alpha*(*x);\
|
|
||||||
\
|
|
||||||
return y_in;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_AXPY_PROTO(NAME, TYPE) \
|
|
||||||
TYPE *NAME(size_t n, TYPE alpha, TYPE *x, size_t incx, TYPE *y, size_t incy);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_defs.h
|
|
||||||
\brief This file contains various constants definitions
|
|
||||||
|
|
||||||
\date Started 3/27/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_defs.h 1277 2007-03-27 21:17:33Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_DEFS_H_
|
|
||||||
#define _GK_DEFS_H_
|
|
||||||
|
|
||||||
|
|
||||||
#define LTERM (void **) 0 /* List terminator for GKfree() */
|
|
||||||
|
|
||||||
#define HTABLE_EMPTY -1
|
|
||||||
#define HTABLE_DELETED -2
|
|
||||||
#define HTABLE_FIRST 1
|
|
||||||
#define HTABLE_NEXT 2
|
|
||||||
|
|
||||||
/* pdb corruption bit switches */
|
|
||||||
#define CRP_ALTLOCS 1
|
|
||||||
#define CRP_MISSINGCA 2
|
|
||||||
#define CRP_MISSINGBB 4
|
|
||||||
#define CRP_MULTICHAIN 8
|
|
||||||
#define CRP_MULTICA 16
|
|
||||||
#define CRP_MULTIBB 32
|
|
||||||
|
|
||||||
#define MAXLINELEN 300000
|
|
||||||
|
|
||||||
/* custom signals */
|
|
||||||
#define SIGMEM SIGABRT
|
|
||||||
#define SIGERR SIGABRT
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,21 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_externs.h
|
|
||||||
\brief This file contains definitions of external variables created by GKlib
|
|
||||||
|
|
||||||
\date Started 3/27/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_externs.h 1277 2007-03-27 21:17:33Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_EXTERNS_H_
|
|
||||||
#define _GK_EXTERNS_H_
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Extern variable definition. Hopefully, the __thread makes them thread-safe.
|
|
||||||
**************************************************************************/
|
|
||||||
#ifndef _GK_ERROR_C_
|
|
||||||
extern __thread jmp_buf gk_return_to_entry; /* declared in error.c */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_getopt.h
|
|
||||||
\brief This file contains GNU's externs/structs/prototypes
|
|
||||||
|
|
||||||
\date Started 3/27/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_getopt.h 1277 2007-03-27 21:17:33Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_GETOPT_H_
|
|
||||||
#define _GK_GETOPT_H_
|
|
||||||
|
|
||||||
|
|
||||||
/* Externals from getopt.c */
|
|
||||||
extern char *gk_optarg;
|
|
||||||
extern int gk_optind;
|
|
||||||
extern int gk_opterr;
|
|
||||||
extern int gk_optopt;
|
|
||||||
|
|
||||||
|
|
||||||
/*! \brief The structure that stores the information about the command-line options
|
|
||||||
|
|
||||||
This structure describes a single long option name for the sake of
|
|
||||||
gk_getopt_long(). The argument <tt>long_options</tt> must be an array
|
|
||||||
of these structures, one for each long option. Terminate the array with
|
|
||||||
an element containing all zeros.
|
|
||||||
*/
|
|
||||||
struct gk_option {
|
|
||||||
const char *name; /*!< This field is the name of the option. */
|
|
||||||
int has_arg; /*!< This field says whether the option takes an argument.
|
|
||||||
It is an integer, and there are three legitimate values:
|
|
||||||
no_argument, required_argument and optional_argument.
|
|
||||||
|
|
||||||
\todo Need to better define/use the constants for this member
|
|
||||||
variable.
|
|
||||||
*/
|
|
||||||
int *flag; /*!< See the discussion on ::gk_option#val */
|
|
||||||
int val; /*!< These fields control how to report or act on the option
|
|
||||||
when it occurs.
|
|
||||||
|
|
||||||
If flag is a null pointer, then the val is a value which
|
|
||||||
identifies this option. Often these values are chosen
|
|
||||||
to uniquely identify particular long options.
|
|
||||||
|
|
||||||
If flag is not a null pointer, it should be the address
|
|
||||||
of an int variable which is the flag for this option.
|
|
||||||
The value in val is the value to store in the flag to
|
|
||||||
indicate that the option was seen. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Names for the values of the `has_arg' field of `struct gk_option'. */
|
|
||||||
#define no_argument 0
|
|
||||||
#define required_argument 1
|
|
||||||
#define optional_argument 2
|
|
||||||
|
|
||||||
|
|
||||||
/* Function prototypes */
|
|
||||||
extern int gk_getopt(int __argc, char **__argv, const char *__shortopts);
|
|
||||||
extern int gk_getopt_long(int __argc, char *const *__argv, const char *__shortopts,
|
|
||||||
const struct gk_option *__longopts, int *__longind);
|
|
||||||
extern int gk_getopt_long_only (int __argc, char *const *__argv,
|
|
||||||
const char *__shortopts, const struct gk_option *__longopts, int *__longind);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_macros.h
|
|
||||||
\brief This file contains various macros
|
|
||||||
|
|
||||||
\date Started 3/27/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_macros.h 1432 2007-04-07 20:06:19Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_MACROS_H_
|
|
||||||
#define _GK_MACROS_H_
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* Usefull commands
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
#define amax(a, b) ((a) >= (b) ? (a) : (b))
|
|
||||||
#define amin(a, b) ((a) >= (b) ? (b) : (a))
|
|
||||||
#define amax3(a, b, c) ((a) >= (b) && (a) >= (c) ? (a) : ((b) >= (a) && (b) >= (c) ? (b) : (c)))
|
|
||||||
#define SWAP(a, b, tmp) do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0)
|
|
||||||
#define INC_DEC(a, b, val) do {(a) += (val); (b) -= (val);} while(0)
|
|
||||||
#define gk_ccopy(n, a, b) (int *)memmove((void *)(b), (void *)(a), sizeof(char)*(n))
|
|
||||||
#define gk_icopy(n, a, b) (int *)memmove((void *)(b), (void *)(a), sizeof(int)*(n))
|
|
||||||
#define gk_fcopy(n, a, b) (float *)memmove((void *)(b), (void *)(a), sizeof(float)*(n))
|
|
||||||
#define gk_dcopy(n, a, b) (double *)memmove((void *)(b), (void *)(a), sizeof(double)*(n))
|
|
||||||
#define gk_idxcopy(n, a, b) (double *)memmove((void *)(b), (void *)(a), sizeof(gk_idx_t)*(n))
|
|
||||||
#define sign(a, b) ((a >= 0 ? b : -b))
|
|
||||||
|
|
||||||
#define ONEOVERRANDMAX (1.0/(RAND_MAX+1.0))
|
|
||||||
#define RandomInRange(u) ((int) (ONEOVERRANDMAX*(u)*rand()))
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* Timing macros
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
#define gk_clearcputimer(tmr) (tmr = 0.0)
|
|
||||||
#define gk_startcputimer(tmr) (tmr -= gk_CPUSeconds())
|
|
||||||
#define gk_stopcputimer(tmr) (tmr += gk_CPUSeconds())
|
|
||||||
#define gk_getcputimer(tmr) (tmr)
|
|
||||||
|
|
||||||
#define gk_clearwctimer(tmr) (tmr = 0.0)
|
|
||||||
#define gk_startwctimer(tmr) (tmr -= gk_WClockSeconds())
|
|
||||||
#define gk_stopwctimer(tmr) (tmr += gk_WClockSeconds())
|
|
||||||
#define gk_getwctimer(tmr) (tmr)
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* dbglvl handling macros
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
#define IFSET(a, flag, cmd) if ((a)&(flag)) (cmd);
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* gracefull library exit macro
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
#define GKSETJMP() (setjmp(gk_return_to_entry))
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* Debuging memory leaks
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
#ifdef DMALLOC
|
|
||||||
# define MALLOC_CHECK(ptr) \
|
|
||||||
if (malloc_verify((ptr)) == DMALLOC_VERIFY_ERROR) { \
|
|
||||||
printf("***MALLOC_CHECK failed on line %d of file %s: " #ptr "\n", \
|
|
||||||
__LINE__, __FILE__); \
|
|
||||||
abort(); \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define MALLOC_CHECK(ptr) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* CSR conversion macros
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
#define MAKECSR(i, n, a) \
|
|
||||||
do { \
|
|
||||||
for (i=1; i<n; i++) a[i] += a[i-1]; \
|
|
||||||
for (i=n; i>0; i--) a[i] = a[i-1]; \
|
|
||||||
a[0] = 0; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define SHIFTCSR(i, n, a) \
|
|
||||||
do { \
|
|
||||||
for (i=n; i>0; i--) a[i] = a[i-1]; \
|
|
||||||
a[0] = 0; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* Program Assertions
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
#ifdef DEBUG
|
|
||||||
# define ASSERT(expr) \
|
|
||||||
if (!(expr)) { \
|
|
||||||
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
|
|
||||||
__LINE__, __FILE__); \
|
|
||||||
abort(); \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define ASSERT(expr) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
# define ASSERTP(expr,msg) \
|
|
||||||
if (!(expr)) { \
|
|
||||||
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
|
|
||||||
__LINE__, __FILE__); \
|
|
||||||
printf msg ; \
|
|
||||||
printf("\n"); \
|
|
||||||
abort(); \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define ASSERTP(expr,msg) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,110 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_memory.h
|
|
||||||
\brief This file contains GKlib's code generators for memory allocation routines
|
|
||||||
|
|
||||||
\date Started 3/29/07
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_memory.h 1432 2007-04-07 20:06:19Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_MEMORY_H_
|
|
||||||
#define _GK_MEMORY_H_
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?malloc()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_XMALLOC(NAME, TYPE)\
|
|
||||||
TYPE *NAME(size_t n, char *msg)\
|
|
||||||
{ return (TYPE *)gk_malloc(sizeof(TYPE)*n, msg); }
|
|
||||||
|
|
||||||
#define GK_XMALLOC_PROTO(NAME, TYPE)\
|
|
||||||
TYPE *NAME(size_t n, char *msg);
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?realloc()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_XREALLOC(NAME, TYPE)\
|
|
||||||
TYPE *NAME(TYPE *ptr, size_t n, char *msg)\
|
|
||||||
{ return (TYPE *)gk_realloc((void *)ptr, sizeof(TYPE)*n, msg); }
|
|
||||||
|
|
||||||
#define GK_XREALLOC_PROTO(NAME, TYPE)\
|
|
||||||
TYPE *NAME(TYPE *ptr, size_t n, char *msg);
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?smalloc()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_XSMALLOC(NAME, TYPE, SET)\
|
|
||||||
TYPE *NAME(size_t n, TYPE ival, char *msg)\
|
|
||||||
{ return SET(n, ival, (TYPE *)gk_malloc(sizeof(TYPE)*n, msg)); }
|
|
||||||
|
|
||||||
#define GK_XSMALLOC_PROTO(NAME, TYPE)\
|
|
||||||
TYPE *NAME(size_t n, TYPE ival, char *msg);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?AllocMatrix()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_ALLOCMATRIX(NAME, TYPE, ROWALLOC)\
|
|
||||||
TYPE **NAME(size_t ndim1, size_t ndim2, TYPE value, char *errmsg)\
|
|
||||||
{\
|
|
||||||
gk_loop_t i;\
|
|
||||||
TYPE **matrix;\
|
|
||||||
\
|
|
||||||
matrix = (TYPE **)gk_malloc(ndim1*sizeof(TYPE *), errmsg);\
|
|
||||||
for (i=0; i<ndim1; i++) \
|
|
||||||
matrix[i] = ROWALLOC(ndim2, value, errmsg);\
|
|
||||||
\
|
|
||||||
return matrix;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_ALLOCMATRIX_PROTO(NAME, TYPE) \
|
|
||||||
TYPE **NAME(size_t ndim1, size_t ndim2, TYPE value, char *errmsg);
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?AllocMatrix()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_FREEMATRIX(NAME, TYPE)\
|
|
||||||
void NAME(TYPE ***r_matrix, size_t ndim1, size_t ndim2)\
|
|
||||||
{\
|
|
||||||
gk_loop_t i;\
|
|
||||||
TYPE **matrix;\
|
|
||||||
\
|
|
||||||
matrix = *r_matrix;\
|
|
||||||
\
|
|
||||||
for (i=0; i<ndim1; i++) \
|
|
||||||
gk_free((void **)&(matrix[i]), LTERM);\
|
|
||||||
\
|
|
||||||
gk_free((void **)matrix, LTERM);\
|
|
||||||
\
|
|
||||||
*r_matrix = NULL;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_FREEMATRIX_PROTO(NAME, TYPE)\
|
|
||||||
void NAME(TYPE ***r_matrix, size_t ndim1, size_t ndim2);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! The macro for gk_?SetMatrix()-class of routines */
|
|
||||||
/**************************************************************************/
|
|
||||||
#define GK_SETMATRIX(NAME, TYPE)\
|
|
||||||
void NAME(TYPE **matrix, size_t ndim1, size_t ndim2, TYPE value)\
|
|
||||||
{\
|
|
||||||
gk_loop_t i, j;\
|
|
||||||
\
|
|
||||||
for (i=0; i<ndim1; i++) {\
|
|
||||||
for (j=0; j<ndim2; j++)\
|
|
||||||
matrix[i][j] = value;\
|
|
||||||
}\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GK_SETMATRIX_PROTO(NAME, TYPE)\
|
|
||||||
void NAME(TYPE **matrix, size_t ndim1, size_t ndim2, TYPE value);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,320 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_proto.h
|
|
||||||
\brief This file contains function prototypes
|
|
||||||
|
|
||||||
\date Started 3/27/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_proto.h 1432 2007-04-07 20:06:19Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_PROTO_H_
|
|
||||||
#define _GK_PROTO_H_
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* blas.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
GK_SET_PROTO(gk_cset, char)
|
|
||||||
GK_SET_PROTO(gk_iset, int)
|
|
||||||
GK_SET_PROTO(gk_fset, float)
|
|
||||||
GK_SET_PROTO(gk_dset, double)
|
|
||||||
GK_SET_PROTO(gk_idxset, gk_idx_t)
|
|
||||||
GK_INCSET_PROTO(gk_cincset, char)
|
|
||||||
GK_INCSET_PROTO(gk_iincset, int)
|
|
||||||
GK_INCSET_PROTO(gk_fincset, float)
|
|
||||||
GK_INCSET_PROTO(gk_dincset, double)
|
|
||||||
GK_INCSET_PROTO(gk_idxincset, gk_idx_t)
|
|
||||||
GK_ARGMAX_PROTO(gk_cargmax, char)
|
|
||||||
GK_ARGMAX_PROTO(gk_iargmax, int)
|
|
||||||
GK_ARGMAX_PROTO(gk_fargmax, float)
|
|
||||||
GK_ARGMAX_PROTO(gk_dargmax, double)
|
|
||||||
GK_ARGMAX_PROTO(gk_idxargmax, gk_idx_t)
|
|
||||||
GK_ARGMIN_PROTO(gk_cargmin, char)
|
|
||||||
GK_ARGMIN_PROTO(gk_iargmin, int)
|
|
||||||
GK_ARGMIN_PROTO(gk_fargmin, float)
|
|
||||||
GK_ARGMIN_PROTO(gk_dargmin, double)
|
|
||||||
GK_ARGMIN_PROTO(gk_idxargmin, gk_idx_t)
|
|
||||||
GK_ARGMAX_N_PROTO(gk_cargmax_n, char)
|
|
||||||
GK_ARGMAX_N_PROTO(gk_iargmax_n, int)
|
|
||||||
GK_ARGMAX_N_PROTO(gk_fargmax_n, float)
|
|
||||||
GK_ARGMAX_N_PROTO(gk_dargmax_n, double)
|
|
||||||
GK_ARGMAX_N_PROTO(gk_idxargmax_n, gk_idx_t)
|
|
||||||
GK_SUM_PROTO(gk_csum, char, intmax_t)
|
|
||||||
GK_SUM_PROTO(gk_isum, int, intmax_t)
|
|
||||||
GK_SUM_PROTO(gk_fsum, float, float)
|
|
||||||
GK_SUM_PROTO(gk_dsum, double, double)
|
|
||||||
GK_SUM_PROTO(gk_idxsum, gk_idx_t, intmax_t)
|
|
||||||
GK_SCALE_PROTO(gk_cscale, char)
|
|
||||||
GK_SCALE_PROTO(gk_iscale, int)
|
|
||||||
GK_SCALE_PROTO(gk_fscale, float)
|
|
||||||
GK_SCALE_PROTO(gk_dscale, double)
|
|
||||||
GK_SCALE_PROTO(gk_idxscale, gk_idx_t)
|
|
||||||
GK_NORM2_PROTO(gk_cnorm2, char, intmax_t)
|
|
||||||
GK_NORM2_PROTO(gk_inorm2, int, intmax_t)
|
|
||||||
GK_NORM2_PROTO(gk_fnorm2, float, float)
|
|
||||||
GK_NORM2_PROTO(gk_dnorm2, double, double)
|
|
||||||
GK_NORM2_PROTO(gk_idxnorm2, gk_idx_t, intmax_t)
|
|
||||||
GK_DOT_PROTO(gk_cdot, char, intmax_t)
|
|
||||||
GK_DOT_PROTO(gk_idot, int, intmax_t)
|
|
||||||
GK_DOT_PROTO(gk_fdot, float, float)
|
|
||||||
GK_DOT_PROTO(gk_ddot, double, double)
|
|
||||||
GK_DOT_PROTO(gk_idxdot, gk_idx_t, intmax_t)
|
|
||||||
GK_AXPY_PROTO(gk_caxpy, char)
|
|
||||||
GK_AXPY_PROTO(gk_iaxpy, int)
|
|
||||||
GK_AXPY_PROTO(gk_faxpy, float)
|
|
||||||
GK_AXPY_PROTO(gk_daxpy, double)
|
|
||||||
GK_AXPY_PROTO(gk_idxaxpy, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* io.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
FILE *gk_fopen(char *, char *, const char *);
|
|
||||||
void gk_fclose(FILE *);
|
|
||||||
gk_loop_t gk_getline(char **lineptr, size_t *n, FILE *stream);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* fs.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
int gk_fexists(char *);
|
|
||||||
int gk_dexists(char *);
|
|
||||||
intmax_t gk_getfsize(char *);
|
|
||||||
void gk_getfilestats(char *fname, int *r_nlines, int *r_ntokens, int *r_nbytes);
|
|
||||||
char *gk_getbasename(char *path);
|
|
||||||
char *gk_getextname(char *path);
|
|
||||||
char *gk_getfilename(char *path);
|
|
||||||
char *gk_getpathname(char *path);
|
|
||||||
int gk_mkpath(char *);
|
|
||||||
int gk_rmpath(char *);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* memory.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
GK_XMALLOC_PROTO(gk_cmalloc, char)
|
|
||||||
GK_XMALLOC_PROTO(gk_imalloc, int)
|
|
||||||
GK_XMALLOC_PROTO(gk_fmalloc, float)
|
|
||||||
GK_XMALLOC_PROTO(gk_dmalloc, double)
|
|
||||||
GK_XMALLOC_PROTO(gk_idxmalloc, gk_idx_t)
|
|
||||||
GK_XMALLOC_PROTO(gk_ckvmalloc, gk_ckv_t)
|
|
||||||
GK_XMALLOC_PROTO(gk_ikvmalloc, gk_ikv_t)
|
|
||||||
GK_XMALLOC_PROTO(gk_fkvmalloc, gk_fkv_t)
|
|
||||||
GK_XMALLOC_PROTO(gk_dkvmalloc, gk_dkv_t)
|
|
||||||
GK_XMALLOC_PROTO(gk_skvmalloc, gk_skv_t)
|
|
||||||
GK_XMALLOC_PROTO(gk_idxkvmalloc, gk_idxkv_t)
|
|
||||||
|
|
||||||
GK_XREALLOC_PROTO(gk_crealloc, char)
|
|
||||||
GK_XREALLOC_PROTO(gk_irealloc, int)
|
|
||||||
GK_XREALLOC_PROTO(gk_frealloc, float)
|
|
||||||
GK_XREALLOC_PROTO(gk_drealloc, double)
|
|
||||||
GK_XREALLOC_PROTO(gk_idxrealloc, gk_idx_t)
|
|
||||||
GK_XREALLOC_PROTO(gk_ckvrealloc, gk_ckv_t)
|
|
||||||
GK_XREALLOC_PROTO(gk_ikvrealloc, gk_ikv_t)
|
|
||||||
GK_XREALLOC_PROTO(gk_fkvrealloc, gk_fkv_t)
|
|
||||||
GK_XREALLOC_PROTO(gk_dkvrealloc, gk_dkv_t)
|
|
||||||
GK_XREALLOC_PROTO(gk_skvrealloc, gk_skv_t)
|
|
||||||
GK_XREALLOC_PROTO(gk_idxkvrealloc, gk_idxkv_t)
|
|
||||||
|
|
||||||
GK_XSMALLOC_PROTO(gk_csmalloc, char)
|
|
||||||
GK_XSMALLOC_PROTO(gk_ismalloc, int)
|
|
||||||
GK_XSMALLOC_PROTO(gk_fsmalloc, float)
|
|
||||||
GK_XSMALLOC_PROTO(gk_dsmalloc, double)
|
|
||||||
GK_XSMALLOC_PROTO(gk_idxsmalloc, gk_idx_t)
|
|
||||||
GK_ALLOCMATRIX_PROTO(gk_cAllocMatrix, char)
|
|
||||||
GK_ALLOCMATRIX_PROTO(gk_iAllocMatrix, int)
|
|
||||||
GK_ALLOCMATRIX_PROTO(gk_fAllocMatrix, float)
|
|
||||||
GK_ALLOCMATRIX_PROTO(gk_dAllocMatrix, double)
|
|
||||||
GK_ALLOCMATRIX_PROTO(gk_idxAllocMatrix, gk_idx_t)
|
|
||||||
GK_FREEMATRIX_PROTO(gk_cFreeMatrix, char)
|
|
||||||
GK_FREEMATRIX_PROTO(gk_iFreeMatrix, int)
|
|
||||||
GK_FREEMATRIX_PROTO(gk_fFreeMatrix, float)
|
|
||||||
GK_FREEMATRIX_PROTO(gk_dFreeMatrix, double)
|
|
||||||
GK_FREEMATRIX_PROTO(gk_idxFreeMatrix, gk_idx_t)
|
|
||||||
GK_SETMATRIX_PROTO(gk_cSetMatrix, char)
|
|
||||||
GK_SETMATRIX_PROTO(gk_iSetMatrix, int)
|
|
||||||
GK_SETMATRIX_PROTO(gk_fSetMatrix, float)
|
|
||||||
GK_SETMATRIX_PROTO(gk_dSetMatrix, double)
|
|
||||||
GK_SETMATRIX_PROTO(gk_idxSetMatrix, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void gk_AllocMatrix(void ***, size_t, size_t , size_t);
|
|
||||||
void gk_FreeMatrix(void ***, size_t, size_t);
|
|
||||||
void *gk_malloc(size_t, char *);
|
|
||||||
void *gk_realloc(void *, size_t, char *);
|
|
||||||
void gk_free(void **ptr1,...);
|
|
||||||
void gk_malloc_cleanup();
|
|
||||||
size_t gk_GetCurMemoryUsed();
|
|
||||||
size_t gk_GetMaxMemoryUsed();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* seq.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
gk_seq_t *gk_seq_ReadGKMODPSSM(char *file_name);
|
|
||||||
gk_i2cc2i_t *gk_i2cc2i_create_common(char *alphabet);
|
|
||||||
void gk_seq_init(gk_seq_t *seq);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* pdb.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
char gk_threetoone(char *res);
|
|
||||||
void gk_freepdbf(pdbf *p);
|
|
||||||
pdbf *gk_readpdbfile(char *fname);
|
|
||||||
void gk_writefullatom(pdbf *p, char *fname);
|
|
||||||
void gk_writebackbone(pdbf *p, char *fname);
|
|
||||||
void gk_writealphacarbons(pdbf *p, char *fname);
|
|
||||||
void gk_showcorruption(pdbf *p);
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* error.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
void errexit(char *,...);
|
|
||||||
void gk_errexit(int signum, char *,...);
|
|
||||||
void gk_SetSignalHandlers();
|
|
||||||
void gk_UnsetSignalHandlers();
|
|
||||||
void gk_NonLocalExit_Handler(int signum);
|
|
||||||
char *gk_strerror(int errnum);
|
|
||||||
void PrintBackTrace();
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* util.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
void gk_RandomPermute(size_t, int *, int);
|
|
||||||
void gk_array2csr(size_t n, size_t range, int *array, int *ptr, int *ind);
|
|
||||||
int gk_log2(int);
|
|
||||||
int gk_ispow2(int);
|
|
||||||
float gk_flog2(float);
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* time.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
gk_wclock_t gk_WClockSeconds(void);
|
|
||||||
double gk_CPUSeconds(void);
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* string.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
char *gk_strchr_replace(char *str, char *fromlist, char *tolist);
|
|
||||||
int gk_strstr_replace(char *str, char *pattern, char *replacement, char *options, char **new_str);
|
|
||||||
char *gk_strtprune(char *, char *);
|
|
||||||
char *gk_strhprune(char *, char *);
|
|
||||||
char *gk_strtoupper(char *);
|
|
||||||
char *gk_strtolower(char *);
|
|
||||||
char *gk_strdup(char *orgstr);
|
|
||||||
int gk_strcasecmp(char *s1, char *s2);
|
|
||||||
char *gk_time2str(time_t time);
|
|
||||||
time_t gk_str2time(char *str);
|
|
||||||
int gk_GetStringID(gk_StringMap_t *strmap, char *key);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* sort.c
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
void gk_icsort(int, char *);
|
|
||||||
void gk_dcsort(int, char *);
|
|
||||||
void gk_iisort(int, int *);
|
|
||||||
void gk_disort(int, int *);
|
|
||||||
void gk_ifsort(int, float *);
|
|
||||||
void gk_dfsort(int, float *);
|
|
||||||
void gk_idsort(int, double *);
|
|
||||||
void gk_ddsort(int, double *);
|
|
||||||
void gk_iidxsort(int, gk_idx_t *);
|
|
||||||
void gk_didxsort(int, gk_idx_t *);
|
|
||||||
void gk_ickvsort(int, gk_ckv_t *);
|
|
||||||
void gk_dckvsort(int, gk_ckv_t *);
|
|
||||||
void gk_iikvsort(int, gk_ikv_t *);
|
|
||||||
void gk_dikvsort(int, gk_ikv_t *);
|
|
||||||
void gk_ifkvsort(int, gk_fkv_t *);
|
|
||||||
void gk_dfkvsort(int, gk_fkv_t *);
|
|
||||||
void gk_idkvsort(int, gk_dkv_t *);
|
|
||||||
void gk_ddkvsort(int, gk_dkv_t *);
|
|
||||||
void gk_iskvsort(int, gk_skv_t *);
|
|
||||||
void gk_dskvsort(int, gk_skv_t *);
|
|
||||||
void gk_iidxkvsort(int, gk_idxkv_t *);
|
|
||||||
void gk_didxkvsort(int, gk_idxkv_t *);
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* Selection routines
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
int gk_dfkvkselect(int, int, gk_fkv_t *);
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* Priority queue
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
void gk_PQueueInit(gk_PQueue_t *, int);
|
|
||||||
void gk_PQueueReset(gk_PQueue_t *);
|
|
||||||
void gk_PQueueFree(gk_PQueue_t *);
|
|
||||||
int gk_PQueueGetSize(gk_PQueue_t *);
|
|
||||||
int gk_PQueueInsert(gk_PQueue_t *, int, float);
|
|
||||||
int gk_PQueueDelete(gk_PQueue_t *, int);
|
|
||||||
int gk_PQueueUpdate(gk_PQueue_t *, int, float);
|
|
||||||
int gk_PQueueGetMax(gk_PQueue_t *);
|
|
||||||
int gk_PQueueSeeMaxVal(gk_PQueue_t *queue);
|
|
||||||
float gk_PQueueSeeMaxKey(gk_PQueue_t *queue);
|
|
||||||
int gk_PQueueLength(gk_PQueue_t *);
|
|
||||||
int gk_PQueueSeeConstraintMax(gk_PQueue_t *queue, float maxwgt, double *wgts);
|
|
||||||
float gk_PQueueSeeKey(gk_PQueue_t *queue, int node);
|
|
||||||
int gk_CheckHeap(gk_PQueue_t *);
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* HTable routines
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
gk_HTable_t *HTable_Create(int nelements);
|
|
||||||
void HTable_Reset(gk_HTable_t *htable);
|
|
||||||
void HTable_Resize(gk_HTable_t *htable, int nelements);
|
|
||||||
void HTable_Insert(gk_HTable_t *htable, int key, int val);
|
|
||||||
void HTable_Delete(gk_HTable_t *htable, int key);
|
|
||||||
int HTable_Search(gk_HTable_t *htable, int key);
|
|
||||||
int HTable_GetNext(gk_HTable_t *htable, int key, int *val, int type);
|
|
||||||
int HTable_SearchAndDelete(gk_HTable_t *htable, int key);
|
|
||||||
void HTable_Destroy(gk_HTable_t *htable);
|
|
||||||
int HTable_HFunction(int nelements, int key);
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* Tokenizer routines
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
void gk_strtokenize(char *line, char *delim, gk_Tokens_t *tokens);
|
|
||||||
void gk_freetokenslist(gk_Tokens_t *tokens);
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* Encoder/Decoder
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
void encodeblock(unsigned char *in, unsigned char *out);
|
|
||||||
void decodeblock(unsigned char *in, unsigned char *out);
|
|
||||||
void GKEncodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer);
|
|
||||||
void GKDecodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer);
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* OpenMP fake functions
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
#if !defined(__OPENMP__)
|
|
||||||
void omp_set_num_threads(int num_threads);
|
|
||||||
int omp_get_num_threads(void);
|
|
||||||
int omp_get_max_threads(void);
|
|
||||||
int omp_get_thread_num(void);
|
|
||||||
int omp_get_num_procs(void);
|
|
||||||
int omp_in_parallel(void);
|
|
||||||
void omp_set_dynamic(int num_threads);
|
|
||||||
int omp_get_dynamic(void);
|
|
||||||
void omp_set_nested(int nested);
|
|
||||||
int omp_get_nested(void);
|
|
||||||
#endif /* __OPENMP__ */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@ -1,273 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_sort.h
|
|
||||||
\brief This file contains GKlib's code generator for the qsort routines
|
|
||||||
|
|
||||||
\date Started 3/28/07
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_sort.h 1421 2007-04-06 14:37:41Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _GK_SORT_H_
|
|
||||||
#define _GK_SORT_H_
|
|
||||||
|
|
||||||
/* $Id: gk_sort.h 1421 2007-04-06 14:37:41Z karypis $
|
|
||||||
* Adopted from GNU glibc by Mjt.
|
|
||||||
* See stdlib/qsort.c in glibc */
|
|
||||||
|
|
||||||
/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
|
|
||||||
This file is part of the GNU C Library.
|
|
||||||
Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
|
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with the GNU C Library; if not, write to the Free
|
|
||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
02111-1307 USA. */
|
|
||||||
|
|
||||||
/* in-line qsort implementation. Differs from traditional qsort() routine
|
|
||||||
* in that it is a macro, not a function, and instead of passing an address
|
|
||||||
* of a comparision routine to the function, it is possible to inline
|
|
||||||
* comparision routine, thus speed up sorting alot.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* #include "iqsort.h"
|
|
||||||
* #define islt(a,b) (strcmp((*a),(*b))<0)
|
|
||||||
* char *arr[];
|
|
||||||
* int n;
|
|
||||||
* GKQSORT(char*, arr, n, islt);
|
|
||||||
*
|
|
||||||
* The "prototype" and 4 arguments are:
|
|
||||||
* GKQSORT(TYPE,BASE,NELT,ISLT)
|
|
||||||
* 1) type of each element, TYPE,
|
|
||||||
* 2) address of the beginning of the array, of type TYPE*,
|
|
||||||
* 3) number of elements in the array, and
|
|
||||||
* 4) comparision routine.
|
|
||||||
* Array pointer and number of elements are referenced only once.
|
|
||||||
* This is similar to a call
|
|
||||||
* qsort(BASE,NELT,sizeof(TYPE),ISLT)
|
|
||||||
* with the difference in last parameter.
|
|
||||||
* Note the islt macro/routine (it receives pointers to two elements):
|
|
||||||
* the only condition of interest is whenever one element is less than
|
|
||||||
* another, no other conditions (greather than, equal to etc) are tested.
|
|
||||||
* So, for example, to define integer sort, use:
|
|
||||||
* #define islt(a,b) ((*a)<(*b))
|
|
||||||
* GKQSORT(int, arr, n, islt)
|
|
||||||
*
|
|
||||||
* The macro could be used to implement a sorting function (see examples
|
|
||||||
* below), or to implement the sorting algorithm inline. That is, either
|
|
||||||
* create a sorting function and use it whenever you want to sort something,
|
|
||||||
* or use GKQSORT() macro directly instead a call to such routine. Note that
|
|
||||||
* the macro expands to quite some code (compiled size of int qsort on x86
|
|
||||||
* is about 700..800 bytes).
|
|
||||||
*
|
|
||||||
* Using this macro directly it isn't possible to implement traditional
|
|
||||||
* qsort() routine, because the macro assumes sizeof(element) == sizeof(TYPE),
|
|
||||||
* while qsort() allows element size to be different.
|
|
||||||
*
|
|
||||||
* Several ready-to-use examples:
|
|
||||||
*
|
|
||||||
* Sorting array of integers:
|
|
||||||
* void int_qsort(int *arr, unsigned n) {
|
|
||||||
* #define int_lt(a,b) ((*a)<(*b))
|
|
||||||
* GKQSORT(int, arr, n, int_lt);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* Sorting array of string pointers:
|
|
||||||
* void str_qsort(char *arr[], unsigned n) {
|
|
||||||
* #define str_lt(a,b) (strcmp((*a),(*b)) < 0)
|
|
||||||
* GKQSORT(char*, arr, n, str_lt);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* Sorting array of structures:
|
|
||||||
*
|
|
||||||
* struct elt {
|
|
||||||
* int key;
|
|
||||||
* ...
|
|
||||||
* };
|
|
||||||
* void elt_qsort(struct elt *arr, unsigned n) {
|
|
||||||
* #define elt_lt(a,b) ((a)->key < (b)->key)
|
|
||||||
* GKQSORT(struct elt, arr, n, elt_lt);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* And so on.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Swap two items pointed to by A and B using temporary buffer t. */
|
|
||||||
#define _GKQSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t)))
|
|
||||||
|
|
||||||
/* Discontinue quicksort algorithm when partition gets below this size.
|
|
||||||
This particular magic number was chosen to work best on a Sun 4/260. */
|
|
||||||
#define _GKQSORT_MAX_THRESH 4
|
|
||||||
|
|
||||||
/* The next 4 #defines implement a very fast in-line stack abstraction. */
|
|
||||||
#define _GKQSORT_STACK_SIZE (8 * sizeof(size_t))
|
|
||||||
#define _GKQSORT_PUSH(top, low, high) (((top->_lo = (low)), (top->_hi = (high)), ++top))
|
|
||||||
#define _GKQSORT_POP(low, high, top) ((--top, (low = top->_lo), (high = top->_hi)))
|
|
||||||
#define _GKQSORT_STACK_NOT_EMPTY (_stack < _top)
|
|
||||||
|
|
||||||
|
|
||||||
/* The main code starts here... */
|
|
||||||
#define GKQSORT(GKQSORT_TYPE,GKQSORT_BASE,GKQSORT_NELT,GKQSORT_LT) \
|
|
||||||
{ \
|
|
||||||
GKQSORT_TYPE *const _base = (GKQSORT_BASE); \
|
|
||||||
const size_t _elems = (GKQSORT_NELT); \
|
|
||||||
GKQSORT_TYPE _hold; \
|
|
||||||
\
|
|
||||||
if (_elems == 0) \
|
|
||||||
return; \
|
|
||||||
\
|
|
||||||
/* Don't declare two variables of type GKQSORT_TYPE in a single \
|
|
||||||
* statement: eg `TYPE a, b;', in case if TYPE is a pointer, \
|
|
||||||
* expands to `type* a, b;' wich isn't what we want. \
|
|
||||||
*/ \
|
|
||||||
\
|
|
||||||
if (_elems > _GKQSORT_MAX_THRESH) { \
|
|
||||||
GKQSORT_TYPE *_lo = _base; \
|
|
||||||
GKQSORT_TYPE *_hi = _lo + _elems - 1; \
|
|
||||||
struct { \
|
|
||||||
GKQSORT_TYPE *_hi; GKQSORT_TYPE *_lo; \
|
|
||||||
} _stack[_GKQSORT_STACK_SIZE], *_top = _stack + 1; \
|
|
||||||
\
|
|
||||||
while (_GKQSORT_STACK_NOT_EMPTY) { \
|
|
||||||
GKQSORT_TYPE *_left_ptr; GKQSORT_TYPE *_right_ptr; \
|
|
||||||
\
|
|
||||||
/* Select median value from among LO, MID, and HI. Rearrange \
|
|
||||||
LO and HI so the three values are sorted. This lowers the \
|
|
||||||
probability of picking a pathological pivot value and \
|
|
||||||
skips a comparison for both the LEFT_PTR and RIGHT_PTR in \
|
|
||||||
the while loops. */ \
|
|
||||||
\
|
|
||||||
GKQSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); \
|
|
||||||
\
|
|
||||||
if (GKQSORT_LT (_mid, _lo)) \
|
|
||||||
_GKQSORT_SWAP (_mid, _lo, _hold); \
|
|
||||||
if (GKQSORT_LT (_hi, _mid)) \
|
|
||||||
_GKQSORT_SWAP (_mid, _hi, _hold); \
|
|
||||||
else \
|
|
||||||
goto _jump_over; \
|
|
||||||
if (GKQSORT_LT (_mid, _lo)) \
|
|
||||||
_GKQSORT_SWAP (_mid, _lo, _hold); \
|
|
||||||
_jump_over:; \
|
|
||||||
\
|
|
||||||
_left_ptr = _lo + 1; \
|
|
||||||
_right_ptr = _hi - 1; \
|
|
||||||
\
|
|
||||||
/* Here's the famous ``collapse the walls'' section of quicksort. \
|
|
||||||
Gotta like those tight inner loops! They are the main reason \
|
|
||||||
that this algorithm runs much faster than others. */ \
|
|
||||||
do { \
|
|
||||||
while (GKQSORT_LT (_left_ptr, _mid)) \
|
|
||||||
++_left_ptr; \
|
|
||||||
\
|
|
||||||
while (GKQSORT_LT (_mid, _right_ptr)) \
|
|
||||||
--_right_ptr; \
|
|
||||||
\
|
|
||||||
if (_left_ptr < _right_ptr) { \
|
|
||||||
_GKQSORT_SWAP (_left_ptr, _right_ptr, _hold); \
|
|
||||||
if (_mid == _left_ptr) \
|
|
||||||
_mid = _right_ptr; \
|
|
||||||
else if (_mid == _right_ptr) \
|
|
||||||
_mid = _left_ptr; \
|
|
||||||
++_left_ptr; \
|
|
||||||
--_right_ptr; \
|
|
||||||
} \
|
|
||||||
else if (_left_ptr == _right_ptr) { \
|
|
||||||
++_left_ptr; \
|
|
||||||
--_right_ptr; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} while (_left_ptr <= _right_ptr); \
|
|
||||||
\
|
|
||||||
/* Set up pointers for next iteration. First determine whether \
|
|
||||||
left and right partitions are below the threshold size. If so, \
|
|
||||||
ignore one or both. Otherwise, push the larger partition's \
|
|
||||||
bounds on the stack and continue sorting the smaller one. */ \
|
|
||||||
\
|
|
||||||
if (_right_ptr - _lo <= _GKQSORT_MAX_THRESH) { \
|
|
||||||
if (_hi - _left_ptr <= _GKQSORT_MAX_THRESH) \
|
|
||||||
/* Ignore both small partitions. */ \
|
|
||||||
_GKQSORT_POP (_lo, _hi, _top); \
|
|
||||||
else \
|
|
||||||
/* Ignore small left partition. */ \
|
|
||||||
_lo = _left_ptr; \
|
|
||||||
} \
|
|
||||||
else if (_hi - _left_ptr <= _GKQSORT_MAX_THRESH) \
|
|
||||||
/* Ignore small right partition. */ \
|
|
||||||
_hi = _right_ptr; \
|
|
||||||
else if (_right_ptr - _lo > _hi - _left_ptr) { \
|
|
||||||
/* Push larger left partition indices. */ \
|
|
||||||
_GKQSORT_PUSH (_top, _lo, _right_ptr); \
|
|
||||||
_lo = _left_ptr; \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
/* Push larger right partition indices. */ \
|
|
||||||
_GKQSORT_PUSH (_top, _left_ptr, _hi); \
|
|
||||||
_hi = _right_ptr; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* Once the BASE array is partially sorted by quicksort the rest \
|
|
||||||
is completely sorted using insertion sort, since this is efficient \
|
|
||||||
for partitions below MAX_THRESH size. BASE points to the \
|
|
||||||
beginning of the array to sort, and END_PTR points at the very \
|
|
||||||
last element in the array (*not* one beyond it!). */ \
|
|
||||||
\
|
|
||||||
{ \
|
|
||||||
GKQSORT_TYPE *const _end_ptr = _base + _elems - 1; \
|
|
||||||
GKQSORT_TYPE *_tmp_ptr = _base; \
|
|
||||||
register GKQSORT_TYPE *_run_ptr; \
|
|
||||||
GKQSORT_TYPE *_thresh; \
|
|
||||||
\
|
|
||||||
_thresh = _base + _GKQSORT_MAX_THRESH; \
|
|
||||||
if (_thresh > _end_ptr) \
|
|
||||||
_thresh = _end_ptr; \
|
|
||||||
\
|
|
||||||
/* Find smallest element in first threshold and place it at the \
|
|
||||||
array's beginning. This is the smallest array element, \
|
|
||||||
and the operation speeds up insertion sort's inner loop. */ \
|
|
||||||
\
|
|
||||||
for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) \
|
|
||||||
if (GKQSORT_LT (_run_ptr, _tmp_ptr)) \
|
|
||||||
_tmp_ptr = _run_ptr; \
|
|
||||||
\
|
|
||||||
if (_tmp_ptr != _base) \
|
|
||||||
_GKQSORT_SWAP (_tmp_ptr, _base, _hold); \
|
|
||||||
\
|
|
||||||
/* Insertion sort, running from left-hand-side \
|
|
||||||
* up to right-hand-side. */ \
|
|
||||||
\
|
|
||||||
_run_ptr = _base + 1; \
|
|
||||||
while (++_run_ptr <= _end_ptr) { \
|
|
||||||
_tmp_ptr = _run_ptr - 1; \
|
|
||||||
while (GKQSORT_LT (_run_ptr, _tmp_ptr)) \
|
|
||||||
--_tmp_ptr; \
|
|
||||||
\
|
|
||||||
++_tmp_ptr; \
|
|
||||||
if (_tmp_ptr != _run_ptr) { \
|
|
||||||
GKQSORT_TYPE *_trav = _run_ptr + 1; \
|
|
||||||
while (--_trav >= _run_ptr) { \
|
|
||||||
GKQSORT_TYPE *_hi; GKQSORT_TYPE *_lo; \
|
|
||||||
_hold = *_trav; \
|
|
||||||
\
|
|
||||||
for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) \
|
|
||||||
*_hi = *_lo; \
|
|
||||||
*_hi = _hold; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,158 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_struct.h
|
|
||||||
\brief This file contains various datastructures used/provided by GKlib
|
|
||||||
|
|
||||||
\date Started 3/27/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_struct.h 1421 2007-04-06 14:37:41Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_STRUCT_H_
|
|
||||||
#define _GK_STRUCT_H_
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************/
|
|
||||||
/*! Generator for gk_??KeyVal_t data structure */
|
|
||||||
/********************************************************************/
|
|
||||||
#define GK_KEYVALUE_T(NAME, KEYTYPE, VALTYPE) \
|
|
||||||
typedef struct {\
|
|
||||||
KEYTYPE key;\
|
|
||||||
VALTYPE val;\
|
|
||||||
} NAME\
|
|
||||||
|
|
||||||
/* The actual KeyVal data structures */
|
|
||||||
GK_KEYVALUE_T(gk_ckv_t, char, gk_idx_t);
|
|
||||||
GK_KEYVALUE_T(gk_ikv_t, int, gk_idx_t);
|
|
||||||
GK_KEYVALUE_T(gk_fkv_t, float, gk_idx_t);
|
|
||||||
GK_KEYVALUE_T(gk_dkv_t, double, gk_idx_t);
|
|
||||||
GK_KEYVALUE_T(gk_skv_t, char *, gk_idx_t);
|
|
||||||
GK_KEYVALUE_T(gk_idxkv_t, gk_idx_t, gk_idx_t);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* The following data structure stores a sparse CSR format
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
int nrows, ncols;
|
|
||||||
int *rowptr, *colptr;
|
|
||||||
int *rowind, *colind;
|
|
||||||
int *irowval, *icolval;
|
|
||||||
float *frowval, *fcolval;
|
|
||||||
} gk_CSR_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* The following data structure implements max-heap priority
|
|
||||||
* queue
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
int nnodes;
|
|
||||||
int maxnodes;
|
|
||||||
|
|
||||||
/* Heap version of the data structure */
|
|
||||||
gk_fkv_t *heap;
|
|
||||||
int *locator;
|
|
||||||
} gk_PQueue_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------
|
|
||||||
* The following data structure implements a string-2-int mapping
|
|
||||||
* table used for parsing command-line options
|
|
||||||
*-------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
int id;
|
|
||||||
} gk_StringMap_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
* This structure implements a simple hash table
|
|
||||||
*------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
int nelements; /* The overall size of the hash-table */
|
|
||||||
int htsize; /* The current size of the hash-table */
|
|
||||||
gk_ikv_t *harray; /* The actual hash-table */
|
|
||||||
} gk_HTable_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
* This structure implements a gk_Tokens_t list returned by the
|
|
||||||
* string tokenizer
|
|
||||||
*------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
int ntoks; /* The number of tokens in the input string */
|
|
||||||
char *strbuf; /* The memory that stores all the entries */
|
|
||||||
char **list; /* Pointers to the strbuf for each element */
|
|
||||||
} gk_Tokens_t;
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
* This structure implements storage for an atom in a pdb file
|
|
||||||
*------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
int serial;
|
|
||||||
char *name;
|
|
||||||
char altLoc;
|
|
||||||
char *resname;
|
|
||||||
char chainid;
|
|
||||||
int rserial;
|
|
||||||
char icode;
|
|
||||||
char element;
|
|
||||||
double x;
|
|
||||||
double y;
|
|
||||||
double z;
|
|
||||||
double opcy;
|
|
||||||
double tmpt;
|
|
||||||
} atom;
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
* This structure implements storage for a pdb protein
|
|
||||||
*------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
int natoms; /* Number of atoms */
|
|
||||||
int nresidues; /* Number of residues based on coordinates */
|
|
||||||
int ncas;
|
|
||||||
int nbbs;
|
|
||||||
int corruption;
|
|
||||||
char *resSeq; /* Residue sequence based on coordinates */
|
|
||||||
atom *atoms;
|
|
||||||
atom **bbs;
|
|
||||||
atom **cas;
|
|
||||||
} pdbf;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Localization Structures for converting characters to integers
|
|
||||||
*************************************************************/
|
|
||||||
typedef struct {
|
|
||||||
int n;
|
|
||||||
char *i2c;
|
|
||||||
int *c2i;
|
|
||||||
} gk_i2cc2i_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
*This structure implements storage of a protein sequence
|
|
||||||
* *****************************************************************/
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
int len; /*Number of Residues */
|
|
||||||
int *sequence; /* Stores the sequence*/
|
|
||||||
|
|
||||||
|
|
||||||
int **pssm; /* Stores the pssm matrix */
|
|
||||||
int **psfm; /* Stores the psfm matrix */
|
|
||||||
char *name; /* Stores the name of the sequence */
|
|
||||||
|
|
||||||
int nsymbols;
|
|
||||||
|
|
||||||
|
|
||||||
} gk_seq_t;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gk_types.h
|
|
||||||
\brief This file contains basic scalar datatype used in GKlib
|
|
||||||
|
|
||||||
\date Started 3/27/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gk_types.h 1413 2007-04-05 02:43:48Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GK_TYPES_H_
|
|
||||||
#define _GK_TYPES_H_
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Basic data type definitions. These definitions allow GKlib to separate
|
|
||||||
* the following elemental types:
|
|
||||||
* - loop iterator variables, which are set to size_t
|
|
||||||
* - signed and unsigned int variables that can be set to any # of bits
|
|
||||||
* - signed and unsigned long variables that can be set to any # of bits
|
|
||||||
* - real variables, which can be set to single or double precision.
|
|
||||||
**************************************************************************/
|
|
||||||
typedef ptrdiff_t gk_loop_t; /* loop index variable */
|
|
||||||
typedef ptrdiff_t gk_idx_t; /* index variable */
|
|
||||||
typedef int32_t gk_int_t; /* integer values */
|
|
||||||
typedef uint32_t gk_uint_t; /* unsigned integer values */
|
|
||||||
typedef int64_t gk_long_t; /* long integer values */
|
|
||||||
typedef uint64_t gk_ulong_t; /* unsigned long integer values */
|
|
||||||
typedef float gk_real_t; /* real type */
|
|
||||||
typedef double gk_dreal_t; /* double precission real type */
|
|
||||||
typedef time_t gk_wclock_t; /* wall-clock time */
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,247 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* This file contains routines for manipulating a direct-access hash table
|
|
||||||
*
|
|
||||||
* Started 3/22/04
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function creates the hash-table
|
|
||||||
*******************************************************************************/
|
|
||||||
gk_HTable_t *HTable_Create(int nelements)
|
|
||||||
{
|
|
||||||
gk_HTable_t *htable;
|
|
||||||
|
|
||||||
htable = gk_malloc(sizeof(gk_HTable_t), "HTable_Create: htable");
|
|
||||||
htable->harray = gk_ikvmalloc(nelements, "HTable_Create: harray");
|
|
||||||
htable->nelements = nelements;
|
|
||||||
|
|
||||||
HTable_Reset(htable);
|
|
||||||
|
|
||||||
return htable;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function resets the data-structures associated with the hash-table
|
|
||||||
*******************************************************************************/
|
|
||||||
void HTable_Reset(gk_HTable_t *htable)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i<htable->nelements; i++)
|
|
||||||
htable->harray[i].key = HTABLE_EMPTY;
|
|
||||||
htable->htsize = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function resizes the hash-table
|
|
||||||
*******************************************************************************/
|
|
||||||
void HTable_Resize(gk_HTable_t *htable, int nelements)
|
|
||||||
{
|
|
||||||
int i, old_nelements;
|
|
||||||
gk_ikv_t *old_harray;
|
|
||||||
|
|
||||||
old_nelements = htable->nelements;
|
|
||||||
old_harray = htable->harray;
|
|
||||||
|
|
||||||
/* prepare larger hash */
|
|
||||||
htable->nelements = nelements;
|
|
||||||
htable->htsize = 0;
|
|
||||||
htable->harray = gk_ikvmalloc(nelements, "HTable_Resize: harray");
|
|
||||||
for (i=0; i<nelements; i++)
|
|
||||||
htable->harray[i].key = HTABLE_EMPTY;
|
|
||||||
|
|
||||||
/* reassign the values */
|
|
||||||
for (i=0; i<old_nelements; i++)
|
|
||||||
if (old_harray[i].key != HTABLE_EMPTY)
|
|
||||||
HTable_Insert(htable, old_harray[i].key, old_harray[i].val);
|
|
||||||
|
|
||||||
/* remove old harray */
|
|
||||||
gk_free((void *)&old_harray, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function inserts a key-value pair in the array
|
|
||||||
*******************************************************************************/
|
|
||||||
void HTable_Insert(gk_HTable_t *htable, int key, int val)
|
|
||||||
{
|
|
||||||
int i, first;
|
|
||||||
|
|
||||||
if (htable->htsize > htable->nelements/2)
|
|
||||||
HTable_Resize(htable, 2*htable->nelements);
|
|
||||||
|
|
||||||
first = HTable_HFunction(htable->nelements, key);
|
|
||||||
|
|
||||||
for (i=first; i<htable->nelements; i++) {
|
|
||||||
if (htable->harray[i].key == HTABLE_EMPTY || htable->harray[i].key == HTABLE_DELETED) {
|
|
||||||
htable->harray[i].key = key;
|
|
||||||
htable->harray[i].val = val;
|
|
||||||
htable->htsize++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<first; i++) {
|
|
||||||
if (htable->harray[i].key == HTABLE_EMPTY || htable->harray[i].key == HTABLE_DELETED) {
|
|
||||||
htable->harray[i].key = key;
|
|
||||||
htable->harray[i].val = val;
|
|
||||||
htable->htsize++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function deletes key from the htable
|
|
||||||
*******************************************************************************/
|
|
||||||
void HTable_Delete(gk_HTable_t *htable, int key)
|
|
||||||
{
|
|
||||||
int i, first;
|
|
||||||
|
|
||||||
first = HTable_HFunction(htable->nelements, key);
|
|
||||||
|
|
||||||
for (i=first; i<htable->nelements; i++) {
|
|
||||||
if (htable->harray[i].key == key) {
|
|
||||||
htable->harray[i].key = HTABLE_DELETED;
|
|
||||||
htable->htsize--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<first; i++) {
|
|
||||||
if (htable->harray[i].key == key) {
|
|
||||||
htable->harray[i].key = HTABLE_DELETED;
|
|
||||||
htable->htsize--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function returns the data associated with the key in the hastable
|
|
||||||
*******************************************************************************/
|
|
||||||
int HTable_Search(gk_HTable_t *htable, int key)
|
|
||||||
{
|
|
||||||
int i, first;
|
|
||||||
|
|
||||||
first = HTable_HFunction(htable->nelements, key);
|
|
||||||
|
|
||||||
for (i=first; i<htable->nelements; i++) {
|
|
||||||
if (htable->harray[i].key == key)
|
|
||||||
return htable->harray[i].val;
|
|
||||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<first; i++) {
|
|
||||||
if (htable->harray[i].key == key)
|
|
||||||
return htable->harray[i].val;
|
|
||||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function returns the next key/val
|
|
||||||
*******************************************************************************/
|
|
||||||
int HTable_GetNext(gk_HTable_t *htable, int key, int *r_val, int type)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
static int first, last;
|
|
||||||
|
|
||||||
if (type == HTABLE_FIRST)
|
|
||||||
first = last = HTable_HFunction(htable->nelements, key);
|
|
||||||
|
|
||||||
if (first > last) {
|
|
||||||
for (i=first; i<htable->nelements; i++) {
|
|
||||||
if (htable->harray[i].key == key) {
|
|
||||||
*r_val = htable->harray[i].val;
|
|
||||||
first = i+1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=first; i<last; i++) {
|
|
||||||
if (htable->harray[i].key == key) {
|
|
||||||
*r_val = htable->harray[i].val;
|
|
||||||
first = i+1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function returns the data associated with the key in the hastable
|
|
||||||
*******************************************************************************/
|
|
||||||
int HTable_SearchAndDelete(gk_HTable_t *htable, int key)
|
|
||||||
{
|
|
||||||
int i, first;
|
|
||||||
|
|
||||||
first = HTable_HFunction(htable->nelements, key);
|
|
||||||
|
|
||||||
for (i=first; i<htable->nelements; i++) {
|
|
||||||
if (htable->harray[i].key == key) {
|
|
||||||
htable->harray[i].key = HTABLE_DELETED;
|
|
||||||
htable->htsize--;
|
|
||||||
return htable->harray[i].val;
|
|
||||||
}
|
|
||||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
|
||||||
gk_errexit(SIGERR, "HTable_SearchAndDelete: Failed to find the key!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<first; i++) {
|
|
||||||
if (htable->harray[i].key == key) {
|
|
||||||
htable->harray[i].key = HTABLE_DELETED;
|
|
||||||
htable->htsize--;
|
|
||||||
return htable->harray[i].val;
|
|
||||||
}
|
|
||||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
|
||||||
gk_errexit(SIGERR, "HTable_SearchAndDelete: Failed to find the key!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This function destroys the data structures associated with the hash-table
|
|
||||||
*******************************************************************************/
|
|
||||||
void HTable_Destroy(gk_HTable_t *htable)
|
|
||||||
{
|
|
||||||
gk_free((void *)&htable->harray, &htable, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* This is the hash-function. Based on multiplication
|
|
||||||
*******************************************************************************/
|
|
||||||
int HTable_HFunction(int nelements, int key)
|
|
||||||
{
|
|
||||||
return (int)(key%nelements);
|
|
||||||
}
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file io.c
|
|
||||||
\brief Various file I/O functions.
|
|
||||||
|
|
||||||
This file contains various functions that perform I/O.
|
|
||||||
|
|
||||||
\date Started 4/10/95
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: io.c 1430 2007-04-07 17:53:07Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function opens a file
|
|
||||||
**************************************************************************/
|
|
||||||
FILE *gk_fopen(char *fname, char *mode, const char *msg)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char errmsg[8192];
|
|
||||||
|
|
||||||
fp = fopen(fname, mode);
|
|
||||||
if (fp != NULL)
|
|
||||||
return fp;
|
|
||||||
|
|
||||||
sprintf(errmsg,"file: %s, mode: %s, [%s]", fname, mode, msg);
|
|
||||||
perror(errmsg);
|
|
||||||
errexit("Failed on gk_fopen()\n");
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function closes a file
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_fclose(FILE *fp)
|
|
||||||
{
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the GKlib implementation of glibc's getline()
|
|
||||||
* function.
|
|
||||||
**************************************************************************/
|
|
||||||
gk_loop_t gk_getline(char **lineptr, size_t *n, FILE *stream)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
if (feof(stream))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Initial memory allocation if *lineptr is NULL */
|
|
||||||
if (*lineptr == NULL || *n == 0) {
|
|
||||||
*n = 1024;
|
|
||||||
*lineptr = gk_malloc((*n)*sizeof(char), "gk_getline: lineptr");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get into the main loop */
|
|
||||||
for (i = 0; (ch = getc(stream)) != EOF; i++) {
|
|
||||||
(*lineptr)[i] = (char)ch;
|
|
||||||
|
|
||||||
/* reallocate memory if reached at the end of the buffer. The +2 is for '\0' */
|
|
||||||
if (i+2 == *n) {
|
|
||||||
*n = 2* (*n);
|
|
||||||
*lineptr = gk_realloc(*lineptr, (*n)*sizeof(char), "gk_getline: lineptr");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ch == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
(*lineptr)[i+1] = '\0';
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,319 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file memory.c
|
|
||||||
\brief This file contains various allocation routines
|
|
||||||
|
|
||||||
The allocation routines included are for 1D and 2D arrays of the
|
|
||||||
most datatypes that GKlib support. Many of these routines are
|
|
||||||
defined with the help of the macros in gk_memory.h. These macros
|
|
||||||
can be used to define other memory allocation routines.
|
|
||||||
|
|
||||||
\date Started 4/3/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: memory.c 1432 2007-04-07 20:06:19Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
#ifdef GKMSPACE
|
|
||||||
/* This is the mspace for all the gk_malloc() calls. This is a thread local allocation */
|
|
||||||
static __thread mspace gk_mspace = 0;
|
|
||||||
|
|
||||||
/* This function is mostly for debugging */
|
|
||||||
void gk_printmspaceaddr() { printf("mspace: %p\n", (void *)gk_mspace); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Routines for allocating an array of a particular data type */
|
|
||||||
/**************************************************************************/
|
|
||||||
GK_XMALLOC(gk_cmalloc, char)
|
|
||||||
GK_XMALLOC(gk_imalloc, int)
|
|
||||||
GK_XMALLOC(gk_fmalloc, float)
|
|
||||||
GK_XMALLOC(gk_dmalloc, double)
|
|
||||||
GK_XMALLOC(gk_idxmalloc, gk_idx_t)
|
|
||||||
|
|
||||||
GK_XMALLOC(gk_ckvmalloc, gk_ckv_t)
|
|
||||||
GK_XMALLOC(gk_ikvmalloc, gk_ikv_t)
|
|
||||||
GK_XMALLOC(gk_fkvmalloc, gk_fkv_t)
|
|
||||||
GK_XMALLOC(gk_dkvmalloc, gk_dkv_t)
|
|
||||||
GK_XMALLOC(gk_skvmalloc, gk_skv_t)
|
|
||||||
GK_XMALLOC(gk_idxkvmalloc, gk_idxkv_t)
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Routines for reallocating an array of a particular data type */
|
|
||||||
/**************************************************************************/
|
|
||||||
GK_XREALLOC(gk_crealloc, char)
|
|
||||||
GK_XREALLOC(gk_irealloc, int)
|
|
||||||
GK_XREALLOC(gk_frealloc, float)
|
|
||||||
GK_XREALLOC(gk_drealloc, double)
|
|
||||||
GK_XREALLOC(gk_idxrealloc, gk_idx_t)
|
|
||||||
|
|
||||||
GK_XREALLOC(gk_ckvrealloc, gk_ckv_t)
|
|
||||||
GK_XREALLOC(gk_ikvrealloc, gk_ikv_t)
|
|
||||||
GK_XREALLOC(gk_fkvrealloc, gk_fkv_t)
|
|
||||||
GK_XREALLOC(gk_dkvrealloc, gk_dkv_t)
|
|
||||||
GK_XREALLOC(gk_skvrealloc, gk_skv_t)
|
|
||||||
GK_XREALLOC(gk_idxkvrealloc, gk_idxkv_t)
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Routines for allocating and setting array of a particular data type */
|
|
||||||
/**************************************************************************/
|
|
||||||
GK_XSMALLOC(gk_csmalloc, char, gk_cset)
|
|
||||||
GK_XSMALLOC(gk_ismalloc, int, gk_iset)
|
|
||||||
GK_XSMALLOC(gk_fsmalloc, float, gk_fset)
|
|
||||||
GK_XSMALLOC(gk_dsmalloc, double, gk_dset)
|
|
||||||
GK_XSMALLOC(gk_idxsmalloc, gk_idx_t, gk_idxset)
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Routines for allocating/setting 2D arrays of a particular data type */
|
|
||||||
/**************************************************************************/
|
|
||||||
GK_ALLOCMATRIX(gk_cAllocMatrix, char, gk_csmalloc)
|
|
||||||
GK_ALLOCMATRIX(gk_iAllocMatrix, int, gk_ismalloc)
|
|
||||||
GK_ALLOCMATRIX(gk_fAllocMatrix, float, gk_fsmalloc)
|
|
||||||
GK_ALLOCMATRIX(gk_dAllocMatrix, double, gk_dsmalloc)
|
|
||||||
GK_ALLOCMATRIX(gk_idxAllocMatrix, gk_idx_t, gk_idxsmalloc)
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Routines for freeing 2D arrays of a particular data type */
|
|
||||||
/**************************************************************************/
|
|
||||||
GK_FREEMATRIX(gk_cFreeMatrix, char)
|
|
||||||
GK_FREEMATRIX(gk_iFreeMatrix, int)
|
|
||||||
GK_FREEMATRIX(gk_fFreeMatrix, float)
|
|
||||||
GK_FREEMATRIX(gk_dFreeMatrix, double)
|
|
||||||
GK_FREEMATRIX(gk_idxFreeMatrix, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Routines for filling a 2D array with a constant value */
|
|
||||||
/**************************************************************************/
|
|
||||||
GK_SETMATRIX(gk_cSetMatrix, char)
|
|
||||||
GK_SETMATRIX(gk_iSetMatrix, int)
|
|
||||||
GK_SETMATRIX(gk_fSetMatrix, float)
|
|
||||||
GK_SETMATRIX(gk_dSetMatrix, double)
|
|
||||||
GK_SETMATRIX(gk_idxSetMatrix, gk_idx_t)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function allocates a two-dimensional matrix
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_AllocMatrix(void ***r_matrix, size_t elmlen, size_t ndim1, size_t ndim2)
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
void **matrix;
|
|
||||||
|
|
||||||
matrix = (void **)gk_malloc(ndim1*sizeof(void *), "GKAllocMatrix: matrix");
|
|
||||||
for (i=0; i<ndim1; i++)
|
|
||||||
matrix[i] = (void *)gk_malloc(ndim2*elmlen, "GKAllocMatrix: matrix[i]");
|
|
||||||
|
|
||||||
*r_matrix = matrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function frees a two-dimensional matrix
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_FreeMatrix(void ***r_matrix, size_t ndim1, size_t ndim2)
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
void **matrix;
|
|
||||||
|
|
||||||
matrix = *r_matrix;
|
|
||||||
|
|
||||||
for (i=0; i<ndim1; i++)
|
|
||||||
gk_free((void **)&matrix[i], LTERM);
|
|
||||||
|
|
||||||
gk_free((void **)matrix, LTERM);
|
|
||||||
|
|
||||||
*r_matrix = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is my wrapper around malloc
|
|
||||||
**************************************************************************/
|
|
||||||
void *gk_malloc(size_t nbytes, char *msg)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
if (nbytes == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#ifdef GKMSPACE
|
|
||||||
if (gk_mspace == 0)
|
|
||||||
gk_mspace = create_mspace(0, 0);
|
|
||||||
|
|
||||||
if (gk_mspace == NULL)
|
|
||||||
gk_errexit(SIGMEM, "***Memory allocation failed for creating gk_mspace.");
|
|
||||||
|
|
||||||
ptr = (void *)mspace_malloc(gk_mspace, nbytes);
|
|
||||||
#else
|
|
||||||
ptr = (void *)dlmalloc(nbytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ptr == NULL) {
|
|
||||||
#ifdef WIN32
|
|
||||||
printf(" Maximum memory used: %10Iu bytes\n", gk_GetMaxMemoryUsed());
|
|
||||||
printf(" Current memory used: %10Iu bytes\n", gk_GetCurMemoryUsed());
|
|
||||||
#endif
|
|
||||||
#ifdef SUNOS
|
|
||||||
printf(" Maximum memory used: %10lu bytes\n", gk_GetMaxMemoryUsed());
|
|
||||||
printf(" Current memory used: %10lu bytes\n", gk_GetCurMemoryUsed());
|
|
||||||
#endif
|
|
||||||
#ifdef LINUX
|
|
||||||
printf(" Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed());
|
|
||||||
printf(" Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gk_errexit(SIGMEM, "***Memory allocation failed for %s. Requested size: %zd bytes", msg, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is my wrapper around realloc
|
|
||||||
**************************************************************************/
|
|
||||||
void *gk_realloc(void *oldptr, size_t nbytes, char *msg)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
if (nbytes == 0) {
|
|
||||||
gk_free((void **)&oldptr, LTERM);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GKMSPACE
|
|
||||||
if (gk_mspace == 0)
|
|
||||||
gk_mspace = create_mspace(0, 0);
|
|
||||||
|
|
||||||
if (gk_mspace == NULL)
|
|
||||||
gk_errexit(SIGMEM, "***Memory allocation failed for creating gk_mspace.");
|
|
||||||
|
|
||||||
ptr = (void *)mspace_realloc(gk_mspace, oldptr, nbytes);
|
|
||||||
#else
|
|
||||||
ptr = (void *)dlrealloc(oldptr, nbytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ptr == NULL) {
|
|
||||||
#ifdef WIN32
|
|
||||||
printf(" Maximum memory used: %10Iu bytes\n", gk_GetMaxMemoryUsed());
|
|
||||||
printf(" Current memory used: %10Iu bytes\n", gk_GetCurMemoryUsed());
|
|
||||||
#endif
|
|
||||||
#ifdef SUNOS
|
|
||||||
printf(" Maximum memory used: %10lu bytes\n", gk_GetMaxMemoryUsed());
|
|
||||||
printf(" Current memory used: %10lu bytes\n", gk_GetCurMemoryUsed());
|
|
||||||
#endif
|
|
||||||
#ifdef LINUX
|
|
||||||
printf(" Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed());
|
|
||||||
printf(" Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gk_errexit(SIGMEM, "***Memory re-allocation failed for %s. Requested size: %zd bytes", msg, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is my wrapper around free, allows multiple pointers
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_free(void **ptr1,...)
|
|
||||||
{
|
|
||||||
va_list plist;
|
|
||||||
void **ptr;
|
|
||||||
|
|
||||||
if (*ptr1 != NULL)
|
|
||||||
#ifdef GKMSPACE
|
|
||||||
mspace_free(gk_mspace, *ptr1);
|
|
||||||
#else
|
|
||||||
dlfree(*ptr1);
|
|
||||||
#endif
|
|
||||||
*ptr1 = NULL;
|
|
||||||
|
|
||||||
va_start(plist, ptr1);
|
|
||||||
|
|
||||||
while ((ptr = va_arg(plist, void **)) != LTERM) {
|
|
||||||
if (*ptr != NULL)
|
|
||||||
#ifdef GKMSPACE
|
|
||||||
mspace_free(gk_mspace, *ptr);
|
|
||||||
#else
|
|
||||||
dlfree(*ptr);
|
|
||||||
#endif
|
|
||||||
*ptr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(plist);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function cleans up the memory that has been allocated thus far.
|
|
||||||
* This work only if code has been compiled with GKMSPACE
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_malloc_cleanup()
|
|
||||||
{
|
|
||||||
#ifdef GKMSPACE
|
|
||||||
if (gk_mspace != 0)
|
|
||||||
destroy_mspace(gk_mspace);
|
|
||||||
gk_mspace = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the current ammount of dynamically allocated
|
|
||||||
* memory that is used by the system
|
|
||||||
**************************************************************************/
|
|
||||||
size_t gk_GetCurMemoryUsed()
|
|
||||||
{
|
|
||||||
struct mallinfo meminfo;
|
|
||||||
size_t cused=0;
|
|
||||||
|
|
||||||
#ifdef GKMSPACE
|
|
||||||
if (gk_mspace != 0) {
|
|
||||||
meminfo = mspace_mallinfo(gk_mspace);
|
|
||||||
cused = meminfo.uordblks;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
meminfo = dlmallinfo();
|
|
||||||
cused = meminfo.uordblks;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return cused;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the maximum ammount of dynamically allocated
|
|
||||||
* memory that was used by the system
|
|
||||||
**************************************************************************/
|
|
||||||
size_t gk_GetMaxMemoryUsed()
|
|
||||||
{
|
|
||||||
struct mallinfo meminfo;
|
|
||||||
size_t mused=0;
|
|
||||||
|
|
||||||
#ifdef GKMSPACE
|
|
||||||
if (gk_mspace != 0) {
|
|
||||||
meminfo = mspace_mallinfo(gk_mspace);
|
|
||||||
mused = meminfo.usmblks;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
meminfo = dlmallinfo();
|
|
||||||
mused = meminfo.usmblks;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return mused;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* omp.c
|
|
||||||
*
|
|
||||||
* This file contains "fake" implementations of OpenMP's runtime libraries
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
#if !defined(__OPENMP__)
|
|
||||||
void omp_set_num_threads(int num_threads) { return; }
|
|
||||||
int omp_get_num_threads(void) { return 1; }
|
|
||||||
int omp_get_max_threads(void) { return 1; }
|
|
||||||
int omp_get_thread_num(void) { return 1; }
|
|
||||||
int omp_get_num_procs(void) { return 1; }
|
|
||||||
int omp_in_parallel(void) { return 0; }
|
|
||||||
void omp_set_dynamic(int num_threads) { return; }
|
|
||||||
int omp_get_dynamic(void) { return 0; }
|
|
||||||
void omp_set_nested(int nested) { return; }
|
|
||||||
int omp_get_nested(void) { return 0; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,410 +0,0 @@
|
|||||||
/************************************************************************/
|
|
||||||
/*! \file pdb.c
|
|
||||||
|
|
||||||
\brief Functions for parsing pdb files.
|
|
||||||
|
|
||||||
Pdb reader (parser). Loads arrays of pointers for easy backbone access.
|
|
||||||
|
|
||||||
\date Started 10/20/06
|
|
||||||
\author Kevin
|
|
||||||
\version $Id: pdb.c 1414 2007-04-05 02:52:46Z karypis $
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <GKlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Converts three-letter amino acid codes to one-leter codes.
|
|
||||||
|
|
||||||
This function takes a three letter \c * and converts it to a single \c
|
|
||||||
|
|
||||||
\param res is the three-letter code to be converted.
|
|
||||||
\returns A \c representing the amino acid.
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
char gk_threetoone(char *res) { /* {{{ */
|
|
||||||
/* make sure the matching works */
|
|
||||||
res[0] = toupper(res[0]);
|
|
||||||
res[1] = toupper(res[1]);
|
|
||||||
res[2] = toupper(res[2]);
|
|
||||||
if(strcmp(res,"ALA") == 0) {
|
|
||||||
return 'A';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"CYS") == 0) {
|
|
||||||
return 'C';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"ASP") == 0) {
|
|
||||||
return 'D';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"GLU") == 0) {
|
|
||||||
return 'E';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"PHE") == 0) {
|
|
||||||
return 'F';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"GLY") == 0) {
|
|
||||||
return 'G';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"HIS") == 0) {
|
|
||||||
return 'H';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"ILE") == 0) {
|
|
||||||
return 'I';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"LYS") == 0) {
|
|
||||||
return 'K';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"LEU") == 0) {
|
|
||||||
return 'L';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"MET") == 0) {
|
|
||||||
return 'M';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"ASN") == 0) {
|
|
||||||
return 'N';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"PRO") == 0) {
|
|
||||||
return 'P';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"GLN") == 0) {
|
|
||||||
return 'Q';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"ARG") == 0) {
|
|
||||||
return 'R';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"SER") == 0) {
|
|
||||||
return 'S';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"THR") == 0) {
|
|
||||||
return 'T';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"SCY") == 0) {
|
|
||||||
return 'U';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"VAL") == 0) {
|
|
||||||
return 'V';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"TRP") == 0) {
|
|
||||||
return 'W';
|
|
||||||
}
|
|
||||||
else if(strcmp(res,"TYR") == 0) {
|
|
||||||
return 'Y';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 'X';
|
|
||||||
}
|
|
||||||
} /* }}} */
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Frees the memory of a pdbf structure.
|
|
||||||
|
|
||||||
This function takes a pdbf pointer and frees all the memory below it.
|
|
||||||
|
|
||||||
\param p is the pdbf structure to be freed.
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
void gk_freepdbf(pdbf *p) { /* {{{ */
|
|
||||||
int i;
|
|
||||||
if(p != NULL) {
|
|
||||||
gk_free((void *)&p->resSeq, LTERM);
|
|
||||||
for(i=0; i<p->natoms; i++) {
|
|
||||||
gk_free((void *)&p->atoms[i].name, &p->atoms[i].resname, LTERM);
|
|
||||||
}
|
|
||||||
/* this may look like it's wrong, but it's just a 1-d array of pointers, and
|
|
||||||
the pointers themselves are freed above */
|
|
||||||
gk_free((void *)&p->bbs, &p->cas, &p->atoms, LTERM);
|
|
||||||
}
|
|
||||||
gk_free((void *)&p, LTERM);
|
|
||||||
} /* }}} */
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Reads a pdb file into a pdbf structure
|
|
||||||
|
|
||||||
This function allocates a pdbf structure and reads the file fname into
|
|
||||||
that structure.
|
|
||||||
|
|
||||||
\param fname is the file name to be read
|
|
||||||
\returns A filled pdbf structure.
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
pdbf *gk_readpdbfile(char *fname) { /* {{{ */
|
|
||||||
int i=0, res=0;
|
|
||||||
char linetype[6];
|
|
||||||
int aserial;
|
|
||||||
char aname[5] = " \0";
|
|
||||||
char altLoc = ' ';
|
|
||||||
char rname[4] = " \0";
|
|
||||||
char chainid = ' ';
|
|
||||||
char oldchainid = ' ';
|
|
||||||
int rserial;
|
|
||||||
int oldRserial = -37;
|
|
||||||
char icode = ' ';
|
|
||||||
char element = ' ';
|
|
||||||
double x;
|
|
||||||
double y;
|
|
||||||
double z;
|
|
||||||
double opcy;
|
|
||||||
double tmpt;
|
|
||||||
char line[MAXLINELEN];
|
|
||||||
int corruption=0;
|
|
||||||
|
|
||||||
int atoms=0, residues=0, cas=0, bbs=0, firstres=1;
|
|
||||||
pdbf *toFill = gk_malloc(sizeof(pdbf),"fillme");
|
|
||||||
FILE *FPIN;
|
|
||||||
|
|
||||||
FPIN = gk_fopen(fname,"r",fname);
|
|
||||||
while(fgets(line, 256, FPIN)) {
|
|
||||||
sscanf(line,"%s ",linetype);
|
|
||||||
/* It seems the only reliable parts are through temperature, so we only use these parts */
|
|
||||||
/* if(strstr(linetype, "ATOM") != NULL || strstr(linetype, "HETATM") != NULL) { */
|
|
||||||
if(strstr(linetype, "ATOM") != NULL) {
|
|
||||||
sscanf(line, "%6s%5d%*1c%4c%1c%3c%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf %c\n",
|
|
||||||
linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,&element);
|
|
||||||
sscanf(linetype, " %s ",linetype);
|
|
||||||
sscanf(aname, " %s ",aname);
|
|
||||||
sscanf(rname, " %s ",rname);
|
|
||||||
if(altLoc != ' ') {
|
|
||||||
corruption = corruption|CRP_ALTLOCS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(firstres == 1) {
|
|
||||||
oldRserial = rserial;
|
|
||||||
oldchainid = chainid;
|
|
||||||
residues++;
|
|
||||||
firstres = 0;
|
|
||||||
}
|
|
||||||
if(oldRserial != rserial) {
|
|
||||||
residues++;
|
|
||||||
oldRserial = rserial;
|
|
||||||
}
|
|
||||||
if(oldchainid != chainid) {
|
|
||||||
corruption = corruption|CRP_MULTICHAIN;
|
|
||||||
}
|
|
||||||
oldchainid = chainid;
|
|
||||||
atoms++;
|
|
||||||
if(strcmp(aname,"CA") == 0) {
|
|
||||||
cas++;
|
|
||||||
}
|
|
||||||
if(strcmp(aname,"N") == 0 || strcmp(aname,"CA") == 0 ||
|
|
||||||
strcmp(aname,"C") == 0 || strcmp(aname,"O") == 0) {
|
|
||||||
bbs++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(strstr(linetype, "ENDMDL") != NULL || strstr(linetype, "END") != NULL || strstr(linetype, "TER") != NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(FPIN);
|
|
||||||
|
|
||||||
/* printf("File has coordinates for %d atoms in %d residues\n",atoms,residues); */
|
|
||||||
toFill->natoms = atoms;
|
|
||||||
toFill->ncas = cas;
|
|
||||||
toFill->nbbs = bbs;
|
|
||||||
toFill->nresidues = residues;
|
|
||||||
toFill->resSeq = (char *)gk_malloc (residues*sizeof(char),"residue seq");
|
|
||||||
toFill->atoms = (atom *)gk_malloc(atoms*sizeof(atom), "atoms");
|
|
||||||
toFill->bbs = (atom **)gk_malloc( bbs*sizeof(atom *),"bbs");
|
|
||||||
toFill->cas = (atom **)gk_malloc( cas*sizeof(atom *),"cas");
|
|
||||||
res=0; firstres=1; cas=0; bbs=0; i=0;
|
|
||||||
|
|
||||||
FPIN = gk_fopen(fname,"r",fname);
|
|
||||||
while(fgets(line, 256, FPIN)) {
|
|
||||||
sscanf(line,"%s ",linetype);
|
|
||||||
/* It seems the only reliable parts are through temperature, so we only use these parts */
|
|
||||||
/* if(strstr(linetype, "ATOM") != NULL || strstr(linetype, "HETATM") != NULL) { */
|
|
||||||
if(strstr(linetype, "ATOM") != NULL ) {
|
|
||||||
|
|
||||||
/* to ensure our memory doesn't get corrupted by the biologists, we only read this far */
|
|
||||||
sscanf(line, "%6s%5d%*1c%4c%1c%3c%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf %c\n",
|
|
||||||
linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,&element);
|
|
||||||
sscanf(aname, "%s",aname);
|
|
||||||
sscanf(rname, "%s",rname);
|
|
||||||
if(firstres == 1) {
|
|
||||||
toFill->resSeq[res] = gk_threetoone(rname);
|
|
||||||
oldRserial = rserial;
|
|
||||||
res++;
|
|
||||||
firstres = 0;
|
|
||||||
}
|
|
||||||
if(oldRserial != rserial) {
|
|
||||||
toFill->resSeq[res] = gk_threetoone(rname);
|
|
||||||
res++;
|
|
||||||
oldRserial = rserial;
|
|
||||||
}
|
|
||||||
|
|
||||||
toFill->atoms[i].x = x;
|
|
||||||
toFill->atoms[i].y = y;
|
|
||||||
toFill->atoms[i].z = z;
|
|
||||||
toFill->atoms[i].opcy = opcy;
|
|
||||||
toFill->atoms[i].tmpt = tmpt;
|
|
||||||
toFill->atoms[i].element = element;
|
|
||||||
toFill->atoms[i].serial = aserial;
|
|
||||||
toFill->atoms[i].chainid = chainid;
|
|
||||||
toFill->atoms[i].altLoc = altLoc;
|
|
||||||
toFill->atoms[i].rserial = rserial;
|
|
||||||
toFill->atoms[i].icode = icode;
|
|
||||||
toFill->atoms[i].name = gk_strdup(aname);
|
|
||||||
toFill->atoms[i].resname = gk_strdup(rname);
|
|
||||||
/* Set up pointers for the backbone and c-alpha shortcuts */
|
|
||||||
if(strcmp(aname,"CA") == 0) {
|
|
||||||
toFill->cas[cas] = &(toFill->atoms[i]);
|
|
||||||
cas++;
|
|
||||||
}
|
|
||||||
if(strcmp(aname,"N") == 0 || strcmp(aname,"CA") == 0 || strcmp(aname,"C") == 0 || strcmp(aname,"O") == 0) {
|
|
||||||
toFill->bbs[bbs] = &(toFill->atoms[i]);
|
|
||||||
bbs++;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if(strstr(linetype, "ENDMDL") != NULL || strstr(linetype, "END") != NULL || strstr(linetype, "TER") != NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Begin test code */
|
|
||||||
if(cas != residues) {
|
|
||||||
printf("Number of residues and CA coordinates differs by %d (!)\n",residues-cas);
|
|
||||||
if(cas < residues) {
|
|
||||||
corruption = corruption|CRP_MISSINGCA;
|
|
||||||
}
|
|
||||||
else if(cas > residues) {
|
|
||||||
corruption = corruption|CRP_MULTICA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(bbs < residues*4) {
|
|
||||||
corruption = corruption|CRP_MISSINGBB;
|
|
||||||
}
|
|
||||||
else if(bbs > residues*4) {
|
|
||||||
corruption = corruption|CRP_MULTIBB;
|
|
||||||
}
|
|
||||||
fclose(FPIN);
|
|
||||||
toFill->corruption = corruption;
|
|
||||||
/* if(corruption == 0)
|
|
||||||
printf("File was clean!\n"); */
|
|
||||||
return(toFill);
|
|
||||||
} /* }}} */
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Writes the sequence of residues from a pdb file.
|
|
||||||
|
|
||||||
This function takes a pdbf structure and a filename, and writes out
|
|
||||||
the amino acid sequence according to the atomic coordinates. The output
|
|
||||||
is in fasta format.
|
|
||||||
|
|
||||||
|
|
||||||
\param p is the pdbf structure with the sequence of interest
|
|
||||||
\param fname is the file name to be written
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
void gk_writefastafrompdb(pdbf *pb, char *fname) {
|
|
||||||
int i;
|
|
||||||
FILE *OUT = gk_fopen(fname,"w",fname);
|
|
||||||
fprintf(OUT,"> %s\n",fname);
|
|
||||||
|
|
||||||
for(i=0; i<pb->nresidues; i++)
|
|
||||||
fprintf(OUT,"%c",pb->resSeq[i]);
|
|
||||||
|
|
||||||
fprintf(OUT,"\n");
|
|
||||||
fclose(OUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Writes all atoms in p in pdb-format to file fname.
|
|
||||||
|
|
||||||
This function takes a pdbf structure and writes out all the atom
|
|
||||||
information to file fname.
|
|
||||||
|
|
||||||
\param p is the pdbf structure to write out
|
|
||||||
\param fname is the file name to be written
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
void gk_writefullatom(pdbf *p, char *fname) {
|
|
||||||
int i;
|
|
||||||
FILE *FPIN;
|
|
||||||
FPIN = gk_fopen(fname,"w",fname);
|
|
||||||
for(i=0; i<p->natoms; i++) {
|
|
||||||
fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n",
|
|
||||||
"ATOM ",p->atoms[i].serial,p->atoms[i].name,p->atoms[i].altLoc,p->atoms[i].resname,p->atoms[i].chainid,p->atoms[i].rserial,p->atoms[i].icode,p->atoms[i].x,p->atoms[i].y,p->atoms[i].z,p->atoms[i].opcy,p->atoms[i].tmpt);
|
|
||||||
}
|
|
||||||
fclose(FPIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Writes out all the backbone atoms of a structure in pdb format
|
|
||||||
|
|
||||||
This function takes a pdbf structure p and writes only the backbone atoms
|
|
||||||
to a filename fname.
|
|
||||||
|
|
||||||
\param p is the pdb structure to write out.
|
|
||||||
\param fname is the file name to be written.
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
void gk_writebackbone(pdbf *p, char *fname) {
|
|
||||||
int i;
|
|
||||||
FILE *FPIN;
|
|
||||||
FPIN = gk_fopen(fname,"w",fname);
|
|
||||||
for(i=0; i<p->nbbs; i++) {
|
|
||||||
fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n",
|
|
||||||
"ATOM ",p->bbs[i]->serial,p->bbs[i]->name,p->bbs[i]->altLoc,p->bbs[i]->resname,p->bbs[i]->chainid,p->bbs[i]->rserial,p->bbs[i]->icode,p->bbs[i]->x,p->bbs[i]->y,p->bbs[i]->z,p->bbs[i]->opcy,p->bbs[i]->tmpt);
|
|
||||||
}
|
|
||||||
fclose(FPIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Writes out all the alpha carbon atoms of a structure
|
|
||||||
|
|
||||||
This function takes a pdbf structure p and writes only the alpha carbon
|
|
||||||
atoms to a filename fname.
|
|
||||||
|
|
||||||
\param p is the pdb structure to write out.
|
|
||||||
\param fname is the file name to be written.
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
void gk_writealphacarbons(pdbf *p, char *fname) {
|
|
||||||
int i;
|
|
||||||
FILE *FPIN;
|
|
||||||
FPIN = gk_fopen(fname,"w",fname);
|
|
||||||
for(i=0; i<p->ncas; i++) {
|
|
||||||
fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n",
|
|
||||||
"ATOM ",p->cas[i]->serial,p->cas[i]->name,p->cas[i]->altLoc,p->cas[i]->resname,p->cas[i]->chainid,p->cas[i]->rserial,p->cas[i]->icode,p->cas[i]->x,p->cas[i]->y,p->cas[i]->z,p->cas[i]->opcy,p->cas[i]->tmpt);
|
|
||||||
}
|
|
||||||
fclose(FPIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Decodes the corruption bitswitch and prints any problems
|
|
||||||
|
|
||||||
Due to the totally unreliable nature of the pdb format, reading a pdb
|
|
||||||
file stores a corruption bitswitch, and this function decodes that switch
|
|
||||||
and prints the result on stdout.
|
|
||||||
|
|
||||||
\param p is the pdb structure to write out.
|
|
||||||
\param fname is the file name to be written.
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
void gk_showcorruption(pdbf *p) {
|
|
||||||
int corruption = p->corruption;
|
|
||||||
if(corruption&CRP_ALTLOCS)
|
|
||||||
printf("Multiple coordinate sets for at least one atom\n");
|
|
||||||
if(corruption&CRP_MISSINGCA)
|
|
||||||
printf("Missing coordiantes for at least one CA atom\n");
|
|
||||||
if(corruption&CRP_MISSINGBB)
|
|
||||||
printf("Missing coordiantes for at least one backbone atom (N,CA,C,O)\n");
|
|
||||||
if(corruption&CRP_MULTICHAIN)
|
|
||||||
printf("File contains coordinates for multiple chains\n");
|
|
||||||
if(corruption&CRP_MULTICA)
|
|
||||||
printf("Multiple CA atoms found for the same residue (could be alternate locators)\n");
|
|
||||||
if(corruption&CRP_MULTICA)
|
|
||||||
printf("Multiple copies of backbone atoms found for the same residue (could be alternate locators)\n");
|
|
||||||
}
|
|
||||||
/* sscanf(line, "%6s%5d%*1c%4s%1c%3s%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf%*6c%4s%2s%2s\n",
|
|
||||||
linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,segId,element,charge);
|
|
||||||
printf(".%s.%s.%s.\n",segId,element,charge);
|
|
||||||
printf("%-6s%5d%-1s%-4s%1c%3s%1s%1c%4d%1c%3s%8.3lf%8.3lf%8.3lf%6.2f%6.2f%6s%4s%2s%2s\n",
|
|
||||||
linetype,aserial," ",aname,altLoc,rname," ",chainid,rserial,icode," ",x,y,z,opcy,tmpt," ",segId,element,charge); */
|
|
||||||
|
|
||||||
/* and we could probably get away with this using astral files, */
|
|
||||||
/* sscanf(line, "%6s%5d%*1c%4s%1c%3s%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf%*6c%6s\n",
|
|
||||||
linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,element);
|
|
||||||
printf("%-6s%5d%-1s%-4s%1c%3s%1s%1c%4d%1c%3s%8.3lf%8.3lf%8.3lf%6.2f%6.2f%6s%6s\n",
|
|
||||||
linetype,aserial," ",aname,altLoc,rname," ",chainid,rserial,icode," ",x,y,z,opcy,tmpt," ",element); */
|
|
||||||
@ -1,390 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* pqueue.c
|
|
||||||
*
|
|
||||||
* This file contains functions for manipulating the bucket list
|
|
||||||
* representation of the gains associated with each vertex in a graph.
|
|
||||||
* These functions are used by the refinement algorithms
|
|
||||||
*
|
|
||||||
* Started 9/2/94
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: pqueue.c 1414 2007-04-05 02:52:46Z karypis $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function initializes the data structures of the priority queue
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_PQueueInit(gk_PQueue_t *queue, int maxnodes)
|
|
||||||
{
|
|
||||||
queue->nnodes = 0;
|
|
||||||
queue->maxnodes = maxnodes;
|
|
||||||
|
|
||||||
queue->heap = gk_fkvmalloc(maxnodes, "gk_PQueueInit: heap");
|
|
||||||
queue->locator = gk_ismalloc(maxnodes, -1, "gk_PQueueInit: locator");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function resets the buckets
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_PQueueReset(gk_PQueue_t *queue)
|
|
||||||
{
|
|
||||||
queue->nnodes = 0;
|
|
||||||
|
|
||||||
gk_iset(queue->maxnodes, -1, queue->locator);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function frees the buckets
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_PQueueFree(gk_PQueue_t *queue)
|
|
||||||
{
|
|
||||||
gk_free((void *)&queue->heap, &queue->locator, LTERM);
|
|
||||||
queue->maxnodes = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the number of nodes in the queue
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_PQueueGetSize(gk_PQueue_t *queue)
|
|
||||||
{
|
|
||||||
return queue->nnodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function adds an item in the priority queue
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_PQueueInsert(gk_PQueue_t *queue, int node, float key)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
int *locator;
|
|
||||||
gk_fkv_t *heap;
|
|
||||||
|
|
||||||
ASSERT(gk_CheckHeap(queue));
|
|
||||||
|
|
||||||
heap = queue->heap;
|
|
||||||
locator = queue->locator;
|
|
||||||
|
|
||||||
ASSERT(locator[node] == -1);
|
|
||||||
|
|
||||||
i = queue->nnodes++;
|
|
||||||
while (i > 0) {
|
|
||||||
j = (i-1)/2;
|
|
||||||
if (heap[j].key < key) {
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ASSERT(i >= 0);
|
|
||||||
heap[i].key = key;
|
|
||||||
heap[i].val = node;
|
|
||||||
locator[node] = i;
|
|
||||||
|
|
||||||
ASSERT(gk_CheckHeap(queue));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function deletes an item from the priority queue
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_PQueueDelete(gk_PQueue_t *queue, int node)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
float newkey, oldkey;
|
|
||||||
int *locator;
|
|
||||||
gk_fkv_t *heap;
|
|
||||||
|
|
||||||
heap = queue->heap;
|
|
||||||
locator = queue->locator;
|
|
||||||
|
|
||||||
ASSERT(locator[node] != -1);
|
|
||||||
ASSERT(heap[locator[node]].val == node);
|
|
||||||
|
|
||||||
ASSERT(gk_CheckHeap(queue));
|
|
||||||
|
|
||||||
i = locator[node];
|
|
||||||
locator[node] = -1;
|
|
||||||
|
|
||||||
if (--queue->nnodes > 0 && heap[queue->nnodes].val != node) {
|
|
||||||
node = heap[queue->nnodes].val;
|
|
||||||
newkey = heap[queue->nnodes].key;
|
|
||||||
oldkey = heap[i].key;
|
|
||||||
|
|
||||||
if (oldkey < newkey) { /* Filter-up */
|
|
||||||
while (i > 0) {
|
|
||||||
j = (i-1)>>1;
|
|
||||||
if (heap[j].key < newkey) {
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* Filter down */
|
|
||||||
while ((j=2*i+1) < queue->nnodes) {
|
|
||||||
if (heap[j].key > newkey) {
|
|
||||||
if (j+1 < queue->nnodes && heap[j+1].key > heap[j].key)
|
|
||||||
j = j+1;
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else if (j+1 < queue->nnodes && heap[j+1].key > newkey) {
|
|
||||||
j = j+1;
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
heap[i].key = newkey;
|
|
||||||
heap[i].val = node;
|
|
||||||
locator[node] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(gk_CheckHeap(queue));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function deletes a node from a partition and reinserts it with
|
|
||||||
* an updated key value
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_PQueueUpdate(gk_PQueue_t *queue, int node, float newkey)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
int *locator;
|
|
||||||
gk_fkv_t *heap;
|
|
||||||
float oldkey;
|
|
||||||
|
|
||||||
heap = queue->heap;
|
|
||||||
locator = queue->locator;
|
|
||||||
|
|
||||||
oldkey = heap[locator[node]].key;
|
|
||||||
|
|
||||||
ASSERT(locator[node] != -1);
|
|
||||||
ASSERT(heap[locator[node]].val == node);
|
|
||||||
ASSERT(gk_CheckHeap(queue));
|
|
||||||
|
|
||||||
i = locator[node];
|
|
||||||
|
|
||||||
if (oldkey < newkey) { /* Filter-up */
|
|
||||||
while (i > 0) {
|
|
||||||
j = (i-1)>>1;
|
|
||||||
if (heap[j].key < newkey) {
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* Filter down */
|
|
||||||
while ((j=2*i+1) < queue->nnodes) {
|
|
||||||
if (heap[j].key > newkey) {
|
|
||||||
if (j+1 < queue->nnodes && heap[j+1].key > heap[j].key)
|
|
||||||
j = j+1;
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else if (j+1 < queue->nnodes && heap[j+1].key > newkey) {
|
|
||||||
j = j+1;
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
heap[i].key = newkey;
|
|
||||||
heap[i].val = node;
|
|
||||||
locator[node] = i;
|
|
||||||
|
|
||||||
ASSERT(gk_CheckHeap(queue));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the item with the largest key-value and removes
|
|
||||||
* it from the priority queue
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_PQueueGetMax(gk_PQueue_t *queue)
|
|
||||||
{
|
|
||||||
int vtx, i, j, node;
|
|
||||||
int *locator;
|
|
||||||
gk_fkv_t *heap;
|
|
||||||
float key;
|
|
||||||
|
|
||||||
if (queue->nnodes == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
queue->nnodes--;
|
|
||||||
|
|
||||||
heap = queue->heap;
|
|
||||||
locator = queue->locator;
|
|
||||||
|
|
||||||
vtx = heap[0].val;
|
|
||||||
locator[vtx] = -1;
|
|
||||||
|
|
||||||
if ((i = queue->nnodes) > 0) {
|
|
||||||
key = heap[i].key;
|
|
||||||
node = heap[i].val;
|
|
||||||
i = 0;
|
|
||||||
while ((j=2*i+1) < queue->nnodes) {
|
|
||||||
if (heap[j].key > key) {
|
|
||||||
if (j+1 < queue->nnodes && heap[j+1].key > heap[j].key)
|
|
||||||
j = j+1;
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else if (j+1 < queue->nnodes && heap[j+1].key > key) {
|
|
||||||
j = j+1;
|
|
||||||
heap[i] = heap[j];
|
|
||||||
locator[heap[i].val] = i;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
heap[i].key = key;
|
|
||||||
heap[i].val = node;
|
|
||||||
locator[node] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(gk_CheckHeap(queue));
|
|
||||||
return vtx;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the vertex with the largest gain from a partition
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_PQueueSeeMaxVal(gk_PQueue_t *queue)
|
|
||||||
{
|
|
||||||
return (queue->nnodes == 0 ? -1 : queue->heap[0].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the vertex with the largest gain from a partition
|
|
||||||
**************************************************************************/
|
|
||||||
float gk_PQueueSeeMaxKey(gk_PQueue_t *queue)
|
|
||||||
{
|
|
||||||
return (queue->nnodes == 0 ? FLT_MAX : queue->heap[0].key);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the length of the queue
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_PQueueLength(gk_PQueue_t *queue)
|
|
||||||
{
|
|
||||||
return queue->nnodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the vertex with the largest gain from a partition
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_PQueueSeeConstraintMax(gk_PQueue_t *queue, float maxwgt, double *wgts)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (queue->nnodes == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (maxwgt <= 1000)
|
|
||||||
return gk_PQueueSeeMaxVal(queue);
|
|
||||||
|
|
||||||
for (i=0; i<queue->nnodes; i++) {
|
|
||||||
if (queue->heap[i].key > 0) {
|
|
||||||
if (wgts[queue->heap[i].val] <= maxwgt)
|
|
||||||
return queue->heap[i].val;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (queue->heap[i/2].key <= 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return queue->heap[0].val;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the key of a specific node
|
|
||||||
**************************************************************************/
|
|
||||||
float gk_PQueueSeeKey(gk_PQueue_t *queue, int node)
|
|
||||||
{
|
|
||||||
int *locator;
|
|
||||||
gk_fkv_t *heap;
|
|
||||||
|
|
||||||
heap = queue->heap;
|
|
||||||
locator = queue->locator;
|
|
||||||
|
|
||||||
return heap[locator[node]].key;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This functions checks the consistency of the heap
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_CheckHeap(gk_PQueue_t *queue)
|
|
||||||
{
|
|
||||||
int i, j, nnodes;
|
|
||||||
int *locator;
|
|
||||||
gk_fkv_t *heap;
|
|
||||||
|
|
||||||
heap = queue->heap;
|
|
||||||
locator = queue->locator;
|
|
||||||
nnodes = queue->nnodes;
|
|
||||||
|
|
||||||
if (nnodes == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
ASSERT(locator[heap[0].val] == 0);
|
|
||||||
for (i=1; i<nnodes; i++) {
|
|
||||||
ASSERTP(locator[heap[i].val] == i, ("%d %d %d %d\n", nnodes, i, heap[i].val, locator[heap[i].val]));
|
|
||||||
ASSERTP(heap[i].key <= heap[(i-1)/2].key, ("%d %d %d %f %f\n", i, (i-1)/2, nnodes, heap[i].key, heap[(i-1)/2].key));
|
|
||||||
}
|
|
||||||
for (i=1; i<nnodes; i++)
|
|
||||||
ASSERT(heap[i].key <= heap[0].key);
|
|
||||||
|
|
||||||
for (j=i=0; i<queue->maxnodes; i++) {
|
|
||||||
if (locator[i] != -1)
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
ASSERTP(j == nnodes, ("%d %d\n", j, nnodes));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Sequence handler library by Huzefa Rangwala
|
|
||||||
* Date : 03.01.2007
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include<GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************/
|
|
||||||
/* ! \brief Initializes the <tt>gk_seq_t</tt> variable
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\param A pointer to gk_seq_t itself
|
|
||||||
\returns null
|
|
||||||
*/
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
void gk_seq_init(gk_seq_t *seq)
|
|
||||||
{
|
|
||||||
|
|
||||||
seq->len = 0;
|
|
||||||
seq->sequence = NULL;
|
|
||||||
|
|
||||||
seq->pssm = NULL;
|
|
||||||
seq->psfm = NULL;
|
|
||||||
|
|
||||||
seq->name = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
/*! \brief This function creates the localizations for the various sequences
|
|
||||||
|
|
||||||
\param string i.e amino acids, nucleotides, sequences
|
|
||||||
\returns gk_i2cc2i_t variable
|
|
||||||
*/
|
|
||||||
/*********************************************************************/
|
|
||||||
|
|
||||||
gk_i2cc2i_t *gk_i2cc2i_create_common(char *alphabet)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
int nsymbols;
|
|
||||||
gk_loop_t i;
|
|
||||||
gk_i2cc2i_t *t;
|
|
||||||
|
|
||||||
nsymbols = strlen(alphabet);
|
|
||||||
t = gk_malloc(sizeof(gk_i2cc2i_t),"gk_i2c_create_common");
|
|
||||||
t->n = nsymbols;
|
|
||||||
t->i2c = gk_cmalloc(256, "gk_i2c_create_common");
|
|
||||||
t->c2i = gk_imalloc(256, "gk_i2c_create_common");
|
|
||||||
|
|
||||||
|
|
||||||
gk_cset(256, -1, t->i2c);
|
|
||||||
gk_iset(256, -1, t->c2i);
|
|
||||||
|
|
||||||
for(i=0;i<nsymbols;i++){
|
|
||||||
t->i2c[i] = alphabet[i];
|
|
||||||
t->c2i[(int)alphabet[i]] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
/*! \brief This function reads a pssm in the format of gkmod pssm
|
|
||||||
|
|
||||||
\param file_name is the name of the pssm file
|
|
||||||
\returns gk_seq_t
|
|
||||||
*/
|
|
||||||
/********************************************************************/
|
|
||||||
gk_seq_t *gk_seq_ReadGKMODPSSM(char *filename)
|
|
||||||
{
|
|
||||||
|
|
||||||
gk_seq_t *seq;
|
|
||||||
gk_loop_t i, j, ii;
|
|
||||||
int ntokens,nbytes,len;
|
|
||||||
FILE *fpin;
|
|
||||||
|
|
||||||
|
|
||||||
gk_Tokens_t tokens;
|
|
||||||
static char *AAORDER = "ARNDCQEGHILKMFPSTWYVBZX*";
|
|
||||||
static int PSSMWIDTH = 20;
|
|
||||||
char header[PSSMWIDTH], line[MAXLINELEN];
|
|
||||||
gk_i2cc2i_t *converter;
|
|
||||||
|
|
||||||
|
|
||||||
converter = gk_i2cc2i_create_common(AAORDER);
|
|
||||||
|
|
||||||
gk_getfilestats(filename, &len, &ntokens, &nbytes);
|
|
||||||
len --;
|
|
||||||
|
|
||||||
seq = gk_malloc(sizeof(gk_seq_t),"gk_seq_ReadGKMODPSSM");
|
|
||||||
gk_seq_init(seq);
|
|
||||||
|
|
||||||
seq->len = len;
|
|
||||||
seq->sequence = gk_imalloc(len, "gk_seq_ReadGKMODPSSM");
|
|
||||||
seq->pssm = gk_iAllocMatrix(len, PSSMWIDTH, 0, "gk_seq_ReadGKMODPSSM");
|
|
||||||
seq->psfm = gk_iAllocMatrix(len, PSSMWIDTH, 0, "gk_seq_ReadGKMODPSSM");
|
|
||||||
|
|
||||||
seq->nsymbols = PSSMWIDTH;
|
|
||||||
seq->name = gk_getbasename(filename);
|
|
||||||
|
|
||||||
fpin = gk_fopen(filename,"r","gk_seq_ReadGKMODPSSM");
|
|
||||||
|
|
||||||
|
|
||||||
/* Read the header line */
|
|
||||||
fgets(line, MAXLINELEN-1, fpin);
|
|
||||||
gk_strtoupper(line);
|
|
||||||
gk_strtokenize(line, " \t\n", &tokens);
|
|
||||||
|
|
||||||
for (i=0; i<PSSMWIDTH; i++)
|
|
||||||
header[i] = tokens.list[i][0];
|
|
||||||
|
|
||||||
gk_freetokenslist(&tokens);
|
|
||||||
|
|
||||||
|
|
||||||
/* Read the rest of the lines */
|
|
||||||
for (i=0, ii=0; ii<len; ii++) {
|
|
||||||
fgets(line, MAXLINELEN-1, fpin);
|
|
||||||
gk_strtoupper(line);
|
|
||||||
gk_strtokenize(line, " \t\n", &tokens);
|
|
||||||
|
|
||||||
seq->sequence[i] = converter->c2i[(int)tokens.list[1][0]];
|
|
||||||
|
|
||||||
for (j=0; j<PSSMWIDTH; j++) {
|
|
||||||
seq->pssm[i][converter->c2i[(int)header[j]]] = atoi(tokens.list[2+j]);
|
|
||||||
seq->psfm[i][converter->c2i[(int)header[j]]] = atoi(tokens.list[2+PSSMWIDTH+j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gk_freetokenslist(&tokens);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
seq->len = i; /* Reset the length if certain characters were skipped */
|
|
||||||
|
|
||||||
gk_fclose(fpin);
|
|
||||||
|
|
||||||
return seq;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*! \brief This function frees the memory allocated to the seq structure.
|
|
||||||
|
|
||||||
\param gk_seq_t
|
|
||||||
\returns nothing
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void gk_seq_free(gk_seq_t *seq)
|
|
||||||
{
|
|
||||||
gk_iFreeMatrix(&seq->pssm, seq->len, seq->nsymbols);
|
|
||||||
gk_iFreeMatrix(&seq->psfm, seq->len, seq->nsymbols);
|
|
||||||
gk_free((void **)&seq->name, &seq->sequence, LTERM);
|
|
||||||
//gk_free((void **)&seq, LTERM);
|
|
||||||
gk_free((void **) &seq, LTERM);
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,239 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file sort.c
|
|
||||||
\brief This file contains GKlib's various sorting routines
|
|
||||||
|
|
||||||
These routines are implemented using the GKSORT macro that is defined
|
|
||||||
in gk_qsort.h and is based on GNU's GLIBC qsort() implementation.
|
|
||||||
|
|
||||||
Additional sorting routines can be created using the same way that
|
|
||||||
these routines where defined.
|
|
||||||
|
|
||||||
\date Started 4/4/07
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: sort.c 1421 2007-04-06 14:37:41Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of chars in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_icsort(int n, char *base)
|
|
||||||
{
|
|
||||||
#define char_lt(a, b) ((*a) < (*b))
|
|
||||||
GKQSORT(char, base, n, char_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of chars in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_dcsort(int n, char *base)
|
|
||||||
{
|
|
||||||
#define char_gt(a, b) ((*a) > (*b))
|
|
||||||
GKQSORT(char, base, n, char_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of integers in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_iisort(int n, int *base)
|
|
||||||
{
|
|
||||||
#define int_lt(a, b) ((*a) < (*b))
|
|
||||||
GKQSORT(int, base, n, int_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of integers in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_disort(int n, int *base)
|
|
||||||
{
|
|
||||||
#define int_gt(a, b) ((*a) > (*b))
|
|
||||||
GKQSORT(int, base, n, int_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of floats in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_ifsort(int n, float *base)
|
|
||||||
{
|
|
||||||
#define float_lt(a, b) ((*a) < (*b))
|
|
||||||
GKQSORT(float, base, n, float_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of floats in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_dfsort(int n, float *base)
|
|
||||||
{
|
|
||||||
#define float_gt(a, b) ((*a) > (*b))
|
|
||||||
GKQSORT(float, base, n, float_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of doubles in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_idsort(int n, double *base)
|
|
||||||
{
|
|
||||||
#define double_lt(a, b) ((*a) < (*b))
|
|
||||||
GKQSORT(double, base, n, double_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of doubles in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_ddsort(int n, double *base)
|
|
||||||
{
|
|
||||||
#define double_gt(a, b) ((*a) > (*b))
|
|
||||||
GKQSORT(double, base, n, double_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_idx_t in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_iidxsort(int n, gk_idx_t *base)
|
|
||||||
{
|
|
||||||
#define idx_lt(a, b) ((*a) < (*b))
|
|
||||||
GKQSORT(gk_idx_t, base, n, idx_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_idx_t in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_didxsort(int n, gk_idx_t *base)
|
|
||||||
{
|
|
||||||
#define idx_gt(a, b) ((*a) > (*b))
|
|
||||||
GKQSORT(gk_idx_t, base, n, idx_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_ckv_t in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_ickvsort(int n, gk_ckv_t *base)
|
|
||||||
{
|
|
||||||
#define ckey_lt(a, b) ((a)->key < (b)->key)
|
|
||||||
GKQSORT(gk_ckv_t, base, n, ckey_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_ckv_t in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_dckvsort(int n, gk_ckv_t *base)
|
|
||||||
{
|
|
||||||
#define ckey_gt(a, b) ((a)->key > (b)->key)
|
|
||||||
GKQSORT(gk_ckv_t, base, n, ckey_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_ikv_t in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_iikvsort(int n, gk_ikv_t *base)
|
|
||||||
{
|
|
||||||
#define ikey_lt(a, b) ((a)->key < (b)->key)
|
|
||||||
GKQSORT(gk_ikv_t, base, n, ikey_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_ikv_t in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_dikvsort(int n, gk_ikv_t *base)
|
|
||||||
{
|
|
||||||
#define ikey_gt(a, b) ((a)->key > (b)->key)
|
|
||||||
GKQSORT(gk_ikv_t, base, n, ikey_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_fkv_t in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_ifkvsort(int n, gk_fkv_t *base)
|
|
||||||
{
|
|
||||||
#define fkey_lt(a, b) ((a)->key < (b)->key)
|
|
||||||
GKQSORT(gk_fkv_t, base, n, fkey_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_fkv_t in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_dfkvsort(int n, gk_fkv_t *base)
|
|
||||||
{
|
|
||||||
#define fkey_gt(a, b) ((a)->key > (b)->key)
|
|
||||||
GKQSORT(gk_fkv_t, base, n, fkey_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_dkv_t in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_idkvsort(int n, gk_dkv_t *base)
|
|
||||||
{
|
|
||||||
#define dkey_lt(a, b) ((a)->key < (b)->key)
|
|
||||||
GKQSORT(gk_dkv_t, base, n, dkey_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_fkv_t in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_ddkvsort(int n, gk_dkv_t *base)
|
|
||||||
{
|
|
||||||
#define dkey_gt(a, b) ((a)->key > (b)->key)
|
|
||||||
GKQSORT(gk_dkv_t, base, n, dkey_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_skv_t in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_iskvsort(int n, gk_skv_t *base)
|
|
||||||
{
|
|
||||||
#define skey_lt(a, b) (strcmp((a)->key, (b)->key) < 0)
|
|
||||||
GKQSORT(gk_skv_t, base, n, skey_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_skv_t in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_dskvsort(int n, gk_skv_t *base)
|
|
||||||
{
|
|
||||||
#define skey_gt(a, b) (strcmp((a)->key, (b)->key) > 0)
|
|
||||||
GKQSORT(gk_skv_t, base, n, skey_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_idxkv_t in increasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_iidxkvsort(int n, gk_idxkv_t *base)
|
|
||||||
{
|
|
||||||
#define idxkey_lt(a, b) ((a)->key < (b)->key)
|
|
||||||
GKQSORT(gk_idxkv_t, base, n, idxkey_lt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Sorts an array of gk_idxkv_t in decreasing order */
|
|
||||||
/*************************************************************************/
|
|
||||||
void gk_didxkvsort(int n, gk_idxkv_t *base)
|
|
||||||
{
|
|
||||||
#define idxkey_gt(a, b) ((a)->key > (b)->key)
|
|
||||||
GKQSORT(gk_idxkv_t, base, n, idxkey_gt);
|
|
||||||
}
|
|
||||||
@ -1,495 +0,0 @@
|
|||||||
/************************************************************************/
|
|
||||||
/*! \file string.c
|
|
||||||
|
|
||||||
\brief Functions for manipulating strings.
|
|
||||||
|
|
||||||
Various functions for manipulating strings. Some of these functions
|
|
||||||
provide new functionality, whereas others are drop-in replacements
|
|
||||||
of standard functions (but with enhanced functionality).
|
|
||||||
|
|
||||||
\date Started 11/1/99
|
|
||||||
\author George
|
|
||||||
\version $Id: string.c 1421 2007-04-06 14:37:41Z karypis $
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Replaces certain characters in a string.
|
|
||||||
|
|
||||||
This function takes a string and replaces all the characters in the
|
|
||||||
\c fromlist with the corresponding characters from the \c tolist.
|
|
||||||
That is, each occurence of <tt>fromlist[i]</tt> is replaced by
|
|
||||||
<tt>tolist[i]</tt>.
|
|
||||||
If the \c tolist is shorter than \c fromlist, then the corresponding
|
|
||||||
characters are deleted. The modifications on \c str are done in place.
|
|
||||||
It tries to provide a functionality similar to Perl's \b tr// function.
|
|
||||||
|
|
||||||
\param str is the string whose characters will be replaced.
|
|
||||||
\param fromlist is the set of characters to be replaced.
|
|
||||||
\param tolist is the set of replacement characters .
|
|
||||||
\returns A pointer to \c str itself.
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
char *gk_strchr_replace(char *str, char *fromlist, char *tolist)
|
|
||||||
{
|
|
||||||
gk_idx_t i, j, k;
|
|
||||||
size_t len, fromlen, tolen;
|
|
||||||
|
|
||||||
len = strlen(str);
|
|
||||||
fromlen = strlen(fromlist);
|
|
||||||
tolen = strlen(tolist);
|
|
||||||
|
|
||||||
for (i=j=0; i<len; i++) {
|
|
||||||
for (k=0; k<fromlen; k++) {
|
|
||||||
if (str[i] == fromlist[k]) {
|
|
||||||
if (k < tolen)
|
|
||||||
str[j++] = tolist[k];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k == fromlen)
|
|
||||||
str[j++] = str[i];
|
|
||||||
}
|
|
||||||
str[j] = '\0';
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Regex-based search-and-replace function
|
|
||||||
|
|
||||||
This function is a C implementation of Perl's <tt> s//</tt> regular-expression
|
|
||||||
based substitution function.
|
|
||||||
|
|
||||||
\param str
|
|
||||||
is the input string on which the operation will be performed.
|
|
||||||
\param pattern
|
|
||||||
is the regular expression for the pattern to be matched for substitution.
|
|
||||||
\param replacement
|
|
||||||
is the replacement string, in which the possible captured pattern substrings
|
|
||||||
are referred to as $1, $2, ..., $9. The entire matched pattern is refered
|
|
||||||
to as $0.
|
|
||||||
\param options
|
|
||||||
is a string specified options for the substitution operation. Currently the
|
|
||||||
<tt>"i"</tt> (case insensitive) and <tt>"g"</tt> (global substitution) are
|
|
||||||
supported.
|
|
||||||
\param new_str
|
|
||||||
is a reference to a pointer that will store a pointer to the newly created
|
|
||||||
string that results from the substitutions. This string is allocated via
|
|
||||||
gk_malloc() and needs to be freed using gk_free(). The string is returned
|
|
||||||
even if no substitutions were performed.
|
|
||||||
\returns
|
|
||||||
If successful, it returns 1 + the number of substitutions that were performed.
|
|
||||||
Thus, if no substitutions were performed, the returned value will be 1.
|
|
||||||
Otherwise it returns 0. In case of error, a meaningful error message is
|
|
||||||
returned in <tt>newstr</tt>, which also needs to be freed afterwards.
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
int gk_strstr_replace(char *str, char *pattern, char *replacement, char *options,
|
|
||||||
char **new_str)
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
int j, rc, flags, global, nmatches;
|
|
||||||
size_t len, rlen, nlen, offset, noffset;
|
|
||||||
regex_t re;
|
|
||||||
regmatch_t matches[10];
|
|
||||||
|
|
||||||
|
|
||||||
/* Parse the options */
|
|
||||||
flags = REG_EXTENDED;
|
|
||||||
if (strchr(options, 'i') != NULL)
|
|
||||||
flags = flags | REG_ICASE;
|
|
||||||
global = (strchr(options, 'g') != NULL ? 1 : 0);
|
|
||||||
|
|
||||||
|
|
||||||
/* Compile the regex */
|
|
||||||
if ((rc = regcomp(&re, pattern, flags)) != 0) {
|
|
||||||
len = regerror(rc, &re, NULL, 0);
|
|
||||||
*new_str = gk_cmalloc(len, "gk_strstr_replace: new_str");
|
|
||||||
regerror(rc, &re, *new_str, len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare the output string */
|
|
||||||
len = strlen(str);
|
|
||||||
nlen = 2*len;
|
|
||||||
noffset = 0;
|
|
||||||
*new_str = gk_cmalloc(nlen+1, "gk_strstr_replace: new_str");
|
|
||||||
|
|
||||||
|
|
||||||
/* Get into the matching-replacing loop */
|
|
||||||
rlen = strlen(replacement);
|
|
||||||
offset = 0;
|
|
||||||
nmatches = 0;
|
|
||||||
do {
|
|
||||||
rc = regexec(&re, str+offset, 10, matches, 0);
|
|
||||||
|
|
||||||
if (rc == REG_ESPACE) {
|
|
||||||
gk_free((void **)new_str, LTERM);
|
|
||||||
*new_str = gk_strdup("regexec ran out of memory.");
|
|
||||||
regfree(&re);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (rc == REG_NOMATCH) {
|
|
||||||
if (nlen-noffset < len-offset) {
|
|
||||||
nlen += (len-offset) - (nlen-noffset);
|
|
||||||
*new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str");
|
|
||||||
}
|
|
||||||
strcpy(*new_str+noffset, str+offset);
|
|
||||||
noffset += (len-offset);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else { /* A match was found! */
|
|
||||||
nmatches++;
|
|
||||||
|
|
||||||
/* Copy the left unmatched portion of the string */
|
|
||||||
if (matches[0].rm_so > 0) {
|
|
||||||
if (nlen-noffset < matches[0].rm_so) {
|
|
||||||
nlen += matches[0].rm_so - (nlen-noffset);
|
|
||||||
*new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str");
|
|
||||||
}
|
|
||||||
strncpy(*new_str+noffset, str+offset, matches[0].rm_so);
|
|
||||||
noffset += matches[0].rm_so;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Go and append the replacement string */
|
|
||||||
for (i=0; i<rlen; i++) {
|
|
||||||
switch (replacement[i]) {
|
|
||||||
case '\\':
|
|
||||||
if (i+1 < rlen) {
|
|
||||||
if (nlen-noffset < 1) {
|
|
||||||
nlen += nlen + 1;
|
|
||||||
*new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str");
|
|
||||||
}
|
|
||||||
*new_str[noffset++] = replacement[++i];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gk_free((void **)new_str, LTERM);
|
|
||||||
*new_str = gk_strdup("Error in replacement string. Missing character following '\'.");
|
|
||||||
regfree(&re);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '$':
|
|
||||||
if (i+1 < rlen) {
|
|
||||||
j = (int)(replacement[++i] - '0');
|
|
||||||
if (j < 0 || j > 9) {
|
|
||||||
gk_free((void **)new_str, LTERM);
|
|
||||||
*new_str = gk_strdup("Error in captured subexpression specification.");
|
|
||||||
regfree(&re);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nlen-noffset < matches[j].rm_eo-matches[j].rm_so) {
|
|
||||||
nlen += nlen + (matches[j].rm_eo-matches[j].rm_so);
|
|
||||||
*new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str");
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(*new_str+noffset, str+offset+matches[j].rm_so, matches[j].rm_eo);
|
|
||||||
noffset += matches[j].rm_eo-matches[j].rm_so;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gk_free((void **)new_str, LTERM);
|
|
||||||
*new_str = gk_strdup("Error in replacement string. Missing subexpression number folloing '$'.");
|
|
||||||
regfree(&re);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (nlen-noffset < 1) {
|
|
||||||
nlen += nlen + 1;
|
|
||||||
*new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str");
|
|
||||||
}
|
|
||||||
(*new_str)[noffset++] = replacement[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the offset of str for the next match */
|
|
||||||
offset += matches[0].rm_eo;
|
|
||||||
|
|
||||||
if (!global) {
|
|
||||||
/* Copy the right portion of the string if no 'g' option */
|
|
||||||
if (nlen-noffset < len-offset) {
|
|
||||||
nlen += (len-offset) - (nlen-noffset);
|
|
||||||
*new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str");
|
|
||||||
}
|
|
||||||
strcpy(*new_str+noffset, str+offset);
|
|
||||||
noffset += (len-offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (global);
|
|
||||||
|
|
||||||
(*new_str)[noffset] = '\0';
|
|
||||||
|
|
||||||
regfree(&re);
|
|
||||||
return nmatches + 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Prunes characters from the end of the string.
|
|
||||||
|
|
||||||
This function removes any trailing characters that are included in the
|
|
||||||
\c rmlist. The trimming stops at the last character (i.e., first character
|
|
||||||
from the end) that is not in \c rmlist.
|
|
||||||
This function can be used to removed trailing spaces, newlines, etc.
|
|
||||||
This is a distructive operation as it modifies the string.
|
|
||||||
|
|
||||||
\param str is the string that will be trimmed.
|
|
||||||
\param rmlist contains the set of characters that will be removed.
|
|
||||||
\returns A pointer to \c str itself.
|
|
||||||
\sa gk_strhprune()
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
char *gk_strtprune(char *str, char *rmlist)
|
|
||||||
{
|
|
||||||
gk_idx_t i, j;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = strlen(rmlist);
|
|
||||||
|
|
||||||
for (i=strlen(str)-1; i>=0; i--) {
|
|
||||||
for (j=0; j<len; j++) {
|
|
||||||
if (str[i] == rmlist[j])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (j == len)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
str[i+1] = '\0';
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Prunes characters from the beginning of the string.
|
|
||||||
|
|
||||||
This function removes any starting characters that are included in the
|
|
||||||
\c rmlist. The trimming stops at the first character that is not in
|
|
||||||
\c rmlist.
|
|
||||||
This function can be used to removed leading spaces, tabs, etc.
|
|
||||||
This is a distructive operation as it modifies the string.
|
|
||||||
|
|
||||||
\param str is the string that will be trimmed.
|
|
||||||
\param rmlist contains the set of characters that will be removed.
|
|
||||||
\returns A pointer to \c str itself.
|
|
||||||
\sa gk_strtprune()
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
char *gk_strhprune(char *str, char *rmlist)
|
|
||||||
{
|
|
||||||
gk_idx_t i, j;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = strlen(rmlist);
|
|
||||||
|
|
||||||
for (i=0; str[i]; i++) {
|
|
||||||
for (j=0; j<len; j++) {
|
|
||||||
if (str[i] == rmlist[j])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (j == len)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i>0) { /* If something needs to be removed */
|
|
||||||
for (j=0; str[i]; i++, j++)
|
|
||||||
str[j] = str[i];
|
|
||||||
str[j] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Converts a string to upper case.
|
|
||||||
|
|
||||||
This function converts a string to upper case. This operation modifies the
|
|
||||||
string itself.
|
|
||||||
|
|
||||||
\param str is the string whose case will be changed.
|
|
||||||
\returns A pointer to \c str itself.
|
|
||||||
\sa gk_strtolower()
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
char *gk_strtoupper(char *str)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; str[i]!='\0'; str[i]=toupper(str[i]), i++);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Converts a string to lower case.
|
|
||||||
|
|
||||||
This function converts a string to lower case. This operation modifies the
|
|
||||||
string itself.
|
|
||||||
|
|
||||||
\param str is the string whose case will be changed.
|
|
||||||
\returns A pointer to \c str itself.
|
|
||||||
\sa gk_strtoupper()
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
char *gk_strtolower(char *str)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; str[i]!='\0'; str[i]=tolower(str[i]), i++);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Duplicates a string
|
|
||||||
|
|
||||||
This function is a replacement for C's standard <em>strdup()</em> function.
|
|
||||||
The key differences between the two are that gk_strdup():
|
|
||||||
- uses the dynamic memory allocation routines of \e GKlib.
|
|
||||||
- it correctly handles NULL input strings.
|
|
||||||
|
|
||||||
The string that is returned must be freed by gk_free().
|
|
||||||
|
|
||||||
\param orgstr is the string that will be duplicated.
|
|
||||||
\returns A pointer to the newly created string.
|
|
||||||
\sa gk_free()
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
char *gk_strdup(char *orgstr)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
char *str=NULL;
|
|
||||||
|
|
||||||
if (orgstr != NULL) {
|
|
||||||
len = strlen(orgstr)+1;
|
|
||||||
str = gk_malloc(len*sizeof(char), "gk_strdup: str");
|
|
||||||
strcpy(str, orgstr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Case insensitive string comparison.
|
|
||||||
|
|
||||||
This function compares two strings for equality by ignoring the case of the
|
|
||||||
strings.
|
|
||||||
|
|
||||||
\warning This function is \b not equivalent to a case-insensitive
|
|
||||||
<em>strcmp()</em> function, as it does not return ordering
|
|
||||||
information.
|
|
||||||
|
|
||||||
\todo Remove the above warning.
|
|
||||||
|
|
||||||
\param s1 is the first string to be compared.
|
|
||||||
\param s2 is the second string to be compared.
|
|
||||||
\retval 1 if the strings are identical,
|
|
||||||
\retval 0 otherwise.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
int gk_strcasecmp(char *s1, char *s2)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
|
|
||||||
if (strlen(s1) != strlen(s2))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (s1[i] != '\0') {
|
|
||||||
if (tolower(s1[i]) != tolower(s2[i]))
|
|
||||||
return 0;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Converts a time_t time into a string
|
|
||||||
|
|
||||||
This function takes a time_t-specified time and returns a string-formated
|
|
||||||
representation of the corresponding time. The format of the string is
|
|
||||||
<em>mm/dd/yyyy hh:mm:ss</em>, in which the hours are in military time.
|
|
||||||
|
|
||||||
\param time is the time to be converted.
|
|
||||||
\return It returns a pointer to a statically allocated string that is
|
|
||||||
over-written in successive calls of this function. If the
|
|
||||||
conversion failed, it returns NULL.
|
|
||||||
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
char *gk_time2str(time_t time)
|
|
||||||
{
|
|
||||||
static char datestr[128];
|
|
||||||
struct tm *tm;
|
|
||||||
|
|
||||||
tm = localtime(&time);
|
|
||||||
|
|
||||||
if (strftime(datestr, 128, "%m/%d/%Y %H:%M:%S", tm) == 0)
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
return datestr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/*! \brief Converts a date/time string into its equivalent time_t value
|
|
||||||
|
|
||||||
This function takes date and/or time specification and converts it in
|
|
||||||
the equivalent time_t representation. The conversion is done using the
|
|
||||||
strptime() function. The format that gk_str2time() understands is
|
|
||||||
<em>mm/dd/yyyy hh:mm:ss</em>, in which the hours are in military time.
|
|
||||||
|
|
||||||
\param str is the date/time string to be converted.
|
|
||||||
\return If the conversion was successful it returns the time, otherwise
|
|
||||||
it returns -1.
|
|
||||||
*/
|
|
||||||
/*************************************************************************/
|
|
||||||
time_t gk_str2time(char *str)
|
|
||||||
{
|
|
||||||
struct tm time;
|
|
||||||
time_t rtime;
|
|
||||||
|
|
||||||
memset(&time, '\0', sizeof(time));
|
|
||||||
|
|
||||||
if (strptime(str, "%m/%d/%Y %H:%M:%S", &time) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
rtime = mktime(&time);
|
|
||||||
return (rtime < 0 ? 0 : rtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the ID of a particular string based on the
|
|
||||||
* supplied StringMap array
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_GetStringID(gk_StringMap_t *strmap, char *key)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; strmap[i].name; i++) {
|
|
||||||
if (gk_strcasecmp(key, strmap[i].name))
|
|
||||||
return strmap[i].id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
include Makefile.in
|
|
||||||
|
|
||||||
STRINGSOBJS = $(PRGBUILDDIR)/strings$(OBJEXT)
|
|
||||||
GKSORTOBJS = $(PRGBUILDDIR)/gksort$(OBJEXT)
|
|
||||||
|
|
||||||
HEADERS = $(wildcard $(GKLIBINCDIR)/*.h)
|
|
||||||
|
|
||||||
|
|
||||||
default: $(BUILDDIR)/strings$(EXEEXT) $(BUILDDIR)/gksort$(EXEEXT)
|
|
||||||
|
|
||||||
|
|
||||||
$(BUILDDIR)/strings$(EXEEXT): $(STRINGSOBJS) $(GKLIBBUILDDIR)/libGKlib.a
|
|
||||||
$(LD) $(LDOPTIONS) $(EXEOUTPUTFILE) $(STRINGSOBJS) $(LIBSDIR) $(LIBS) ; $(MERGEMANIFEST)
|
|
||||||
chmod 744 $@
|
|
||||||
|
|
||||||
$(BUILDDIR)/gksort$(EXEEXT): $(GKSORTOBJS) $(GKLIBBUILDDIR)/libGKlib.a
|
|
||||||
$(LD) $(LDOPTIONS) $(EXEOUTPUTFILE) $(GKSORTOBJS) $(LIBSDIR) $(LIBS) ; $(MERGEMANIFEST)
|
|
||||||
chmod 744 $@
|
|
||||||
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(PRGBUILDDIR)
|
|
||||||
|
|
||||||
realclean:
|
|
||||||
rm -rf $(PRGBUILDDIR) ;\
|
|
||||||
rm -rf $(BUILDDIR) ;
|
|
||||||
|
|
||||||
|
|
||||||
$(STRINGSOBJS) : $(HEADERS) Makefile.in Makefile $(GKLIBBUILDDIR)/libGKlib.a
|
|
||||||
|
|
||||||
|
|
||||||
$(PRGBUILDDIR)/%$(OBJEXT) : %.c
|
|
||||||
$(CC) $(CFLAGS) $(SOURCEFILE) $(OUTPUTFILE)
|
|
||||||
|
|
||||||
@ -1,258 +0,0 @@
|
|||||||
#*************************************************************************
|
|
||||||
# Global flags
|
|
||||||
#*************************************************************************
|
|
||||||
gdb = yes
|
|
||||||
debug = no
|
|
||||||
memdbg = no
|
|
||||||
openmp = no
|
|
||||||
x86compiler = gcc
|
|
||||||
|
|
||||||
VERNUM = 0.1.0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#*************************************************************************
|
|
||||||
# System-specific compilation flags
|
|
||||||
#*************************************************************************
|
|
||||||
# Get some basic information about the system that you are working on
|
|
||||||
cputype = $(shell uname -m | sed "s/\\ /_/g")
|
|
||||||
systype = $(shell uname)
|
|
||||||
ifeq ($(findstring CYGWIN, $(systype)),CYGWIN)
|
|
||||||
# systype = CYGWIN
|
|
||||||
systype = MSWIN
|
|
||||||
cputype = x86
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
GKLIBINCDIR = $(HOME)/work/algorithms/GKlib/trunk/
|
|
||||||
GKLIBBUILDDIR = $(HOME)/work/algorithms/GKlib/builds/$(systype)-$(cputype)
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(systype),MSWIN)
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
# These defs are very much Visual Studio Specific
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
#Compiler information
|
|
||||||
CC = cl
|
|
||||||
OPTFLAGS = /Ox
|
|
||||||
COPTIONS = -DWIN32 -DMSC -D_CRT_SECURE_NO_DEPRECATE
|
|
||||||
|
|
||||||
#Compile input/output file specification
|
|
||||||
SOURCEFILE = /c $<
|
|
||||||
OUTPUTFILE = /Fo$@
|
|
||||||
|
|
||||||
#Output specification for executables
|
|
||||||
EXEOUTPUTFILE = /Fe$@ # This option is when cl is used for linking
|
|
||||||
#EXEOUTPUTFILE = /OUT:$@ # This option is used when link is used for linking
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS = /MT
|
|
||||||
#LD = /cygdrive/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/VC/BIN/link
|
|
||||||
LD = cl
|
|
||||||
MERGEMANIFEST =
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = lib /OUT:$@
|
|
||||||
RANLIB =
|
|
||||||
|
|
||||||
ifeq ($(openmp),yes)
|
|
||||||
COPTIONS += -D__OPENMP__ /openmp
|
|
||||||
LDOPTIONS += /openmp
|
|
||||||
MERGEMANIFEST = vc_mt -manifest $@.manifest -outputresource:$@\;1
|
|
||||||
endif
|
|
||||||
|
|
||||||
#Library information
|
|
||||||
ifeq ($(cputype),i386)
|
|
||||||
LIBPLOTDIR = ../Libplot/Win32
|
|
||||||
else
|
|
||||||
LIBPLOTDIR = ../Libplot/Win64
|
|
||||||
endif
|
|
||||||
LIBS = $(LIBPLOTDIR)/libplot.lib $(BUILDDIR)/libcluto.lib $(GKLIBBUILDDIR)/libGKlib.lib
|
|
||||||
|
|
||||||
# Standard file extensions
|
|
||||||
OBJEXT = .obj
|
|
||||||
LIBEXT = .lib
|
|
||||||
EXEEXT = .exe
|
|
||||||
else
|
|
||||||
ifeq ($(systype),Linux)
|
|
||||||
ifeq ($(x86compiler),gcc)
|
|
||||||
#Compiler information
|
|
||||||
CC = gcc
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS = -DLINUX -D_FILE_OFFSET_BITS=64 -pedantic -std=c99 -pthread
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = gcc
|
|
||||||
|
|
||||||
MERGEMANIFEST =
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = ar rv
|
|
||||||
RANLIB = ar -ts
|
|
||||||
else
|
|
||||||
#Compiler information
|
|
||||||
CC = icc
|
|
||||||
OPTFLAGS = -O3
|
|
||||||
COPTIONS = -DLINUX -D_FILE_OFFSET_BITS=64 -std=c99
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = icc
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = ar rv
|
|
||||||
RANLIB = ar -ts
|
|
||||||
|
|
||||||
ifeq ($(openmp),yes)
|
|
||||||
COPTIONS += -D__OPENMP__ -openmp -openmp-report2
|
|
||||||
LDOPTIONS += -openmp
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
#Library information
|
|
||||||
ifeq ($(cputype),x86_64)
|
|
||||||
LIBPLOTDIR = ../Libplot/Linux64
|
|
||||||
else
|
|
||||||
LIBPLOTDIR = ../Libplot/Linux32
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(systype),SunOS)
|
|
||||||
#Compiler information
|
|
||||||
CC = /opt/SUNWspro/bin/cc
|
|
||||||
OPTFLAGS = -xO4
|
|
||||||
COPTIONS =-DSUNOS
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = /opt/SUNWspro/bin/cc
|
|
||||||
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = ar rv
|
|
||||||
RANLIB = ar -ts
|
|
||||||
|
|
||||||
#Library information
|
|
||||||
LIBPLOTDIR = ../Libplot/SunOS
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(systype),Darwin)
|
|
||||||
#Compiler information
|
|
||||||
CC = gcc
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS = -DDARWIN -D_FILE_OFFSET_BITS=64 -pedantic -std=c99
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS = -fvisibility=default
|
|
||||||
LD = gcc
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = ar rv
|
|
||||||
RANLIB = ar -ts
|
|
||||||
|
|
||||||
#Library information
|
|
||||||
ifeq ($(cputype),i386)
|
|
||||||
LIBPLOTDIR = ../Libplot/Darwini386
|
|
||||||
else
|
|
||||||
LIBPLOTDIR = ../Libplot/DarwinPPC
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(systype),CYGWIN)
|
|
||||||
#Compiler information
|
|
||||||
CC = gcc
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS = -DCYGWIN -DWIN32 -D_FILE_OFFSET_BITS=64 -Wall -std=c99 -pedantic -mno-cygwin
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS = -mno-cygwin
|
|
||||||
LD = gcc
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = ar crv
|
|
||||||
RANLIB = ar -ts
|
|
||||||
|
|
||||||
#Library information
|
|
||||||
LIBPLOTDIR = ../Libplot/CYGWIN
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
# These defs are common among the GNU/GCC based systems
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
#Compile input/output file specification
|
|
||||||
SOURCEFILE = -c $<
|
|
||||||
OUTPUTFILE = -o $@
|
|
||||||
|
|
||||||
#Output specification for executables
|
|
||||||
EXEOUTPUTFILE = -o $@
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = ar crv $@
|
|
||||||
RANLIB = ar -ts $@
|
|
||||||
|
|
||||||
#Libraries needed for linking
|
|
||||||
LIBSDIR = -L$(BUILDDIR) -L$(GKLIBBUILDDIR) -L$(HOME)/local/lib
|
|
||||||
LIBS = -lGKlib -lpcreposix -lpcre -lz -lm
|
|
||||||
|
|
||||||
# Standard file extensions
|
|
||||||
OBJEXT = .o
|
|
||||||
LIBEXT = .a
|
|
||||||
EXEEXT =
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
#**************************************************************************
|
|
||||||
DMALLOCINC =
|
|
||||||
DMALLOCFLAGS =
|
|
||||||
DEBUGFLAGS =
|
|
||||||
|
|
||||||
ifeq ($(dmalloc),yes)
|
|
||||||
DMALLOCINC = -I$(HOME)/local/include
|
|
||||||
DMALLOCFLAGS = -DDMALLOC
|
|
||||||
OPTFLAGS = -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(debug),yes)
|
|
||||||
DEBUGFLAGS = -DDEBUG
|
|
||||||
OPTFLAGS = -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(gdb),yes)
|
|
||||||
OPTFLAGS += -g
|
|
||||||
endif
|
|
||||||
#**************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#**************************************************************************
|
|
||||||
# Create the build directory if it does not exist
|
|
||||||
#**************************************************************************
|
|
||||||
ifeq ($(systype),Darwin)
|
|
||||||
BINDIR = $(HOME)
|
|
||||||
else
|
|
||||||
BINDIR = $(HOME)/work/bin/$(systype)-$(cputype)
|
|
||||||
$(shell mkdir -p $(BINDIR))
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(openmp),no)
|
|
||||||
BUILDDIR = ./builds/$(systype)-$(cputype)
|
|
||||||
else
|
|
||||||
BUILDDIR = ./builds/$(systype)-$(cputype)-openmp
|
|
||||||
endif
|
|
||||||
|
|
||||||
LIBBUILDDIR = $(BUILDDIR)/lib
|
|
||||||
PRGBUILDDIR = $(BUILDDIR)/prg
|
|
||||||
$(shell mkdir -p $(BUILDDIR))
|
|
||||||
$(shell mkdir -p $(LIBBUILDDIR))
|
|
||||||
$(shell mkdir -p $(PRGBUILDDIR))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INCLUDES = -I./ -I$(GKLIBINCDIR) -I$(LIBPLOTDIR) -I$(HOME)/local/include
|
|
||||||
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(DEBUGFLAGS) $(INCLUDES)
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,342 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file gksort.c
|
|
||||||
\brief Testing module for the various sorting routines in GKlib
|
|
||||||
|
|
||||||
\date Started 4/4/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: gksort.c 1421 2007-04-06 14:37:41Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
#define N 10000
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_?isort() routine */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_isort()
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
int array[N];
|
|
||||||
|
|
||||||
/* test the increasing sort */
|
|
||||||
printf("Testing iisort...\n");
|
|
||||||
for (i=0; i<N; i++)
|
|
||||||
array[i] = RandomInRange(123432);
|
|
||||||
|
|
||||||
gk_iisort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i] > array[i+1])
|
|
||||||
printf("gk_iisort error at index %jd [%d %d]\n", (intmax_t)i, array[i], array[i+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* test the decreasing sort */
|
|
||||||
printf("Testing disort...\n");
|
|
||||||
for (i=0; i<N; i++)
|
|
||||||
array[i] = RandomInRange(123432);
|
|
||||||
|
|
||||||
gk_disort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i] < array[i+1])
|
|
||||||
printf("gk_disort error at index %jd [%d %d]\n", (intmax_t)i, array[i], array[i+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_?fsort() routine */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_fsort()
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
float array[N];
|
|
||||||
|
|
||||||
/* test the increasing sort */
|
|
||||||
printf("Testing ifsort...\n");
|
|
||||||
for (i=0; i<N; i++)
|
|
||||||
array[i] = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
|
||||||
|
|
||||||
gk_ifsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i] > array[i+1])
|
|
||||||
printf("gk_ifsort error at index %jd [%f %f]\n", (intmax_t)i, array[i], array[i+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* test the decreasing sort */
|
|
||||||
printf("Testing dfsort...\n");
|
|
||||||
for (i=0; i<N; i++)
|
|
||||||
array[i] = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
|
||||||
|
|
||||||
gk_dfsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i] < array[i+1])
|
|
||||||
printf("gk_dfsort error at index %jd [%f %f]\n", (intmax_t)i, array[i], array[i+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_?idxsort() routine */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_idxsort()
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
gk_idx_t array[N];
|
|
||||||
|
|
||||||
/* test the increasing sort */
|
|
||||||
printf("Testing iidxsort...\n");
|
|
||||||
for (i=0; i<N; i++)
|
|
||||||
array[i] = RandomInRange(123432);
|
|
||||||
|
|
||||||
gk_iidxsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i] > array[i+1])
|
|
||||||
printf("gk_iidxsort error at index %jd [%jd %jd]\n", (intmax_t)i, array[i], array[i+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* test the decreasing sort */
|
|
||||||
printf("Testing didxsort...\n");
|
|
||||||
for (i=0; i<N; i++)
|
|
||||||
array[i] = RandomInRange(123432);
|
|
||||||
|
|
||||||
gk_didxsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i] < array[i+1])
|
|
||||||
printf("gk_didxsort error at index %jd [%jd %jd]\n", (intmax_t)i, array[i], array[i+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_?ikvsort() routine */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_ikvsort()
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
gk_ikv_t array[N];
|
|
||||||
|
|
||||||
/* test the increasing sort */
|
|
||||||
printf("Testing iikvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
array[i].key = RandomInRange(123432);
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_iikvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i].key > array[i+1].key)
|
|
||||||
printf("gk_iikvsort error at index %jd [%d %d] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* test the decreasing sort */
|
|
||||||
printf("Testing dikvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
array[i].key = RandomInRange(123432);
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_dikvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i].key < array[i+1].key)
|
|
||||||
printf("gk_dikvsort error at index %jd [%d %d] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_?fkvsort() routine */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_fkvsort()
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
gk_fkv_t array[N];
|
|
||||||
|
|
||||||
/* test the increasing sort */
|
|
||||||
printf("Testing ifkvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
array[i].key = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_ifkvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i].key > array[i+1].key)
|
|
||||||
printf("gk_ifkvsort error at index %jd [%f %f] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* test the decreasing sort */
|
|
||||||
printf("Testing dfkvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
array[i].key = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_dfkvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i].key < array[i+1].key)
|
|
||||||
printf("gk_dfkvsort error at index %jd [%f %f] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_?dkvsort() routine */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_dkvsort()
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
gk_dkv_t array[N];
|
|
||||||
|
|
||||||
/* test the increasing sort */
|
|
||||||
printf("Testing idkvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
array[i].key = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_idkvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i].key > array[i+1].key)
|
|
||||||
printf("gk_idkvsort error at index %jd [%lf %lf] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* test the decreasing sort */
|
|
||||||
printf("Testing ddkvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
array[i].key = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_ddkvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i].key < array[i+1].key)
|
|
||||||
printf("gk_ddkvsort error at index %jd [%lf %lf] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_?skvsort() routine */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_skvsort()
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
gk_skv_t array[N];
|
|
||||||
char line[256];
|
|
||||||
|
|
||||||
/* test the increasing sort */
|
|
||||||
printf("Testing iskvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
sprintf(line, "%d", RandomInRange(123432));
|
|
||||||
array[i].key = gk_strdup(line);
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_iskvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (strcmp(array[i].key, array[i+1].key) > 0)
|
|
||||||
printf("gk_idkvsort error at index %jd [%s %s] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* test the decreasing sort */
|
|
||||||
printf("Testing dskvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
sprintf(line, "%d", RandomInRange(123432));
|
|
||||||
array[i].key = gk_strdup(line);
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_dskvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
/*printf("%s\n", array[i].key);*/
|
|
||||||
if (strcmp(array[i].key, array[i+1].key) < 0)
|
|
||||||
printf("gk_ddkvsort error at index %jd [%s %s] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_?idxkvsort() routine */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_idxkvsort()
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
gk_idxkv_t array[N];
|
|
||||||
|
|
||||||
/* test the increasing sort */
|
|
||||||
printf("Testing iidxkvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
array[i].key = RandomInRange(123432);
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_iidxkvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i].key > array[i+1].key)
|
|
||||||
printf("gk_iidxkvsort error at index %jd [%jd %jd] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* test the decreasing sort */
|
|
||||||
printf("Testing didxkvsort...\n");
|
|
||||||
for (i=0; i<N; i++) {
|
|
||||||
array[i].key = RandomInRange(123432);
|
|
||||||
array[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_didxkvsort(N, array);
|
|
||||||
|
|
||||||
for (i=0; i<N-1; i++) {
|
|
||||||
if (array[i].key < array[i+1].key)
|
|
||||||
printf("gk_didxkvsort error at index %jd [%jd %jd] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
test_isort();
|
|
||||||
test_fsort();
|
|
||||||
test_idxsort();
|
|
||||||
|
|
||||||
test_ikvsort();
|
|
||||||
test_fkvsort();
|
|
||||||
test_dkvsort();
|
|
||||||
test_skvsort();
|
|
||||||
test_idxkvsort();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
/*!
|
|
||||||
\file strings.c
|
|
||||||
\brief Testing module for the string functions in GKlib
|
|
||||||
|
|
||||||
\date Started 3/5/2007
|
|
||||||
\author George
|
|
||||||
\version\verbatim $Id: strings.c 1413 2007-04-05 02:43:48Z karypis $ \endverbatim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*! Testing module for gk_strstr_replace() */
|
|
||||||
/*************************************************************************/
|
|
||||||
void test_strstr_replace()
|
|
||||||
{
|
|
||||||
char *new_str;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("This is a simple string", "s", "S", "", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("This is a simple string", "s", "S", "g", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("This is a simple SS & ss string", "s", "T", "g", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("This is a simple SS & ss string", "s", "T", "ig", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("This is a simple SS & ss string", "\\b\\w(\\w+)\\w\\b", "$1", "ig", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("This is a simple SS & ss string", "\\b\\w+\\b", "word", "ig", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4",
|
|
||||||
"(http://www\\.cs\\.umn\\.edu/)(.*)-T(\\d+)", "$1$2-P$3", "g", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4",
|
|
||||||
"(\\d+)", "number:$1", "ig", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
|
|
||||||
rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4",
|
|
||||||
"(http://www\\.cs\\.umn\\.edu/)", "[$1]", "g", &new_str);
|
|
||||||
printf("%d, %s.\n", rc, new_str);
|
|
||||||
gk_free((void **)&new_str, LTERM);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
test_strstr_replace();
|
|
||||||
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i=0; i<1000; i++)
|
|
||||||
printf("%d\n", RandomInRange(3));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* time.c
|
|
||||||
*
|
|
||||||
* This file contains various functions that do with time
|
|
||||||
*
|
|
||||||
* $Id: timers.c 934 2007-02-21 18:31:42Z karypis $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the CPU seconds
|
|
||||||
**************************************************************************/
|
|
||||||
gk_wclock_t gk_WClockSeconds(void)
|
|
||||||
{
|
|
||||||
return time(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the CPU seconds
|
|
||||||
**************************************************************************/
|
|
||||||
double gk_CPUSeconds(void)
|
|
||||||
{
|
|
||||||
#ifdef __OPENMP__
|
|
||||||
return omp_get_wtime();
|
|
||||||
#else
|
|
||||||
#ifdef WIN32
|
|
||||||
return((double) clock()/CLOCKS_PER_SEC);
|
|
||||||
#else
|
|
||||||
struct rusage r;
|
|
||||||
|
|
||||||
getrusage(RUSAGE_SELF, &r);
|
|
||||||
return ((r.ru_utime.tv_sec + r.ru_stime.tv_sec) + 1.0e-6*(r.ru_utime.tv_usec + r.ru_stime.tv_usec));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* tokenizer.c
|
|
||||||
*
|
|
||||||
* This file contains various routines for splitting an input string into
|
|
||||||
* tokens and returning them in form of a list. The goal is to mimic
|
|
||||||
* perl's split function
|
|
||||||
*
|
|
||||||
* Started 11/23/04
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: tokenizer.c 1414 2007-04-05 02:52:46Z karypis $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* This function tokenizes a string based on the user-supplied delimiters
|
|
||||||
* list. The resulting tokens are returned into an array of strings.
|
|
||||||
*************************************************************************/
|
|
||||||
void gk_strtokenize(char *str, char *delim, gk_Tokens_t *tokens)
|
|
||||||
{
|
|
||||||
int i, ntoks, slen;
|
|
||||||
|
|
||||||
tokens->strbuf = gk_strdup(str);
|
|
||||||
|
|
||||||
slen = strlen(str);
|
|
||||||
str = tokens->strbuf;
|
|
||||||
|
|
||||||
/* Scan once to determine the number of tokens */
|
|
||||||
for (ntoks=0, i=0; i<slen;) {
|
|
||||||
/* Consume all the consecutive characters from the delimiters list */
|
|
||||||
while (i<slen && strchr(delim, str[i]))
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i == slen)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ntoks++;
|
|
||||||
|
|
||||||
/* Consume all the consecutive characters from the token */
|
|
||||||
while (i<slen && !strchr(delim, str[i]))
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tokens->ntoks = ntoks;
|
|
||||||
tokens->list = (char **)gk_malloc(ntoks*sizeof(char *), "strtokenize: tokens->list");
|
|
||||||
|
|
||||||
|
|
||||||
/* Scan a second time to mark and link the tokens */
|
|
||||||
for (ntoks=0, i=0; i<slen;) {
|
|
||||||
/* Consume all the consecutive characters from the delimiters list */
|
|
||||||
while (i<slen && strchr(delim, str[i]))
|
|
||||||
str[i++] = '\0';
|
|
||||||
|
|
||||||
if (i == slen)
|
|
||||||
break;
|
|
||||||
|
|
||||||
tokens->list[ntoks++] = str+i;
|
|
||||||
|
|
||||||
/* Consume all the consecutive characters from the token */
|
|
||||||
while (i<slen && !strchr(delim, str[i]))
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* This function frees the memory associated with a gk_Tokens_t
|
|
||||||
*************************************************************************/
|
|
||||||
void gk_freetokenslist(gk_Tokens_t *tokens)
|
|
||||||
{
|
|
||||||
gk_free((void *)&tokens->list, &tokens->strbuf, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* util.c
|
|
||||||
*
|
|
||||||
* This file contains utility functions
|
|
||||||
*
|
|
||||||
* $Id: util.c 1421 2007-04-06 14:37:41Z karypis $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <GKlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This file randomly permutes the contents of an array.
|
|
||||||
* flag == 0, don't initialize perm
|
|
||||||
* flag == 1, set p[i] = i
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_RandomPermute(size_t n, int *p, int flag)
|
|
||||||
{
|
|
||||||
gk_idx_t i, u, v;
|
|
||||||
int tmp;
|
|
||||||
|
|
||||||
if (flag == 1) {
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
p[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<n/2; i++) {
|
|
||||||
v = RandomInRange(n);
|
|
||||||
u = RandomInRange(n);
|
|
||||||
SWAP(p[v], p[u], tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function converts an element-based set membership to a set-based
|
|
||||||
* element membership.
|
|
||||||
* That is, it takes an array such as part[] that stores where each element
|
|
||||||
* belongs to, and returns a pair of arrays (pptr[], pind[]) that store in
|
|
||||||
* CSF format the list of elements belonging in each partition.
|
|
||||||
* Parameters:
|
|
||||||
* n - the number of elements in the array (e.g., # of vertices)
|
|
||||||
* range - the cardinality of the set (e.g., # of partitions)
|
|
||||||
**************************************************************************/
|
|
||||||
void gk_array2csr(size_t n, size_t range, int *array, int *ptr, int *ind)
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
|
|
||||||
gk_iset(range+1, 0, ptr);
|
|
||||||
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
ptr[array[i]]++;
|
|
||||||
|
|
||||||
/* Compute the ptr, ind structure */
|
|
||||||
MAKECSR(i, range, ptr);
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
ind[ptr[array[i]]++] = i;
|
|
||||||
SHIFTCSR(i, range, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the log2(x)
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_log2(int a)
|
|
||||||
{
|
|
||||||
gk_idx_t i;
|
|
||||||
|
|
||||||
for (i=1; a > 1; i++, a = a>>1);
|
|
||||||
return i-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks if the argument is a power of 2
|
|
||||||
**************************************************************************/
|
|
||||||
int gk_ispow2(int a)
|
|
||||||
{
|
|
||||||
return (a == (1<<gk_log2(a)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the log2(x)
|
|
||||||
**************************************************************************/
|
|
||||||
float gk_flog2(float a)
|
|
||||||
{
|
|
||||||
return log(a)/log(2.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
|
|
||||||
Copyright 1998, Regents of the University of Minnesota.
|
|
||||||
METIS was written by George Karypis (karypis@cs.umn.edu)
|
|
||||||
|
|
||||||
Introduction ------------------------------------------------------------
|
|
||||||
|
|
||||||
METIS is a software package for partitioning unstructured graphs, partitioning
|
|
||||||
meshes, and computing fill-reducing orderings of sparse matrices.
|
|
||||||
The documentation of METIS can be found in the Doc/manual.ps file.
|
|
||||||
|
|
||||||
METIS is written in ANSI C and should compile on Unix systems that have
|
|
||||||
a ANSI C compiler. It has been extensively tested on the following
|
|
||||||
architectures:
|
|
||||||
|
|
||||||
AIX
|
|
||||||
SunOS
|
|
||||||
Solaris
|
|
||||||
IRIX
|
|
||||||
Unicos
|
|
||||||
Linux
|
|
||||||
HP-UX
|
|
||||||
FreeBSD
|
|
||||||
|
|
||||||
|
|
||||||
Installation Instructions -----------------------------------------------
|
|
||||||
|
|
||||||
In order to build METIS you need
|
|
||||||
(a) a C compiler that is ANSI compatible
|
|
||||||
(b) make
|
|
||||||
|
|
||||||
Edit the file Makefile.in that resides in the same directory as this file
|
|
||||||
according to the requirements of your system. In particular you may need
|
|
||||||
to modify the following:
|
|
||||||
1. The CC variable, to be the name of the ANSI C compiler
|
|
||||||
in your system. The GNU C compiler (gcc) will do.
|
|
||||||
2. The settings for the AR and RANLIB variables that are suitable for
|
|
||||||
you system. Note that some systems do not have 'ranlib' but they use
|
|
||||||
'ar -ts' instead, or it is not needed all together.
|
|
||||||
3. You can use COPTIONS and LDOPTIONS to provide additional command line
|
|
||||||
options that are required by your compiler and linker.
|
|
||||||
|
|
||||||
|
|
||||||
After saving the modified Makefile.in, type 'make' at the prompt. This will
|
|
||||||
build all of METIS's stand-alone programs, METIS's library, and a program that
|
|
||||||
tests the various partitioning algorithms.
|
|
||||||
Upon successful completion, make creates the following 11 files:
|
|
||||||
|
|
||||||
pmetis,
|
|
||||||
kmetis,
|
|
||||||
oemetis,
|
|
||||||
onmetis,
|
|
||||||
partnmesh,
|
|
||||||
partdmesh,
|
|
||||||
mesh2nodal,
|
|
||||||
mesh2dual,
|
|
||||||
graphchk,
|
|
||||||
libmetis.a
|
|
||||||
Graphs/mtest
|
|
||||||
|
|
||||||
Please read the instructions in the file Graphs/0README on how to go and
|
|
||||||
test the various programs.
|
|
||||||
|
|
||||||
|
|
||||||
Contact Information -----------------------------------------------------
|
|
||||||
|
|
||||||
If you have any comments, suggestions, or bug reports, please send them
|
|
||||||
to metis@cs.umn.edu.
|
|
||||||
|
|
||||||
Any bug fixes and upgrades of the METIS packages is available on WWW at
|
|
||||||
URL: http://www.cs.umn.edu/~metis
|
|
||||||
or
|
|
||||||
URL: http://www.cs.umn.edu/~karypis/metis
|
|
||||||
|
|
||||||
|
|
||||||
George Karypis
|
|
||||||
Sun Sep 20 13:18:36 CDT 1998
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
|
|
||||||
These are some preliminary instructions for the 5.0 release of METIS.
|
|
||||||
|
|
||||||
1. You need to have a C compiler that supports the C99 standard.
|
|
||||||
Gcc works just fine, but I have not tested it on many other architectures
|
|
||||||
(any feedback/patches for different architectures are welcomed)
|
|
||||||
|
|
||||||
|
|
||||||
2. Edit the file include/metis.h and specify the width (32 or 64 bits) of the
|
|
||||||
elementary data type used in METIS. This is controled by the IDXTYPEWIDTH
|
|
||||||
constant.
|
|
||||||
|
|
||||||
For now, on a 32 bit architecture you can only specify a width of 32,
|
|
||||||
whereas for a 64 bit architecture you can specify a width of either
|
|
||||||
32 or 64 bits.
|
|
||||||
|
|
||||||
|
|
||||||
3. At the top of METIS's directory execute the following:
|
|
||||||
|
|
||||||
'make all'
|
|
||||||
|
|
||||||
On successful compilation, it will put the library and executables in
|
|
||||||
the ./build/ARCH/ directory where ARCH will depend on the architecture
|
|
||||||
where you are building it.
|
|
||||||
|
|
||||||
If you just type 'make' you will see some help instructions on how
|
|
||||||
to specify some additional options.
|
|
||||||
|
|
||||||
*** You will notice some warnings while it is building some of the
|
|
||||||
files in GKlib. You can ignore them for now.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
Copyright Notice
|
|
||||||
----------------
|
|
||||||
|
|
||||||
The METIS package is copyrighted by the Regents of the University of
|
|
||||||
Minnesota. It can be freely used for educational and research purposes
|
|
||||||
by non-profit institutions and US government agencies only. Other
|
|
||||||
organizations are allowed to use METIS only for evaluation purposes,
|
|
||||||
and any further uses will require prior approval. The software
|
|
||||||
may not be sold or redistributed without prior approval. One may
|
|
||||||
make copies of the software for their use provided that the copies,
|
|
||||||
are not sold or distributed, are used under the same terms and
|
|
||||||
conditions.
|
|
||||||
|
|
||||||
As unestablished research software, this code is provided on an
|
|
||||||
``as is'' basis without warranty of any kind, either expressed or
|
|
||||||
implied. The downloading, or executing any part of this software
|
|
||||||
constitutes an implicit agreement to these terms. These terms and
|
|
||||||
conditions are subject to change at any time without prior notice.
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
|
|
||||||
default:
|
|
||||||
more Makefile.help
|
|
||||||
|
|
||||||
all:
|
|
||||||
$(MAKE) -C GKlib/trunk
|
|
||||||
$(MAKE) -C libmetis
|
|
||||||
$(MAKE) -C programs
|
|
||||||
$(MAKE) -C test
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(MAKE) -C GKlib/trunk clean
|
|
||||||
$(MAKE) -C libmetis clean
|
|
||||||
$(MAKE) -C programs clean
|
|
||||||
$(MAKE) -C test clean
|
|
||||||
|
|
||||||
realclean:
|
|
||||||
$(MAKE) -C GKlib/trunk realclean
|
|
||||||
$(MAKE) -C libmetis realclean
|
|
||||||
$(MAKE) -C programs realclean
|
|
||||||
$(MAKE) -C test realclean
|
|
||||||
|
|
||||||
dist:
|
|
||||||
$(MAKE) -C dist dist
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
-------------------------------------------------------------------------------
|
|
||||||
This is the Makefile for building METIS's library and stand-alone programs.
|
|
||||||
|
|
||||||
***Important***
|
|
||||||
METIS's Makefiles need to be processed using GNU's make, which is the default
|
|
||||||
make system on Linux systems, and on other systems is sometimes called 'gmake'.
|
|
||||||
|
|
||||||
The Makefile understands the following targets:
|
|
||||||
make all
|
|
||||||
Builds the library and all the stand-alone programs. The library and
|
|
||||||
programs are placed in the build/<systype> directory where <systype> is
|
|
||||||
the name of the system on which your are building METIS.
|
|
||||||
|
|
||||||
***Important***
|
|
||||||
Make sure that you look at include/metis.h and change any of the
|
|
||||||
parameters based on your target system and desired built.
|
|
||||||
|
|
||||||
make clean
|
|
||||||
Removes all object files that were generated as part of the build process
|
|
||||||
but it will leave the built libraries and stand-alone programs intact.
|
|
||||||
|
|
||||||
make realclean
|
|
||||||
Removes both object files as well as libraries and stand-alone programs.
|
|
||||||
|
|
||||||
|
|
||||||
The build system detects Linux, cygwin, SunOS, & Darwin systems. In the case
|
|
||||||
of cygwin, it actually builds a MS Windows set of libraries and executables
|
|
||||||
using Visual Studio 2005, using the command-line interface to the VC++ compiler
|
|
||||||
(make sure that 'cl' is on the path).
|
|
||||||
|
|
||||||
On any other system, the Makefiles default to using the cc compiler. If you
|
|
||||||
want to build METIS using another compiler you can do that by setting the 'CC'
|
|
||||||
variable on the command line. For example, 'make "CC=icc" all' will build
|
|
||||||
METIS using the icc (intel's) compiler.
|
|
||||||
|
|
||||||
In addition to 'CC' you can also set the following variables that are used by
|
|
||||||
the build system:
|
|
||||||
OPTFLAGS Specifies optimization parameters (e.g., -O3)
|
|
||||||
CFLAGS Specifies compiler-specific arguments. If you decide to specify
|
|
||||||
this, make sure that you also provide -DUNIX as one of the
|
|
||||||
options (e.g., "CFLAGS=-DUNIX -Wall").
|
|
||||||
LD Specifies the linker. Defaults to CC.
|
|
||||||
LDOPTIONS Specifies any options to be passed to the linker.
|
|
||||||
|
|
||||||
Finally, the Makefiles understand the following variables, which are used for
|
|
||||||
now only for development purposes:
|
|
||||||
useopenmp=1 Specifies if OpenMP will be used.
|
|
||||||
usegdb=1 Specifies that everything will be build with -g option.
|
|
||||||
withdebug=1 Turns on internal error and assertion checking.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
@ -1,196 +0,0 @@
|
|||||||
SHELL = /bin/sh
|
|
||||||
usegdb=1
|
|
||||||
|
|
||||||
#*************************************************************************
|
|
||||||
# System-specific compilation flags
|
|
||||||
#*************************************************************************
|
|
||||||
# Get some basic information about the system that you are working on
|
|
||||||
cputype = $(shell uname -m | sed "s/\\ /_/g")
|
|
||||||
systype = $(shell uname -s)
|
|
||||||
ifeq ($(findstring CYGWIN, $(systype)),CYGWIN)
|
|
||||||
# systype = CYGWIN
|
|
||||||
systype = MSWIN
|
|
||||||
cputype = x86
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(systype),MSWIN)
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
# Visual Studio 2005 specific definitions
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
#Compiler information
|
|
||||||
CC = cl
|
|
||||||
OPTFLAGS = /Ox
|
|
||||||
COPTIONS = -DWIN32 -DMSC -D_CRT_SECURE_NO_DEPRECATE
|
|
||||||
|
|
||||||
#Compile input/output file specification
|
|
||||||
SOURCEFILE = /c $<
|
|
||||||
OUTPUTFILE = /Fo$@
|
|
||||||
|
|
||||||
#Output specification for executables
|
|
||||||
EXEOUTPUTFILE = /Fe$@ # This option is when cl is used for linking
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS = /MT
|
|
||||||
LD = $(CC)
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = lib /OUT:$@
|
|
||||||
RANLIB =
|
|
||||||
|
|
||||||
ifeq ($(openmp),yes)
|
|
||||||
COPTIONS += -D__OPENMP__ /openmp
|
|
||||||
LDOPTIONS += /openmp
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Standard file extensions
|
|
||||||
OBJEXT = .obj
|
|
||||||
LIBEXT = .lib
|
|
||||||
EXEEXT = .exe
|
|
||||||
else
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
# These defs are common for Unix based systems
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
#Compiler information
|
|
||||||
CC = cc
|
|
||||||
OPTFLAGS = -O3
|
|
||||||
COPTIONS = -DUNIX -pedantic -std=c99
|
|
||||||
|
|
||||||
#Linker information
|
|
||||||
LDOPTIONS =
|
|
||||||
LD = $(CC)
|
|
||||||
|
|
||||||
#Library creation information
|
|
||||||
AR = ar crv $@
|
|
||||||
RANLIB = ar -ts $@
|
|
||||||
RANLIB = ranlib $@
|
|
||||||
|
|
||||||
#Compile input/output file specification
|
|
||||||
SOURCEFILE = -c $<
|
|
||||||
OUTPUTFILE = -o $@
|
|
||||||
|
|
||||||
#Output specification for executables
|
|
||||||
EXEOUTPUTFILE = -o $@
|
|
||||||
|
|
||||||
# Standard file extensions
|
|
||||||
OBJEXT = .o
|
|
||||||
LIBEXT = .a
|
|
||||||
EXEEXT =
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
# Overide any of the common definitions based on the system
|
|
||||||
#-------------------------------------------------------------------
|
|
||||||
ifeq ($(systype),Linux)
|
|
||||||
ifeq ($(CC),icc)
|
|
||||||
#Compiler information
|
|
||||||
OPTFLAGS = -O3
|
|
||||||
COPTIONS = -DLINUX -DUNIX -std=c99
|
|
||||||
else
|
|
||||||
#Compiler information
|
|
||||||
CC = gcc
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS += -DLINUX -D_FILE_OFFSET_BITS=64
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(systype),SunOS)
|
|
||||||
#Compiler information
|
|
||||||
OPTFLAGS = -xO4
|
|
||||||
COPTIONS =-DSUNOS
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(systype),Darwin)
|
|
||||||
#Compiler information
|
|
||||||
CC = gcc
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS += -DDARWINPPC
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(systype),CYGWIN)
|
|
||||||
#Compiler information
|
|
||||||
OPTFLAGS = -O6
|
|
||||||
COPTIONS += -DCYGWIN
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#**************************************************************************
|
|
||||||
# Deal with the build-specific options (if specified)
|
|
||||||
#**************************************************************************
|
|
||||||
ifdef usegdb
|
|
||||||
OPTFLAGS += -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef ($(withdebug))
|
|
||||||
OPTFLAGS += -g
|
|
||||||
COPTIONS += -DDEBUG
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
ifdef ($(useopenmp))
|
|
||||||
ifeq ($(systype),MSWIN)
|
|
||||||
COPTIONS += -D__OPENMP__ /openmp
|
|
||||||
LDOPTIONS += /openmp
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(systype),Linux)
|
|
||||||
ifeq ($(CC),icc)
|
|
||||||
COPTIONS += -D__OPENMP__ -openmp -openmp-report2
|
|
||||||
LDOPTIONS += -openmp
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#**************************************************************************
|
|
||||||
# Setup the project-specific parameters of the build. This part of the
|
|
||||||
# Makefile.in is different for different project.
|
|
||||||
#**************************************************************************
|
|
||||||
# Version of the build/source
|
|
||||||
VERNUM = 5.0pre2
|
|
||||||
PKGNAME = metis-$(VERNUM)
|
|
||||||
|
|
||||||
# Create the build directory if it does not exist
|
|
||||||
ifeq ($(systype),Darwin)
|
|
||||||
BINDIR = $(HOME)
|
|
||||||
else
|
|
||||||
BINDIR = $(HOME)/work/bin/$(systype)-$(cputype)
|
|
||||||
$(shell mkdir -p $(BINDIR))
|
|
||||||
endif
|
|
||||||
BINDIR=
|
|
||||||
|
|
||||||
TOPDIR = ..
|
|
||||||
|
|
||||||
BUILDDIR = $(TOPDIR)/build/$(systype)-$(cputype)
|
|
||||||
LIBBUILDDIR = $(BUILDDIR)/libmetis
|
|
||||||
PRGBUILDDIR = $(BUILDDIR)/programs
|
|
||||||
TSTBUILDDIR = $(BUILDDIR)/test
|
|
||||||
|
|
||||||
GKLIBDIR = $(TOPDIR)/GKlib
|
|
||||||
GKLIBINCDIR = $(GKLIBDIR)/trunk
|
|
||||||
GKLIBBUILDDIR = $(GKLIBDIR)/builds/$(systype)-$(cputype)
|
|
||||||
|
|
||||||
$(shell mkdir -p $(BUILDDIR))
|
|
||||||
$(shell mkdir -p $(LIBBUILDDIR))
|
|
||||||
$(shell mkdir -p $(PRGBUILDDIR))
|
|
||||||
$(shell mkdir -p $(TSTBUILDDIR))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INCLUDES = -I./ -I$(TOPDIR)/include -I$(GKLIBINCDIR) #-I$(TOPDIR)/config
|
|
||||||
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(INCLUDES)
|
|
||||||
|
|
||||||
|
|
||||||
#Libraries needed for linking
|
|
||||||
ifeq ($(systype),MSWIN)
|
|
||||||
#Library information
|
|
||||||
LIBS = $(BUILDDIR)/libmetis.lib
|
|
||||||
else
|
|
||||||
LIBSDIR = -L$(BUILDDIR)
|
|
||||||
LIBS = -lmetis -lm
|
|
||||||
endif
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,84 +0,0 @@
|
|||||||
|
|
||||||
#ifndef CONFIG_H
|
|
||||||
#define CONFIG_H 1
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* A set of defines that can be modified by the user
|
|
||||||
*****************************************************************************/
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
Specifies the width of the elementary data type that will hold information
|
|
||||||
about vertices and their adjacency lists.
|
|
||||||
|
|
||||||
Possible values:
|
|
||||||
32 : Use 32 bit signed integers
|
|
||||||
64 : Use 64 bit signed integers
|
|
||||||
|
|
||||||
A width of 64 should be specified if the number of vertices or the total
|
|
||||||
number of edges in the graph exceed the limits of a 32 bit signed integer
|
|
||||||
i.e., 2^31-1.
|
|
||||||
Proper use of 64 bit integers requires that the c99 standard datatypes
|
|
||||||
int32_t and int64_t are supported by the compiler.
|
|
||||||
GCC does provides these definitions in stdint.h, but it may require some
|
|
||||||
modifications on other architectures.
|
|
||||||
--------------------------------------------------------------------------*/
|
|
||||||
#define IDXTYPEWIDTH 32
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
Specifies if the __thread storage directive is available by the compiler
|
|
||||||
to indicate thread local storage. This storage directive is available in
|
|
||||||
most systems using gcc compiler but it may not be available in other
|
|
||||||
systems.
|
|
||||||
|
|
||||||
Possible values:
|
|
||||||
0 : Not available and do not use thread local storage
|
|
||||||
1 : It is available and the __thread modifier will be used
|
|
||||||
--------------------------------------------------------------------------*/
|
|
||||||
#define HAVE_THREADLOCALSTORAGE 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Do not change anything bellow this point
|
|
||||||
*****************************************************************************/
|
|
||||||
/* Uniform defines for various compilers */
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define COMPILER_MSC
|
|
||||||
#endif
|
|
||||||
#if defined(__ICC)
|
|
||||||
#define COMPILER_ICC
|
|
||||||
#endif
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
#define COMPILER_GCC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(COMPILER_GCC)
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(COMPILER_MSC)
|
|
||||||
#include <ctrdefs.h>
|
|
||||||
#define __thread __declspec( thread )
|
|
||||||
|
|
||||||
typedef __int32 int32_t;
|
|
||||||
typedef __int64 int64_t;
|
|
||||||
typedef unsigned __int32 uint32_t;
|
|
||||||
typedef unsigned __int64 uint64_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(UNIX)
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENABLE_OPENMP)
|
|
||||||
#include <omp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* CONFIG_H */
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,84 +0,0 @@
|
|||||||
|
|
||||||
This file contains some test graphs and meshes
|
|
||||||
|
|
||||||
4elt.graph
|
|
||||||
copter2.graph
|
|
||||||
mdual.graph
|
|
||||||
These are small to medium size graphs corresponding to 2D and 3D
|
|
||||||
finite element mesh
|
|
||||||
|
|
||||||
test.mgraph
|
|
||||||
This is a very small graph with two vertex weights (multi-constraint)
|
|
||||||
|
|
||||||
metis.mesh
|
|
||||||
This is a small 2D mesh (It is a triangulation of 'METIS')
|
|
||||||
|
|
||||||
|
|
||||||
You can use them to test the various partitioning, and ordering routines.
|
|
||||||
For example try something like
|
|
||||||
|
|
||||||
../build/ARCH/kmetis 4elt.graph 40
|
|
||||||
../build/ARCH/onmetis 4elt.graph
|
|
||||||
../build/ARCH/pmetis test.mgraph 2
|
|
||||||
../build/ARCH/kmetis test.mgraph 2
|
|
||||||
../build/ARCH/kmetis test.mgraph 5
|
|
||||||
../build/ARCH/partnmesh metis.mesh 10
|
|
||||||
../build/ARCH/partdmesh metis.mesh 10
|
|
||||||
../build/ARCH/mesh2dual metis.mesh
|
|
||||||
../build/ARCH/kmetis metis.mesh.dgraph 10
|
|
||||||
|
|
||||||
and so on...
|
|
||||||
|
|
||||||
|
|
||||||
You can also use the 'mtest' program that tests the various partitioning
|
|
||||||
routines. Here is how the correct output of 'mtest 4elt.graph' should
|
|
||||||
look like.
|
|
||||||
|
|
||||||
prompt%: mtest 4elt.graph
|
|
||||||
**********************************************************************
|
|
||||||
METIS 4.0 Copyright 1998, Regents of the University of Minnesota
|
|
||||||
|
|
||||||
Graph Information ---------------------------------------------------
|
|
||||||
Name: 4elt.graph, #Vertices: 15606, #Edges: 45878
|
|
||||||
|
|
||||||
Testing METIS_PartGraphRecursive ------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok]
|
|
||||||
|
|
||||||
Testing METIS_WPartGraphRecursive -----------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok]
|
|
||||||
|
|
||||||
Testing METIS_PartGraphKway -----------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok][7:ok][8:ok]
|
|
||||||
|
|
||||||
Testing METIS_WPartGraphKway ----------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok][7:ok][8:ok]
|
|
||||||
|
|
||||||
Testing METIS_PartGraphVKway ----------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok][7:ok]
|
|
||||||
|
|
||||||
Testing METIS_WPartGraphVKway ---------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok][7:ok]
|
|
||||||
|
|
||||||
Testing METIS_mCPartGraphRecursive ----------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok][7:ok][8:ok][9:ok][10:ok]
|
|
||||||
[11:ok][12:ok]
|
|
||||||
|
|
||||||
Testing METIS_mCPartGraphKway ---------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok][7:ok][8:ok][9:ok][10:ok]
|
|
||||||
[11:ok][12:ok][13:ok][14:ok]
|
|
||||||
|
|
||||||
Testing METIS_EdgeND ------------------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok]
|
|
||||||
|
|
||||||
Testing METIS_NodeND ------------------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok][7:ok][8:ok][9:ok][10:ok]
|
|
||||||
[11:ok][12:ok][13:ok]
|
|
||||||
|
|
||||||
Testing METIS_NodeWND -----------------------------------------------
|
|
||||||
[1:ok][2:ok][3:ok][4:ok][5:ok][6:ok]
|
|
||||||
|
|
||||||
---------------------------------------------------------------------
|
|
||||||
Testing completed.
|
|
||||||
**********************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,770 +0,0 @@
|
|||||||
%% graph file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
%% 1st line: n, m
|
|
||||||
%% ff lines: vwgt1, vwgt2, adjacencies
|
|
||||||
766 1314 10 2
|
|
||||||
1 1 479 389 571 2
|
|
||||||
2 2 395 1 534 4
|
|
||||||
4 4 148 207 409 498
|
|
||||||
4 4 2 729 6 695
|
|
||||||
4 4 572 6 708 393
|
|
||||||
2 2 571 727 4 5
|
|
||||||
2 2 746 397 575 573
|
|
||||||
24 8 152 733 638 746
|
|
||||||
1 1 573 524 11 13
|
|
||||||
1 1 11 497 532 14
|
|
||||||
2 2 12 531 10 9
|
|
||||||
4 4 754 490 616 11
|
|
||||||
1 1 9 706 403 14
|
|
||||||
1 1 13 10 18 15
|
|
||||||
1 1 14 402 530 20
|
|
||||||
24 8 742 692 17 581
|
|
||||||
4 4 16 109 116 620
|
|
||||||
1 1 14 512 535 20
|
|
||||||
1 1 20 404 408 24
|
|
||||||
1 1 18 15 19 22
|
|
||||||
38 8 645 628 148 536
|
|
||||||
1 1 20 527 421 24
|
|
||||||
24 8 179 28 629 30
|
|
||||||
1 1 19 22 513 27
|
|
||||||
24 8 742 159 174 28
|
|
||||||
0 0 411 440 539 442
|
|
||||||
1 1 24 411 410 538
|
|
||||||
24 8 25 254 23 29
|
|
||||||
4 4 174 28 750 30
|
|
||||||
4 4 596 23 29 745
|
|
||||||
52 8 645 192 581 525
|
|
||||||
1 1 51 332 406
|
|
||||||
1 1 577 330 51
|
|
||||||
1 1 418 682 423
|
|
||||||
68 8 711 36 606
|
|
||||||
68 8 626 35 153
|
|
||||||
0 0 52 333 420
|
|
||||||
2 2 422 358 419
|
|
||||||
1 1 58 345 578
|
|
||||||
1 1 59 348 58
|
|
||||||
68 8 208 144 734
|
|
||||||
68 8 143 483 484
|
|
||||||
1 1 64 349 425
|
|
||||||
2 2 66 334 426
|
|
||||||
68 8 579 141 427
|
|
||||||
0 0 420 50 339
|
|
||||||
68 8 764 48 564
|
|
||||||
68 8 587 47 443
|
|
||||||
2 2 62 673 687
|
|
||||||
0 0 578 46 565
|
|
||||||
1 1 33 584 32
|
|
||||||
0 0 406 429 37
|
|
||||||
68 8 485 335 731
|
|
||||||
68 8 758 55 519
|
|
||||||
68 8 586 54 183
|
|
||||||
1 1 426 64 577
|
|
||||||
0 0 552 630
|
|
||||||
1 1 40 429 39
|
|
||||||
1 1 425 584 40
|
|
||||||
0 0 462
|
|
||||||
68 8 308 162 647
|
|
||||||
4 4 690 431 49
|
|
||||||
68 8 161 672 305
|
|
||||||
1 1 687 56 43
|
|
||||||
68 8 588 168 253
|
|
||||||
4 4 368 431 44
|
|
||||||
68 8 560 68 709
|
|
||||||
68 8 500 67 196
|
|
||||||
68 8 566 170 433
|
|
||||||
68 8 724 163 366
|
|
||||||
1 1 113 97
|
|
||||||
1 1 177 79
|
|
||||||
1 1 601 142
|
|
||||||
24 8 92 738 739
|
|
||||||
24 8 454 644 595
|
|
||||||
1 1 545 146 502
|
|
||||||
1 1 591 351 435
|
|
||||||
1 1 344 436 437
|
|
||||||
1 1 146 72 487 434
|
|
||||||
1 1 103 354 439
|
|
||||||
2 2 437 463 115
|
|
||||||
1 1 601 304
|
|
||||||
2 2 109 174 592
|
|
||||||
0 0 110 355 440
|
|
||||||
1 1 112 353 441
|
|
||||||
0 0 440 442 593
|
|
||||||
0 0 263
|
|
||||||
1 1 444 381 111
|
|
||||||
0 0 91 442 357
|
|
||||||
8 8 594 740 732
|
|
||||||
0 0 445 446 89
|
|
||||||
24 8 595 447 74
|
|
||||||
8 8 763 741 744
|
|
||||||
1 1 757 667 448
|
|
||||||
1 1 453 436 108
|
|
||||||
52 8 130 686 208
|
|
||||||
1 1 71 268
|
|
||||||
1 1 304 157
|
|
||||||
0 0 101 100
|
|
||||||
0 0 474 99 126
|
|
||||||
0 0 474 630 99
|
|
||||||
1 1 117 383 107
|
|
||||||
1 1 441 449 80
|
|
||||||
2 2 116 207 338
|
|
||||||
52 8 763 187 205 692
|
|
||||||
24 8 713 447 763
|
|
||||||
1 1 102 449 444
|
|
||||||
2 2 95 388 450
|
|
||||||
4 4 742 17 83
|
|
||||||
1 1 439 451 84
|
|
||||||
1 1 88 451 445
|
|
||||||
1 1 435 452 85
|
|
||||||
1 1 309 71 282
|
|
||||||
0 0 743
|
|
||||||
4 4 81 119 454
|
|
||||||
4 4 744 17 104
|
|
||||||
1 1 448 452 102
|
|
||||||
1 1 178 600
|
|
||||||
4 4 450 115 661
|
|
||||||
1 1 356 178
|
|
||||||
1 1 601 602
|
|
||||||
0 0 123 460
|
|
||||||
0 0 663 122 248
|
|
||||||
24 8 222 253
|
|
||||||
24 8 603 461
|
|
||||||
0 0 100 248
|
|
||||||
4 4 220 218 604
|
|
||||||
1 1 549 685
|
|
||||||
0 0 529 234 567 151
|
|
||||||
68 8 606 96
|
|
||||||
0 0 607 261 462
|
|
||||||
68 8 417 711
|
|
||||||
1 1 550 608 267
|
|
||||||
1 1 649 214
|
|
||||||
1 1 235 611 704
|
|
||||||
1 1 280 219 613
|
|
||||||
0 0 654 221
|
|
||||||
1 1 266 211 615
|
|
||||||
24 8 736 176
|
|
||||||
24 8 579 558
|
|
||||||
68 8 676 45 518
|
|
||||||
1 1 177 73 542
|
|
||||||
68 8 42 526 191
|
|
||||||
68 8 179 41 629
|
|
||||||
0 0 224 621
|
|
||||||
1 1 76 79 258
|
|
||||||
68 8 468 747 731
|
|
||||||
8 8 391 392 21 3
|
|
||||||
4 4 346 556
|
|
||||||
2 2 639 229 232
|
|
||||||
0 0 464 129
|
|
||||||
24 8 526 191 8 412
|
|
||||||
52 8 36 738 712 167
|
|
||||||
68 8 466 194 526
|
|
||||||
52 8 496 695 753 748
|
|
||||||
2 2 350 623
|
|
||||||
1 1 98 465 309
|
|
||||||
1 1 233 217 238
|
|
||||||
52 8 167 190 179 25
|
|
||||||
68 8 644 595 626
|
|
||||||
52 8 390 63 308
|
|
||||||
68 8 697 61 749
|
|
||||||
68 8 628 70 725
|
|
||||||
4 4 225 674
|
|
||||||
68 8 629 726 191
|
|
||||||
4 4 710 328 169 318
|
|
||||||
68 8 153 739 159
|
|
||||||
68 8 631 65 751
|
|
||||||
4 4 721 166 398 490
|
|
||||||
68 8 632 69 637
|
|
||||||
0 0 657 226
|
|
||||||
68 8 253 603
|
|
||||||
68 8 468 200 640
|
|
||||||
4 4 25 83 413 29
|
|
||||||
0 0 203 469 470
|
|
||||||
52 8 564 139 609 240
|
|
||||||
1 1 142 72 438
|
|
||||||
1 1 455 120 118
|
|
||||||
52 8 159 144 180 23
|
|
||||||
24 8 190 179 208 596
|
|
||||||
4 4 237 659
|
|
||||||
68 8 183 205 628
|
|
||||||
64 8 55 568 735 182
|
|
||||||
68 8 748 209 715
|
|
||||||
1 1 227 471
|
|
||||||
1 1 231 310
|
|
||||||
68 8 447 105 739
|
|
||||||
1 1 215 650
|
|
||||||
68 8 707 209 619
|
|
||||||
24 8 159 686 180 413
|
|
||||||
52 8 143 165 752 152
|
|
||||||
68 8 31 726 618
|
|
||||||
68 8 599 595 447
|
|
||||||
68 8 624 154 733
|
|
||||||
1 1 241 635
|
|
||||||
68 8 68 210 632
|
|
||||||
8 8 651 756 662
|
|
||||||
24 8 387 683 651
|
|
||||||
52 8 749 651 758 586
|
|
||||||
68 8 641 173 528
|
|
||||||
0 0 252 239 256
|
|
||||||
68 8 213 642 546
|
|
||||||
0 0 696 250 175
|
|
||||||
24 8 759 694 386
|
|
||||||
68 8 105 182 645
|
|
||||||
0 0 246 322
|
|
||||||
4 4 391 407 104 3
|
|
||||||
52 8 96 41 180 223
|
|
||||||
68 8 189 184 617
|
|
||||||
68 8 546 196 624
|
|
||||||
1 1 646 138 354
|
|
||||||
68 8 647 758
|
|
||||||
68 8 475 202 648
|
|
||||||
1 1 134 610 233 330
|
|
||||||
1 1 290 260 472 188
|
|
||||||
68 8 519 694
|
|
||||||
1 1 330 158 332
|
|
||||||
4 4 612 652 127
|
|
||||||
1 1 653 136 353
|
|
||||||
2 2 704 297 127
|
|
||||||
0 0 137 243 657
|
|
||||||
24 8 604 588 124
|
|
||||||
24 8 208 734 350
|
|
||||||
0 0 655 145 270 355
|
|
||||||
4 4 295 249 164 278
|
|
||||||
0 0 467 171 262 339
|
|
||||||
1 1 327 185 681 517
|
|
||||||
1 1 471 259 456
|
|
||||||
4 4 271 150 334
|
|
||||||
4 4 461 561 639
|
|
||||||
1 1 659 244 186
|
|
||||||
1 1 150 299 649
|
|
||||||
1 1 214 291 158
|
|
||||||
0 0 593 129 462
|
|
||||||
1 1 602 236 135
|
|
||||||
1 1 633 235 491
|
|
||||||
8 8 558 242 181
|
|
||||||
1 1 158 301 654
|
|
||||||
0 0 540 201 319
|
|
||||||
24 8 176 718 579
|
|
||||||
1 1 310 247 195
|
|
||||||
24 8 427 518 237 504
|
|
||||||
0 0 614 221 313 333
|
|
||||||
2 2 307 292 231 658
|
|
||||||
0 0 416 460 567
|
|
||||||
0 0 319 256 477 206
|
|
||||||
1 1 241 660 289 635
|
|
||||||
0 0 126 264 123
|
|
||||||
2 2 650 312 225
|
|
||||||
0 0 503 565 203
|
|
||||||
1 1 542 255 465
|
|
||||||
1 1 541 300 201
|
|
||||||
52 8 124 65 172 554
|
|
||||||
24 8 581 28 726 750
|
|
||||||
1 1 478 251 523
|
|
||||||
0 0 201 562 246
|
|
||||||
0 0 265 481 263
|
|
||||||
1 1 146 327 478
|
|
||||||
1 1 523 228 455
|
|
||||||
1 1 482 285 215
|
|
||||||
0 0 363 131 460
|
|
||||||
0 0 226 316 627
|
|
||||||
0 0 257 470 87
|
|
||||||
0 0 480 663 343 248
|
|
||||||
0 0 570 257
|
|
||||||
1 1 613 360 138
|
|
||||||
1 1 133 361 549
|
|
||||||
1 1 97 282 597
|
|
||||||
0 0 671 287
|
|
||||||
1 1 615 362 224
|
|
||||||
24 8 582 315 229
|
|
||||||
1 1 670 284
|
|
||||||
0 0 621 688 547
|
|
||||||
68 8 427 483
|
|
||||||
1 1 352 293
|
|
||||||
68 8 734 484
|
|
||||||
68 8 335 764
|
|
||||||
8 8 225 580 656 674
|
|
||||||
2 2 643 384
|
|
||||||
1 1 668 765 136
|
|
||||||
68 8 485 414
|
|
||||||
1 1 113 356 458 268
|
|
||||||
4 4 486 387
|
|
||||||
1 1 272 665 381 348
|
|
||||||
1 1 487 260 590
|
|
||||||
24 8 724 430 643
|
|
||||||
0 0 269 345 570
|
|
||||||
24 8 324 636 320
|
|
||||||
1 1 488 247 321
|
|
||||||
1 1 548 365 215
|
|
||||||
1 1 537 233 329
|
|
||||||
2 2 318 244 634
|
|
||||||
1 1 428 275 383 349
|
|
||||||
2 2 491 341 297
|
|
||||||
2 2 650 723 225
|
|
||||||
24 8 680 631 331
|
|
||||||
4 4 294 220 563
|
|
||||||
1 1 458 597 358 388
|
|
||||||
1 1 398 232 492
|
|
||||||
1 1 493 252 562
|
|
||||||
1 1 329 238 494
|
|
||||||
8 8 755 473 561
|
|
||||||
1 1 590 341 495
|
|
||||||
1 1 82 98 418
|
|
||||||
68 8 63 761
|
|
||||||
1 1 492 317 537
|
|
||||||
4 4 504 659 675 244
|
|
||||||
68 8 161 61
|
|
||||||
1 1 113 157 422
|
|
||||||
1 1 186 677 241
|
|
||||||
24 8 676 473 559
|
|
||||||
4 4 495 249 669
|
|
||||||
0 0 494 326 243
|
|
||||||
1 1 635 374 540
|
|
||||||
52 8 566 271 368
|
|
||||||
0 0 499 262 760
|
|
||||||
1 1 634 306 488
|
|
||||||
4 4 702 166 292
|
|
||||||
0 0 239 378 246
|
|
||||||
24 8 288 475 678
|
|
||||||
1 1 289 501 493
|
|
||||||
0 0 206 679 474
|
|
||||||
68 8 366 433
|
|
||||||
24 8 669 432 288
|
|
||||||
1 1 550 471 361
|
|
||||||
0 0 313 562 499
|
|
||||||
1 1 502 258 227
|
|
||||||
2 2 561 166 398
|
|
||||||
1 1 291 501 301
|
|
||||||
1 1 214 33 217
|
|
||||||
24 8 296 475 751
|
|
||||||
1 1 217 32 654
|
|
||||||
0 0 243 37 657 467
|
|
||||||
2 2 229 44 649
|
|
||||||
52 8 585 53 277
|
|
||||||
1 1 602 682 611
|
|
||||||
24 8 483 340 569
|
|
||||||
1 1 104 544 757
|
|
||||||
0 0 226 46 503
|
|
||||||
24 8 484 337 372
|
|
||||||
2 2 303 727 294 708
|
|
||||||
0 0 343 469 416
|
|
||||||
0 0 720 264 342
|
|
||||||
1 1 608 78 549
|
|
||||||
1 1 671 39 700 287
|
|
||||||
2 2 685 463 149
|
|
||||||
24 8 556 644 594
|
|
||||||
1 1 284 40 671
|
|
||||||
1 1 293 43 670
|
|
||||||
4 4 596 223 156 745
|
|
||||||
1 1 623 77 653
|
|
||||||
1 1 384 673 275
|
|
||||||
1 1 219 85 646
|
|
||||||
1 1 211 80 655
|
|
||||||
0 0 224 84 621 666
|
|
||||||
1 1 120 282 453
|
|
||||||
0 0 89 470 464
|
|
||||||
2 2 298 38 486
|
|
||||||
0 0 370 679 663
|
|
||||||
1 1 689 266 377
|
|
||||||
1 1 325 267 505
|
|
||||||
1 1 506 270 379
|
|
||||||
0 0 364 507 261
|
|
||||||
0 0 508 688 363
|
|
||||||
1 1 681 290 511
|
|
||||||
52 8 70 323 430 698
|
|
||||||
2 2 505 691 369
|
|
||||||
24 8 433 315 66
|
|
||||||
4 4 367 509 701
|
|
||||||
0 0 510 507 359
|
|
||||||
2 2 372 765 376
|
|
||||||
4 4 340 396 693 371
|
|
||||||
2 2 511 691 723
|
|
||||||
1 1 385 314 405
|
|
||||||
1 1 399 677 514
|
|
||||||
1 1 371 380 689
|
|
||||||
1 1 360 400 506
|
|
||||||
0 0 515 319 510
|
|
||||||
0 0 362 382 508
|
|
||||||
1 1 693 376 399
|
|
||||||
1 1 284 88 671
|
|
||||||
0 0 405 379 515
|
|
||||||
1 1 293 102 670
|
|
||||||
1 1 279 667 352
|
|
||||||
1 1 514 400 374
|
|
||||||
24 8 401 204 766 407
|
|
||||||
24 8 283 664 749 198
|
|
||||||
2 2 298 108 486
|
|
||||||
1 1 517 1 516 505
|
|
||||||
24 8 419 496 697 161
|
|
||||||
8 8 401 744 148 207
|
|
||||||
38 8 401 628 766 148
|
|
||||||
24 8 5 468 707 619
|
|
||||||
52 8 695 622 753 641
|
|
||||||
1 1 523 521 522 2
|
|
||||||
4 4 752 412 372 575
|
|
||||||
2 2 553 7 435 524
|
|
||||||
2 2 639 328 169 299
|
|
||||||
1 1 737 380 375 574
|
|
||||||
1 1 512 377 385 404
|
|
||||||
24 8 735 392 386 391
|
|
||||||
1 1 449 15 444 408
|
|
||||||
1 1 452 13 441 449
|
|
||||||
1 1 400 19 506 405
|
|
||||||
1 1 374 404 513 382
|
|
||||||
1 1 32 421 614 52
|
|
||||||
4 4 386 207 409
|
|
||||||
1 1 402 439 19 451
|
|
||||||
4 4 766 407 3 643
|
|
||||||
1 1 429 27 578 420
|
|
||||||
1 1 451 27 445 26
|
|
||||||
4 4 152 717 396 746
|
|
||||||
4 4 190 174 596
|
|
||||||
68 8 281 415 417
|
|
||||||
52 8 701 424 640 414
|
|
||||||
0 0 459 529 342 245
|
|
||||||
52 8 556 414 132
|
|
||||||
1 1 304 589 465 34
|
|
||||||
4 4 423 38 390
|
|
||||||
0 0 37 410 467 46
|
|
||||||
1 1 584 406 22 429
|
|
||||||
1 1 309 458 522 38
|
|
||||||
2 2 522 34 419 729
|
|
||||||
24 8 463 415 625 556
|
|
||||||
1 1 43 530 665 59
|
|
||||||
1 1 44 531 532 56
|
|
||||||
52 8 45 558 274 242
|
|
||||||
1 1 673 448 687 293
|
|
||||||
1 1 421 58 52 410
|
|
||||||
24 8 366 286 690
|
|
||||||
4 4 533 66 62 531
|
|
||||||
24 8 563 520 324 617
|
|
||||||
52 8 323 69 368 533
|
|
||||||
1 1 478 79 438 699
|
|
||||||
1 1 77 397 653 112
|
|
||||||
1 1 521 78 95 534
|
|
||||||
1 1 78 605 534 81
|
|
||||||
1 1 542 177 434 633
|
|
||||||
1 1 80 408 655 110
|
|
||||||
0 0 84 26 666 86
|
|
||||||
1 1 85 403 646 103
|
|
||||||
0 0 26 89 86 529
|
|
||||||
52 8 636 48 564 678
|
|
||||||
1 1 107 665 402 88
|
|
||||||
1 1 111 700 411 91
|
|
||||||
0 0 700 570 91 481
|
|
||||||
52 8 193 106 92 187
|
|
||||||
1 1 94 524 428 117
|
|
||||||
1 1 403 107 402 103
|
|
||||||
4 4 534 108 622 119
|
|
||||||
1 1 408 111 110 411
|
|
||||||
1 1 524 112 117 403
|
|
||||||
1 1 356 521 458 95
|
|
||||||
24 8 115 625 528 75
|
|
||||||
1 1 178 259 521 600
|
|
||||||
1 1 228 550 600
|
|
||||||
24 8 483 504 526 675
|
|
||||||
1 1 282 422 453 298
|
|
||||||
0 0 507 416 663 460
|
|
||||||
0 0 459 261 245 122
|
|
||||||
24 8 560 125 582 230
|
|
||||||
0 0 131 234 567 60
|
|
||||||
4 4 509 81 346 424
|
|
||||||
0 0 529 357 469 151
|
|
||||||
1 1 157 251 418 522
|
|
||||||
52 8 518 154 702 504
|
|
||||||
0 0 333 499 420 226
|
|
||||||
52 8 393 730 173 147
|
|
||||||
0 0 342 175 464
|
|
||||||
0 0 481 357 175 263
|
|
||||||
1 1 228 185 517 325
|
|
||||||
1 1 215 511 705 650
|
|
||||||
24 8 546 311 302 710
|
|
||||||
0 0 322 101 480 100
|
|
||||||
52 8 617 320 331 213
|
|
||||||
1 1 502 548 681
|
|
||||||
0 0 246 510 499 679
|
|
||||||
1 1 258 255 434 479
|
|
||||||
1 1 517 478 523 1
|
|
||||||
0 0 679 760 474 264
|
|
||||||
0 0 446 565 257 470
|
|
||||||
1 1 545 548 260
|
|
||||||
52 8 274 42 457 337
|
|
||||||
52 8 42 276 752 340
|
|
||||||
52 8 701 53 281
|
|
||||||
4 4 358 388 664 283
|
|
||||||
1 1 545 79 285
|
|
||||||
1 1 317 660 289 535
|
|
||||||
4 4 643 498 690 667
|
|
||||||
2 2 169 12 634 492
|
|
||||||
1 1 236 703 294 704
|
|
||||||
1 1 299 490 497 306
|
|
||||||
1 1 321 541 300 527
|
|
||||||
1 1 301 527 614 313
|
|
||||||
2 2 705 303 312 708
|
|
||||||
24 8 729 390 155 672
|
|
||||||
1 1 492 610 10 537
|
|
||||||
4 4 3 536 757 489
|
|
||||||
0 0 326 467 477 316
|
|
||||||
52 8 648 755 68 546
|
|
||||||
1 1 535 329 321 527
|
|
||||||
1 1 76 476 327
|
|
||||||
0 0 339 627 250
|
|
||||||
24 8 242 457 466 307
|
|
||||||
1 1 361 389 605 367
|
|
||||||
1 1 377 615 404 362
|
|
||||||
0 0 539 370 363 459
|
|
||||||
0 0 379 666 539 364
|
|
||||||
2 2 605 685 369 463
|
|
||||||
0 0 378 538 477 370
|
|
||||||
1 1 365 516 472 373
|
|
||||||
1 1 574 514 18 400
|
|
||||||
1 1 405 540 24 515
|
|
||||||
1 1 375 512 660 385
|
|
||||||
0 0 513 382 378 538
|
|
||||||
2 2 389 511 572 691
|
|
||||||
1 1 479 227 471 389
|
|
||||||
52 8 141 559 466 242
|
|
||||||
52 8 756 54 759 216
|
|
||||||
24 8 708 669 619 432
|
|
||||||
1 1 455 453 395 436
|
|
||||||
1 1 465 422 395 423
|
|
||||||
1 1 259 255 479 395
|
|
||||||
1 1 397 448 9 452
|
|
||||||
24 8 31 536 618 598
|
|
||||||
52 8 143 154 457 152
|
|
||||||
1 1 501 22 494 493
|
|
||||||
52 8 661 454 200 599
|
|
||||||
0 0 442 416 464 129
|
|
||||||
1 1 577 425 15 584
|
|
||||||
2 2 431 11 426 687
|
|
||||||
1 1 426 610 10 577
|
|
||||||
24 8 433 698 637 431
|
|
||||||
2 2 436 2 437 450
|
|
||||||
1 1 537 488 18 501
|
|
||||||
24 8 21 525 725 498
|
|
||||||
1 1 306 497 291 535
|
|
||||||
0 0 515 27 539 510
|
|
||||||
0 0 538 508 26 507
|
|
||||||
1 1 314 541 513 239
|
|
||||||
1 1 635 493 252 540
|
|
||||||
1 1 142 251 438 589
|
|
||||||
1 1 592 544 591
|
|
||||||
2 2 620 338 598 543
|
|
||||||
1 1 76 487 482
|
|
||||||
52 8 202 500 473 210
|
|
||||||
0 0 273 607
|
|
||||||
1 1 476 482 290
|
|
||||||
1 1 267 344 605 128
|
|
||||||
1 1 456 325 133
|
|
||||||
0 0 743 552 696
|
|
||||||
0 0 57 551 720
|
|
||||||
4 4 638 591 598 397
|
|
||||||
24 8 253 555 603
|
|
||||||
24 8 751 554 755
|
|
||||||
24 8 149 424 417 347
|
|
||||||
8 8 674 636 736
|
|
||||||
24 8 140 427 237
|
|
||||||
24 8 311 518 702
|
|
||||||
52 8 603 67 755 461
|
|
||||||
4 4 302 230 328
|
|
||||||
0 0 300 326 256
|
|
||||||
8 8 297 432 680
|
|
||||||
52 8 736 47 443 176
|
|
||||||
0 0 50 481 250
|
|
||||||
68 8 709 315 69
|
|
||||||
0 0 245 129 462
|
|
||||||
32 8 583 741 763 183
|
|
||||||
4 4 337 675 693
|
|
||||||
0 0 287 446 265
|
|
||||||
1 1 699 1 572 6
|
|
||||||
2 2 571 705 516 5
|
|
||||||
1 1 7 616 9 706
|
|
||||||
1 1 399 706 689 512
|
|
||||||
2 2 396 668 7 765
|
|
||||||
52 8 715 604 761 588
|
|
||||||
1 1 56 532 33 530
|
|
||||||
1 1 39 410 700 50
|
|
||||||
52 8 609 240 45 140
|
|
||||||
24 8 278 585 587 764
|
|
||||||
24 8 16 254 31 620
|
|
||||||
24 8 461 709 271 639
|
|
||||||
52 8 651 713 586 568
|
|
||||||
1 1 51 530 59 421
|
|
||||||
24 8 723 731 335 580
|
|
||||||
68 8 199 583 55
|
|
||||||
52 8 580 656 747 48
|
|
||||||
52 8 576 631 222 65
|
|
||||||
1 1 601 542 418 714
|
|
||||||
1 1 285 699 705 303
|
|
||||||
2 2 750 543 553 77
|
|
||||||
2 2 620 83 750 543
|
|
||||||
0 0 86 607 234
|
|
||||||
24 8 347 711 90 626
|
|
||||||
52 8 75 193 92 160
|
|
||||||
4 4 180 413 30 350
|
|
||||||
1 1 268 298
|
|
||||||
4 4 525 544 757 553
|
|
||||||
68 8 528 713 193
|
|
||||||
1 1 118 456 455 608
|
|
||||||
1 1 73 82 121 589
|
|
||||||
1 1 121 714 235 336
|
|
||||||
52 8 172 554 125 560
|
|
||||||
24 8 127 576 652 222
|
|
||||||
1 1 549 505 437 509
|
|
||||||
52 8 740 35 712 130
|
|
||||||
0 0 688 547 593 131
|
|
||||||
1 1 600 133 344
|
|
||||||
68 8 176 579
|
|
||||||
1 1 649 497 532 214
|
|
||||||
1 1 336 135 612
|
|
||||||
2 2 611 719 704 218
|
|
||||||
1 1 136 722 646 266
|
|
||||||
1 1 654 494 406 243
|
|
||||||
1 1 138 506 655 270
|
|
||||||
2 2 746 12 737 573
|
|
||||||
52 8 432 680 209 475
|
|
||||||
52 8 192 716 525 638
|
|
||||||
52 8 393 520 747 189
|
|
||||||
4 4 17 581 592 544
|
|
||||||
0 0 145 355 273
|
|
||||||
24 8 450 394 664 661
|
|
||||||
2 2 745 351 156 668
|
|
||||||
52 8 210 194 710 721
|
|
||||||
52 8 454 424 640 644
|
|
||||||
52 8 594 160 36 738
|
|
||||||
0 0 262 503 696 743
|
|
||||||
64 8 182 392 163 21
|
|
||||||
52 8 144 165 23 762
|
|
||||||
0 0 760 101 57
|
|
||||||
52 8 715 588 296 168
|
|
||||||
52 8 196 170 709 721
|
|
||||||
1 1 438 714 236 703
|
|
||||||
1 1 292 490 658 317
|
|
||||||
1 1 247 195 314 541
|
|
||||||
24 8 656 557 288 443
|
|
||||||
52 8 170 728 754 533
|
|
||||||
24 8 726 618 8 553
|
|
||||||
4 4 230 582 398 150
|
|
||||||
68 8 173 415 625
|
|
||||||
68 8 707 394 200
|
|
||||||
68 8 678 202 676
|
|
||||||
4 4 409 286 279 489
|
|
||||||
52 8 625 75 347 160
|
|
||||||
52 8 205 692 21 31
|
|
||||||
1 1 353 613 441 211
|
|
||||||
52 8 749 61 212
|
|
||||||
68 8 751 213 500
|
|
||||||
1 1 232 334 610 134
|
|
||||||
1 1 188 472 295 249
|
|
||||||
24 8 198 199 197 583
|
|
||||||
24 8 218 761 604
|
|
||||||
1 1 351 668 435 219
|
|
||||||
1 1 238 332 614 137
|
|
||||||
1 1 354 615 439 224
|
|
||||||
24 8 278 669 587 636
|
|
||||||
0 0 221 333 171
|
|
||||||
1 1 244 737 634 677
|
|
||||||
2 2 181 307 231
|
|
||||||
1 1 677 488 247 514
|
|
||||||
24 8 119 622 528 683
|
|
||||||
8 8 197 741 759
|
|
||||||
0 0 359 459 264 123
|
|
||||||
24 8 486 697 622 387
|
|
||||||
1 1 670 444 425 284
|
|
||||||
0 0 355 508 440 688
|
|
||||||
2 2 489 384 94 673
|
|
||||||
2 2 623 575 653 280
|
|
||||||
24 8 312 520 656 324
|
|
||||||
1 1 383 349 665 272
|
|
||||||
1 1 348 381 269 345
|
|
||||||
52 8 496 761 63 748
|
|
||||||
2 2 667 49 352 428
|
|
||||||
8 8 278 164 684 557
|
|
||||||
4 4 457 569 307 717
|
|
||||||
52 8 642 718 141 311
|
|
||||||
1 1 658 310 375 660
|
|
||||||
52 8 443 320 642 718
|
|
||||||
0 0 477 322 359 480
|
|
||||||
24 8 563 715 617 296
|
|
||||||
1 1 476 227 365
|
|
||||||
1 1 714 34 336 719
|
|
||||||
24 8 661 198 713
|
|
||||||
24 8 674 764 736
|
|
||||||
1 1 128 509 346
|
|
||||||
24 8 712 96 190
|
|
||||||
1 1 49 531 428 64
|
|
||||||
0 0 273 666 364 607
|
|
||||||
1 1 376 722 574 360
|
|
||||||
8 8 430 698 489 62
|
|
||||||
4 4 367 516 373 730
|
|
||||||
24 8 105 744 16 645
|
|
||||||
2 2 569 372 717 380
|
|
||||||
52 8 216 204 724
|
|
||||||
24 8 4 394 155 707
|
|
||||||
0 0 627 720 203 551
|
|
||||||
52 8 390 664 753 162
|
|
||||||
24 8 366 725 533 690
|
|
||||||
1 1 434 571 590 727
|
|
||||||
1 1 345 445 578 446
|
|
||||||
24 8 369 730 415 485
|
|
||||||
24 8 559 710 466 318
|
|
||||||
1 1 633 727 719 491
|
|
||||||
1 1 135 491 612 220
|
|
||||||
1 1 590 472 572 495
|
|
||||||
1 1 573 722 574 13
|
|
||||||
52 8 695 393 641 189
|
|
||||||
4 4 495 5 341 520
|
|
||||||
52 8 67 566 582 632
|
|
||||||
24 8 473 624 702 166
|
|
||||||
52 8 594 132 740 35
|
|
||||||
24 8 606 732 153 686
|
|
||||||
52 8 683 599 106 583
|
|
||||||
1 1 589 602 633 682
|
|
||||||
52 8 576 680 184 631
|
|
||||||
68 8 728 618 733
|
|
||||||
2 2 675 412 693 737
|
|
||||||
24 8 678 240 676
|
|
||||||
2 2 682 703 729 612
|
|
||||||
0 0 760 696 343 552
|
|
||||||
24 8 624 632 754 169
|
|
||||||
1 1 765 706 689 613
|
|
||||||
4 4 373 295 585
|
|
||||||
52 8 694 70 766 286
|
|
||||||
52 8 163 728 536 698
|
|
||||||
52 8 192 165 254 638
|
|
||||||
1 1 699 703 6 341
|
|
||||||
68 8 716 725 637
|
|
||||||
4 4 423 4 719 496
|
|
||||||
24 8 691 701 468 731
|
|
||||||
52 8 730 585 53 147
|
|
||||||
8 8 90 738 712
|
|
||||||
52 8 194 716 754 8
|
|
||||||
52 8 41 276 223 762
|
|
||||||
38 8 183 759 741 401
|
|
||||||
24 8 684 557 564 139
|
|
||||||
1 1 717 658 616 399
|
|
||||||
24 8 626 732 74 153
|
|
||||||
52 8 74 187 167 742
|
|
||||||
24 8 711 90 606
|
|
||||||
8 8 568 662 93 735
|
|
||||||
24 8 739 109 16 25
|
|
||||||
0 0 627 114 551
|
|
||||||
8 8 93 692 116 391
|
|
||||||
4 4 30 350 762 623
|
|
||||||
4 4 8 412 616 7
|
|
||||||
68 8 147 619 587
|
|
||||||
68 8 155 672 184
|
|
||||||
52 8 387 647 162 199
|
|
||||||
4 4 592 254 29 591
|
|
||||||
52 8 168 331 648 555
|
|
||||||
24 8 191 484 762 396
|
|
||||||
68 8 155 697 394
|
|
||||||
24 8 721 733 637 12
|
|
||||||
24 8 555 500 560 302
|
|
||||||
24 8 758 197 519
|
|
||||||
2 2 498 338 598 94
|
|
||||||
52 8 199 212 756 54
|
|
||||||
24 8 519 662 735 204
|
|
||||||
0 0 316 480 630 720
|
|
||||||
52 8 672 652 305 576
|
|
||||||
24 8 629 734 752 745
|
|
||||||
24 8 106 568 93 105
|
|
||||||
52 8 580 684 277 47
|
|
||||||
1 1 575 371 280 722
|
|
||||||
24 8 386 392 724 409
|
|
||||||
@ -1,297 +0,0 @@
|
|||||||
/*
|
|
||||||
* metis.h
|
|
||||||
*
|
|
||||||
* This file contains function prototypes and constant definitions
|
|
||||||
* for METIS
|
|
||||||
*
|
|
||||||
* Started 8/9/02
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef METIS_H
|
|
||||||
#define METIS_H 1
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* A set of defines that can be modified by the user
|
|
||||||
*****************************************************************************/
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
Specifies the width of the elementary data type that will hold information
|
|
||||||
about vertices and their adjacency lists.
|
|
||||||
|
|
||||||
Possible values:
|
|
||||||
32 : Use 32 bit signed integers
|
|
||||||
64 : Use 64 bit signed integers
|
|
||||||
|
|
||||||
A width of 64 should be specified if the number of vertices or the total
|
|
||||||
number of edges in the graph exceed the limits of a 32 bit signed integer
|
|
||||||
i.e., 2^31-1.
|
|
||||||
Proper use of 64 bit integers requires that the c99 standard datatypes
|
|
||||||
int32_t and int64_t are supported by the compiler.
|
|
||||||
GCC does provides these definitions in stdint.h, but it may require some
|
|
||||||
modifications on other architectures.
|
|
||||||
--------------------------------------------------------------------------*/
|
|
||||||
#define IDXTYPEWIDTH 32
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
Specifies if the __thread storage directive is available by the compiler
|
|
||||||
to indicate thread local storage. This storage directive is available in
|
|
||||||
most systems using gcc compiler but it may not be available in other
|
|
||||||
systems.
|
|
||||||
|
|
||||||
Possible values:
|
|
||||||
0 : Not available and do not use thread local storage
|
|
||||||
1 : It is available and the __thread modifier will be used
|
|
||||||
--------------------------------------------------------------------------*/
|
|
||||||
#define HAVE_THREADLOCALSTORAGE 0
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* In principle, nothing needs to be changed beyond this point, unless the
|
|
||||||
* int32_t and int64_t cannot be found in the normal places.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/* Uniform definitions for various compilers */
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define COMPILER_MSC
|
|
||||||
#endif
|
|
||||||
#if defined(__ICC)
|
|
||||||
#define COMPILER_ICC
|
|
||||||
#endif
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
#define COMPILER_GCC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(COMPILER_MSC)
|
|
||||||
#include <ctrdefs.h>
|
|
||||||
#define __thread __declspec( thread )
|
|
||||||
|
|
||||||
typedef __int32 int32_t;
|
|
||||||
typedef __int64 int64_t;
|
|
||||||
typedef unsigned __int32 uint32_t;
|
|
||||||
typedef unsigned __int64 uint64_t;
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------
|
|
||||||
* Undefine the following #define in order to use short idxtype as the idxtype
|
|
||||||
*-------------------------------------------------------------------------*/
|
|
||||||
#if IDXTYPEWIDTH == 32
|
|
||||||
#define SCNIDX SCNd32
|
|
||||||
#define PRIIDX PRId32
|
|
||||||
|
|
||||||
typedef int32_t idxtype;
|
|
||||||
#elif IDXTYPEWIDTH == 64
|
|
||||||
#define SCNIDX SCNd64
|
|
||||||
#define PRIIDX PRId64
|
|
||||||
|
|
||||||
typedef int64_t idxtype;
|
|
||||||
#else
|
|
||||||
#error "Incorrect user-supplied value fo IDXTYPEWIDTH"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------
|
|
||||||
* Function prototypes
|
|
||||||
*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if !defined(__cdecl)
|
|
||||||
#define __cdecl
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void __cdecl METIS_EstimateMemory(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag,
|
|
||||||
idxtype *optype, idxtype *nbytes);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartGraphKway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options,
|
|
||||||
idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_WPartGraphKway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts,
|
|
||||||
idxtype *options, idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartGraphVKway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options,
|
|
||||||
idxtype *volume, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_WPartGraphVKway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts,
|
|
||||||
idxtype *options, idxtype *volume, idxtype *part);
|
|
||||||
|
|
||||||
idxtype __cdecl METIS_MeshToDualCount(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *elms, idxtype *etype,
|
|
||||||
idxtype *numflag);
|
|
||||||
|
|
||||||
void __cdecl METIS_MeshToDual(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *elms, idxtype *etype,
|
|
||||||
idxtype *numflag, idxtype *dxadj, idxtype *dadjncy);
|
|
||||||
|
|
||||||
idxtype __cdecl METIS_MixedMeshToDualCount(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype * elms,
|
|
||||||
idxtype *etype, idxtype *numflag, idxtype *conmat, idxtype custom);
|
|
||||||
|
|
||||||
void __cdecl METIS_MixedMeshToDual(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *elms,
|
|
||||||
idxtype *etype, idxtype *numflag,idxtype *dxadj, idxtype *dadjncy,idxtype *conmat,
|
|
||||||
idxtype custom);
|
|
||||||
|
|
||||||
void __cdecl METIS_MeshToNodal(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag,
|
|
||||||
idxtype *dxadj, idxtype *dadjncy);
|
|
||||||
|
|
||||||
void __cdecl METIS_MixedMeshToNodal(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype,
|
|
||||||
idxtype *numflag, idxtype *dxadj, idxtype *dadjncy);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartMeshNodal(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag,
|
|
||||||
idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartMixedMeshNodal(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag,
|
|
||||||
idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartMeshDual(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag,
|
|
||||||
idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart, idxtype wgtflag,
|
|
||||||
idxtype * vwgt);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartMixedMeshDual(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag,
|
|
||||||
idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart, idxtype *conmat,
|
|
||||||
idxtype custom, idxtype wgtflag, idxtype *vwgt);
|
|
||||||
|
|
||||||
void __cdecl METIS_mCPartGraphKway(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy,
|
|
||||||
idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts,
|
|
||||||
float *rubvec, idxtype *options, idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_mCPartGraphRecursive(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy,
|
|
||||||
idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts,
|
|
||||||
idxtype *options, idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_mCHPartGraphRecursive(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy,
|
|
||||||
idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts,
|
|
||||||
float *ubvec, idxtype *options, idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_mCPartGraphRecursiveInternal(idxtype *nvtxs, idxtype *ncon, idxtype *xadj,
|
|
||||||
idxtype *adjncy, float *nvwgt, idxtype *adjwgt, idxtype *nparts, idxtype *options,
|
|
||||||
idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_mCHPartGraphRecursiveInternal(idxtype *nvtxs, idxtype *ncon, idxtype *xadj,
|
|
||||||
idxtype *adjncy, float *nvwgt, idxtype *adjwgt, idxtype *nparts, float *ubvec,
|
|
||||||
idxtype *options, idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_EdgeND(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options,
|
|
||||||
idxtype *perm, idxtype *iperm);
|
|
||||||
|
|
||||||
void __cdecl METIS_NodeND(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options,
|
|
||||||
idxtype *perm, idxtype *iperm);
|
|
||||||
|
|
||||||
|
|
||||||
void __cdecl METIS_NodeWND(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *numflag,
|
|
||||||
idxtype *options, idxtype *perm, idxtype *iperm);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartGraphKway2(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options,
|
|
||||||
idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_WPartGraphKway2(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts,
|
|
||||||
idxtype *options, idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_NodeNDP(idxtype nvtxs, idxtype *xadj, idxtype *adjncy, idxtype npes, idxtype *options,
|
|
||||||
idxtype *perm, idxtype *iperm, idxtype *sizes);
|
|
||||||
|
|
||||||
void __cdecl METIS_NodeComputeSeparator(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *options, idxtype *sepsize, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_EdgeComputeSeparator(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *options, idxtype *sepsize, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartGraphRecursive(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options,
|
|
||||||
idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_WPartGraphRecursive(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts,
|
|
||||||
idxtype *options, idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
void __cdecl METIS_PartFillGraph(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options,
|
|
||||||
idxtype *edgecut, idxtype *part);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------
|
|
||||||
* Constant definitions
|
|
||||||
*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Matching Schemes */
|
|
||||||
#define MTYPE_RM 1
|
|
||||||
#define MTYPE_HEM 2
|
|
||||||
#define MTYPE_SHEM 3
|
|
||||||
#define MTYPE_SHEMKWAY 4
|
|
||||||
#define MTYPE_SHEBM_ONENORM 5
|
|
||||||
#define MTYPE_SHEBM_INFNORM 6
|
|
||||||
#define MTYPE_SBHEM_ONENORM 7
|
|
||||||
#define MTYPE_SBHEM_INFNORM 8
|
|
||||||
|
|
||||||
/* Initial partitioning schemes for PMETIS and ONMETIS */
|
|
||||||
#define ITYPE_GGPKL 1
|
|
||||||
#define ITYPE_GGPKLNODE 2
|
|
||||||
#define ITYPE_RANDOM 2
|
|
||||||
|
|
||||||
/* Refinement schemes for PMETIS */
|
|
||||||
#define RTYPE_FM 1
|
|
||||||
|
|
||||||
/* Initial partitioning schemes for KMETIS */
|
|
||||||
#define ITYPE_PMETIS 1
|
|
||||||
|
|
||||||
/* Refinement schemes for KMETIS */
|
|
||||||
#define RTYPE_KWAYRANDOM 1
|
|
||||||
#define RTYPE_KWAYGREEDY 2
|
|
||||||
#define RTYPE_KWAYRANDOM_MCONN 3
|
|
||||||
|
|
||||||
/* Refinement schemes for ONMETIS */
|
|
||||||
#define RTYPE_SEP2SIDED 1
|
|
||||||
#define RTYPE_SEP1SIDED 2
|
|
||||||
|
|
||||||
/* Initial Partitioning Schemes for McKMETIS */
|
|
||||||
#define ITYPE_McPMETIS 1 /* Simple McPMETIS */
|
|
||||||
#define ITYPE_McHPMETIS 2 /* horizontally relaxed McPMETIS */
|
|
||||||
|
|
||||||
|
|
||||||
/* Debug Levels */
|
|
||||||
#define DBG_TIME 1 /* Perform timing analysis */
|
|
||||||
#define DBG_OUTPUT 2
|
|
||||||
#define DBG_COARSEN 4 /* Show the coarsening progress */
|
|
||||||
#define DBG_REFINE 8 /* Show info on communication during folding */
|
|
||||||
#define DBG_IPART 16 /* Show info on initial partition */
|
|
||||||
#define DBG_MOVEINFO 32 /* Show info on communication during folding */
|
|
||||||
#define DBG_KWAYPINFO 64 /* Show info on communication during folding */
|
|
||||||
#define DBG_SEPINFO 128 /* Show info on communication during folding */
|
|
||||||
|
|
||||||
|
|
||||||
/* Metis's version number */
|
|
||||||
#define METIS_VER_MAJOR 5
|
|
||||||
#define METIS_VER_MINOR 0
|
|
||||||
#define METIS_VER_SUBMINOR 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* METIS_H */
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
balance.c
|
|
||||||
bucketsort.c
|
|
||||||
ccgraph.c
|
|
||||||
checkgraph.c
|
|
||||||
cmetis.c
|
|
||||||
coarsen.c
|
|
||||||
compress.c
|
|
||||||
debug.c
|
|
||||||
estmem.c
|
|
||||||
fm.c
|
|
||||||
fortran.c
|
|
||||||
frename.c
|
|
||||||
graph.c
|
|
||||||
initpart.c
|
|
||||||
/* kfmetis.c */
|
|
||||||
kmetis.c
|
|
||||||
kvmetis.c
|
|
||||||
kwayfm.c
|
|
||||||
kwayrefine.c
|
|
||||||
kwayvolfm.c
|
|
||||||
kwayvolrefine.c
|
|
||||||
match.c
|
|
||||||
mbalance2.c
|
|
||||||
mbalance.c
|
|
||||||
mcoarsen.c
|
|
||||||
memory.c
|
|
||||||
mesh.c
|
|
||||||
meshpart.c
|
|
||||||
mfm2.c
|
|
||||||
mfm.c
|
|
||||||
mincover.c
|
|
||||||
minitpart2.c
|
|
||||||
minitpart.c
|
|
||||||
mkmetis.c
|
|
||||||
mkwayfmh.c
|
|
||||||
mkwayrefine.c
|
|
||||||
mmatch.c
|
|
||||||
mmd.c
|
|
||||||
mpmetis.c
|
|
||||||
mrefine2.c
|
|
||||||
mrefine.c
|
|
||||||
mrkmetis.c
|
|
||||||
mutil.c
|
|
||||||
myqsort.c
|
|
||||||
ometis.c
|
|
||||||
parmetis.c
|
|
||||||
pmetis.c
|
|
||||||
pqueue.c
|
|
||||||
refine.c
|
|
||||||
rkmetis.c
|
|
||||||
separator.c
|
|
||||||
sfm.c
|
|
||||||
srefine.c
|
|
||||||
stat.c
|
|
||||||
streamio.c
|
|
||||||
subdomains.c
|
|
||||||
timing.c
|
|
||||||
util.c
|
|
||||||
|
|
||||||
LIB = $(FOAM_LIBBIN)/libmetis
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
EXE_INC = \
|
|
||||||
-I../include \
|
|
||||||
-I../GKlib/trunk
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
include ../Makefile.in
|
|
||||||
|
|
||||||
CURBUILDDIR = $(LIBBUILDDIR)
|
|
||||||
|
|
||||||
OBJS = $(patsubst %.c, $(CURBUILDDIR)/%$(OBJEXT), $(wildcard *.c))
|
|
||||||
HEADERS = $(wildcard *.h) $(TOPDIR)/include/metis.h $(wildcard $(GKLIBINCDIR)/*.h)
|
|
||||||
|
|
||||||
GKLIBOBJS = $(wildcard $(GKLIBBUILDDIR)/*$(OBJEXT))
|
|
||||||
|
|
||||||
$(BUILDDIR)/libmetis$(LIBEXT): $(OBJS) $(GKLIBOBJS)
|
|
||||||
$(AR) $(OBJS) $(GKLIBOBJS)
|
|
||||||
$(RANLIB)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJS)
|
|
||||||
|
|
||||||
realclean:
|
|
||||||
rm -f $(OBJS) ; rm -f $(BUILDDIR)/libmetis$(LIBEXT)
|
|
||||||
|
|
||||||
dist:
|
|
||||||
mkdir $(TOPDIR)/../$(PKGNAME) ;\
|
|
||||||
cp -r $(TOPDIR)/* $(TOPDIR)/../$(PKGNAME) ;\
|
|
||||||
tar -C $(TOPDIR)/../ --exclude=.svn -czf $(TOPDIR)/$(PKGNAME).tar.gz $(PKGNAME);\
|
|
||||||
rm -rf $(TOPDIR)/../$(PKGNAME)
|
|
||||||
|
|
||||||
$(OBJS) : $(HEADERS) ../Makefile.in Makefile
|
|
||||||
|
|
||||||
|
|
||||||
$(CURBUILDDIR)/%$(OBJEXT) : %.c
|
|
||||||
$(CC) $(CFLAGS) $(SOURCEFILE) $(OUTPUTFILE)
|
|
||||||
@ -1,276 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* balance.c
|
|
||||||
*
|
|
||||||
* This file contains code that is used to forcefully balance either
|
|
||||||
* bisections or k-sections
|
|
||||||
*
|
|
||||||
* Started 7/29/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry poidxtype of the bisection balancing algorithms.
|
|
||||||
**************************************************************************/
|
|
||||||
void Balance2Way(CtrlType *ctrl, GraphType *graph, idxtype *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, j, nvtxs, from, imax, gain, mindiff;
|
|
||||||
idxtype *id, *ed;
|
|
||||||
|
|
||||||
/* Return right away if the balance is OK */
|
|
||||||
mindiff = idxtype_abs(tpwgts[0]-graph->pwgts[0]);
|
|
||||||
if (mindiff < 3*(graph->pwgts[0]+graph->pwgts[1])/graph->nvtxs)
|
|
||||||
return;
|
|
||||||
if (graph->pwgts[0] > tpwgts[0] && graph->pwgts[0] < (int)(ubfactor*tpwgts[0]))
|
|
||||||
return;
|
|
||||||
if (graph->pwgts[1] > tpwgts[1] && graph->pwgts[1] < (int)(ubfactor*tpwgts[1]))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (graph->nbnd > 0)
|
|
||||||
Bnd2WayBalance(ctrl, graph, tpwgts);
|
|
||||||
else
|
|
||||||
General2WayBalance(ctrl, graph, tpwgts);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function balances two partitions by moving boundary nodes
|
|
||||||
* from the domain that is overweight to the one that is underweight.
|
|
||||||
**************************************************************************/
|
|
||||||
void Bnd2WayBalance(CtrlType *ctrl, GraphType *graph, idxtype *tpwgts)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, tmp;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts;
|
|
||||||
idxtype *moved, *perm;
|
|
||||||
PQueueType parts;
|
|
||||||
idxtype higain, oldgain, mincut, mindiff;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
where = graph->where;
|
|
||||||
id = graph->id;
|
|
||||||
ed = graph->ed;
|
|
||||||
pwgts = graph->pwgts;
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
|
|
||||||
moved = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
|
|
||||||
/* Determine from which domain you will be moving data */
|
|
||||||
mindiff = idxtype_abs(tpwgts[0]-pwgts[0]);
|
|
||||||
from = (pwgts[0] < tpwgts[0] ? 1 : 0);
|
|
||||||
to = (from+1)%2;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("Partitions: [%6D %6D] T[%6D %6D], Nv-Nb[%6D %6D]. ICut: %6D [B]\n",
|
|
||||||
pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));
|
|
||||||
|
|
||||||
tmp = graph->adjwgtsum[idxargmax(nvtxs, graph->adjwgtsum)];
|
|
||||||
PQueueInit(ctrl, &parts, nvtxs, tmp);
|
|
||||||
|
|
||||||
idxset(nvtxs, -1, moved);
|
|
||||||
|
|
||||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
|
||||||
ASSERT(CheckBnd(graph));
|
|
||||||
|
|
||||||
/* Insert the boundary nodes of the proper partition whose size is OK in the priority queue */
|
|
||||||
nbnd = graph->nbnd;
|
|
||||||
RandomPermute(nbnd, perm, 1);
|
|
||||||
for (ii=0; ii<nbnd; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
ASSERT(ed[bndind[i]] > 0 || id[bndind[i]] == 0);
|
|
||||||
ASSERT(bndptr[bndind[i]] != -1);
|
|
||||||
if (where[bndind[i]] == from && vwgt[bndind[i]] <= mindiff)
|
|
||||||
PQueueInsert(&parts, bndind[i], ed[bndind[i]]-id[bndind[i]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
mincut = graph->mincut;
|
|
||||||
for (nswaps=0; nswaps<nvtxs; nswaps++) {
|
|
||||||
if ((higain = PQueueGetMax(&parts)) == -1)
|
|
||||||
break;
|
|
||||||
ASSERT(bndptr[higain] != -1);
|
|
||||||
|
|
||||||
if (pwgts[to]+vwgt[higain] > tpwgts[to])
|
|
||||||
break;
|
|
||||||
|
|
||||||
mincut -= (ed[higain]-id[higain]);
|
|
||||||
INC_DEC(pwgts[to], pwgts[from], vwgt[higain]);
|
|
||||||
|
|
||||||
where[higain] = to;
|
|
||||||
moved[higain] = nswaps;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_MOVEINFO,
|
|
||||||
mprintf("Moved %6D from %D. [%3D %3D] %5D [%4D %4D]\n", higain, from, ed[higain]-id[higain], vwgt[higain], mincut, pwgts[0], pwgts[1]));
|
|
||||||
|
|
||||||
/**************************************************************
|
|
||||||
* Update the id[i]/ed[i] values of the affected nodes
|
|
||||||
***************************************************************/
|
|
||||||
SWAP(id[higain], ed[higain], tmp);
|
|
||||||
if (ed[higain] == 0 && xadj[higain] < xadj[higain+1])
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, higain);
|
|
||||||
|
|
||||||
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
oldgain = ed[k]-id[k];
|
|
||||||
|
|
||||||
kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]);
|
|
||||||
INC_DEC(id[k], ed[k], kwgt);
|
|
||||||
|
|
||||||
/* Update its boundary information and queue position */
|
|
||||||
if (bndptr[k] != -1) { /* If k was a boundary vertex */
|
|
||||||
if (ed[k] == 0) { /* Not a boundary vertex any more */
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, k);
|
|
||||||
if (moved[k] == -1 && where[k] == from && vwgt[k] <= mindiff) /* Remove it if in the queues */
|
|
||||||
PQueueDelete(&parts, k, oldgain);
|
|
||||||
}
|
|
||||||
else { /* If it has not been moved, update its position in the queue */
|
|
||||||
if (moved[k] == -1 && where[k] == from && vwgt[k] <= mindiff)
|
|
||||||
PQueueUpdate(&parts, k, oldgain, ed[k]-id[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (ed[k] > 0) { /* It will now become a boundary vertex */
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, k);
|
|
||||||
if (moved[k] == -1 && where[k] == from && vwgt[k] <= mindiff)
|
|
||||||
PQueueInsert(&parts, k, ed[k]-id[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("\tMinimum cut: %6D, PWGTS: [%6D %6D], NBND: %6D\n", mincut, pwgts[0], pwgts[1], nbnd));
|
|
||||||
|
|
||||||
graph->mincut = mincut;
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
|
|
||||||
PQueueFree(ctrl, &parts);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function balances two partitions by moving the highest gain
|
|
||||||
* (including negative gain) vertices to the other domain.
|
|
||||||
* It is used only when tha unbalance is due to non contigous
|
|
||||||
* subdomains. That is, the are no boundary vertices.
|
|
||||||
* It moves vertices from the domain that is overweight to the one that
|
|
||||||
* is underweight.
|
|
||||||
**************************************************************************/
|
|
||||||
void General2WayBalance(CtrlType *ctrl, GraphType *graph, idxtype *tpwgts)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, tmp;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts;
|
|
||||||
idxtype *moved, *perm;
|
|
||||||
PQueueType parts;
|
|
||||||
idxtype higain, oldgain, mincut, mindiff;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
where = graph->where;
|
|
||||||
id = graph->id;
|
|
||||||
ed = graph->ed;
|
|
||||||
pwgts = graph->pwgts;
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
|
|
||||||
moved = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
|
|
||||||
/* Determine from which domain you will be moving data */
|
|
||||||
mindiff = idxtype_abs(tpwgts[0]-pwgts[0]);
|
|
||||||
from = (pwgts[0] < tpwgts[0] ? 1 : 0);
|
|
||||||
to = (from+1)%2;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("Partitions: [%6D %6D] T[%6D %6D], Nv-Nb[%6D %6D]. ICut: %6D [B]\n",
|
|
||||||
pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));
|
|
||||||
|
|
||||||
tmp = graph->adjwgtsum[idxargmax(nvtxs, graph->adjwgtsum)];
|
|
||||||
PQueueInit(ctrl, &parts, nvtxs, tmp);
|
|
||||||
|
|
||||||
idxset(nvtxs, -1, moved);
|
|
||||||
|
|
||||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
|
||||||
ASSERT(CheckBnd(graph));
|
|
||||||
|
|
||||||
/* Insert the nodes of the proper partition whose size is OK in the priority queue */
|
|
||||||
RandomPermute(nvtxs, perm, 1);
|
|
||||||
for (ii=0; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
if (where[i] == from && vwgt[i] <= mindiff)
|
|
||||||
PQueueInsert(&parts, i, ed[i]-id[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
mincut = graph->mincut;
|
|
||||||
nbnd = graph->nbnd;
|
|
||||||
for (nswaps=0; nswaps<nvtxs; nswaps++) {
|
|
||||||
if ((higain = PQueueGetMax(&parts)) == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (pwgts[to]+vwgt[higain] > tpwgts[to])
|
|
||||||
break;
|
|
||||||
|
|
||||||
mincut -= (ed[higain]-id[higain]);
|
|
||||||
INC_DEC(pwgts[to], pwgts[from], vwgt[higain]);
|
|
||||||
|
|
||||||
where[higain] = to;
|
|
||||||
moved[higain] = nswaps;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_MOVEINFO,
|
|
||||||
mprintf("Moved %6D from %D. [%3D %3D] %5D [%4D %4D]\n", higain, from, ed[higain]-id[higain], vwgt[higain], mincut, pwgts[0], pwgts[1]));
|
|
||||||
|
|
||||||
/**************************************************************
|
|
||||||
* Update the id[i]/ed[i] values of the affected nodes
|
|
||||||
***************************************************************/
|
|
||||||
SWAP(id[higain], ed[higain], tmp);
|
|
||||||
if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1])
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, higain);
|
|
||||||
if (ed[higain] > 0 && bndptr[higain] == -1)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, higain);
|
|
||||||
|
|
||||||
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
oldgain = ed[k]-id[k];
|
|
||||||
|
|
||||||
kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]);
|
|
||||||
INC_DEC(id[k], ed[k], kwgt);
|
|
||||||
|
|
||||||
/* Update the queue position */
|
|
||||||
if (moved[k] == -1 && where[k] == from && vwgt[k] <= mindiff)
|
|
||||||
PQueueUpdate(&parts, k, oldgain, ed[k]-id[k]);
|
|
||||||
|
|
||||||
/* Update its boundary information */
|
|
||||||
if (ed[k] == 0 && bndptr[k] != -1)
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, k);
|
|
||||||
else if (ed[k] > 0 && bndptr[k] == -1)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("\tMinimum cut: %6D, PWGTS: [%6D %6D], NBND: %6D\n", mincut, pwgts[0], pwgts[1], nbnd));
|
|
||||||
|
|
||||||
graph->mincut = mincut;
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
|
|
||||||
PQueueFree(ctrl, &parts);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* bucketsort.c
|
|
||||||
*
|
|
||||||
* This file contains code that implement a variety of counting sorting
|
|
||||||
* algorithms
|
|
||||||
*
|
|
||||||
* Started 7/25/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function uses simple counting sort to return a permutation array
|
|
||||||
* corresponding to the sorted order. The keys are agk_fsumed to start from
|
|
||||||
* 0 and they are positive. This sorting is used during matching.
|
|
||||||
**************************************************************************/
|
|
||||||
void BucketSortKeysInc(idxtype n, idxtype max, idxtype *keys, idxtype *tperm, idxtype *perm)
|
|
||||||
{
|
|
||||||
idxtype i, ii;
|
|
||||||
idxtype *counts;
|
|
||||||
|
|
||||||
counts = idxsmalloc(max+2, 0, "BucketSortKeysInc: counts");
|
|
||||||
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
counts[keys[i]]++;
|
|
||||||
MAKECSR(i, max+1, counts);
|
|
||||||
|
|
||||||
for (ii=0; ii<n; ii++) {
|
|
||||||
i = tperm[ii];
|
|
||||||
perm[counts[keys[i]]++] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_free((void **)&counts, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,520 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* ccgraph.c
|
|
||||||
*
|
|
||||||
* This file contains the functions that create the coarse graph
|
|
||||||
*
|
|
||||||
* Started 8/11/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function creates the coarser graph
|
|
||||||
**************************************************************************/
|
|
||||||
void CreateCoarseGraph(CtrlType *ctrl, GraphType *graph, idxtype cnvtxs, idxtype *match, idxtype *perm)
|
|
||||||
{
|
|
||||||
idxtype i, j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, mask, dovsize;
|
|
||||||
idxtype *xadj, *vwgt, *vsize, *adjncy, *adjwgt, *adjwgtsum, *auxadj;
|
|
||||||
idxtype *cmap, *htable;
|
|
||||||
idxtype *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt, *cadjwgtsum;
|
|
||||||
float *nvwgt, *cnvwgt;
|
|
||||||
GraphType *cgraph;
|
|
||||||
|
|
||||||
dovsize = (ctrl->optype == OP_KVMETIS ? 1 : 0);
|
|
||||||
|
|
||||||
mask = HTLENGTH;
|
|
||||||
if (cnvtxs < 8*mask || graph->nedges/graph->nvtxs > 15) {
|
|
||||||
CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match, perm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
ncon = graph->ncon;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
vsize = graph->vsize;
|
|
||||||
nvwgt = graph->nvwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
adjwgtsum = graph->adjwgtsum;
|
|
||||||
cmap = graph->cmap;
|
|
||||||
|
|
||||||
/* Initialize the coarser graph */
|
|
||||||
cgraph = SetUpCoarseGraph(graph, cnvtxs, dovsize);
|
|
||||||
cxadj = cgraph->xadj;
|
|
||||||
cvwgt = cgraph->vwgt;
|
|
||||||
cvsize = cgraph->vsize;
|
|
||||||
cnvwgt = cgraph->nvwgt;
|
|
||||||
cadjwgtsum = cgraph->adjwgtsum;
|
|
||||||
cadjncy = cgraph->adjncy;
|
|
||||||
cadjwgt = cgraph->adjwgt;
|
|
||||||
|
|
||||||
|
|
||||||
iend = xadj[nvtxs];
|
|
||||||
auxadj = ctrl->wspace.auxcore;
|
|
||||||
memcpy(auxadj, adjncy, iend*sizeof(idxtype));
|
|
||||||
for (i=0; i<iend; i++)
|
|
||||||
auxadj[i] = cmap[auxadj[i]];
|
|
||||||
|
|
||||||
htable = idxset(mask+1, -1, idxwspacemalloc(ctrl, mask+1));
|
|
||||||
|
|
||||||
cxadj[0] = cnvtxs = cnedges = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
v = perm[i];
|
|
||||||
if (cmap[v] != cnvtxs)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
u = match[v];
|
|
||||||
if (ncon == 1)
|
|
||||||
cvwgt[cnvtxs] = vwgt[v];
|
|
||||||
else
|
|
||||||
gk_fcopy(ncon, nvwgt+v*ncon, cnvwgt+cnvtxs*ncon);
|
|
||||||
|
|
||||||
if (dovsize)
|
|
||||||
cvsize[cnvtxs] = vsize[v];
|
|
||||||
|
|
||||||
cadjwgtsum[cnvtxs] = adjwgtsum[v];
|
|
||||||
nedges = 0;
|
|
||||||
|
|
||||||
istart = xadj[v];
|
|
||||||
iend = xadj[v+1];
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
k = auxadj[j];
|
|
||||||
kk = k&mask;
|
|
||||||
if ((m = htable[kk]) == -1) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges] = adjwgt[j];
|
|
||||||
htable[kk] = nedges++;
|
|
||||||
}
|
|
||||||
else if (cadjncy[m] == k) {
|
|
||||||
cadjwgt[m] += adjwgt[j];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (jj=0; jj<nedges; jj++) {
|
|
||||||
if (cadjncy[jj] == k) {
|
|
||||||
cadjwgt[jj] += adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (jj == nedges) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges++] = adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v != u) {
|
|
||||||
if (ncon == 1)
|
|
||||||
cvwgt[cnvtxs] += vwgt[u];
|
|
||||||
else
|
|
||||||
gk_faxpy(ncon, 1.0, nvwgt+u*ncon, 1, cnvwgt+cnvtxs*ncon, 1);
|
|
||||||
|
|
||||||
if (dovsize)
|
|
||||||
cvsize[cnvtxs] += vsize[u];
|
|
||||||
|
|
||||||
cadjwgtsum[cnvtxs] += adjwgtsum[u];
|
|
||||||
|
|
||||||
istart = xadj[u];
|
|
||||||
iend = xadj[u+1];
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
k = auxadj[j];
|
|
||||||
kk = k&mask;
|
|
||||||
if ((m = htable[kk]) == -1) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges] = adjwgt[j];
|
|
||||||
htable[kk] = nedges++;
|
|
||||||
}
|
|
||||||
else if (cadjncy[m] == k) {
|
|
||||||
cadjwgt[m] += adjwgt[j];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (jj=0; jj<nedges; jj++) {
|
|
||||||
if (cadjncy[jj] == k) {
|
|
||||||
cadjwgt[jj] += adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (jj == nedges) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges++] = adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the contracted adjacency weight */
|
|
||||||
jj = htable[cnvtxs&mask];
|
|
||||||
if (jj >= 0 && cadjncy[jj] != cnvtxs) {
|
|
||||||
for (jj=0; jj<nedges; jj++) {
|
|
||||||
if (cadjncy[jj] == cnvtxs)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (jj >= 0 && cadjncy[jj] == cnvtxs) { /* This 2nd check is needed for non-adjacent matchings */
|
|
||||||
cadjwgtsum[cnvtxs] -= cadjwgt[jj];
|
|
||||||
cadjncy[jj] = cadjncy[--nedges];
|
|
||||||
cadjwgt[jj] = cadjwgt[nedges];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERTP(cadjwgtsum[cnvtxs] == idxsum(nedges, cadjwgt), ("%d %d %d %d %d\n", cnvtxs, cadjwgtsum[cnvtxs], idxsum(nedges, cadjwgt), adjwgtsum[u], adjwgtsum[v]));
|
|
||||||
|
|
||||||
for (j=0; j<nedges; j++)
|
|
||||||
htable[cadjncy[j]&mask] = -1; /* Zero out the htable */
|
|
||||||
htable[cnvtxs&mask] = -1;
|
|
||||||
|
|
||||||
cnedges += nedges;
|
|
||||||
cxadj[++cnvtxs] = cnedges;
|
|
||||||
cadjncy += nedges;
|
|
||||||
cadjwgt += nedges;
|
|
||||||
}
|
|
||||||
|
|
||||||
cgraph->nedges = cnedges;
|
|
||||||
|
|
||||||
ReAdjustMemory(graph, cgraph, dovsize);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, mask+1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function creates the coarser graph
|
|
||||||
**************************************************************************/
|
|
||||||
void CreateCoarseGraphNoMask(CtrlType *ctrl, GraphType *graph, idxtype cnvtxs, idxtype *match, idxtype *perm)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, dovsize;
|
|
||||||
idxtype *xadj, *vwgt, *vsize, *adjncy, *adjwgt, *adjwgtsum, *auxadj;
|
|
||||||
idxtype *cmap, *htable;
|
|
||||||
idxtype *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt, *cadjwgtsum;
|
|
||||||
float *nvwgt, *cnvwgt;
|
|
||||||
GraphType *cgraph;
|
|
||||||
|
|
||||||
dovsize = (ctrl->optype == OP_KVMETIS ? 1 : 0);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
ncon = graph->ncon;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
vsize = graph->vsize;
|
|
||||||
nvwgt = graph->nvwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
adjwgtsum = graph->adjwgtsum;
|
|
||||||
cmap = graph->cmap;
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the coarser graph */
|
|
||||||
cgraph = SetUpCoarseGraph(graph, cnvtxs, dovsize);
|
|
||||||
cxadj = cgraph->xadj;
|
|
||||||
cvwgt = cgraph->vwgt;
|
|
||||||
cvsize = cgraph->vsize;
|
|
||||||
cnvwgt = cgraph->nvwgt;
|
|
||||||
cadjwgtsum = cgraph->adjwgtsum;
|
|
||||||
cadjncy = cgraph->adjncy;
|
|
||||||
cadjwgt = cgraph->adjwgt;
|
|
||||||
|
|
||||||
|
|
||||||
htable = idxset(cnvtxs, -1, idxwspacemalloc(ctrl, cnvtxs));
|
|
||||||
|
|
||||||
iend = xadj[nvtxs];
|
|
||||||
auxadj = ctrl->wspace.auxcore;
|
|
||||||
memcpy(auxadj, adjncy, iend*sizeof(idxtype));
|
|
||||||
for (i=0; i<iend; i++)
|
|
||||||
auxadj[i] = cmap[auxadj[i]];
|
|
||||||
|
|
||||||
cxadj[0] = cnvtxs = cnedges = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
v = perm[i];
|
|
||||||
if (cmap[v] != cnvtxs)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
u = match[v];
|
|
||||||
if (ncon == 1)
|
|
||||||
cvwgt[cnvtxs] = vwgt[v];
|
|
||||||
else
|
|
||||||
gk_fcopy(ncon, nvwgt+v*ncon, cnvwgt+cnvtxs*ncon);
|
|
||||||
|
|
||||||
if (dovsize)
|
|
||||||
cvsize[cnvtxs] = vsize[v];
|
|
||||||
|
|
||||||
cadjwgtsum[cnvtxs] = adjwgtsum[v];
|
|
||||||
nedges = 0;
|
|
||||||
|
|
||||||
istart = xadj[v];
|
|
||||||
iend = xadj[v+1];
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
k = auxadj[j];
|
|
||||||
if ((m = htable[k]) == -1) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges] = adjwgt[j];
|
|
||||||
htable[k] = nedges++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cadjwgt[m] += adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v != u) {
|
|
||||||
if (ncon == 1)
|
|
||||||
cvwgt[cnvtxs] += vwgt[u];
|
|
||||||
else
|
|
||||||
gk_faxpy(ncon, 1.0, nvwgt+u*ncon, 1, cnvwgt+cnvtxs*ncon, 1);
|
|
||||||
|
|
||||||
if (dovsize)
|
|
||||||
cvsize[cnvtxs] += vsize[u];
|
|
||||||
|
|
||||||
cadjwgtsum[cnvtxs] += adjwgtsum[u];
|
|
||||||
|
|
||||||
istart = xadj[u];
|
|
||||||
iend = xadj[u+1];
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
k = auxadj[j];
|
|
||||||
if ((m = htable[k]) == -1) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges] = adjwgt[j];
|
|
||||||
htable[k] = nedges++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cadjwgt[m] += adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the contracted adjacency weight */
|
|
||||||
if ((j = htable[cnvtxs]) != -1) {
|
|
||||||
ASSERT(cadjncy[j] == cnvtxs);
|
|
||||||
cadjwgtsum[cnvtxs] -= cadjwgt[j];
|
|
||||||
cadjncy[j] = cadjncy[--nedges];
|
|
||||||
cadjwgt[j] = cadjwgt[nedges];
|
|
||||||
htable[cnvtxs] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERTP(cadjwgtsum[cnvtxs] == idxsum(nedges, cadjwgt), ("%d %d\n", cadjwgtsum[cnvtxs], idxsum(nedges, cadjwgt)));
|
|
||||||
|
|
||||||
for (j=0; j<nedges; j++)
|
|
||||||
htable[cadjncy[j]] = -1; /* Zero out the htable */
|
|
||||||
|
|
||||||
cnedges += nedges;
|
|
||||||
cxadj[++cnvtxs] = cnedges;
|
|
||||||
cadjncy += nedges;
|
|
||||||
cadjwgt += nedges;
|
|
||||||
}
|
|
||||||
|
|
||||||
cgraph->nedges = cnedges;
|
|
||||||
|
|
||||||
ReAdjustMemory(graph, cgraph, dovsize);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, cnvtxs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function creates the coarser graph
|
|
||||||
**************************************************************************/
|
|
||||||
void CreateCoarseGraph_NVW(CtrlType *ctrl, GraphType *graph, idxtype cnvtxs, idxtype *match, idxtype *perm)
|
|
||||||
{
|
|
||||||
idxtype i, j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, mask;
|
|
||||||
idxtype *xadj, *adjncy, *adjwgtsum, *auxadj;
|
|
||||||
idxtype *cmap, *htable;
|
|
||||||
idxtype *cxadj, *cvwgt, *cadjncy, *cadjwgt, *cadjwgtsum;
|
|
||||||
float *nvwgt, *cnvwgt;
|
|
||||||
GraphType *cgraph;
|
|
||||||
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->ContractTmr));
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
ncon = graph->ncon;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
nvwgt = graph->nvwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgtsum = graph->adjwgtsum;
|
|
||||||
cmap = graph->cmap;
|
|
||||||
|
|
||||||
/* Initialize the coarser graph */
|
|
||||||
cgraph = SetUpCoarseGraph(graph, cnvtxs, 0);
|
|
||||||
cxadj = cgraph->xadj;
|
|
||||||
cvwgt = cgraph->vwgt;
|
|
||||||
cnvwgt = cgraph->nvwgt;
|
|
||||||
cadjwgtsum = cgraph->adjwgtsum;
|
|
||||||
cadjncy = cgraph->adjncy;
|
|
||||||
cadjwgt = cgraph->adjwgt;
|
|
||||||
|
|
||||||
|
|
||||||
iend = xadj[nvtxs];
|
|
||||||
auxadj = ctrl->wspace.auxcore;
|
|
||||||
memcpy(auxadj, adjncy, iend*sizeof(idxtype));
|
|
||||||
for (i=0; i<iend; i++)
|
|
||||||
auxadj[i] = cmap[auxadj[i]];
|
|
||||||
|
|
||||||
mask = HTLENGTH;
|
|
||||||
htable = idxset(mask+1, -1, idxwspacemalloc(ctrl, mask+1));
|
|
||||||
|
|
||||||
cxadj[0] = cnvtxs = cnedges = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
v = perm[i];
|
|
||||||
if (cmap[v] != cnvtxs)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
u = match[v];
|
|
||||||
cvwgt[cnvtxs] = 1;
|
|
||||||
cadjwgtsum[cnvtxs] = adjwgtsum[v];
|
|
||||||
nedges = 0;
|
|
||||||
|
|
||||||
istart = xadj[v];
|
|
||||||
iend = xadj[v+1];
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
k = auxadj[j];
|
|
||||||
kk = k&mask;
|
|
||||||
if ((m = htable[kk]) == -1) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges] = 1;
|
|
||||||
htable[kk] = nedges++;
|
|
||||||
}
|
|
||||||
else if (cadjncy[m] == k) {
|
|
||||||
cadjwgt[m]++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (jj=0; jj<nedges; jj++) {
|
|
||||||
if (cadjncy[jj] == k) {
|
|
||||||
cadjwgt[jj]++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (jj == nedges) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges++] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v != u) {
|
|
||||||
cvwgt[cnvtxs]++;
|
|
||||||
cadjwgtsum[cnvtxs] += adjwgtsum[u];
|
|
||||||
|
|
||||||
istart = xadj[u];
|
|
||||||
iend = xadj[u+1];
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
k = auxadj[j];
|
|
||||||
kk = k&mask;
|
|
||||||
if ((m = htable[kk]) == -1) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges] = 1;
|
|
||||||
htable[kk] = nedges++;
|
|
||||||
}
|
|
||||||
else if (cadjncy[m] == k) {
|
|
||||||
cadjwgt[m]++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (jj=0; jj<nedges; jj++) {
|
|
||||||
if (cadjncy[jj] == k) {
|
|
||||||
cadjwgt[jj]++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (jj == nedges) {
|
|
||||||
cadjncy[nedges] = k;
|
|
||||||
cadjwgt[nedges++] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the contracted adjacency weight */
|
|
||||||
jj = htable[cnvtxs&mask];
|
|
||||||
if (jj >= 0 && cadjncy[jj] != cnvtxs) {
|
|
||||||
for (jj=0; jj<nedges; jj++) {
|
|
||||||
if (cadjncy[jj] == cnvtxs)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (jj >= 0 && cadjncy[jj] == cnvtxs) { /* This 2nd check is needed for non-adjacent matchings */
|
|
||||||
cadjwgtsum[cnvtxs] -= cadjwgt[jj];
|
|
||||||
cadjncy[jj] = cadjncy[--nedges];
|
|
||||||
cadjwgt[jj] = cadjwgt[nedges];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERTP(cadjwgtsum[cnvtxs] == idxsum(nedges, cadjwgt), ("%d %d %d %d %d\n", cnvtxs, cadjwgtsum[cnvtxs], idxsum(nedges, cadjwgt), adjwgtsum[u], adjwgtsum[v]));
|
|
||||||
|
|
||||||
for (j=0; j<nedges; j++)
|
|
||||||
htable[cadjncy[j]&mask] = -1; /* Zero out the htable */
|
|
||||||
htable[cnvtxs&mask] = -1;
|
|
||||||
|
|
||||||
cnedges += nedges;
|
|
||||||
cxadj[++cnvtxs] = cnedges;
|
|
||||||
cadjncy += nedges;
|
|
||||||
cadjwgt += nedges;
|
|
||||||
}
|
|
||||||
|
|
||||||
cgraph->nedges = cnedges;
|
|
||||||
|
|
||||||
ReAdjustMemory(graph, cgraph, 0);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->ContractTmr));
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, mask+1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Setup the various arrays for the coarse graph
|
|
||||||
**************************************************************************/
|
|
||||||
GraphType *SetUpCoarseGraph(GraphType *graph, idxtype cnvtxs, idxtype dovsize)
|
|
||||||
{
|
|
||||||
GraphType *cgraph;
|
|
||||||
|
|
||||||
cgraph = CreateGraph();
|
|
||||||
|
|
||||||
cgraph->nvtxs = cnvtxs;
|
|
||||||
cgraph->ncon = graph->ncon;
|
|
||||||
|
|
||||||
cgraph->finer = graph;
|
|
||||||
graph->coarser = cgraph;
|
|
||||||
|
|
||||||
|
|
||||||
/* Allocate memory for the coarser graph */
|
|
||||||
cgraph->xadj = idxmalloc(cnvtxs+1, "SetUpCoarseGraph: xadj");
|
|
||||||
cgraph->adjwgtsum = idxmalloc(cnvtxs, "SetUpCoarseGraph: adjwgtsum");
|
|
||||||
cgraph->cmap = idxmalloc(cnvtxs, "SetUpCoarseGraph: cmap");
|
|
||||||
cgraph->adjncy = idxmalloc(graph->nedges, "SetUpCoarseGraph: adjncy");
|
|
||||||
cgraph->adjwgt = idxmalloc(graph->nedges, "SetUpCoarseGraph: adjwgt");
|
|
||||||
|
|
||||||
if (graph->ncon == 1)
|
|
||||||
cgraph->vwgt = idxmalloc(cnvtxs, "SetUpCoarseGraph: vwgt");
|
|
||||||
else
|
|
||||||
cgraph->nvwgt = gk_fmalloc(graph->ncon*cnvtxs, "SetUpCoarseGraph: nvwgt");
|
|
||||||
|
|
||||||
if (dovsize)
|
|
||||||
cgraph->vsize = idxmalloc(cnvtxs, "SetUpCoarseGraph: vsize");
|
|
||||||
|
|
||||||
return cgraph;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function re-adjusts the amount of memory that was allocated if
|
|
||||||
* it will lead to significant savings
|
|
||||||
**************************************************************************/
|
|
||||||
void ReAdjustMemory(GraphType *graph, GraphType *cgraph, idxtype dovsize)
|
|
||||||
{
|
|
||||||
if (cgraph->nedges > 10000 && cgraph->nedges < 0.8*graph->nedges) {
|
|
||||||
cgraph->adjncy = idxrealloc(cgraph->adjncy, cgraph->nedges, "ReAdjustMemory: adjncy");
|
|
||||||
cgraph->adjwgt = idxrealloc(cgraph->adjwgt, cgraph->nedges, "ReAdjustMemory: adjwgt");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* checkgraph.c
|
|
||||||
*
|
|
||||||
* This file contains routines related to I/O
|
|
||||||
*
|
|
||||||
* Started 8/28/94
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks if a graph is valid
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype CheckGraph(GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, l;
|
|
||||||
idxtype nvtxs, ncon, err=0;
|
|
||||||
idxtype minedge, maxedge, minewgt, maxewgt;
|
|
||||||
float minvwgt[MAXNCON], maxvwgt[MAXNCON];
|
|
||||||
idxtype *xadj, *adjncy, *adjwgt, *htable;
|
|
||||||
float *nvwgt, ntvwgts[MAXNCON];
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
ncon = graph->ncon;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
nvwgt = graph->nvwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
htable = idxsmalloc(nvtxs, 0, "htable");
|
|
||||||
|
|
||||||
if (ncon > 1) {
|
|
||||||
for (j=0; j<ncon; j++) {
|
|
||||||
minvwgt[j] = maxvwgt[j] = nvwgt[j];
|
|
||||||
ntvwgts[j] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
minedge = maxedge = adjncy[0];
|
|
||||||
minewgt = maxewgt = adjwgt[0];
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (ncon > 1) {
|
|
||||||
for (j=0; j<ncon; j++) {
|
|
||||||
ntvwgts[j] += nvwgt[i*ncon+j];
|
|
||||||
minvwgt[j] = (nvwgt[i*ncon+j] < minvwgt[j]) ? nvwgt[i*ncon+j] : minvwgt[j];
|
|
||||||
maxvwgt[j] = (nvwgt[i*ncon+j] > maxvwgt[j]) ? nvwgt[i*ncon+j] : maxvwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
|
|
||||||
minedge = (k < minedge) ? k : minedge;
|
|
||||||
maxedge = (k > maxedge) ? k : maxedge;
|
|
||||||
minewgt = (adjwgt[j] < minewgt) ? adjwgt[j] : minewgt;
|
|
||||||
maxewgt = (adjwgt[j] > maxewgt) ? adjwgt[j] : maxewgt;
|
|
||||||
|
|
||||||
if (i == k) {
|
|
||||||
mprintf("Vertex %D contains a self-loop (i.e., diagonal entry in the matrix)!\n", i);
|
|
||||||
err++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (l=xadj[k]; l<xadj[k+1]; l++) {
|
|
||||||
if (adjncy[l] == i) {
|
|
||||||
if (adjwgt != NULL && adjwgt[l] != adjwgt[j]) {
|
|
||||||
mprintf("Edges (%D %D) and (%D %D) do not have the same weight! %D %D\n", i,k,k,i, adjwgt[l], adjwgt[j]);
|
|
||||||
err++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (l == xadj[k+1]) {
|
|
||||||
mprintf("Missing edge: (%D %D)!\n", k, i);
|
|
||||||
err++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (htable[k] == 0) {
|
|
||||||
htable[k]++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mprintf("Edge %D from vertex %D is repeated %D times\n", k, i, htable[k]++);
|
|
||||||
err++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
htable[adjncy[j]] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ncon > 1) {
|
|
||||||
for (j=0; j<ncon; j++) {
|
|
||||||
if (fabs(ntvwgts[j] - 1.0) > 0.0001) {
|
|
||||||
mprintf("Normalized vwgts don't sum to one. Weight %D = %.8f.\n", j, ntvwgts[j]);
|
|
||||||
err++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
mprintf("errs: %D, adjncy: [%D %D], adjwgt: [%D %D]\n",
|
|
||||||
err, minedge, maxedge, minewgt, maxewgt);
|
|
||||||
if (ncon > 1) {
|
|
||||||
for (j=0; j<ncon; j++)
|
|
||||||
mprintf("[%.5f %.5f] ", minvwgt[j], maxvwgt[j]);
|
|
||||||
mprintf("\n");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (err > 0) {
|
|
||||||
mprintf("A total of %D errors exist in the input file. Correct them, and run again!\n", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_free((void **)&htable, LTERM);
|
|
||||||
return (err == 0 ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* coarsen.c
|
|
||||||
*
|
|
||||||
* This file contains the driving routines for the coarsening process
|
|
||||||
*
|
|
||||||
* Started 7/23/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes a graph and creates a sequence of coarser graphs
|
|
||||||
**************************************************************************/
|
|
||||||
GraphType *Coarsen2Way(CtrlType *ctrl, GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype clevel;
|
|
||||||
GraphType *cgraph;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr));
|
|
||||||
|
|
||||||
cgraph = graph;
|
|
||||||
|
|
||||||
/* The following is ahack to allow the multiple bisections to go through with correct
|
|
||||||
coarsening */
|
|
||||||
if (ctrl->CType > 20) {
|
|
||||||
clevel = 1;
|
|
||||||
ctrl->CType -= 20;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
clevel = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
IFSET(ctrl->dbglvl, DBG_COARSEN, mprintf("%6D %7D %7D [%D] [%D %D]\n",
|
|
||||||
cgraph->nvtxs, cgraph->nedges/2, idxsum(cgraph->nvtxs, cgraph->adjwgtsum, 1)/2,
|
|
||||||
ctrl->CoarsenTo, ctrl->maxvwgt,
|
|
||||||
(cgraph->vwgt ? idxsum(cgraph->nvtxs, cgraph->vwgt, 1) : cgraph->nvtxs)));
|
|
||||||
|
|
||||||
if (cgraph->adjwgt) {
|
|
||||||
switch (ctrl->CType) {
|
|
||||||
case MTYPE_RM:
|
|
||||||
Match_RM(ctrl, cgraph);
|
|
||||||
break;
|
|
||||||
case MTYPE_HEM:
|
|
||||||
if (clevel < 1 || cgraph->nedges == 0)
|
|
||||||
Match_RM(ctrl, cgraph);
|
|
||||||
else
|
|
||||||
Match_HEM(ctrl, cgraph);
|
|
||||||
break;
|
|
||||||
case MTYPE_SHEM:
|
|
||||||
if (clevel < 1 || cgraph->nedges == 0)
|
|
||||||
Match_RM(ctrl, cgraph);
|
|
||||||
else
|
|
||||||
Match_SHEM(ctrl, cgraph);
|
|
||||||
break;
|
|
||||||
case MTYPE_SHEMKWAY:
|
|
||||||
if (cgraph->nedges == 0)
|
|
||||||
Match_RM(ctrl, cgraph);
|
|
||||||
else
|
|
||||||
Match_SHEM(ctrl, cgraph);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errexit("Unknown CType: %d\n", ctrl->CType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Match_RM_NVW(ctrl, cgraph);
|
|
||||||
}
|
|
||||||
|
|
||||||
cgraph = cgraph->coarser;
|
|
||||||
clevel++;
|
|
||||||
|
|
||||||
} while (cgraph->nvtxs > ctrl->CoarsenTo && cgraph->nvtxs < COARSEN_FRACTION2*cgraph->finer->nvtxs && cgraph->nedges > cgraph->nvtxs/2);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_COARSEN, mprintf("%6D %7D %7D [%D] [%D %D]\n",
|
|
||||||
cgraph->nvtxs, cgraph->nedges/2, idxsum(cgraph->nvtxs, cgraph->adjwgtsum, 1)/2,
|
|
||||||
ctrl->CoarsenTo, ctrl->maxvwgt,
|
|
||||||
(cgraph->vwgt ? idxsum(cgraph->nvtxs, cgraph->vwgt, 1) : cgraph->nvtxs)));
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr));
|
|
||||||
|
|
||||||
return cgraph;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,255 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* compress.c
|
|
||||||
*
|
|
||||||
* This file contains code for compressing nodes with identical adjacency
|
|
||||||
* structure and for prunning dense columns
|
|
||||||
*
|
|
||||||
* Started 9/17/97
|
|
||||||
* George
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function compresses a graph by merging identical vertices
|
|
||||||
* The compression should lead to at least 10% reduction.
|
|
||||||
**************************************************************************/
|
|
||||||
void CompressGraph(CtrlType *ctrl, GraphType *graph, idxtype nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *cptr, idxtype *cind)
|
|
||||||
{
|
|
||||||
idxtype i, ii, iii, j, jj, k, l, cnvtxs, cnedges;
|
|
||||||
idxtype *cxadj, *cadjncy, *cvwgt, *mark, *map;
|
|
||||||
KeyValueType *keys;
|
|
||||||
|
|
||||||
mark = idxsmalloc(nvtxs, -1, "CompressGraph: mark");
|
|
||||||
map = idxsmalloc(nvtxs, -1, "CompressGraph: map");
|
|
||||||
keys = (KeyValueType *)gk_malloc(nvtxs*sizeof(KeyValueType), "CompressGraph: keys");
|
|
||||||
|
|
||||||
/* Compute a key for each adjacency list */
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
k = 0;
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++)
|
|
||||||
k += adjncy[j];
|
|
||||||
keys[i].key = k+i; /* Add the diagonal entry as well */
|
|
||||||
keys[i].val = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
ikeysort(nvtxs, keys);
|
|
||||||
|
|
||||||
l = cptr[0] = 0;
|
|
||||||
for (cnvtxs=i=0; i<nvtxs; i++) {
|
|
||||||
ii = keys[i].val;
|
|
||||||
if (map[ii] == -1) {
|
|
||||||
mark[ii] = i; /* Add the diagonal entry */
|
|
||||||
for (j=xadj[ii]; j<xadj[ii+1]; j++)
|
|
||||||
mark[adjncy[j]] = i;
|
|
||||||
|
|
||||||
cind[l++] = ii;
|
|
||||||
map[ii] = cnvtxs;
|
|
||||||
|
|
||||||
for (j=i+1; j<nvtxs; j++) {
|
|
||||||
iii = keys[j].val;
|
|
||||||
|
|
||||||
if (keys[i].key != keys[j].key || xadj[ii+1]-xadj[ii] != xadj[iii+1]-xadj[iii])
|
|
||||||
break; /* Break if keys or degrees are different */
|
|
||||||
|
|
||||||
if (map[iii] == -1) { /* Do a comparison if iii has not been mapped */
|
|
||||||
for (jj=xadj[iii]; jj<xadj[iii+1]; jj++) {
|
|
||||||
if (mark[adjncy[jj]] != i)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jj == xadj[iii+1]) { /* Identical adjacency structure */
|
|
||||||
map[iii] = cnvtxs;
|
|
||||||
cind[l++] = iii;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cptr[++cnvtxs] = l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mprintf("Original: %6D, Compressed: %6D\n", nvtxs, cnvtxs); */
|
|
||||||
|
|
||||||
|
|
||||||
InitGraph(graph);
|
|
||||||
|
|
||||||
if (cnvtxs >= COMPRESSION_FRACTION*nvtxs) {
|
|
||||||
graph->nvtxs = nvtxs;
|
|
||||||
graph->nedges = xadj[nvtxs];
|
|
||||||
graph->ncon = 1;
|
|
||||||
graph->xadj = xadj;
|
|
||||||
graph->free_xadj = 0;
|
|
||||||
graph->adjncy = adjncy;
|
|
||||||
graph->free_adjncy = 0;
|
|
||||||
|
|
||||||
graph->vwgt = idxmalloc(nvtxs, "CompressGraph: vwgt");
|
|
||||||
graph->adjwgtsum = idxmalloc(nvtxs, "CompressGraph: adjwgtsum");
|
|
||||||
graph->cmap = idxmalloc(nvtxs, "CompressGraph: cmap");
|
|
||||||
graph->adjwgt = idxmalloc(graph->nedges, "CompressGraph: adjwgt");
|
|
||||||
|
|
||||||
idxset(nvtxs, 1, graph->vwgt);
|
|
||||||
idxset(graph->nedges, 1, graph->adjwgt);
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
graph->adjwgtsum[i] = xadj[i+1]-xadj[i];
|
|
||||||
|
|
||||||
graph->label = idxmalloc(nvtxs, "CompressGraph: label");
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
graph->label[i] = i;
|
|
||||||
}
|
|
||||||
else { /* Ok, form the compressed graph */
|
|
||||||
cnedges = 0;
|
|
||||||
for (i=0; i<cnvtxs; i++) {
|
|
||||||
ii = cind[cptr[i]];
|
|
||||||
cnedges += xadj[ii+1]-xadj[ii];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate memory for the compressed graph*/
|
|
||||||
cxadj = graph->xadj = idxmalloc(cnvtxs+1, "CompressGraph: xadj");
|
|
||||||
cvwgt = graph->vwgt = idxmalloc(cnvtxs, "CompressGraph: vwgt");
|
|
||||||
graph->adjwgtsum = idxmalloc(cnvtxs, "CompressGraph: adjwgtsum");
|
|
||||||
graph->cmap = idxmalloc(cnvtxs, "CompressGraph: cmap");
|
|
||||||
cadjncy = graph->adjncy = idxmalloc(cnedges, "CompressGraph: adjncy");
|
|
||||||
graph->adjwgt = idxmalloc(cnedges, "CompressGraph: adjwgt");
|
|
||||||
|
|
||||||
/* Now go and compress the graph */
|
|
||||||
idxset(nvtxs, -1, mark);
|
|
||||||
l = cxadj[0] = 0;
|
|
||||||
for (i=0; i<cnvtxs; i++) {
|
|
||||||
cvwgt[i] = cptr[i+1]-cptr[i];
|
|
||||||
mark[i] = i; /* Remove any dioganal entries in the compressed graph */
|
|
||||||
for (j=cptr[i]; j<cptr[i+1]; j++) {
|
|
||||||
ii = cind[j];
|
|
||||||
for (jj=xadj[ii]; jj<xadj[ii+1]; jj++) {
|
|
||||||
k = map[adjncy[jj]];
|
|
||||||
if (mark[k] != i)
|
|
||||||
cadjncy[l++] = k;
|
|
||||||
mark[k] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cxadj[i+1] = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nvtxs = cnvtxs;
|
|
||||||
graph->nedges = l;
|
|
||||||
graph->ncon = 1;
|
|
||||||
|
|
||||||
idxset(graph->nedges, 1, graph->adjwgt);
|
|
||||||
for (i=0; i<cnvtxs; i++)
|
|
||||||
graph->adjwgtsum[i] = cxadj[i+1]-cxadj[i];
|
|
||||||
|
|
||||||
graph->label = idxmalloc(cnvtxs, "CompressGraph: label");
|
|
||||||
for (i=0; i<cnvtxs; i++)
|
|
||||||
graph->label[i] = i;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_free((void **)&keys, &map, &mark, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function prunes all the vertices in a graph with degree greater
|
|
||||||
* than factor*average
|
|
||||||
**************************************************************************/
|
|
||||||
void PruneGraph(CtrlType *ctrl, GraphType *graph, idxtype nvtxs, idxtype *xadj,
|
|
||||||
idxtype *adjncy, idxtype *iperm, float factor)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, l, nlarge, pnvtxs, pnedges;
|
|
||||||
idxtype *pxadj, *padjncy, *padjwgt;
|
|
||||||
idxtype *perm;
|
|
||||||
|
|
||||||
perm = idxmalloc(nvtxs, "PruneGraph: perm");
|
|
||||||
|
|
||||||
factor = factor*xadj[nvtxs]/nvtxs;
|
|
||||||
|
|
||||||
pnvtxs = pnedges = nlarge = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (xadj[i+1]-xadj[i] < factor) {
|
|
||||||
perm[i] = pnvtxs;
|
|
||||||
iperm[pnvtxs++] = i;
|
|
||||||
pnedges += xadj[i+1]-xadj[i];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
perm[i] = nvtxs - ++nlarge;
|
|
||||||
iperm[nvtxs-nlarge] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mprintf("Pruned %D vertices\n", nlarge); */
|
|
||||||
|
|
||||||
InitGraph(graph);
|
|
||||||
|
|
||||||
if (nlarge == 0) { /* No prunning */
|
|
||||||
graph->nvtxs = nvtxs;
|
|
||||||
graph->nedges = xadj[nvtxs];
|
|
||||||
graph->ncon = 1;
|
|
||||||
graph->xadj = xadj;
|
|
||||||
graph->free_xadj = 0;
|
|
||||||
graph->adjncy = adjncy;
|
|
||||||
graph->free_adjncy = 0;
|
|
||||||
|
|
||||||
graph->vwgt = idxmalloc(nvtxs, "PruneGraph: vwgt");
|
|
||||||
graph->adjwgtsum = idxmalloc(nvtxs, "PruneGraph: adjwgtsum");
|
|
||||||
graph->cmap = idxmalloc(nvtxs, "PruneGraph: cmap");
|
|
||||||
graph->adjwgt = idxmalloc(graph->nedges, "PruneGraph: adjwgt");
|
|
||||||
|
|
||||||
idxset(nvtxs, 1, graph->vwgt);
|
|
||||||
idxset(graph->nedges, 1, graph->adjwgt);
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
graph->adjwgtsum[i] = xadj[i+1]-xadj[i];
|
|
||||||
|
|
||||||
graph->label = idxmalloc(nvtxs, "CompressGraph: label");
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
graph->label[i] = i;
|
|
||||||
}
|
|
||||||
else { /* Prune the graph */
|
|
||||||
/* Allocate memory for the prunned graph*/
|
|
||||||
pxadj = graph->xadj = idxmalloc(pnvtxs+1, "PruneGraph: xadj");
|
|
||||||
graph->vwgt = idxmalloc(pnvtxs, "PruneGraph: vwgt");
|
|
||||||
graph->adjwgtsum = idxmalloc(pnvtxs, "PruneGraph: adjwgtsum");
|
|
||||||
graph->cmap = idxmalloc(pnvtxs, "PruneGraph: cmap");
|
|
||||||
padjncy = graph->adjncy = idxmalloc(pnedges, "PruneGraph: adjncy");
|
|
||||||
graph->adjwgt = idxmalloc(pnedges, "PruneGraph: adjwgt");
|
|
||||||
|
|
||||||
pxadj[0] = pnedges = l = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (xadj[i+1]-xadj[i] < factor) {
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = perm[adjncy[j]];
|
|
||||||
if (k < pnvtxs)
|
|
||||||
padjncy[pnedges++] = k;
|
|
||||||
}
|
|
||||||
pxadj[++l] = pnedges;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nvtxs = pnvtxs;
|
|
||||||
graph->nedges = pnedges;
|
|
||||||
graph->ncon = 1;
|
|
||||||
|
|
||||||
idxset(pnvtxs, 1, graph->vwgt);
|
|
||||||
idxset(pnedges, 1, graph->adjwgt);
|
|
||||||
for (i=0; i<pnvtxs; i++)
|
|
||||||
graph->adjwgtsum[i] = pxadj[i+1]-pxadj[i];
|
|
||||||
|
|
||||||
graph->label = idxmalloc(pnvtxs, "CompressGraph: label");
|
|
||||||
for (i=0; i<pnvtxs; i++)
|
|
||||||
graph->label[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_free((void **)&perm, LTERM);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,272 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* debug.c
|
|
||||||
*
|
|
||||||
* This file contains code that performs self debuging
|
|
||||||
*
|
|
||||||
* Started 7/24/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the cut given the graph and a where vector
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype ComputeCut(GraphType *graph, idxtype *where)
|
|
||||||
{
|
|
||||||
idxtype i, j, cut;
|
|
||||||
|
|
||||||
if (graph->adjwgt == NULL) {
|
|
||||||
for (cut=0, i=0; i<graph->nvtxs; i++) {
|
|
||||||
for (j=graph->xadj[i]; j<graph->xadj[i+1]; j++)
|
|
||||||
if (where[i] != where[graph->adjncy[j]])
|
|
||||||
cut++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (cut=0, i=0; i<graph->nvtxs; i++) {
|
|
||||||
for (j=graph->xadj[i]; j<graph->xadj[i+1]; j++)
|
|
||||||
if (where[i] != where[graph->adjncy[j]])
|
|
||||||
cut += graph->adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cut/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the cut given the graph and a where vector
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype ComputeMaxCut(GraphType *graph, idxtype nparts, idxtype *where)
|
|
||||||
{
|
|
||||||
idxtype i, j, maxcut;
|
|
||||||
idxtype *cuts;
|
|
||||||
|
|
||||||
cuts = idxsmalloc(nparts, 0, "ComputeMaxCut: cuts");
|
|
||||||
|
|
||||||
if (graph->adjwgt == NULL) {
|
|
||||||
for (i=0; i<graph->nvtxs; i++) {
|
|
||||||
for (j=graph->xadj[i]; j<graph->xadj[i+1]; j++)
|
|
||||||
if (where[i] != where[graph->adjncy[j]])
|
|
||||||
cuts[where[i]]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (i=0; i<graph->nvtxs; i++) {
|
|
||||||
for (j=graph->xadj[i]; j<graph->xadj[i+1]; j++)
|
|
||||||
if (where[i] != where[graph->adjncy[j]])
|
|
||||||
cuts[where[i]] += graph->adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
maxcut = cuts[idxargmax(nparts, cuts)];
|
|
||||||
|
|
||||||
mprintf("%D => %D\n", idxargmax(nparts, cuts), maxcut);
|
|
||||||
|
|
||||||
gk_free((void **)&cuts, LTERM);
|
|
||||||
|
|
||||||
return maxcut;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks whether or not the boundary information is correct
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype CheckBnd(GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, j, nvtxs, nbnd;
|
|
||||||
idxtype *xadj, *adjncy, *where, *bndptr, *bndind;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
where = graph->where;
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
|
|
||||||
for (nbnd=0, i=0; i<nvtxs; i++) {
|
|
||||||
if (xadj[i+1]-xadj[i] == 0)
|
|
||||||
nbnd++; /* Islands are considered to be boundary vertices */
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (where[i] != where[adjncy[j]]) {
|
|
||||||
nbnd++;
|
|
||||||
ASSERT(bndptr[i] != -1);
|
|
||||||
ASSERT(bndind[bndptr[i]] == i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERTP(nbnd == graph->nbnd, ("%d %d\n", nbnd, graph->nbnd));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks whether or not the boundary information is correct
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype CheckBnd2(GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, j, nvtxs, nbnd, id, ed;
|
|
||||||
idxtype *xadj, *adjncy, *where, *bndptr, *bndind;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
where = graph->where;
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
|
|
||||||
for (nbnd=0, i=0; i<nvtxs; i++) {
|
|
||||||
id = ed = 0;
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (where[i] != where[adjncy[j]])
|
|
||||||
ed += graph->adjwgt[j];
|
|
||||||
else
|
|
||||||
id += graph->adjwgt[j];
|
|
||||||
}
|
|
||||||
if (ed - id >= 0 && xadj[i] < xadj[i+1]) {
|
|
||||||
nbnd++;
|
|
||||||
ASSERTP(bndptr[i] != -1, ("%d %d %d\n", i, id, ed));
|
|
||||||
ASSERT(bndind[bndptr[i]] == i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERTP(nbnd == graph->nbnd, ("%d %d\n", nbnd, graph->nbnd));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks whether or not the boundary information is correct
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype CheckNodeBnd(GraphType *graph, idxtype onbnd)
|
|
||||||
{
|
|
||||||
idxtype i, j, nvtxs, nbnd;
|
|
||||||
idxtype *xadj, *adjncy, *where, *bndptr, *bndind;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
where = graph->where;
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
|
|
||||||
for (nbnd=0, i=0; i<nvtxs; i++) {
|
|
||||||
if (where[i] == 2)
|
|
||||||
nbnd++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERTP(nbnd == onbnd, ("%d %d\n", nbnd, onbnd));
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (where[i] != 2) {
|
|
||||||
ASSERTP(bndptr[i] == -1, ("%d %d\n", i, bndptr[i]));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ASSERTP(bndptr[i] != -1, ("%d %d\n", i, bndptr[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks whether or not the rinfo of a vertex is consistent
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype CheckRInfo(RInfoType *rinfo)
|
|
||||||
{
|
|
||||||
idxtype i, j;
|
|
||||||
|
|
||||||
for (i=0; i<rinfo->ndegrees; i++) {
|
|
||||||
for (j=i+1; j<rinfo->ndegrees; j++)
|
|
||||||
ASSERTP(rinfo->edegrees[i].pid != rinfo->edegrees[j].pid, ("%d %d %d %d\n", i, j, rinfo->edegrees[i].pid, rinfo->edegrees[j].pid));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks the correctness of the NodeFM data structures
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype CheckNodePartitionParams(GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, l, nvtxs, me, other;
|
|
||||||
idxtype *xadj, *adjncy, *adjwgt, *vwgt, *where;
|
|
||||||
idxtype edegrees[2], pwgts[3];
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
where = graph->where;
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
/ Compute now the separator external degrees
|
|
||||||
/------------------------------------------------------------*/
|
|
||||||
pwgts[0] = pwgts[1] = pwgts[2] = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
me = where[i];
|
|
||||||
pwgts[me] += vwgt[i];
|
|
||||||
|
|
||||||
if (me == 2) { /* If it is on the separator do some computations */
|
|
||||||
edegrees[0] = edegrees[1] = 0;
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
other = where[adjncy[j]];
|
|
||||||
if (other != 2)
|
|
||||||
edegrees[other] += vwgt[adjncy[j]];
|
|
||||||
}
|
|
||||||
if (edegrees[0] != graph->nrinfo[i].edegrees[0] || edegrees[1] != graph->nrinfo[i].edegrees[1]) {
|
|
||||||
mprintf("Something wrong with edegrees: %D %D %D %D %D\n", i, edegrees[0], edegrees[1], graph->nrinfo[i].edegrees[0], graph->nrinfo[i].edegrees[1]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pwgts[0] != graph->pwgts[0] || pwgts[1] != graph->pwgts[1] || pwgts[2] != graph->pwgts[2])
|
|
||||||
mprintf("Something wrong with part-weights: %D %D %D %D %D %D\n", pwgts[0], pwgts[1], pwgts[2], graph->pwgts[0], graph->pwgts[1], graph->pwgts[2]);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks if the separator is indeed a separator
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype IsSeparable(GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, j, nvtxs, other;
|
|
||||||
idxtype *xadj, *adjncy, *where;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
where = graph->where;
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (where[i] == 2)
|
|
||||||
continue;
|
|
||||||
other = (where[i]+1)%2;
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
ASSERTP(where[adjncy[j]] != other, ("%d %d %d %d %d %d\n", i, where[i], adjncy[j], where[adjncy[j]], xadj[i+1]-xadj[i], xadj[adjncy[j]+1]-xadj[adjncy[j]]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* defs.h
|
|
||||||
*
|
|
||||||
* This file contains constant definitions
|
|
||||||
*
|
|
||||||
* Started 8/27/94
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: defs.h,v 1.4 2003/01/29 15:54:41 karypis Exp $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define METISTITLE " METIS 5.0 Copyright 2001-06, Regents of the University of Minnesota\n\n"
|
|
||||||
#define MAXLINE 1280000
|
|
||||||
|
|
||||||
#define LTERM (void **) 0 /* List terminator for gk_free() */
|
|
||||||
|
|
||||||
#define MAXNCON 16 /* The maximum number of constrains */
|
|
||||||
#define MAXNOBJ 16 /* The maximum number of objectives */
|
|
||||||
|
|
||||||
#define PLUS_GAINSPAN 500 /* Parameters for FM buckets */
|
|
||||||
#define NEG_GAINSPAN 500
|
|
||||||
|
|
||||||
#define HTLENGTH ((1<<11)-1)
|
|
||||||
|
|
||||||
/* Meaning of various options[] parameters */
|
|
||||||
#define OPTION_PTYPE 0
|
|
||||||
#define OPTION_CTYPE 1
|
|
||||||
#define OPTION_ITYPE 2
|
|
||||||
#define OPTION_RTYPE 3
|
|
||||||
#define OPTION_DBGLVL 4
|
|
||||||
#define OPTION_OFLAGS 5
|
|
||||||
#define OPTION_PFACTOR 6
|
|
||||||
#define OPTION_NSEPS 7
|
|
||||||
|
|
||||||
#define OFLAG_COMPRESS 1 /* Try to compress the graph */
|
|
||||||
#define OFLAG_CCMP 2 /* Find and order connected components */
|
|
||||||
|
|
||||||
|
|
||||||
/* Default options for PMETIS */
|
|
||||||
#define PMETIS_CTYPE MTYPE_SHEM
|
|
||||||
#define PMETIS_ITYPE ITYPE_GGPKL
|
|
||||||
#define PMETIS_RTYPE RTYPE_FM
|
|
||||||
#define PMETIS_DBGLVL 0
|
|
||||||
|
|
||||||
/* Default options for KMETIS */
|
|
||||||
#define KMETIS_CTYPE MTYPE_SHEM
|
|
||||||
#define KMETIS_ITYPE ITYPE_PMETIS
|
|
||||||
#define KMETIS_RTYPE RTYPE_KWAYRANDOM_MCONN
|
|
||||||
#define KMETIS_DBGLVL 0
|
|
||||||
|
|
||||||
/* Default options for OEMETIS */
|
|
||||||
#define OEMETIS_CTYPE MTYPE_SHEM
|
|
||||||
#define OEMETIS_ITYPE ITYPE_GGPKL
|
|
||||||
#define OEMETIS_RTYPE RTYPE_FM
|
|
||||||
#define OEMETIS_DBGLVL 0
|
|
||||||
|
|
||||||
/* Default options for ONMETIS */
|
|
||||||
#define ONMETIS_CTYPE MTYPE_SHEM
|
|
||||||
#define ONMETIS_ITYPE ITYPE_GGPKL
|
|
||||||
#define ONMETIS_RTYPE RTYPE_SEP1SIDED
|
|
||||||
#define ONMETIS_DBGLVL 0
|
|
||||||
#define ONMETIS_OFLAGS OFLAG_COMPRESS
|
|
||||||
#define ONMETIS_PFACTOR -1
|
|
||||||
#define ONMETIS_NSEPS 1
|
|
||||||
|
|
||||||
/* Default options for McPMETIS */
|
|
||||||
#define McPMETIS_CTYPE MTYPE_SHEBM_ONENORM
|
|
||||||
#define McPMETIS_ITYPE ITYPE_RANDOM
|
|
||||||
#define McPMETIS_RTYPE RTYPE_FM
|
|
||||||
#define McPMETIS_DBGLVL 0
|
|
||||||
|
|
||||||
/* Default options for McKMETIS */
|
|
||||||
#define McKMETIS_CTYPE MTYPE_SHEBM_ONENORM
|
|
||||||
#define McKMETIS_ITYPE ITYPE_McHPMETIS
|
|
||||||
#define McKMETIS_RTYPE RTYPE_KWAYRANDOM
|
|
||||||
#define McKMETIS_DBGLVL 0
|
|
||||||
|
|
||||||
/* Default options for KVMETIS */
|
|
||||||
#define KVMETIS_CTYPE MTYPE_SHEM
|
|
||||||
#define KVMETIS_ITYPE ITYPE_PMETIS
|
|
||||||
#define KVMETIS_RTYPE RTYPE_KWAYRANDOM
|
|
||||||
#define KVMETIS_DBGLVL 0
|
|
||||||
|
|
||||||
|
|
||||||
/* Operations supported by stand-alone code */
|
|
||||||
#define OP_PMETIS 1
|
|
||||||
#define OP_KMETIS 2
|
|
||||||
#define OP_OEMETIS 3
|
|
||||||
#define OP_ONMETIS 4
|
|
||||||
#define OP_ONWMETIS 5
|
|
||||||
#define OP_KVMETIS 6
|
|
||||||
|
|
||||||
|
|
||||||
#define UNMATCHED -1
|
|
||||||
|
|
||||||
#define HTABLE_EMPTY -1
|
|
||||||
|
|
||||||
#define NGR_PASSES 4 /* Number of greedy refinement passes */
|
|
||||||
#define NLGR_PASSES 5 /* Number of GR refinement during IPartition */
|
|
||||||
|
|
||||||
#define LARGENIPARTS 8 /* Number of random initial partitions */
|
|
||||||
#define SMALLNIPARTS 3 /* Number of random initial partitions */
|
|
||||||
|
|
||||||
#define COARSEN_FRACTION 0.75 /* Node reduction between succesive coarsening levels */
|
|
||||||
#define COARSEN_FRACTION2 0.99 /* Node reduction between succesive coarsening levels */
|
|
||||||
#define UNBALANCE_FRACTION 1.03
|
|
||||||
|
|
||||||
#define COMPRESSION_FRACTION 0.85
|
|
||||||
|
|
||||||
#define ORDER_UNBALANCE_FRACTION 1.10
|
|
||||||
|
|
||||||
#define MMDSWITCH 200
|
|
||||||
|
|
||||||
#define HORIZONTAL_IMBALANCE 1.05
|
|
||||||
|
|
||||||
/* Debug Levels */
|
|
||||||
#define DBG_TIME 1 /* Perform timing analysis */
|
|
||||||
#define DBG_OUTPUT 2
|
|
||||||
#define DBG_COARSEN 4 /* Show the coarsening progress */
|
|
||||||
#define DBG_REFINE 8 /* Show info on communication during folding */
|
|
||||||
#define DBG_IPART 16 /* Show info on initial partition */
|
|
||||||
#define DBG_MOVEINFO 32 /* Show info on communication during folding */
|
|
||||||
#define DBG_KWAYPINFO 64 /* Show info on communication during folding */
|
|
||||||
#define DBG_SEPINFO 128 /* Show info on communication during folding */
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* estmem.c
|
|
||||||
*
|
|
||||||
* This file contains code for estimating the amount of memory required by
|
|
||||||
* the various routines in METIS
|
|
||||||
*
|
|
||||||
* Started 11/4/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes how much memory will be required by the various
|
|
||||||
* routines in METIS
|
|
||||||
**************************************************************************/
|
|
||||||
void METIS_EstimateMemory(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *optype, idxtype *nbytes)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nedges, nlevels;
|
|
||||||
float vfraction, efraction, vmult, emult;
|
|
||||||
idxtype coresize, gdata, rdata;
|
|
||||||
|
|
||||||
if (*numflag == 1)
|
|
||||||
Change2CNumbering(*nvtxs, xadj, adjncy);
|
|
||||||
|
|
||||||
nedges = xadj[*nvtxs];
|
|
||||||
|
|
||||||
InitRandom(-1);
|
|
||||||
EstimateCFraction(*nvtxs, xadj, adjncy, &vfraction, &efraction);
|
|
||||||
|
|
||||||
/* Estimate the amount of memory for coresize */
|
|
||||||
if (*optype == 2)
|
|
||||||
coresize = nedges;
|
|
||||||
else
|
|
||||||
coresize = 0;
|
|
||||||
coresize += nedges + 11*(*nvtxs) + 4*1024 + 2*(NEG_GAINSPAN+PLUS_GAINSPAN+1)*(sizeof(ListNodeType *)/sizeof(idxtype));
|
|
||||||
coresize += 2*(*nvtxs); /* add some more fore other vectors */
|
|
||||||
|
|
||||||
gdata = nedges; /* Agk_fsume that the user does not pass weights */
|
|
||||||
|
|
||||||
nlevels = (int)(log(100.0/(*nvtxs))/log(vfraction) + .5);
|
|
||||||
vmult = 0.5 + (1.0 - pow(vfraction, nlevels))/(1.0 - vfraction);
|
|
||||||
emult = 1.0 + (1.0 - pow(efraction, nlevels+1))/(1.0 - efraction);
|
|
||||||
|
|
||||||
gdata += vmult*4*(*nvtxs) + emult*2*nedges;
|
|
||||||
if ((vmult-1.0)*4*(*nvtxs) + (emult-1.0)*2*nedges < 5*(*nvtxs))
|
|
||||||
rdata = 0;
|
|
||||||
else
|
|
||||||
rdata = 5*(*nvtxs);
|
|
||||||
|
|
||||||
*nbytes = sizeof(idxtype)*(coresize+gdata+rdata+(*nvtxs));
|
|
||||||
|
|
||||||
if (*numflag == 1)
|
|
||||||
Change2FNumbering2(*nvtxs, xadj, adjncy);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function finds a matching using the HEM heuristic
|
|
||||||
**************************************************************************/
|
|
||||||
void EstimateCFraction(idxtype nvtxs, idxtype *xadj, idxtype *adjncy, float *vfraction, float *efraction)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, cnvtxs, cnedges, maxidx;
|
|
||||||
idxtype *match, *cmap, *perm;
|
|
||||||
|
|
||||||
cmap = idxmalloc(nvtxs, "cmap");
|
|
||||||
match = idxsmalloc(nvtxs, UNMATCHED, "match");
|
|
||||||
perm = idxmalloc(nvtxs, "perm");
|
|
||||||
RandomPermute(nvtxs, perm, 1);
|
|
||||||
|
|
||||||
cnvtxs = 0;
|
|
||||||
for (ii=0; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
|
|
||||||
if (match[i] == UNMATCHED) { /* Unmatched */
|
|
||||||
maxidx = i;
|
|
||||||
|
|
||||||
/* Find a random matching, subject to maxvwgt constraints */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (match[adjncy[j]] == UNMATCHED) {
|
|
||||||
maxidx = adjncy[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmap[i] = cmap[maxidx] = cnvtxs++;
|
|
||||||
match[i] = maxidx;
|
|
||||||
match[maxidx] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cnedges = ComputeCoarseGraphSize(nvtxs, xadj, adjncy, cnvtxs, cmap, match, perm);
|
|
||||||
|
|
||||||
*vfraction = (1.0*cnvtxs)/(1.0*nvtxs);
|
|
||||||
*efraction = (1.0*cnedges)/(1.0*xadj[nvtxs]);
|
|
||||||
|
|
||||||
gk_free((void **)&cmap, &match, &perm, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the size of the coarse graph
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype ComputeCoarseGraphSize(idxtype nvtxs, idxtype *xadj, idxtype *adjncy, idxtype cnvtxs, idxtype *cmap, idxtype *match, idxtype *perm)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, istart, iend, nedges, cnedges, v, u;
|
|
||||||
idxtype *htable;
|
|
||||||
|
|
||||||
htable = idxsmalloc(cnvtxs, -1, "htable");
|
|
||||||
|
|
||||||
cnvtxs = cnedges = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
v = perm[i];
|
|
||||||
if (cmap[v] != cnvtxs)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
htable[cnvtxs] = cnvtxs;
|
|
||||||
|
|
||||||
u = match[v];
|
|
||||||
|
|
||||||
istart = xadj[v];
|
|
||||||
iend = xadj[v+1];
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
k = cmap[adjncy[j]];
|
|
||||||
if (htable[k] != cnvtxs) {
|
|
||||||
htable[k] = cnvtxs;
|
|
||||||
cnedges++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v != u) {
|
|
||||||
istart = xadj[u];
|
|
||||||
iend = xadj[u+1];
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
k = cmap[adjncy[j]];
|
|
||||||
if (htable[k] != cnvtxs) {
|
|
||||||
htable[k] = cnvtxs;
|
|
||||||
cnedges++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cnvtxs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_free((void **)&htable, LTERM);
|
|
||||||
|
|
||||||
return cnedges;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,193 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* fm.c
|
|
||||||
*
|
|
||||||
* This file contains code that implements the edge-based FM refinement
|
|
||||||
*
|
|
||||||
* Started 7/23/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function performs an edge-based FM refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void FM_2WayEdgeRefine(CtrlType *ctrl, GraphType *graph, idxtype *tpwgts, idxtype npasses)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, limit, tmp;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts;
|
|
||||||
idxtype *moved, *swaps, *perm;
|
|
||||||
PQueueType parts[2];
|
|
||||||
idxtype higain, oldgain, mincut, mindiff, origdiff, initcut, newcut, mincutorder, avgvwgt;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
where = graph->where;
|
|
||||||
id = graph->id;
|
|
||||||
ed = graph->ed;
|
|
||||||
pwgts = graph->pwgts;
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
|
|
||||||
moved = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
swaps = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
|
|
||||||
limit = amin(amax(0.01*nvtxs, 15), 100);
|
|
||||||
avgvwgt = amin((pwgts[0]+pwgts[1])/20, 2*(pwgts[0]+pwgts[1])/nvtxs);
|
|
||||||
|
|
||||||
tmp = graph->adjwgtsum[idxargmax(nvtxs, graph->adjwgtsum)];
|
|
||||||
PQueueInit(ctrl, &parts[0], nvtxs, tmp);
|
|
||||||
PQueueInit(ctrl, &parts[1], nvtxs, tmp);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("Partitions: [%6D %6D] T[%6D %6D], Nv-Nb[%6D %6D]. ICut: %6D\n",
|
|
||||||
pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));
|
|
||||||
|
|
||||||
origdiff = idxtype_abs(tpwgts[0]-pwgts[0]);
|
|
||||||
idxset(nvtxs, -1, moved);
|
|
||||||
for (pass=0; pass<npasses; pass++) { /* Do a number of passes */
|
|
||||||
PQueueReset(&parts[0]);
|
|
||||||
PQueueReset(&parts[1]);
|
|
||||||
|
|
||||||
mincutorder = -1;
|
|
||||||
newcut = mincut = initcut = graph->mincut;
|
|
||||||
mindiff = idxtype_abs(tpwgts[0]-pwgts[0]);
|
|
||||||
|
|
||||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
|
||||||
ASSERT(CheckBnd(graph));
|
|
||||||
|
|
||||||
/* Insert boundary nodes in the priority queues */
|
|
||||||
nbnd = graph->nbnd;
|
|
||||||
RandomPermute(nbnd, perm, 1);
|
|
||||||
for (ii=0; ii<nbnd; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
ASSERT(ed[bndind[i]] > 0 || id[bndind[i]] == 0);
|
|
||||||
ASSERT(bndptr[bndind[i]] != -1);
|
|
||||||
PQueueInsert(&parts[where[bndind[i]]], bndind[i], ed[bndind[i]]-id[bndind[i]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (nswaps=0; nswaps<nvtxs; nswaps++) {
|
|
||||||
from = (tpwgts[0]-pwgts[0] < tpwgts[1]-pwgts[1] ? 0 : 1);
|
|
||||||
to = (from+1)%2;
|
|
||||||
|
|
||||||
if ((higain = PQueueGetMax(&parts[from])) == -1)
|
|
||||||
break;
|
|
||||||
ASSERT(bndptr[higain] != -1);
|
|
||||||
|
|
||||||
newcut -= (ed[higain]-id[higain]);
|
|
||||||
INC_DEC(pwgts[to], pwgts[from], vwgt[higain]);
|
|
||||||
|
|
||||||
if ((newcut < mincut && idxtype_abs(tpwgts[0]-pwgts[0]) <= origdiff+avgvwgt) ||
|
|
||||||
(newcut == mincut && idxtype_abs(tpwgts[0]-pwgts[0]) < mindiff)) {
|
|
||||||
mincut = newcut;
|
|
||||||
mindiff = idxtype_abs(tpwgts[0]-pwgts[0]);
|
|
||||||
mincutorder = nswaps;
|
|
||||||
}
|
|
||||||
else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */
|
|
||||||
newcut += (ed[higain]-id[higain]);
|
|
||||||
INC_DEC(pwgts[from], pwgts[to], vwgt[higain]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
where[higain] = to;
|
|
||||||
moved[higain] = nswaps;
|
|
||||||
swaps[nswaps] = higain;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_MOVEINFO,
|
|
||||||
mprintf("Moved %6D from %D. [%3D %3D] %5D [%4D %4D]\n", higain, from, ed[higain]-id[higain], vwgt[higain], newcut, pwgts[0], pwgts[1]));
|
|
||||||
|
|
||||||
/**************************************************************
|
|
||||||
* Update the id[i]/ed[i] values of the affected nodes
|
|
||||||
***************************************************************/
|
|
||||||
SWAP(id[higain], ed[higain], tmp);
|
|
||||||
if (ed[higain] == 0 && xadj[higain] < xadj[higain+1])
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, higain);
|
|
||||||
|
|
||||||
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
oldgain = ed[k]-id[k];
|
|
||||||
|
|
||||||
kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]);
|
|
||||||
INC_DEC(id[k], ed[k], kwgt);
|
|
||||||
|
|
||||||
/* Update its boundary information and queue position */
|
|
||||||
if (bndptr[k] != -1) { /* If k was a boundary vertex */
|
|
||||||
if (ed[k] == 0) { /* Not a boundary vertex any more */
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, k);
|
|
||||||
if (moved[k] == -1) /* Remove it if in the queues */
|
|
||||||
PQueueDelete(&parts[where[k]], k, oldgain);
|
|
||||||
}
|
|
||||||
else { /* If it has not been moved, update its position in the queue */
|
|
||||||
if (moved[k] == -1)
|
|
||||||
PQueueUpdate(&parts[where[k]], k, oldgain, ed[k]-id[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (ed[k] > 0) { /* It will now become a boundary vertex */
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, k);
|
|
||||||
if (moved[k] == -1)
|
|
||||||
PQueueInsert(&parts[where[k]], k, ed[k]-id[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************
|
|
||||||
* Roll back computations
|
|
||||||
*****************************************************************/
|
|
||||||
for (i=0; i<nswaps; i++)
|
|
||||||
moved[swaps[i]] = -1; /* reset moved array */
|
|
||||||
for (nswaps--; nswaps>mincutorder; nswaps--) {
|
|
||||||
higain = swaps[nswaps];
|
|
||||||
|
|
||||||
to = where[higain] = (where[higain]+1)%2;
|
|
||||||
SWAP(id[higain], ed[higain], tmp);
|
|
||||||
if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1])
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, higain);
|
|
||||||
else if (ed[higain] > 0 && bndptr[higain] == -1)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, higain);
|
|
||||||
|
|
||||||
INC_DEC(pwgts[to], pwgts[(to+1)%2], vwgt[higain]);
|
|
||||||
for (j=xadj[higain]; j<xadj[higain+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
|
|
||||||
kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]);
|
|
||||||
INC_DEC(id[k], ed[k], kwgt);
|
|
||||||
|
|
||||||
if (bndptr[k] != -1 && ed[k] == 0)
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, k);
|
|
||||||
if (bndptr[k] == -1 && ed[k] > 0)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("\tMinimum cut: %6D at %5D, PWGTS: [%6D %6D], NBND: %6D\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd));
|
|
||||||
|
|
||||||
graph->mincut = mincut;
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
|
|
||||||
if (mincutorder == -1 || mincut == initcut)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
PQueueFree(ctrl, &parts[0]);
|
|
||||||
PQueueFree(ctrl, &parts[1]);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,150 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* fortran.c
|
|
||||||
*
|
|
||||||
* This file contains code for the fortran to C interface
|
|
||||||
*
|
|
||||||
* Started 8/19/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function changes the numbering to start from 0 instead of 1
|
|
||||||
**************************************************************************/
|
|
||||||
void Change2CNumbering(idxtype nvtxs, idxtype *xadj, idxtype *adjncy)
|
|
||||||
{
|
|
||||||
idxtype i, nedges;
|
|
||||||
|
|
||||||
for (i=0; i<=nvtxs; i++)
|
|
||||||
xadj[i]--;
|
|
||||||
|
|
||||||
nedges = xadj[nvtxs];
|
|
||||||
for (i=0; i<nedges; i++)
|
|
||||||
adjncy[i]--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function changes the numbering to start from 1 instead of 0
|
|
||||||
**************************************************************************/
|
|
||||||
void Change2FNumbering(idxtype nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vector)
|
|
||||||
{
|
|
||||||
idxtype i, nedges;
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
vector[i]++;
|
|
||||||
|
|
||||||
nedges = xadj[nvtxs];
|
|
||||||
for (i=0; i<nedges; i++)
|
|
||||||
adjncy[i]++;
|
|
||||||
|
|
||||||
for (i=0; i<=nvtxs; i++)
|
|
||||||
xadj[i]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function changes the numbering to start from 1 instead of 0
|
|
||||||
**************************************************************************/
|
|
||||||
void Change2FNumbering2(idxtype nvtxs, idxtype *xadj, idxtype *adjncy)
|
|
||||||
{
|
|
||||||
idxtype i, nedges;
|
|
||||||
|
|
||||||
nedges = xadj[nvtxs];
|
|
||||||
for (i=0; i<nedges; i++)
|
|
||||||
adjncy[i]++;
|
|
||||||
|
|
||||||
for (i=0; i<=nvtxs; i++)
|
|
||||||
xadj[i]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function changes the numbering to start from 1 instead of 0
|
|
||||||
**************************************************************************/
|
|
||||||
void Change2FNumberingOrder(idxtype nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *v1, idxtype *v2)
|
|
||||||
{
|
|
||||||
idxtype i, nedges;
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
v1[i]++;
|
|
||||||
v2[i]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
nedges = xadj[nvtxs];
|
|
||||||
for (i=0; i<nedges; i++)
|
|
||||||
adjncy[i]++;
|
|
||||||
|
|
||||||
for (i=0; i<=nvtxs; i++)
|
|
||||||
xadj[i]++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function changes the numbering to start from 0 instead of 1
|
|
||||||
**************************************************************************/
|
|
||||||
void ChangeMesh2CNumbering(idxtype n, idxtype *mesh)
|
|
||||||
{
|
|
||||||
idxtype i;
|
|
||||||
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
mesh[i]--;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function changes the numbering to start from 1 instead of 0
|
|
||||||
**************************************************************************/
|
|
||||||
void ChangeMesh2FNumbering(idxtype n, idxtype *mesh, idxtype nvtxs, idxtype *xadj, idxtype *adjncy)
|
|
||||||
{
|
|
||||||
idxtype i, nedges;
|
|
||||||
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
mesh[i]++;
|
|
||||||
|
|
||||||
nedges = xadj[nvtxs];
|
|
||||||
for (i=0; i<nedges; i++)
|
|
||||||
adjncy[i]++;
|
|
||||||
|
|
||||||
for (i=0; i<=nvtxs; i++)
|
|
||||||
xadj[i]++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function changes the numbering to start from 1 instead of 0
|
|
||||||
**************************************************************************/
|
|
||||||
void ChangeMesh2FNumbering2(idxtype n, idxtype *mesh, idxtype ne, idxtype nn, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
idxtype i, nedges;
|
|
||||||
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
mesh[i]++;
|
|
||||||
|
|
||||||
for (i=0; i<ne; i++)
|
|
||||||
epart[i]++;
|
|
||||||
|
|
||||||
for (i=0; i<nn; i++)
|
|
||||||
npart[i]++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function changes the numbering to start from 1 instead of 0
|
|
||||||
**************************************************************************/
|
|
||||||
void ChangeMesh2FNumbering3(idxtype n, idxtype *mesh)
|
|
||||||
{
|
|
||||||
idxtype i;
|
|
||||||
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
mesh[i]++;
|
|
||||||
}
|
|
||||||
@ -1,310 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* frename.c
|
|
||||||
*
|
|
||||||
* This file contains some renaming routines to deal with different Fortran compilers
|
|
||||||
*
|
|
||||||
* Started 9/15/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_PARTGRAPHRECURSIVE(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphrecursive(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphrecursive_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphrecursive__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_WPARTGRAPHRECURSIVE(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphrecursive(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphrecursive_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphrecursive__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_PARTGRAPHKWAY(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphkway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphkway_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphkway__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_WPARTGRAPHKWAY(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphkway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphkway_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphkway__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_EDGEND(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_EdgeND(nvtxs, xadj, adjncy, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_edgend(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_EdgeND(nvtxs, xadj, adjncy, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_edgend_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_EdgeND(nvtxs, xadj, adjncy, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_edgend__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_EdgeND(nvtxs, xadj, adjncy, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_NODEND(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_NodeND(nvtxs, xadj, adjncy, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_nodend(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_NodeND(nvtxs, xadj, adjncy, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_nodend_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_NodeND(nvtxs, xadj, adjncy, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_nodend__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_NodeND(nvtxs, xadj, adjncy, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_NODEWND(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_NodeWND(nvtxs, xadj, adjncy, vwgt, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_nodewnd(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_NodeWND(nvtxs, xadj, adjncy, vwgt, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_nodewnd_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_NodeWND(nvtxs, xadj, adjncy, vwgt, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
void metis_nodewnd__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *numflag, idxtype *options, idxtype *perm, idxtype *iperm)
|
|
||||||
{
|
|
||||||
METIS_NodeWND(nvtxs, xadj, adjncy, vwgt, numflag, options, perm, iperm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef XXXX
|
|
||||||
void METIS_PARTMESHNODAL(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
METIS_PartMeshNodal(ne, nn, elmnts, etype, numflag, nparts, edgecut, epart, npart);
|
|
||||||
}
|
|
||||||
void metis_partmeshnodal(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
METIS_PartMeshNodal(ne, nn, elmnts, etype, numflag, nparts, edgecut, epart, npart);
|
|
||||||
}
|
|
||||||
void metis_partmeshnodal_(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
METIS_PartMeshNodal(ne, nn, elmnts, etype, numflag, nparts, edgecut, epart, npart);
|
|
||||||
}
|
|
||||||
void metis_partmeshnodal__(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
METIS_PartMeshNodal(ne, nn, elmnts, etype, numflag, nparts, edgecut, epart, npart);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_PARTMESHDUAL(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
METIS_PartMeshDual(ne, nn, elmnts, etype, numflag, nparts, edgecut, epart, npart, 0, NULL);
|
|
||||||
}
|
|
||||||
void metis_partmeshdual(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
METIS_PartMeshDual(ne, nn, elmnts, etype, numflag, nparts, edgecut, epart, npart, 0, NULL);
|
|
||||||
}
|
|
||||||
void metis_partmeshdual_(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
METIS_PartMeshDual(ne, nn, elmnts, etype, numflag, nparts, edgecut, epart, npart, 0, NULL);
|
|
||||||
}
|
|
||||||
void metis_partmeshdual__(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *nparts, idxtype *edgecut, idxtype *epart, idxtype *npart)
|
|
||||||
{
|
|
||||||
METIS_PartMeshDual(ne, nn, elmnts, etype, numflag, nparts, edgecut, epart, npart, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_MESHTONODAL(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *dxadj, idxtype *dadjncy)
|
|
||||||
{
|
|
||||||
METIS_MeshToNodal(ne, nn, elmnts, etype, numflag, dxadj, dadjncy);
|
|
||||||
}
|
|
||||||
void metis_meshtonodal(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *dxadj, idxtype *dadjncy)
|
|
||||||
{
|
|
||||||
METIS_MeshToNodal(ne, nn, elmnts, etype, numflag, dxadj, dadjncy);
|
|
||||||
}
|
|
||||||
void metis_meshtonodal_(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *dxadj, idxtype *dadjncy)
|
|
||||||
{
|
|
||||||
METIS_MeshToNodal(ne, nn, elmnts, etype, numflag, dxadj, dadjncy);
|
|
||||||
}
|
|
||||||
void metis_meshtonodal__(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *dxadj, idxtype *dadjncy)
|
|
||||||
{
|
|
||||||
METIS_MeshToNodal(ne, nn, elmnts, etype, numflag, dxadj, dadjncy);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_MESHTODUAL(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *dxadj, idxtype *dadjncy)
|
|
||||||
{
|
|
||||||
METIS_MeshToDual(ne, nn, elmnts, etype, numflag, dxadj, dadjncy);
|
|
||||||
}
|
|
||||||
void metis_meshtodual(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *dxadj, idxtype *dadjncy)
|
|
||||||
{
|
|
||||||
METIS_MeshToDual(ne, nn, elmnts, etype, numflag, dxadj, dadjncy);
|
|
||||||
}
|
|
||||||
void metis_meshtodual_(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *dxadj, idxtype *dadjncy)
|
|
||||||
{
|
|
||||||
METIS_MeshToDual(ne, nn, elmnts, etype, numflag, dxadj, dadjncy);
|
|
||||||
}
|
|
||||||
void metis_meshtodual__(idxtype *ne, idxtype *nn, idxtype *elmnts, idxtype *etype, idxtype *numflag, idxtype *dxadj, idxtype *dadjncy)
|
|
||||||
{
|
|
||||||
METIS_MeshToDual(ne, nn, elmnts, etype, numflag, dxadj, dadjncy);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void METIS_ESTIMATEMEMORY(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *optype, idxtype *nbytes)
|
|
||||||
{
|
|
||||||
METIS_EstimateMemory(nvtxs, xadj, adjncy, numflag, optype, nbytes);
|
|
||||||
}
|
|
||||||
void metis_estimatememory(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *optype, idxtype *nbytes)
|
|
||||||
{
|
|
||||||
METIS_EstimateMemory(nvtxs, xadj, adjncy, numflag, optype, nbytes);
|
|
||||||
}
|
|
||||||
void metis_estimatememory_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *optype, idxtype *nbytes)
|
|
||||||
{
|
|
||||||
METIS_EstimateMemory(nvtxs, xadj, adjncy, numflag, optype, nbytes);
|
|
||||||
}
|
|
||||||
void metis_estimatememory__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *numflag, idxtype *optype, idxtype *nbytes)
|
|
||||||
{
|
|
||||||
METIS_EstimateMemory(nvtxs, xadj, adjncy, numflag, optype, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_MCPARTGRAPHRECURSIVE(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_mCPartGraphRecursive(nvtxs, ncon, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_mcpartgraphrecursive(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_mCPartGraphRecursive(nvtxs, ncon, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_mcpartgraphrecursive_(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_mCPartGraphRecursive(nvtxs, ncon, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_mcpartgraphrecursive__(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_mCPartGraphRecursive(nvtxs, ncon, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_MCPARTGRAPHKWAY(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *rubvec, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_mCPartGraphKway(nvtxs, ncon, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, rubvec, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_mcpartgraphkway(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *rubvec, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_mCPartGraphKway(nvtxs, ncon, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, rubvec, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_mcpartgraphkway_(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *rubvec, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_mCPartGraphKway(nvtxs, ncon, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, rubvec, options, edgecut, part);
|
|
||||||
}
|
|
||||||
void metis_mcpartgraphkway__(idxtype *nvtxs, idxtype *ncon, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *rubvec, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_mCPartGraphKway(nvtxs, ncon, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, rubvec, options, edgecut, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void METIS_PARTGRAPHVKWAY(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, options, volume, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphvkaway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, options, volume, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphvkaway_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, options, volume, part);
|
|
||||||
}
|
|
||||||
void metis_partgraphvkaway__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_PartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, options, volume, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
void METIS_WPARTGRAPHVKWAY(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, tpwgts, options, volume, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphvkaway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, tpwgts, options, volume, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphvkaway_(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, tpwgts, options, volume, part);
|
|
||||||
}
|
|
||||||
void metis_wpartgraphvkaway__(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
METIS_WPartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, tpwgts, options, volume, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,492 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* graph.c
|
|
||||||
*
|
|
||||||
* This file contains functions that deal with setting up the graphs
|
|
||||||
* for METIS.
|
|
||||||
*
|
|
||||||
* Started 7/25/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function sets up the graph from the user input
|
|
||||||
**************************************************************************/
|
|
||||||
void SetUpGraph(GraphType *graph, idxtype OpType, idxtype nvtxs, idxtype ncon,
|
|
||||||
idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype wgtflag)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, sum;
|
|
||||||
float *nvwgt;
|
|
||||||
idxtype tvwgt[MAXNCON];
|
|
||||||
|
|
||||||
|
|
||||||
InitGraph(graph);
|
|
||||||
|
|
||||||
graph->nvtxs = nvtxs;
|
|
||||||
graph->nedges = xadj[nvtxs];
|
|
||||||
graph->ncon = ncon;
|
|
||||||
|
|
||||||
graph->xadj = xadj;
|
|
||||||
graph->free_xadj = 0;
|
|
||||||
|
|
||||||
graph->adjncy = adjncy;
|
|
||||||
graph->free_adjncy = 0;
|
|
||||||
|
|
||||||
/* setup the vertex weights */
|
|
||||||
if (ncon == 1) { /* We are in the non mC mode */
|
|
||||||
if ((wgtflag&2) == 0) {
|
|
||||||
vwgt = graph->vwgt = idxsmalloc(nvtxs, 1, "SetUpGraph: vwgt");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
graph->vwgt = vwgt;
|
|
||||||
graph->free_vwgt = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* Set up the graph in MOC mode */
|
|
||||||
for (i=0; i<ncon; i++)
|
|
||||||
tvwgt[i] = idxsum(nvtxs, vwgt+i, ncon);
|
|
||||||
|
|
||||||
nvwgt = graph->nvwgt = gk_fmalloc(ncon*nvtxs, "SetUpGraph: nvwgt");
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
for (j=0; j<ncon; j++)
|
|
||||||
nvwgt[i*ncon+j] = (1.0*vwgt[i*ncon+j])/(1.0*tvwgt[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup the edge weights */
|
|
||||||
if ((wgtflag&1) == 0) {
|
|
||||||
adjwgt = graph->adjwgt = idxsmalloc(graph->nedges, 1, "SetUpGraph: adjwgt");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
graph->adjwgt = adjwgt;
|
|
||||||
graph->free_adjwgt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute the initial values of the adjwgtsum */
|
|
||||||
graph->adjwgtsum = idxmalloc(nvtxs, "SetUpGraph: adjwgtsum");
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
for (sum=0, j=xadj[i]; j<xadj[i+1]; j++)
|
|
||||||
sum += adjwgt[j];
|
|
||||||
graph->adjwgtsum[i] = sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->cmap = idxmalloc(nvtxs, "SetUpGraph: cmap");
|
|
||||||
|
|
||||||
|
|
||||||
if (OpType != OP_KMETIS && OpType != OP_KVMETIS) {
|
|
||||||
graph->label = idxmalloc(nvtxs, "SetUpGraph: label");
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
graph->label[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function sets up the graph from the user input. The difference
|
|
||||||
* from the previous routine is that the vertex weights came already in
|
|
||||||
* a normalized fashion.
|
|
||||||
**************************************************************************/
|
|
||||||
void SetUpGraph2(GraphType *graph, idxtype nvtxs, idxtype ncon, idxtype *xadj,
|
|
||||||
idxtype *adjncy, float *nvwgt, idxtype *adjwgt)
|
|
||||||
{
|
|
||||||
idxtype i, j, sum;
|
|
||||||
|
|
||||||
InitGraph(graph);
|
|
||||||
|
|
||||||
graph->nvtxs = nvtxs;
|
|
||||||
graph->nedges = xadj[nvtxs];
|
|
||||||
graph->ncon = ncon;
|
|
||||||
|
|
||||||
graph->xadj = xadj;
|
|
||||||
graph->free_xadj = 0;
|
|
||||||
|
|
||||||
graph->adjncy = adjncy;
|
|
||||||
graph->free_adjncy = 0;
|
|
||||||
|
|
||||||
graph->adjwgt = adjwgt;
|
|
||||||
graph->free_adjwgt = 0;
|
|
||||||
|
|
||||||
graph->nvwgt = gk_fmalloc(nvtxs*ncon, "SetUpGraph2: graph->nvwgt");
|
|
||||||
gk_fcopy(nvtxs*ncon, nvwgt, graph->nvwgt);
|
|
||||||
|
|
||||||
|
|
||||||
/* Compute the initial values of the adjwgtsum */
|
|
||||||
graph->adjwgtsum = idxmalloc(nvtxs, "SetUpGraph2: adjwgtsum");
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
for (sum=0, j=xadj[i]; j<xadj[i+1]; j++)
|
|
||||||
sum += adjwgt[j];
|
|
||||||
graph->adjwgtsum[i] = sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->cmap = idxmalloc(nvtxs, "SetUpGraph2: cmap");
|
|
||||||
|
|
||||||
graph->label = idxmalloc(nvtxs, "SetUpGraph: label");
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
graph->label[i] = i;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function sets up the graph from the user input
|
|
||||||
**************************************************************************/
|
|
||||||
void VolSetUpGraph(GraphType *graph, idxtype OpType, idxtype nvtxs, idxtype ncon, idxtype *xadj,
|
|
||||||
idxtype *adjncy, idxtype *vwgt, idxtype *vsize, idxtype wgtflag)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, sum;
|
|
||||||
idxtype *adjwgt;
|
|
||||||
float *nvwgt;
|
|
||||||
idxtype tvwgt[MAXNCON];
|
|
||||||
|
|
||||||
InitGraph(graph);
|
|
||||||
|
|
||||||
graph->nvtxs = nvtxs;
|
|
||||||
graph->nedges = xadj[nvtxs];
|
|
||||||
graph->ncon = ncon;
|
|
||||||
|
|
||||||
graph->xadj = xadj;
|
|
||||||
graph->free_xadj = 0;
|
|
||||||
|
|
||||||
graph->adjncy = adjncy;
|
|
||||||
graph->free_adjncy = 0;
|
|
||||||
|
|
||||||
/* Setup the vwgt/vwgt */
|
|
||||||
if (ncon == 1) { /* We are in the non mC mode */
|
|
||||||
if ((wgtflag&2) == 0) {
|
|
||||||
vwgt = graph->vwgt = idxsmalloc(nvtxs, 1, "VolSetUpGraph: vwgt");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
graph->vwgt = vwgt;
|
|
||||||
graph->free_vwgt = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* Set up the graph in MOC mode */
|
|
||||||
/* Create the normalized vertex weights along each constraint */
|
|
||||||
for (i=0; i<ncon; i++)
|
|
||||||
tvwgt[i] = idxsum(nvtxs, vwgt+i, ncon);
|
|
||||||
|
|
||||||
nvwgt = graph->nvwgt = gk_fmalloc(ncon*nvtxs, "SetUpGraph: nvwgt");
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
for (j=0; j<ncon; j++)
|
|
||||||
nvwgt[i*ncon+j] = (1.0*vwgt[i*ncon+j])/(1.0*tvwgt[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Setup the vsize */
|
|
||||||
if ((wgtflag&1) == 0) {
|
|
||||||
vsize = graph->vsize = idxsmalloc(nvtxs, 1, "VolSetUpGraph: vsize");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
graph->vsize = vsize;
|
|
||||||
graph->free_vsize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate memory for edge weights and initialize them to the sum of the vsize */
|
|
||||||
adjwgt = graph->adjwgt = idxmalloc(graph->nedges, "VolSetUpGraph: adjwgt");
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++)
|
|
||||||
adjwgt[j] = 1+vsize[i]+vsize[adjncy[j]];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Compute the initial values of the adjwgtsum */
|
|
||||||
graph->adjwgtsum = idxmalloc(nvtxs, "VolSetUpGraph: adjwgtsum");
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
for (sum=0, j=xadj[i]; j<xadj[i+1]; j++)
|
|
||||||
sum += adjwgt[j];
|
|
||||||
graph->adjwgtsum[i] = sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->cmap = idxmalloc(nvtxs, "VolSetUpGraph: cmap");
|
|
||||||
|
|
||||||
|
|
||||||
if (OpType != OP_KVMETIS) {
|
|
||||||
graph->label = idxmalloc(nvtxs, "SetUpGraph: label");
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
graph->label[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function randomly permutes the adjacency lists of a graph
|
|
||||||
**************************************************************************/
|
|
||||||
void RandomizeGraph(GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, l, tmp, nvtxs;
|
|
||||||
idxtype *xadj, *adjncy, *adjwgt;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
l = xadj[i+1]-xadj[i];
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = xadj[i] + RandomInRange(l);
|
|
||||||
SWAP(adjncy[j], adjncy[k], tmp);
|
|
||||||
SWAP(adjwgt[j], adjwgt[k], tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks whether or not partition pid is contigous
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype IsConnectedSubdomain(CtrlType *ctrl, GraphType *graph, idxtype pid, idxtype report)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, first, last, nleft, ncmps, wgt;
|
|
||||||
idxtype *xadj, *adjncy, *where, *touched, *queue;
|
|
||||||
idxtype *cptr;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
where = graph->where;
|
|
||||||
|
|
||||||
touched = idxsmalloc(nvtxs, 0, "IsConnected: touched");
|
|
||||||
queue = idxmalloc(nvtxs, "IsConnected: queue");
|
|
||||||
cptr = idxmalloc(nvtxs+1, "IsConnected: cptr");
|
|
||||||
|
|
||||||
nleft = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (where[i] == pid)
|
|
||||||
nleft++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (where[i] == pid)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
touched[i] = 1;
|
|
||||||
queue[0] = i;
|
|
||||||
first = 0; last = 1;
|
|
||||||
|
|
||||||
cptr[0] = 0; /* This actually points to queue */
|
|
||||||
ncmps = 0;
|
|
||||||
while (first != nleft) {
|
|
||||||
if (first == last) { /* Find another starting vertex */
|
|
||||||
cptr[++ncmps] = first;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (where[i] == pid && !touched[i])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
queue[last++] = i;
|
|
||||||
touched[i] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = queue[first++];
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
if (where[k] == pid && !touched[k]) {
|
|
||||||
queue[last++] = k;
|
|
||||||
touched[k] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cptr[++ncmps] = first;
|
|
||||||
|
|
||||||
if (ncmps > 1 && report) {
|
|
||||||
mprintf("The graph has %D connected components in partition %D:\t", ncmps, pid);
|
|
||||||
for (i=0; i<ncmps; i++) {
|
|
||||||
wgt = 0;
|
|
||||||
for (j=cptr[i]; j<cptr[i+1]; j++)
|
|
||||||
wgt += graph->vwgt[queue[j]];
|
|
||||||
mprintf("[%5D %5D] ", cptr[i+1]-cptr[i], wgt);
|
|
||||||
/*
|
|
||||||
if (cptr[i+1]-cptr[i] == 1)
|
|
||||||
mprintf("[%D %D] ", queue[cptr[i]], xadj[queue[cptr[i]]+1]-xadj[queue[cptr[i]]]);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
mprintf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_free((void **)&touched, &queue, &cptr, LTERM);
|
|
||||||
|
|
||||||
return (ncmps == 1 ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks whether a graph is contigous or not
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype IsConnected(CtrlType *ctrl, GraphType *graph, idxtype report)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, first, last;
|
|
||||||
idxtype *xadj, *adjncy, *touched, *queue;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
|
|
||||||
touched = idxsmalloc(nvtxs, 0, "IsConnected: touched");
|
|
||||||
queue = idxmalloc(nvtxs, "IsConnected: queue");
|
|
||||||
|
|
||||||
touched[0] = 1;
|
|
||||||
queue[0] = 0;
|
|
||||||
first = 0; last = 1;
|
|
||||||
|
|
||||||
while (first < last) {
|
|
||||||
i = queue[first++];
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
if (!touched[k]) {
|
|
||||||
queue[last++] = k;
|
|
||||||
touched[k] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first != nvtxs && report)
|
|
||||||
mprintf("The graph is not connected. It has %D disconnected vertices!\n", nvtxs-first);
|
|
||||||
|
|
||||||
return (first == nvtxs ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks whether or not partition pid is contigous
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype IsConnected2(GraphType *graph, idxtype report)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, first, last, nleft, ncmps, wgt;
|
|
||||||
idxtype *xadj, *adjncy, *where, *touched, *queue;
|
|
||||||
idxtype *cptr;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
where = graph->where;
|
|
||||||
|
|
||||||
touched = idxsmalloc(nvtxs, 0, "IsConnected: touched");
|
|
||||||
queue = idxmalloc(nvtxs, "IsConnected: queue");
|
|
||||||
cptr = idxmalloc(nvtxs+1, "IsConnected: cptr");
|
|
||||||
|
|
||||||
nleft = nvtxs;
|
|
||||||
touched[0] = 1;
|
|
||||||
queue[0] = 0;
|
|
||||||
first = 0; last = 1;
|
|
||||||
|
|
||||||
cptr[0] = 0; /* This actually points to queue */
|
|
||||||
ncmps = 0;
|
|
||||||
while (first != nleft) {
|
|
||||||
if (first == last) { /* Find another starting vertex */
|
|
||||||
cptr[++ncmps] = first;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (!touched[i])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
queue[last++] = i;
|
|
||||||
touched[i] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = queue[first++];
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
if (!touched[k]) {
|
|
||||||
queue[last++] = k;
|
|
||||||
touched[k] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cptr[++ncmps] = first;
|
|
||||||
|
|
||||||
if (ncmps > 1 && report) {
|
|
||||||
mprintf("%D connected components:\t", ncmps);
|
|
||||||
for (i=0; i<ncmps; i++) {
|
|
||||||
if (cptr[i+1]-cptr[i] > 200)
|
|
||||||
mprintf("[%5D] ", cptr[i+1]-cptr[i]);
|
|
||||||
}
|
|
||||||
mprintf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
gk_free((void **)&touched, &queue, &cptr, LTERM);
|
|
||||||
|
|
||||||
return (ncmps == 1 ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function returns the number of connected components in cptr,cind
|
|
||||||
* The separator of the graph is used to split it and then find its components.
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype FindComponents(CtrlType *ctrl, GraphType *graph, idxtype *cptr, idxtype *cind)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, first, last, nleft, ncmps, wgt;
|
|
||||||
idxtype *xadj, *adjncy, *where, *touched, *queue;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
where = graph->where;
|
|
||||||
|
|
||||||
touched = idxsmalloc(nvtxs, 0, "IsConnected: queue");
|
|
||||||
|
|
||||||
for (i=0; i<graph->nbnd; i++)
|
|
||||||
touched[graph->bndind[i]] = 1;
|
|
||||||
|
|
||||||
queue = cind;
|
|
||||||
|
|
||||||
nleft = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (where[i] != 2)
|
|
||||||
nleft++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (where[i] != 2)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
touched[i] = 1;
|
|
||||||
queue[0] = i;
|
|
||||||
first = 0; last = 1;
|
|
||||||
|
|
||||||
cptr[0] = 0; /* This actually points to queue */
|
|
||||||
ncmps = 0;
|
|
||||||
while (first != nleft) {
|
|
||||||
if (first == last) { /* Find another starting vertex */
|
|
||||||
cptr[++ncmps] = first;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (!touched[i])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
queue[last++] = i;
|
|
||||||
touched[i] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = queue[first++];
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
if (!touched[k]) {
|
|
||||||
queue[last++] = k;
|
|
||||||
touched[k] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cptr[++ncmps] = first;
|
|
||||||
|
|
||||||
gk_free((void **)&touched, LTERM);
|
|
||||||
|
|
||||||
return ncmps;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,424 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* initpart.c
|
|
||||||
*
|
|
||||||
* This file contains code that performs the initial partition of the
|
|
||||||
* coarsest graph
|
|
||||||
*
|
|
||||||
* Started 7/23/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the initial bisection of the coarsest graph
|
|
||||||
**************************************************************************/
|
|
||||||
void Init2WayPartition(CtrlType *ctrl, GraphType *graph, idxtype *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype dbglvl;
|
|
||||||
|
|
||||||
dbglvl = ctrl->dbglvl;
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE, ctrl->dbglvl -= DBG_REFINE);
|
|
||||||
IFSET(ctrl->dbglvl, DBG_MOVEINFO, ctrl->dbglvl -= DBG_MOVEINFO);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
|
|
||||||
|
|
||||||
switch (ctrl->IType) {
|
|
||||||
case ITYPE_GGPKL:
|
|
||||||
if (graph->nedges == 0)
|
|
||||||
RandomBisection(ctrl, graph, tpwgts, ubfactor);
|
|
||||||
else
|
|
||||||
GrowBisection(ctrl, graph, tpwgts, ubfactor);
|
|
||||||
break;
|
|
||||||
case ITYPE_RANDOM:
|
|
||||||
RandomBisection(ctrl, graph, tpwgts, ubfactor);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errexit("Unknown initial partition type: %d\n", ctrl->IType);
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_IPART, mprintf("Initial Cut: %D\n", graph->mincut));
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
|
|
||||||
ctrl->dbglvl = dbglvl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
IsConnectedSubdomain(ctrl, graph, 0);
|
|
||||||
IsConnectedSubdomain(ctrl, graph, 1);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the initial bisection of the coarsest graph
|
|
||||||
**************************************************************************/
|
|
||||||
void InitSeparator(CtrlType *ctrl, GraphType *graph, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype dbglvl;
|
|
||||||
|
|
||||||
dbglvl = ctrl->dbglvl;
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE, ctrl->dbglvl -= DBG_REFINE);
|
|
||||||
IFSET(ctrl->dbglvl, DBG_MOVEINFO, ctrl->dbglvl -= DBG_MOVEINFO);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
|
|
||||||
|
|
||||||
GrowBisectionNode(ctrl, graph, ubfactor);
|
|
||||||
Compute2WayNodePartitionParams(ctrl, graph);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_IPART, mprintf("Initial Sep: %D\n", graph->mincut));
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
|
|
||||||
|
|
||||||
ctrl->dbglvl = dbglvl;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes a graph and produces a bisection by using a region
|
|
||||||
* growing algorithm. The resulting partition is returned in
|
|
||||||
* graph->where
|
|
||||||
**************************************************************************/
|
|
||||||
void GrowBisection(CtrlType *ctrl, GraphType *graph, idxtype *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], minpwgt[2],
|
|
||||||
maxpwgt[2], from, bestcut, icut, mincut, me, pass, nbfs, inbfs;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt, *where;
|
|
||||||
idxtype *queue, *touched, *gain, *bestwhere;
|
|
||||||
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
Allocate2WayPartitionMemory(ctrl, graph);
|
|
||||||
where = graph->where;
|
|
||||||
|
|
||||||
bestwhere = idxmalloc(nvtxs, "BisectGraph: bestwhere");
|
|
||||||
queue = idxmalloc(nvtxs, "BisectGraph: queue");
|
|
||||||
touched = idxmalloc(nvtxs, "BisectGraph: touched");
|
|
||||||
|
|
||||||
ASSERTP(tpwgts[0]+tpwgts[1] == idxsum(nvtxs, vwgt, 1), ("%d %d\n", tpwgts[0]+tpwgts[1], idxsum(nvtxs, vwgt, 1)));
|
|
||||||
|
|
||||||
maxpwgt[0] = ubfactor*tpwgts[0];
|
|
||||||
maxpwgt[1] = ubfactor*tpwgts[1];
|
|
||||||
minpwgt[0] = (1.0/ubfactor)*tpwgts[0];
|
|
||||||
minpwgt[1] = (1.0/ubfactor)*tpwgts[1];
|
|
||||||
|
|
||||||
nbfs = (nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS);
|
|
||||||
for (inbfs=0; inbfs<nbfs; inbfs++) {
|
|
||||||
idxset(nvtxs, 0, touched);
|
|
||||||
|
|
||||||
pwgts[1] = tpwgts[0]+tpwgts[1];
|
|
||||||
pwgts[0] = 0;
|
|
||||||
|
|
||||||
idxset(nvtxs, 1, where);
|
|
||||||
|
|
||||||
queue[0] = RandomInRange(nvtxs);
|
|
||||||
touched[queue[0]] = 1;
|
|
||||||
first = 0; last = 1;
|
|
||||||
nleft = nvtxs-1;
|
|
||||||
drain = 0;
|
|
||||||
|
|
||||||
/* Start the BFS from queue to get a partition */
|
|
||||||
for (;;) {
|
|
||||||
if (first == last) { /* Empty. Disconnected graph! */
|
|
||||||
if (nleft == 0 || drain)
|
|
||||||
break;
|
|
||||||
|
|
||||||
k = RandomInRange(nleft);
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (touched[i] == 0) {
|
|
||||||
if (k == 0)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
k--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
queue[0] = i;
|
|
||||||
touched[i] = 1;
|
|
||||||
first = 0; last = 1;;
|
|
||||||
nleft--;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = queue[first++];
|
|
||||||
if (pwgts[0] > 0 && pwgts[1]-vwgt[i] < minpwgt[1]) {
|
|
||||||
drain = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
where[i] = 0;
|
|
||||||
INC_DEC(pwgts[0], pwgts[1], vwgt[i]);
|
|
||||||
if (pwgts[1] <= maxpwgt[1])
|
|
||||||
break;
|
|
||||||
|
|
||||||
drain = 0;
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
if (touched[k] == 0) {
|
|
||||||
queue[last++] = k;
|
|
||||||
touched[k] = 1;
|
|
||||||
nleft--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check to see if we hit any bad limiting cases */
|
|
||||||
if (pwgts[1] == 0) {
|
|
||||||
i = RandomInRange(nvtxs);
|
|
||||||
where[i] = 1;
|
|
||||||
INC_DEC(pwgts[1], pwgts[0], vwgt[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Do some partition refinement
|
|
||||||
**************************************************************/
|
|
||||||
Compute2WayPartitionParams(ctrl, graph);
|
|
||||||
/*mprintf("IPART: %3D [%5D %5D] [%5D %5D] %5D\n", graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); */
|
|
||||||
|
|
||||||
Balance2Way(ctrl, graph, tpwgts, ubfactor);
|
|
||||||
/*mprintf("BPART: [%5D %5D] %5D\n", graph->pwgts[0], graph->pwgts[1], graph->mincut);*/
|
|
||||||
|
|
||||||
FM_2WayEdgeRefine(ctrl, graph, tpwgts, 4);
|
|
||||||
/*mprintf("RPART: [%5D %5D] %5D\n", graph->pwgts[0], graph->pwgts[1], graph->mincut);*/
|
|
||||||
|
|
||||||
if (inbfs == 0 || bestcut > graph->mincut) {
|
|
||||||
bestcut = graph->mincut;
|
|
||||||
idxcopy(nvtxs, where, bestwhere);
|
|
||||||
if (bestcut == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->mincut = bestcut;
|
|
||||||
idxcopy(nvtxs, bestwhere, where);
|
|
||||||
|
|
||||||
gk_free((void **)&bestwhere, &queue, &touched, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes a graph and produces a bisection by using a region
|
|
||||||
* growing algorithm. The resulting partition is returned in
|
|
||||||
* graph->where
|
|
||||||
**************************************************************************/
|
|
||||||
void GrowBisectionNode(CtrlType *ctrl, GraphType *graph, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], tpwgts[2],
|
|
||||||
minpwgt[2], maxpwgt[2], from, bestcut, icut, mincut, me, pass,
|
|
||||||
nbfs, inbfs;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt, *where, *bndind;
|
|
||||||
idxtype *queue, *touched, *gain, *bestwhere;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
bestwhere = idxmalloc(nvtxs, "BisectGraph: bestwhere");
|
|
||||||
queue = idxmalloc(nvtxs, "BisectGraph: queue");
|
|
||||||
touched = idxmalloc(nvtxs, "BisectGraph: touched");
|
|
||||||
|
|
||||||
tpwgts[0] = idxsum(nvtxs, vwgt, 1);
|
|
||||||
tpwgts[1] = tpwgts[0]/2;
|
|
||||||
tpwgts[0] -= tpwgts[1];
|
|
||||||
|
|
||||||
maxpwgt[0] = ubfactor*tpwgts[0];
|
|
||||||
maxpwgt[1] = ubfactor*tpwgts[1];
|
|
||||||
minpwgt[0] = (1.0/ubfactor)*tpwgts[0];
|
|
||||||
minpwgt[1] = (1.0/ubfactor)*tpwgts[1];
|
|
||||||
|
|
||||||
/* Allocate refinement memory. Allocate sufficient memory for both edge and node */
|
|
||||||
graph->pwgts = idxmalloc(3, "GrowBisectionNode: pwgts");
|
|
||||||
graph->where = idxmalloc(nvtxs, "GrowBisectionNode: where");
|
|
||||||
graph->bndptr = idxmalloc(nvtxs, "GrowBisectionNode: bndptr");
|
|
||||||
graph->bndind = idxmalloc(nvtxs, "GrowBisectionNode: bndind");
|
|
||||||
graph->id = idxmalloc(nvtxs, "GrowBisectionNode: id");
|
|
||||||
graph->ed = idxmalloc(nvtxs, "GrowBisectionNode: ed");
|
|
||||||
graph->nrinfo = (NRInfoType *)gk_malloc(nvtxs*sizeof(NRInfoType), "GrowBisectionNode: nrinfo");
|
|
||||||
|
|
||||||
|
|
||||||
where = graph->where;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
|
|
||||||
nbfs = (nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS) + 1;
|
|
||||||
for (inbfs=0; inbfs<nbfs; inbfs++) {
|
|
||||||
idxset(nvtxs, 0, touched);
|
|
||||||
|
|
||||||
pwgts[1] = tpwgts[0]+tpwgts[1];
|
|
||||||
pwgts[0] = 0;
|
|
||||||
|
|
||||||
idxset(nvtxs, 1, where);
|
|
||||||
|
|
||||||
queue[0] = RandomInRange(nvtxs);
|
|
||||||
touched[queue[0]] = 1;
|
|
||||||
first = 0; last = 1;
|
|
||||||
nleft = nvtxs-1;
|
|
||||||
drain = 0;
|
|
||||||
|
|
||||||
/* Start the BFS from queue to get a partition */
|
|
||||||
if (nbfs >= 1) {
|
|
||||||
for (;;) {
|
|
||||||
if (first == last) { /* Empty. Disconnected graph! */
|
|
||||||
if (nleft == 0 || drain)
|
|
||||||
break;
|
|
||||||
|
|
||||||
k = RandomInRange(nleft);
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (touched[i] == 0) {
|
|
||||||
if (k == 0)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
k--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
queue[0] = i;
|
|
||||||
touched[i] = 1;
|
|
||||||
first = 0; last = 1;;
|
|
||||||
nleft--;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = queue[first++];
|
|
||||||
if (pwgts[1]-vwgt[i] < minpwgt[1]) {
|
|
||||||
drain = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
where[i] = 0;
|
|
||||||
INC_DEC(pwgts[0], pwgts[1], vwgt[i]);
|
|
||||||
if (pwgts[1] <= maxpwgt[1])
|
|
||||||
break;
|
|
||||||
|
|
||||||
drain = 0;
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
if (touched[k] == 0) {
|
|
||||||
queue[last++] = k;
|
|
||||||
touched[k] = 1;
|
|
||||||
nleft--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Do some partition refinement
|
|
||||||
**************************************************************/
|
|
||||||
Compute2WayPartitionParams(ctrl, graph);
|
|
||||||
Balance2Way(ctrl, graph, tpwgts, ubfactor);
|
|
||||||
FM_2WayEdgeRefine(ctrl, graph, tpwgts, 4);
|
|
||||||
|
|
||||||
/* Construct and refine the vertex separator */
|
|
||||||
for (i=0; i<graph->nbnd; i++)
|
|
||||||
where[bndind[i]] = 2;
|
|
||||||
|
|
||||||
Compute2WayNodePartitionParams(ctrl, graph);
|
|
||||||
FM_2WayNodeRefine(ctrl, graph, ubfactor, 6);
|
|
||||||
|
|
||||||
/* mprintf("ISep: [%D %D %D] %D\n", graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut); */
|
|
||||||
|
|
||||||
if (inbfs == 0 || bestcut > graph->mincut) {
|
|
||||||
bestcut = graph->mincut;
|
|
||||||
idxcopy(nvtxs, where, bestwhere);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->mincut = bestcut;
|
|
||||||
idxcopy(nvtxs, bestwhere, where);
|
|
||||||
|
|
||||||
Compute2WayNodePartitionParams(ctrl, graph);
|
|
||||||
|
|
||||||
gk_free((void **)&bestwhere, &queue, &touched, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes a graph and produces a bisection by using a region
|
|
||||||
* growing algorithm. The resulting partition is returned in
|
|
||||||
* graph->where
|
|
||||||
**************************************************************************/
|
|
||||||
void RandomBisection(CtrlType *ctrl, GraphType *graph, idxtype *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, nvtxs, pwgts[2], minpwgt[2], maxpwgt[2], from, bestcut,
|
|
||||||
icut, mincut, me, pass, nbfs, inbfs;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt, *where;
|
|
||||||
idxtype *perm, *bestwhere;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
Allocate2WayPartitionMemory(ctrl, graph);
|
|
||||||
where = graph->where;
|
|
||||||
|
|
||||||
bestwhere = idxmalloc(nvtxs, "BisectGraph: bestwhere");
|
|
||||||
perm = idxmalloc(nvtxs, "BisectGraph: queue");
|
|
||||||
|
|
||||||
ASSERTP(tpwgts[0]+tpwgts[1] == idxsum(nvtxs, vwgt, 1), ("%d %d\n", tpwgts[0]+tpwgts[1], idxsum(nvtxs, vwgt, 1)));
|
|
||||||
|
|
||||||
maxpwgt[0] = ubfactor*tpwgts[0];
|
|
||||||
maxpwgt[1] = ubfactor*tpwgts[1];
|
|
||||||
minpwgt[0] = (1.0/ubfactor)*tpwgts[0];
|
|
||||||
minpwgt[1] = (1.0/ubfactor)*tpwgts[1];
|
|
||||||
|
|
||||||
nbfs = (nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS);
|
|
||||||
for (inbfs=0; inbfs<nbfs; inbfs++) {
|
|
||||||
RandomPermute(nvtxs, perm, 1);
|
|
||||||
|
|
||||||
idxset(nvtxs, 1, where);
|
|
||||||
pwgts[1] = tpwgts[0]+tpwgts[1];
|
|
||||||
pwgts[0] = 0;
|
|
||||||
|
|
||||||
|
|
||||||
if (nbfs != 1) {
|
|
||||||
for (ii=0; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
if (pwgts[0]+vwgt[i] < maxpwgt[0]) {
|
|
||||||
where[i] = 0;
|
|
||||||
pwgts[0] += vwgt[i];
|
|
||||||
pwgts[1] -= vwgt[i];
|
|
||||||
if (pwgts[0] > minpwgt[0])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Do some partition refinement
|
|
||||||
**************************************************************/
|
|
||||||
Compute2WayPartitionParams(ctrl, graph);
|
|
||||||
/* mprintf("IPART: %3D [%5D %5D] [%5D %5D] %5D\n", graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); */
|
|
||||||
|
|
||||||
Balance2Way(ctrl, graph, tpwgts, ubfactor);
|
|
||||||
/* mprintf("BPART: [%5D %5D] %5D\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */
|
|
||||||
|
|
||||||
FM_2WayEdgeRefine(ctrl, graph, tpwgts, 4);
|
|
||||||
/* mprintf("RPART: [%5D %5D] %5D\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */
|
|
||||||
|
|
||||||
if (inbfs==0 || bestcut > graph->mincut) {
|
|
||||||
bestcut = graph->mincut;
|
|
||||||
idxcopy(nvtxs, where, bestwhere);
|
|
||||||
if (bestcut == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->mincut = bestcut;
|
|
||||||
idxcopy(nvtxs, bestwhere, where);
|
|
||||||
|
|
||||||
gk_free((void **)&bestwhere, &perm, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,551 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* kfmetis.c
|
|
||||||
*
|
|
||||||
* This file contains the top level routines for computing a k-way partitioning
|
|
||||||
* that also balances the fill-in.
|
|
||||||
*
|
|
||||||
* Started 8/12/02
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry point for KFMETIS
|
|
||||||
**************************************************************************/
|
|
||||||
void METIS_PartFillGraph(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts,
|
|
||||||
idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
idxtype i, j;
|
|
||||||
GraphType graph;
|
|
||||||
CtrlType ctrl;
|
|
||||||
|
|
||||||
/* Compute an initial k-way partitioning of the graph */
|
|
||||||
METIS_PartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts,
|
|
||||||
options, edgecut, part);
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------
|
|
||||||
* Internalize the graph and allocate memory for the workspace
|
|
||||||
*-----------------------------------------------------------------------*/
|
|
||||||
if (*numflag == 1)
|
|
||||||
Change2CNumbering(*nvtxs, xadj, adjncy);
|
|
||||||
|
|
||||||
SetUpGraph(&graph, OP_KMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, *wgtflag);
|
|
||||||
|
|
||||||
if (options[0] == 0) { /* Use the default parameters */
|
|
||||||
ctrl.CType = KMETIS_CTYPE;
|
|
||||||
ctrl.IType = KMETIS_ITYPE;
|
|
||||||
ctrl.RType = KMETIS_RTYPE;
|
|
||||||
ctrl.dbglvl = KMETIS_DBGLVL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ctrl.CType = options[OPTION_CTYPE];
|
|
||||||
ctrl.IType = options[OPTION_ITYPE];
|
|
||||||
ctrl.RType = options[OPTION_RTYPE];
|
|
||||||
ctrl.dbglvl = options[OPTION_DBGLVL];
|
|
||||||
}
|
|
||||||
ctrl.optype = OP_KMETIS;
|
|
||||||
ctrl.CoarsenTo = amax((*nvtxs)/(40*gk_log2(*nparts)), 20*(*nparts));
|
|
||||||
ctrl.maxvwgt = 1.5*((graph.vwgt ? idxsum(*nvtxs, graph.vwgt, 1) : (*nvtxs))/ctrl.CoarsenTo);
|
|
||||||
|
|
||||||
InitRandom(-1);
|
|
||||||
|
|
||||||
AllocateWorkSpace(&ctrl, &graph, *nparts);
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------
|
|
||||||
* Balance the fill-in
|
|
||||||
*-----------------------------------------------------------------------*/
|
|
||||||
BalanceFillIn(&ctrl, &graph, *nparts, part);
|
|
||||||
|
|
||||||
|
|
||||||
*edgecut = ComputeCut(&graph, part);
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------
|
|
||||||
* Post-process the results
|
|
||||||
*-----------------------------------------------------------------------*/
|
|
||||||
FreeWorkSpace(&ctrl, &graph);
|
|
||||||
|
|
||||||
if (*numflag == 1)
|
|
||||||
Change2FNumbering(*nvtxs, xadj, adjncy, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
* This function is the top-level routine of the fill-balancing code
|
|
||||||
***************************************************************************/
|
|
||||||
void BalanceFillIn(CtrlType *ctrl, GraphType *graph, idxtype nparts, idxtype *part)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, options[10];
|
|
||||||
idxtype *fills, *subfills, *ssize, *spart, *vmap, *ppart, *vimap;
|
|
||||||
idxtype oldavg, oldmax, oldcut, oldmaxcut, newavg, newmax, newcut, newmaxcut;
|
|
||||||
idxtype *tssize;
|
|
||||||
float diff, alpha;
|
|
||||||
GraphType *pgraph;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
|
|
||||||
fills = idxsmalloc(nparts, 0, "BalanceFillIn: fills");
|
|
||||||
subfills = idxsmalloc(2*nparts, 0, "BalanceFillIn: subfills");
|
|
||||||
ssize = idxsmalloc(nparts, 0, "BalanceFillIn: ssize");
|
|
||||||
tssize = idxsmalloc(nparts, 0, "BalanceFillIn: tssize");
|
|
||||||
|
|
||||||
spart = idxmalloc(nvtxs, "BalanceFillIn: spart");
|
|
||||||
ppart = idxmalloc(nvtxs, "BalanceFillIn: ppart");
|
|
||||||
vmap = idxmalloc(nvtxs, "BalanceFillIn: vmap");
|
|
||||||
vimap = idxmalloc(nvtxs, "BalanceFillIn: vimap");
|
|
||||||
|
|
||||||
/* Go and compute a top-level vertex separator for each partition */
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
pgraph = ExtractPartitionGraph(graph, part, i, vmap, vimap);
|
|
||||||
|
|
||||||
options[0] = 0;
|
|
||||||
options[7] = -1;
|
|
||||||
METIS_NodeComputeSeparator(&(pgraph->nvtxs), pgraph->xadj, pgraph->adjncy, pgraph->vwgt,
|
|
||||||
pgraph->adjwgt, options, &ssize[i], ppart);
|
|
||||||
|
|
||||||
|
|
||||||
/* Copy the separator and partition information to the global graph's spart vector */
|
|
||||||
for (j=0; j<pgraph->nvtxs; j++)
|
|
||||||
spart[vimap[j]] = ppart[j];
|
|
||||||
|
|
||||||
FreeGraph(pgraph, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Go and compute the fill-ins of each partition */
|
|
||||||
for (i=0; i<nparts; i++)
|
|
||||||
ComputePartitionFillIn(ctrl, graph, nparts, part, spart, i, &fills[i], &subfills[2*i]);
|
|
||||||
|
|
||||||
oldavg = idxsum(nparts, fills, 1)/nparts;
|
|
||||||
oldmax = fills[idxargmax(nparts, fills)];
|
|
||||||
oldcut = ComputeCut(graph, part);
|
|
||||||
oldmaxcut = ComputeMaxCut(graph, nparts, part);
|
|
||||||
|
|
||||||
mprintf("AverageFill: %10D, MaxFill: %10D, LoadImbalance: %.3f, EdgeCut: %5D, MaxCut: %5D\n",
|
|
||||||
oldavg, oldmax, 1.0*oldmax/oldavg, oldcut, oldmaxcut);
|
|
||||||
|
|
||||||
/* Determine the target separator sizes of the domains that are above average */
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
if (fills[i] < 1.05*oldavg) {
|
|
||||||
tssize[i] = ssize[i];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (oldavg - (subfills[2*i] +subfills[2*i+1])< 0) {
|
|
||||||
tssize[i] = ssize[i]/5.0;
|
|
||||||
mprintf("* %2D %7D %7D %6D %6D\n", i, fills[i], subfills[2*i]+subfills[2*i+1], ssize[i], tssize[i]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alpha = sqrt(fills[i] - (subfills[2*i]+subfills[2*i+1]))/ssize[i];
|
|
||||||
tssize[i] = sqrt(oldavg - (subfills[2*i]+subfills[2*i+1]))/alpha;
|
|
||||||
mprintf("< %2D %7D %7D %6D %6D\n", i, fills[i], subfills[2*i]+subfills[2*i+1], ssize[i], tssize[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Perform a simple greedy refinement */
|
|
||||||
RefineTopLevelSeparators(ctrl, graph, nparts, part, spart, fills, subfills, ssize, tssize);
|
|
||||||
|
|
||||||
/* Go and compute the fill-ins of each partition */
|
|
||||||
for (i=0; i<nparts; i++)
|
|
||||||
ComputePartitionFillIn(ctrl, graph, nparts, part, spart, i, &fills[i], &subfills[2*i]);
|
|
||||||
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
if (tssize[i] < ssize[i])
|
|
||||||
mprintf("%3D %6D %6D %8D\n", i, ssize[i], tssize[i], fills[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
newavg = idxsum(nparts, fills, 1)/nparts;
|
|
||||||
newmax = fills[idxargmax(nparts, fills)];
|
|
||||||
newcut = ComputeCut(graph, part);
|
|
||||||
newmaxcut = ComputeMaxCut(graph, nparts, part);
|
|
||||||
|
|
||||||
mprintf("AverageFill: %10D, MaxFill: %10D, LoadImbalance: %.3f, EdgeCut: %5D, MaxCut: %5D\n",
|
|
||||||
newavg, newmax, 1.0*newmax/newavg, newcut, newmaxcut);
|
|
||||||
|
|
||||||
mprintf("Effective Load Imbalance: %.3f, Sum Fill/Comm Ratio: %6.2f, Max Fill/Comm Ratio: %6.2f\n",
|
|
||||||
1.0*newmax/oldavg, 1.0*(oldmax-newmax)/(newcut-oldcut), 1.0*(oldmax-newmax)/(newmaxcut-oldmaxcut));
|
|
||||||
|
|
||||||
gk_free((void **)&fills, &subfills, &ssize, &spart, &ppart, &vmap, &vimap, LTERM);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes a fill-reducing ordering for a particular
|
|
||||||
* partition, whose top-level separator is provided as input
|
|
||||||
**************************************************************************/
|
|
||||||
void ComputePartitionFillIn(CtrlType *ctrl, GraphType *graph, idxtype nparts,
|
|
||||||
idxtype *part, idxtype *spart, idxtype pid, idxtype *r_fill,
|
|
||||||
idxtype *r_subfill)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, pnvtxs, options[10], numflag=0;
|
|
||||||
idxtype *vmap, *vimap, *ppart, *iperm;
|
|
||||||
idxtype *lvmap, *lvimap, *rvmap, *rvimap, *lperm, *liperm, *rperm, *riperm;
|
|
||||||
GraphType *pgraph, *lgraph, *rgraph;
|
|
||||||
|
|
||||||
/* Extract the partition graph */
|
|
||||||
vmap = idxmalloc(graph->nvtxs, "ComputePartitionFillIn: vmap");
|
|
||||||
vimap = idxmalloc(graph->nvtxs, "ComputePartitionFillIn: vimap");
|
|
||||||
|
|
||||||
pgraph = ExtractPartitionGraph(graph, part, pid, vmap, vimap);
|
|
||||||
|
|
||||||
pnvtxs = pgraph->nvtxs;
|
|
||||||
|
|
||||||
iperm = idxmalloc(pnvtxs, "ComputePartitionFillIn: iperm");
|
|
||||||
ppart = idxmalloc(pnvtxs, "ComputePartitionFillIn: ppart");
|
|
||||||
|
|
||||||
lvmap = idxmalloc(pnvtxs, "ComputePartitionFillIn: lvmap");
|
|
||||||
lvimap = idxmalloc(pnvtxs, "ComputePartitionFillIn: lvimap");
|
|
||||||
rvmap = idxmalloc(pnvtxs, "ComputePartitionFillIn: rvmap");
|
|
||||||
rvimap = idxmalloc(pnvtxs, "ComputePartitionFillIn: rvimap");
|
|
||||||
lperm = idxmalloc(pnvtxs, "ComputePartitionFillIn: liperm");
|
|
||||||
liperm = idxmalloc(pnvtxs, "ComputePartitionFillIn: liperm");
|
|
||||||
rperm = idxmalloc(pnvtxs, "ComputePartitionFillIn: riperm");
|
|
||||||
riperm = idxmalloc(pnvtxs, "ComputePartitionFillIn: riperm");
|
|
||||||
|
|
||||||
|
|
||||||
/* project down the separator-partition */
|
|
||||||
for (i=0; i<pnvtxs; i++)
|
|
||||||
ppart[i] = spart[vimap[i]];
|
|
||||||
|
|
||||||
/* Check to see if the separators are indeed separators */
|
|
||||||
for (i=0; i<pnvtxs; i++) {
|
|
||||||
for (j=pgraph->xadj[i]; j<pgraph->xadj[i+1]; j++) {
|
|
||||||
if (ppart[i] != ppart[pgraph->adjncy[j]]) {
|
|
||||||
if (!(ppart[i] == 2 || ppart[pgraph->adjncy[j]] == 2))
|
|
||||||
mprintf("Error: %D %D %D\n", i, ppart[i], ppart[pgraph->adjncy[j]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
lgraph = ExtractPartitionGraph(pgraph, ppart, 0, lvmap, lvimap);
|
|
||||||
rgraph = ExtractPartitionGraph(pgraph, ppart, 1, rvmap, rvimap);
|
|
||||||
|
|
||||||
options[0] = 1;
|
|
||||||
options[1] = 3;
|
|
||||||
options[2] = 1;
|
|
||||||
options[3] = 1;
|
|
||||||
options[4] = 0;
|
|
||||||
options[5] = 0;
|
|
||||||
options[6] = 0;
|
|
||||||
options[7] = 4;
|
|
||||||
METIS_NodeND(&lgraph->nvtxs, lgraph->xadj, lgraph->adjncy, &numflag, options, lperm, liperm);
|
|
||||||
METIS_NodeND(&rgraph->nvtxs, rgraph->xadj, rgraph->adjncy, &numflag, options, rperm, riperm);
|
|
||||||
|
|
||||||
/* Put the ordering together */
|
|
||||||
for (i=0; i<lgraph->nvtxs; i++)
|
|
||||||
iperm[lvimap[i]] = liperm[i];
|
|
||||||
for (i=0; i<rgraph->nvtxs; i++)
|
|
||||||
iperm[rvimap[i]] = lgraph->nvtxs + riperm[i];
|
|
||||||
|
|
||||||
for (j=lgraph->nvtxs+rgraph->nvtxs, i=0; i<pnvtxs; i++) {
|
|
||||||
if (ppart[i] == 2)
|
|
||||||
iperm[i] = j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
*r_fill = ComputeFillIn2(pgraph, iperm);
|
|
||||||
r_subfill[0] = ComputeFillIn2(lgraph, liperm);
|
|
||||||
r_subfill[1] = ComputeFillIn2(rgraph, riperm);
|
|
||||||
|
|
||||||
mprintf("%4D %5D %5D %5D %10D %10D %10D\n", pid, pnvtxs-lgraph->nvtxs-rgraph->nvtxs,
|
|
||||||
lgraph->nvtxs, rgraph->nvtxs, r_subfill[0], r_subfill[1], *r_fill);
|
|
||||||
|
|
||||||
FreeGraph(pgraph, 1);
|
|
||||||
FreeGraph(lgraph, 1);
|
|
||||||
FreeGraph(rgraph, 1);
|
|
||||||
|
|
||||||
gk_free((void **)&vmap, &vimap, &iperm, &ppart, &lvmap, &lvimap, &rvmap, &rvimap,
|
|
||||||
&lperm, &liperm, &rperm, &riperm, LTERM);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function extracts the graph of a partition and returns it.
|
|
||||||
**************************************************************************/
|
|
||||||
GraphType *ExtractPartitionGraph(GraphType *graph, idxtype *part, idxtype pid,
|
|
||||||
idxtype *vmap, idxtype *vimap)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, pnvtxs, pnedges;
|
|
||||||
idxtype *xadj, *adjncy, *vwgt, *adjwgt;
|
|
||||||
idxtype *pxadj, *padjncy, *pvwgt, *padjwgt;
|
|
||||||
GraphType *pgraph;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
|
|
||||||
/* Determine the size of the partition graph */
|
|
||||||
for (pnvtxs=pnedges=0, i=0; i<nvtxs; i++) {
|
|
||||||
if (part[i] != pid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
vmap[i] = pnvtxs;
|
|
||||||
vimap[pnvtxs] = i;
|
|
||||||
pnvtxs++;
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (part[adjncy[j]] == pid)
|
|
||||||
pnedges++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Allocate memory for the partition graph */
|
|
||||||
pgraph = CreateGraph();
|
|
||||||
pgraph->nvtxs = pnvtxs;
|
|
||||||
pgraph->nedges = pnedges;
|
|
||||||
|
|
||||||
pxadj = pgraph->xadj = idxmalloc(pnvtxs+1, "ExtractPartitionGraph: xadj");
|
|
||||||
pvwgt = pgraph->vwgt = idxmalloc(pnvtxs, "ExtractPartitionGraph: vwgt");
|
|
||||||
padjncy = pgraph->adjncy = idxmalloc(pnedges, "ExtractPartitionGraph: adjncy");
|
|
||||||
padjwgt = pgraph->adjwgt = idxmalloc(pnedges, "ExtractPartitionGraph: adjwgt");
|
|
||||||
pgraph->adjwgtsum = idxmalloc(pnvtxs, "ExtractPartitionGraph: adjwgtsum");
|
|
||||||
pgraph->cmap = idxmalloc(pnvtxs, "ExtractPartitionGraph: cmap");
|
|
||||||
|
|
||||||
|
|
||||||
/* Go and extract the partition graph */
|
|
||||||
pxadj[0] = pnvtxs = pnedges = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (part[i] != pid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (part[adjncy[j]] == pid) {
|
|
||||||
padjncy[pnedges] = vmap[adjncy[j]];
|
|
||||||
padjwgt[pnedges] = adjwgt[j];
|
|
||||||
pnedges++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pvwgt[pnvtxs] = vwgt[i];
|
|
||||||
pxadj[++pnvtxs] = pnedges;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pgraph;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function implements a very simple greedy k-way refinement routine
|
|
||||||
* for top level separators
|
|
||||||
**************************************************************************/
|
|
||||||
void RefineTopLevelSeparators(CtrlType *ctrl, GraphType *graph, idxtype nparts,
|
|
||||||
idxtype *part, idxtype *spart, idxtype *fills, idxtype *subfills,
|
|
||||||
idxtype *ssizes, idxtype *tssizes)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, from, to, nvtxs, mincut, ndegrees, pass, avgssize,
|
|
||||||
avgfill, id, maxpwgt, maxspwgt, nmoves, avgdegree, nskip[5];
|
|
||||||
idxtype *xadj, *adjncy, *vwgt, *adjwgt;
|
|
||||||
idxtype *perm, *pwgts, *pdegrees[4], *pmarker, *pids, *spwgts[3];
|
|
||||||
float *alphas[3];
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
|
|
||||||
pwgts = idxsmalloc(nparts, 0, "RefineTopLevelSeparators: pwgts");
|
|
||||||
spwgts[0] = idxsmalloc(nparts, 0, "RefineTopLevelSeparators: spwgts");
|
|
||||||
spwgts[1] = idxsmalloc(nparts, 0, "RefineTopLevelSeparators: spwgts");
|
|
||||||
spwgts[2] = idxsmalloc(nparts, 0, "RefineTopLevelSeparators: spwgts");
|
|
||||||
pdegrees[0] = idxsmalloc(nparts, 0, "RefineTopLevelSeparators: pdegrees");
|
|
||||||
pdegrees[1] = idxsmalloc(nparts, 0, "RefineTopLevelSeparators: pdegrees");
|
|
||||||
pdegrees[2] = idxsmalloc(nparts, 0, "RefineTopLevelSeparators: pdegrees");
|
|
||||||
pdegrees[3] = idxsmalloc(nparts, 0, "RefineTopLevelSeparators: pdegrees");
|
|
||||||
pmarker = idxsmalloc(nparts, -1, "RefineTopLevelSeparators: pmarker ");
|
|
||||||
pids = idxmalloc(nparts, "RefineTopLevelSeparators: pids ");
|
|
||||||
perm = idxmalloc(nvtxs, "RefineTopLevelSeparators: perm");
|
|
||||||
alphas[0] = gk_fmalloc(nparts, "RefineTopLevelSeparators: alphas[0]");
|
|
||||||
alphas[1] = gk_fmalloc(nparts, "RefineTopLevelSeparators: alphas[1]");
|
|
||||||
alphas[2] = gk_fmalloc(nparts, "RefineTopLevelSeparators: alphas[2]");
|
|
||||||
|
|
||||||
mincut = ComputeCut(graph, part);
|
|
||||||
|
|
||||||
/* Compute partition and separator sizes */
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
pwgts[part[i]] += vwgt[i];
|
|
||||||
spwgts[spart[i]][part[i]] += vwgt[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Estimate the exponents for partition-size-fill approximation */
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
alphas[0][i] = log(subfills[2*i])/log(spwgts[0][i]);
|
|
||||||
alphas[1][i] = log(subfills[2*i+1])/log(spwgts[1][i]);
|
|
||||||
alphas[2][i] = log(fills[i] - (subfills[2*i]+subfills[2*i+1]))/log(ssizes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
maxpwgt = (int)((float)((UNBALANCE_FRACTION*idxsum(nparts, pwgts, 1))/nparts));
|
|
||||||
maxspwgt = 1.10*(idxsum(nparts, pwgts, 1)-idxsum(nparts, ssizes, 1))/(2.0*nparts);
|
|
||||||
|
|
||||||
avgssize = idxsum(nparts, ssizes, 1)/nparts;
|
|
||||||
avgfill = idxsum(nparts, fills, 1)/nparts;
|
|
||||||
avgdegree = xadj[nvtxs]/(1.0*nvtxs);
|
|
||||||
|
|
||||||
|
|
||||||
mprintf("Avgssize: %D, Avgfill: %D, AvgDegree: %D\n", avgssize, avgfill, avgdegree);
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
* Go and do the refinement
|
|
||||||
*--------------------------------------------------------------------------*/
|
|
||||||
for (pass=0; pass<10; pass++) {
|
|
||||||
RandomPermute(nvtxs, perm, 1);
|
|
||||||
|
|
||||||
nskip[0] = nskip[1] = nskip[2] = nskip[3] = nskip[4] = 0;
|
|
||||||
for (nmoves=0, ii=0; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
|
|
||||||
from = part[i];
|
|
||||||
|
|
||||||
/* Determine the connectivity of this vertex */
|
|
||||||
for (ndegrees=0, j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
to = part[adjncy[j]];
|
|
||||||
if ((k = pmarker[to]) == -1) {
|
|
||||||
pmarker[to] = k = ndegrees++;
|
|
||||||
pids[k] = to;
|
|
||||||
pdegrees[0][k] = pdegrees[1][k] = pdegrees[2][k] = pdegrees[3][k] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdegrees[spart[adjncy[j]]][k] += adjwgt[j];
|
|
||||||
pdegrees[3][k] += adjwgt[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
id = (pmarker[from] != -1 ? pdegrees[3][pmarker[from]] : 0);
|
|
||||||
|
|
||||||
if (spart[i] == 2) { /* I'm on the separator */
|
|
||||||
for (to=-1, j=0; j<ndegrees; j++) {
|
|
||||||
if (pids[j] == from || pwgts[pids[j]]+vwgt[i] > maxpwgt)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fills[pids[j]] > amax(fills[from], avgfill)) {
|
|
||||||
nskip[0]++;
|
|
||||||
if (tssizes[from] < ssizes[from])
|
|
||||||
nskip[2]++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pdegrees[0][j] > 0 && spwgts[0][pids[j]] > maxspwgt)
|
|
||||||
continue;
|
|
||||||
if (pdegrees[1][j] > 0 && spwgts[1][pids[j]] > maxspwgt)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pdegrees[0][j]*pdegrees[1][j] == 0) { /* will not increase target separator */
|
|
||||||
to = (to == -1 || pdegrees[3][to] < pdegrees[3][j] ? j : to);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to == -1 && tssizes[from] < ssizes[from])
|
|
||||||
nskip[1]++;
|
|
||||||
|
|
||||||
/* See if some of the moves should be skipped */
|
|
||||||
if (to != -1 && pdegrees[3][to] < id && tssizes[from] > ssizes[from])
|
|
||||||
to = -1;
|
|
||||||
|
|
||||||
if (to != -1 && pdegrees[3][to] < id && RandomInRange(3) == 0) {
|
|
||||||
nskip[3]++;
|
|
||||||
to = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to != -1 && id - pdegrees[3][to] > avgdegree*(0.9+0.07*pass)) {
|
|
||||||
nskip[4]++;
|
|
||||||
to = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* I'm not on the separator */
|
|
||||||
for (to=-1, j=0; j<ndegrees; j++) {
|
|
||||||
if (pids[j] == from || pwgts[pids[j]]+vwgt[i] > maxpwgt)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (tssizes[pids[j]] < ssizes[pids[j]])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pdegrees[0][j] > 0 && spwgts[0][pids[j]] > maxspwgt)
|
|
||||||
continue;
|
|
||||||
if (pdegrees[1][j] > 0 && spwgts[1][pids[j]] > maxspwgt)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pdegrees[0][j]*pdegrees[1][j] == 0) { /* will not increase target separator */
|
|
||||||
to = (to == -1 || pdegrees[3][to] < pdegrees[3][j] ? j : to);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to != -1) {
|
|
||||||
if (pdegrees[3][to] < id)
|
|
||||||
to = -1;
|
|
||||||
else if (pdegrees[3][to] == id && fills[from] < fills[pids[to]] /*pwgts[from] < pwgts[pids[to]]*/)
|
|
||||||
to = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to != -1) {
|
|
||||||
/*
|
|
||||||
mprintf("%2D. Moving %6D %3D -> %3D, %2D -> %2D, Gain: %+4D, SepFrom: %4D, SepTo: %3D, Cut: %5D, %4D %4D\n",
|
|
||||||
pass, i, from, pids[to], spart[i], (pdegrees[0][to] > pdegrees[1][to] ? 0 : 1),
|
|
||||||
pdegrees[3][to] - id, ssizes[from], ssizes[pids[to]], mincut, pwgts[from], pwgts[pids[to]]);
|
|
||||||
*/
|
|
||||||
/* Update the approximations of fill of 'from' */
|
|
||||||
if (spart[i] == 2)
|
|
||||||
fills[from] -= (pow(ssizes[from], alphas[2][from]) - pow(ssizes[from]-vwgt[i], alphas[2][from]));
|
|
||||||
else
|
|
||||||
fills[from] -= (pow(spwgts[spart[i]][from], alphas[spart[i]][from]) - pow(spwgts[spart[i]][from]-vwgt[i], alphas[spart[i]][from]));
|
|
||||||
|
|
||||||
|
|
||||||
if (spart[i] == 2)
|
|
||||||
ssizes[from] -= vwgt[i];
|
|
||||||
|
|
||||||
pwgts[from] -= vwgt[i];
|
|
||||||
spwgts[spart[i]][from] -= vwgt[i];
|
|
||||||
|
|
||||||
|
|
||||||
part[i] = pids[to];
|
|
||||||
spart[i] = (pdegrees[0][to] > pdegrees[1][to] ? 0 : 1);
|
|
||||||
|
|
||||||
/* Update the approximations of fill of 'to' */
|
|
||||||
fills[to] += (pow(spwgts[spart[i]][to]+vwgt[i], alphas[spart[i]][to]) - pow(spwgts[spart[i]][to], alphas[spart[i]][to]));
|
|
||||||
|
|
||||||
pwgts[pids[to]] += vwgt[i];
|
|
||||||
spwgts[spart[i]][pids[to]] += vwgt[i];
|
|
||||||
|
|
||||||
mincut = mincut - (pdegrees[3][to] - id);
|
|
||||||
nmoves++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* reset pmarker */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++)
|
|
||||||
pmarker[part[adjncy[j]]] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mprintf("%4D. Nmoves: %4D, Cut: %6D [%4D %4D %4D %4D %4D]\n", pass, nmoves, mincut,
|
|
||||||
nskip[0], nskip[1], nskip[2], nskip[3], nskip[4]);
|
|
||||||
|
|
||||||
if (nmoves == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<nparts; i++)
|
|
||||||
mprintf("%4D %6D %8D %8D\n", i, pwgts[i], ssizes[i], fills[i]);
|
|
||||||
|
|
||||||
mprintf("%D %D %D / %D %D %D / %D %D\n", pwgts[10], spwgts[0][10], spwgts[1][10], pwgts[15], spwgts[0][15], spwgts[1][15], maxpwgt, maxspwgt);
|
|
||||||
|
|
||||||
gk_free((void **)&pwgts, &pdegrees[0], &pdegrees[1], &pdegrees[2], &pdegrees[3],
|
|
||||||
&pmarker, &pids, &perm, &spwgts[0], &spwgts[1], &spwgts[2], &alphas[0],
|
|
||||||
&alphas[1], &alphas[2], LTERM);
|
|
||||||
}
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* kmetis.c
|
|
||||||
*
|
|
||||||
* This file contains the top level routines for the multilevel k-way partitioning
|
|
||||||
* algorithm KMETIS.
|
|
||||||
*
|
|
||||||
* Started 7/28/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry point for KMETIS
|
|
||||||
**************************************************************************/
|
|
||||||
void METIS_PartGraphKway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts,
|
|
||||||
idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
idxtype i;
|
|
||||||
float *tpwgts;
|
|
||||||
|
|
||||||
tpwgts = gk_fmalloc(*nparts, "KMETIS: tpwgts");
|
|
||||||
for (i=0; i<*nparts; i++)
|
|
||||||
tpwgts[i] = 1.0/(1.0*(*nparts));
|
|
||||||
|
|
||||||
METIS_WPartGraphKway(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts,
|
|
||||||
tpwgts, options, edgecut, part);
|
|
||||||
|
|
||||||
gk_free((void **)&tpwgts, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry point for KWMETIS
|
|
||||||
**************************************************************************/
|
|
||||||
void METIS_WPartGraphKway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts,
|
|
||||||
float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part)
|
|
||||||
{
|
|
||||||
idxtype i, j;
|
|
||||||
GraphType graph;
|
|
||||||
CtrlType ctrl;
|
|
||||||
|
|
||||||
if (*numflag == 1)
|
|
||||||
Change2CNumbering(*nvtxs, xadj, adjncy);
|
|
||||||
|
|
||||||
SetUpGraph(&graph, OP_KMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, *wgtflag);
|
|
||||||
|
|
||||||
if (options[0] == 0) { /* Use the default parameters */
|
|
||||||
ctrl.CType = KMETIS_CTYPE;
|
|
||||||
ctrl.IType = KMETIS_ITYPE;
|
|
||||||
ctrl.RType = KMETIS_RTYPE;
|
|
||||||
ctrl.dbglvl = KMETIS_DBGLVL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ctrl.CType = options[OPTION_CTYPE];
|
|
||||||
ctrl.IType = options[OPTION_ITYPE];
|
|
||||||
ctrl.RType = options[OPTION_RTYPE];
|
|
||||||
ctrl.dbglvl = options[OPTION_DBGLVL];
|
|
||||||
}
|
|
||||||
ctrl.optype = OP_KMETIS;
|
|
||||||
ctrl.CoarsenTo = amax((*nvtxs)/(40*gk_log2(*nparts)), 20*(*nparts));
|
|
||||||
ctrl.maxvwgt = 1.5*((graph.vwgt ? idxsum(*nvtxs, graph.vwgt, 1) : (*nvtxs))/ctrl.CoarsenTo);
|
|
||||||
|
|
||||||
InitRandom(-1);
|
|
||||||
|
|
||||||
AllocateWorkSpace(&ctrl, &graph, *nparts);
|
|
||||||
|
|
||||||
IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
|
|
||||||
IFSET(ctrl.dbglvl, DBG_TIME, gk_startcputimer(ctrl.TotalTmr));
|
|
||||||
|
|
||||||
*edgecut = MlevelKWayPartitioning(&ctrl, &graph, *nparts, part, tpwgts, 1.03);
|
|
||||||
|
|
||||||
IFSET(ctrl.dbglvl, DBG_TIME, gk_stopcputimer(ctrl.TotalTmr));
|
|
||||||
IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl));
|
|
||||||
|
|
||||||
FreeWorkSpace(&ctrl, &graph);
|
|
||||||
|
|
||||||
if (*numflag == 1)
|
|
||||||
Change2FNumbering(*nvtxs, xadj, adjncy, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes a graph and produces a bisection of it
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype MlevelKWayPartitioning(CtrlType *ctrl, GraphType *graph, idxtype nparts, idxtype *part, float *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, j, nvtxs, tvwgt, tpwgts2[2];
|
|
||||||
GraphType *cgraph;
|
|
||||||
idxtype wgtflag=3, numflag=0, options[10], edgecut;
|
|
||||||
|
|
||||||
cgraph = Coarsen2Way(ctrl, graph);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
|
|
||||||
AllocateKWayPartitionMemory(ctrl, cgraph, nparts);
|
|
||||||
|
|
||||||
options[0] = 1;
|
|
||||||
options[OPTION_CTYPE] = MTYPE_SHEMKWAY;
|
|
||||||
options[OPTION_ITYPE] = ITYPE_GGPKL;
|
|
||||||
options[OPTION_RTYPE] = RTYPE_FM;
|
|
||||||
options[OPTION_DBGLVL] = 0;
|
|
||||||
|
|
||||||
METIS_WPartGraphRecursive(&cgraph->nvtxs, cgraph->xadj, cgraph->adjncy, cgraph->vwgt,
|
|
||||||
cgraph->adjwgt, &wgtflag, &numflag, &nparts, tpwgts, options,
|
|
||||||
&edgecut, cgraph->where);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
|
|
||||||
IFSET(ctrl->dbglvl, DBG_IPART, mprintf("Initial %D-way partitioning cut: %D\n", nparts, edgecut));
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_KWAYPINFO, ComputePartitionInfo(cgraph, nparts, cgraph->where));
|
|
||||||
|
|
||||||
RefineKWay(ctrl, graph, cgraph, nparts, tpwgts, ubfactor);
|
|
||||||
|
|
||||||
idxcopy(graph->nvtxs, graph->where, part);
|
|
||||||
|
|
||||||
FreeGraph(graph, 0);
|
|
||||||
|
|
||||||
return graph->mincut;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* kvmetis.c
|
|
||||||
*
|
|
||||||
* This file contains the top level routines for the multilevel k-way partitioning
|
|
||||||
* algorithm KMETIS.
|
|
||||||
*
|
|
||||||
* Started 7/28/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: kvmetis.c,v 1.3 2002/08/10 06:57:50 karypis Exp $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry point for KMETIS
|
|
||||||
**************************************************************************/
|
|
||||||
void METIS_PartGraphVKway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts,
|
|
||||||
idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
idxtype i;
|
|
||||||
float *tpwgts;
|
|
||||||
|
|
||||||
tpwgts = gk_fmalloc(*nparts, "KMETIS: tpwgts");
|
|
||||||
for (i=0; i<*nparts; i++)
|
|
||||||
tpwgts[i] = 1.0/(1.0*(*nparts));
|
|
||||||
|
|
||||||
METIS_WPartGraphVKway(nvtxs, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts,
|
|
||||||
tpwgts, options, volume, part);
|
|
||||||
|
|
||||||
gk_free((void **)&tpwgts, LTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry point for KWMETIS
|
|
||||||
**************************************************************************/
|
|
||||||
void METIS_WPartGraphVKway(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
|
|
||||||
idxtype *vsize, idxtype *wgtflag, idxtype *numflag, idxtype *nparts,
|
|
||||||
float *tpwgts, idxtype *options, idxtype *volume, idxtype *part)
|
|
||||||
{
|
|
||||||
idxtype i, j;
|
|
||||||
GraphType graph;
|
|
||||||
CtrlType ctrl;
|
|
||||||
|
|
||||||
if (*numflag == 1)
|
|
||||||
Change2CNumbering(*nvtxs, xadj, adjncy);
|
|
||||||
|
|
||||||
VolSetUpGraph(&graph, OP_KVMETIS, *nvtxs, 1, xadj, adjncy, vwgt, vsize, *wgtflag);
|
|
||||||
|
|
||||||
if (options[0] == 0) { /* Use the default parameters */
|
|
||||||
ctrl.CType = KVMETIS_CTYPE;
|
|
||||||
ctrl.IType = KVMETIS_ITYPE;
|
|
||||||
ctrl.RType = KVMETIS_RTYPE;
|
|
||||||
ctrl.dbglvl = KVMETIS_DBGLVL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ctrl.CType = options[OPTION_CTYPE];
|
|
||||||
ctrl.IType = options[OPTION_ITYPE];
|
|
||||||
ctrl.RType = options[OPTION_RTYPE];
|
|
||||||
ctrl.dbglvl = options[OPTION_DBGLVL];
|
|
||||||
}
|
|
||||||
ctrl.optype = OP_KVMETIS;
|
|
||||||
ctrl.CoarsenTo = amax((*nvtxs)/(40*gk_log2(*nparts)), 20*(*nparts));
|
|
||||||
ctrl.maxvwgt = 1.5*((graph.vwgt ? idxsum(*nvtxs, graph.vwgt, 1) : (*nvtxs))/ctrl.CoarsenTo);
|
|
||||||
|
|
||||||
InitRandom(-1);
|
|
||||||
|
|
||||||
AllocateWorkSpace(&ctrl, &graph, *nparts);
|
|
||||||
|
|
||||||
IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
|
|
||||||
IFSET(ctrl.dbglvl, DBG_TIME, gk_startcputimer(ctrl.TotalTmr));
|
|
||||||
|
|
||||||
*volume = MlevelVolKWayPartitioning(&ctrl, &graph, *nparts, part, tpwgts, 1.03);
|
|
||||||
|
|
||||||
IFSET(ctrl.dbglvl, DBG_TIME, gk_stopcputimer(ctrl.TotalTmr));
|
|
||||||
IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl));
|
|
||||||
|
|
||||||
FreeWorkSpace(&ctrl, &graph);
|
|
||||||
|
|
||||||
if (*numflag == 1)
|
|
||||||
Change2FNumbering(*nvtxs, xadj, adjncy, part);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function takes a graph and produces a bisection of it
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype MlevelVolKWayPartitioning(CtrlType *ctrl, GraphType *graph, idxtype nparts, idxtype *part,
|
|
||||||
float *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, j, nvtxs, tvwgt, tpwgts2[2];
|
|
||||||
GraphType *cgraph;
|
|
||||||
idxtype wgtflag=3, numflag=0, options[10], edgecut;
|
|
||||||
|
|
||||||
cgraph = Coarsen2Way(ctrl, graph);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
|
|
||||||
AllocateVolKWayPartitionMemory(ctrl, cgraph, nparts);
|
|
||||||
|
|
||||||
options[0] = 1;
|
|
||||||
options[OPTION_CTYPE] = MTYPE_SHEMKWAY;
|
|
||||||
options[OPTION_ITYPE] = ITYPE_GGPKL;
|
|
||||||
options[OPTION_RTYPE] = RTYPE_FM;
|
|
||||||
options[OPTION_DBGLVL] = 0;
|
|
||||||
|
|
||||||
METIS_WPartGraphRecursive(&cgraph->nvtxs, cgraph->xadj, cgraph->adjncy, cgraph->vwgt,
|
|
||||||
cgraph->adjwgt, &wgtflag, &numflag, &nparts, tpwgts, options,
|
|
||||||
&edgecut, cgraph->where);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
|
|
||||||
IFSET(ctrl->dbglvl, DBG_IPART, mprintf("Initial %D-way partitioning cut: %D\n", nparts, edgecut));
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_KWAYPINFO, ComputePartitionInfo(cgraph, nparts, cgraph->where));
|
|
||||||
|
|
||||||
RefineVolKWay(ctrl, graph, cgraph, nparts, tpwgts, ubfactor);
|
|
||||||
|
|
||||||
idxcopy(graph->nvtxs, graph->where, part);
|
|
||||||
|
|
||||||
FreeGraph(graph, 0);
|
|
||||||
|
|
||||||
return graph->minvol;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,672 +0,0 @@
|
|||||||
/*
|
|
||||||
* kwayfm.c
|
|
||||||
*
|
|
||||||
* This file contains code that implements the multilevel k-way refinement
|
|
||||||
*
|
|
||||||
* Started 7/28/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: kwayfm.c,v 1.2 2002/08/10 06:29:31 karypis Exp $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function performs k-way refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void Random_KWayEdgeRefine(CtrlType *ctrl, GraphType *graph, idxtype nparts, float *tpwgts, float ubfactor, idxtype npasses, idxtype ffactor)
|
|
||||||
{
|
|
||||||
idxtype i, ii, iii, j, jj, k, l, pass, nvtxs, nmoves, nbnd, tvwgt, myndegrees;
|
|
||||||
idxtype from, me, to, oldcut, vwgt, gain;
|
|
||||||
idxtype *xadj, *adjncy, *adjwgt;
|
|
||||||
idxtype *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts;
|
|
||||||
EDegreeType *myedegrees;
|
|
||||||
RInfoType *myrinfo;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
|
|
||||||
where = graph->where;
|
|
||||||
pwgts = graph->pwgts;
|
|
||||||
|
|
||||||
/* Setup the weight intervals of the various subdomains */
|
|
||||||
minwgt = idxwspacemalloc(ctrl, nparts);
|
|
||||||
maxwgt = idxwspacemalloc(ctrl, nparts);
|
|
||||||
itpwgts = idxwspacemalloc(ctrl, nparts);
|
|
||||||
tvwgt = idxsum(nparts, pwgts, 1);
|
|
||||||
ASSERT(tvwgt == idxsum(nvtxs, graph->vwgt, 1));
|
|
||||||
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
itpwgts[i] = tpwgts[i]*tvwgt;
|
|
||||||
maxwgt[i] = tpwgts[i]*tvwgt*ubfactor;
|
|
||||||
minwgt[i] = tpwgts[i]*tvwgt*(1.0/ubfactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("Partitions: [%6D %6D]-[%6D %6D], Balance: %5.3f, Nv-Nb[%6D %6D]. Cut: %6D\n",
|
|
||||||
pwgts[idxargmin(nparts, pwgts)], pwgts[idxargmax(nparts, pwgts)], minwgt[0], maxwgt[0],
|
|
||||||
1.0*nparts*pwgts[idxargmax(nparts, pwgts)]/tvwgt, graph->nvtxs, graph->nbnd,
|
|
||||||
graph->mincut));
|
|
||||||
|
|
||||||
for (pass=0; pass<npasses; pass++) {
|
|
||||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
|
||||||
|
|
||||||
oldcut = graph->mincut;
|
|
||||||
nbnd = graph->nbnd;
|
|
||||||
|
|
||||||
RandomPermute(nbnd, perm, 1);
|
|
||||||
for (nmoves=iii=0; iii<graph->nbnd; iii++) {
|
|
||||||
ii = perm[iii];
|
|
||||||
if (ii >= nbnd)
|
|
||||||
continue;
|
|
||||||
i = bndind[ii];
|
|
||||||
|
|
||||||
myrinfo = graph->rinfo+i;
|
|
||||||
|
|
||||||
if (myrinfo->ed >= myrinfo->id) { /* Total ED is too high */
|
|
||||||
from = where[i];
|
|
||||||
vwgt = graph->vwgt[i];
|
|
||||||
|
|
||||||
if (myrinfo->id > 0 && pwgts[from]-vwgt < minwgt[from])
|
|
||||||
continue; /* This cannot be moved! */
|
|
||||||
|
|
||||||
myedegrees = myrinfo->edegrees;
|
|
||||||
myndegrees = myrinfo->ndegrees;
|
|
||||||
|
|
||||||
j = myrinfo->id;
|
|
||||||
for (k=0; k<myndegrees; k++) {
|
|
||||||
to = myedegrees[k].pid;
|
|
||||||
gain = myedegrees[k].ed-j; /* j = myrinfo->id. Allow good nodes to move */
|
|
||||||
if (pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain && gain >= 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (k == myndegrees)
|
|
||||||
continue; /* break out if you did not find a candidate */
|
|
||||||
|
|
||||||
for (j=k+1; j<myndegrees; j++) {
|
|
||||||
to = myedegrees[j].pid;
|
|
||||||
if ((myedegrees[j].ed > myedegrees[k].ed && pwgts[to]+vwgt <= maxwgt[to]) ||
|
|
||||||
(myedegrees[j].ed == myedegrees[k].ed &&
|
|
||||||
itpwgts[myedegrees[k].pid]*pwgts[to] < itpwgts[to]*pwgts[myedegrees[k].pid]))
|
|
||||||
k = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
to = myedegrees[k].pid;
|
|
||||||
|
|
||||||
j = 0;
|
|
||||||
if (myedegrees[k].ed-myrinfo->id > 0)
|
|
||||||
j = 1;
|
|
||||||
else if (myedegrees[k].ed-myrinfo->id == 0) {
|
|
||||||
if ((iii&7) == 0 || pwgts[from] >= maxwgt[from] || itpwgts[from]*(pwgts[to]+vwgt) < itpwgts[to]*pwgts[from])
|
|
||||||
j = 1;
|
|
||||||
}
|
|
||||||
if (j == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*=====================================================================
|
|
||||||
* If we got here, we can now move the vertex from 'from' to 'to'
|
|
||||||
*======================================================================*/
|
|
||||||
graph->mincut -= myedegrees[k].ed-myrinfo->id;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_MOVEINFO, mprintf("\t\tMoving %6D to %3D. Gain: %4D. Cut: %6D\n", i, to, myedegrees[k].ed-myrinfo->id, graph->mincut));
|
|
||||||
|
|
||||||
/* Update where, weight, and ID/ED information of the vertex you moved */
|
|
||||||
where[i] = to;
|
|
||||||
INC_DEC(pwgts[to], pwgts[from], vwgt);
|
|
||||||
myrinfo->ed += myrinfo->id-myedegrees[k].ed;
|
|
||||||
SWAP(myrinfo->id, myedegrees[k].ed, j);
|
|
||||||
if (myedegrees[k].ed == 0)
|
|
||||||
myedegrees[k] = myedegrees[--myrinfo->ndegrees];
|
|
||||||
else
|
|
||||||
myedegrees[k].pid = from;
|
|
||||||
|
|
||||||
if (myrinfo->ed-myrinfo->id < 0)
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, i);
|
|
||||||
|
|
||||||
/* Update the degrees of adjacent vertices */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
ii = adjncy[j];
|
|
||||||
me = where[ii];
|
|
||||||
|
|
||||||
myrinfo = graph->rinfo+ii;
|
|
||||||
if (myrinfo->edegrees == NULL) {
|
|
||||||
myrinfo->edegrees = ctrl->wspace.edegrees+ctrl->wspace.cdegree;
|
|
||||||
ctrl->wspace.cdegree += xadj[ii+1]-xadj[ii];
|
|
||||||
}
|
|
||||||
myedegrees = myrinfo->edegrees;
|
|
||||||
|
|
||||||
ASSERT(CheckRInfo(myrinfo));
|
|
||||||
|
|
||||||
if (me == from) {
|
|
||||||
INC_DEC(myrinfo->ed, myrinfo->id, adjwgt[j]);
|
|
||||||
|
|
||||||
if (myrinfo->ed-myrinfo->id >= 0 && bndptr[ii] == -1)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, ii);
|
|
||||||
}
|
|
||||||
else if (me == to) {
|
|
||||||
INC_DEC(myrinfo->id, myrinfo->ed, adjwgt[j]);
|
|
||||||
|
|
||||||
if (myrinfo->ed-myrinfo->id < 0 && bndptr[ii] != -1)
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, ii);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove contribution from the .ed of 'from' */
|
|
||||||
if (me != from) {
|
|
||||||
for (k=0; k<myrinfo->ndegrees; k++) {
|
|
||||||
if (myedegrees[k].pid == from) {
|
|
||||||
if (myedegrees[k].ed == adjwgt[j])
|
|
||||||
myedegrees[k] = myedegrees[--myrinfo->ndegrees];
|
|
||||||
else
|
|
||||||
myedegrees[k].ed -= adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add contribution to the .ed of 'to' */
|
|
||||||
if (me != to) {
|
|
||||||
for (k=0; k<myrinfo->ndegrees; k++) {
|
|
||||||
if (myedegrees[k].pid == to) {
|
|
||||||
myedegrees[k].ed += adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k == myrinfo->ndegrees) {
|
|
||||||
myedegrees[myrinfo->ndegrees].pid = to;
|
|
||||||
myedegrees[myrinfo->ndegrees++].ed = adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(myrinfo->ndegrees <= xadj[ii+1]-xadj[ii]);
|
|
||||||
ASSERT(CheckRInfo(myrinfo));
|
|
||||||
|
|
||||||
}
|
|
||||||
nmoves++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("\t[%6D %6D], Balance: %5.3f, Nb: %6D. Nmoves: %5D, Cut: %6D, Vol: %6D\n",
|
|
||||||
pwgts[idxargmin(nparts, pwgts)], pwgts[idxargmax(nparts, pwgts)],
|
|
||||||
1.0*nparts*pwgts[idxargmax(nparts, pwgts)]/tvwgt, graph->nbnd, nmoves, graph->mincut, ComputeVolume(graph, where)));
|
|
||||||
|
|
||||||
if (graph->mincut == oldcut)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function performs k-way refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void Greedy_KWayEdgeRefine(CtrlType *ctrl, GraphType *graph, idxtype nparts, float *tpwgts, float ubfactor, idxtype npasses)
|
|
||||||
{
|
|
||||||
idxtype i, ii, iii, j, jj, k, l, pass, nvtxs, nbnd, tvwgt, myndegrees, oldgain, gain;
|
|
||||||
idxtype from, me, to, oldcut, vwgt;
|
|
||||||
idxtype *xadj, *adjncy, *adjwgt;
|
|
||||||
idxtype *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *moved, *itpwgts;
|
|
||||||
EDegreeType *myedegrees;
|
|
||||||
RInfoType *myrinfo;
|
|
||||||
PQueueType queue;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
|
|
||||||
where = graph->where;
|
|
||||||
pwgts = graph->pwgts;
|
|
||||||
|
|
||||||
/* Setup the weight intervals of the various subdomains */
|
|
||||||
minwgt = idxwspacemalloc(ctrl, nparts);
|
|
||||||
maxwgt = idxwspacemalloc(ctrl, nparts);
|
|
||||||
itpwgts = idxwspacemalloc(ctrl, nparts);
|
|
||||||
tvwgt = idxsum(nparts, pwgts, 1);
|
|
||||||
ASSERT(tvwgt == idxsum(nvtxs, graph->vwgt, 1));
|
|
||||||
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
itpwgts[i] = tpwgts[i]*tvwgt;
|
|
||||||
maxwgt[i] = tpwgts[i]*tvwgt*ubfactor;
|
|
||||||
minwgt[i] = tpwgts[i]*tvwgt*(1.0/ubfactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
moved = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
|
|
||||||
PQueueInit(ctrl, &queue, nvtxs, graph->adjwgtsum[idxargmax(nvtxs, graph->adjwgtsum)]);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("Partitions: [%6D %6D]-[%6D %6D], Balance: %5.3f, Nv-Nb[%6D %6D]. Cut: %6D\n",
|
|
||||||
pwgts[idxargmin(nparts, pwgts)], pwgts[idxargmax(nparts, pwgts)], minwgt[0], maxwgt[0],
|
|
||||||
1.0*nparts*pwgts[idxargmax(nparts, pwgts)]/tvwgt, graph->nvtxs, graph->nbnd,
|
|
||||||
graph->mincut));
|
|
||||||
|
|
||||||
for (pass=0; pass<npasses; pass++) {
|
|
||||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
|
||||||
|
|
||||||
PQueueReset(&queue);
|
|
||||||
idxset(nvtxs, -1, moved);
|
|
||||||
|
|
||||||
oldcut = graph->mincut;
|
|
||||||
nbnd = graph->nbnd;
|
|
||||||
|
|
||||||
RandomPermute(nbnd, perm, 1);
|
|
||||||
for (ii=0; ii<nbnd; ii++) {
|
|
||||||
i = bndind[perm[ii]];
|
|
||||||
PQueueInsert(&queue, i, graph->rinfo[i].ed - graph->rinfo[i].id);
|
|
||||||
moved[i] = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (iii=0;;iii++) {
|
|
||||||
if ((i = PQueueGetMax(&queue)) == -1)
|
|
||||||
break;
|
|
||||||
moved[i] = 1;
|
|
||||||
|
|
||||||
myrinfo = graph->rinfo+i;
|
|
||||||
from = where[i];
|
|
||||||
vwgt = graph->vwgt[i];
|
|
||||||
|
|
||||||
if (pwgts[from]-vwgt < minwgt[from])
|
|
||||||
continue; /* This cannot be moved! */
|
|
||||||
|
|
||||||
myedegrees = myrinfo->edegrees;
|
|
||||||
myndegrees = myrinfo->ndegrees;
|
|
||||||
|
|
||||||
j = myrinfo->id;
|
|
||||||
for (k=0; k<myndegrees; k++) {
|
|
||||||
to = myedegrees[k].pid;
|
|
||||||
gain = myedegrees[k].ed-j; /* j = myrinfo->id. Allow good nodes to move */
|
|
||||||
if (pwgts[to]+vwgt <= maxwgt[to]+gain && gain >= 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (k == myndegrees)
|
|
||||||
continue; /* break out if you did not find a candidate */
|
|
||||||
|
|
||||||
for (j=k+1; j<myndegrees; j++) {
|
|
||||||
to = myedegrees[j].pid;
|
|
||||||
if ((myedegrees[j].ed > myedegrees[k].ed && pwgts[to]+vwgt <= maxwgt[to]) ||
|
|
||||||
(myedegrees[j].ed == myedegrees[k].ed &&
|
|
||||||
itpwgts[myedegrees[k].pid]*pwgts[to] < itpwgts[to]*pwgts[myedegrees[k].pid]))
|
|
||||||
k = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
to = myedegrees[k].pid;
|
|
||||||
|
|
||||||
j = 0;
|
|
||||||
if (myedegrees[k].ed-myrinfo->id > 0)
|
|
||||||
j = 1;
|
|
||||||
else if (myedegrees[k].ed-myrinfo->id == 0) {
|
|
||||||
if ((iii&7) == 0 || pwgts[from] >= maxwgt[from] || itpwgts[from]*(pwgts[to]+vwgt) < itpwgts[to]*pwgts[from])
|
|
||||||
j = 1;
|
|
||||||
}
|
|
||||||
if (j == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*=====================================================================
|
|
||||||
* If we got here, we can now move the vertex from 'from' to 'to'
|
|
||||||
*======================================================================*/
|
|
||||||
graph->mincut -= myedegrees[k].ed-myrinfo->id;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_MOVEINFO, mprintf("\t\tMoving %6D to %3D. Gain: %4D. Cut: %6D\n", i, to, myedegrees[k].ed-myrinfo->id, graph->mincut));
|
|
||||||
|
|
||||||
/* Update where, weight, and ID/ED information of the vertex you moved */
|
|
||||||
where[i] = to;
|
|
||||||
INC_DEC(pwgts[to], pwgts[from], vwgt);
|
|
||||||
myrinfo->ed += myrinfo->id-myedegrees[k].ed;
|
|
||||||
SWAP(myrinfo->id, myedegrees[k].ed, j);
|
|
||||||
if (myedegrees[k].ed == 0)
|
|
||||||
myedegrees[k] = myedegrees[--myrinfo->ndegrees];
|
|
||||||
else
|
|
||||||
myedegrees[k].pid = from;
|
|
||||||
|
|
||||||
if (myrinfo->ed < myrinfo->id)
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, i);
|
|
||||||
|
|
||||||
/* Update the degrees of adjacent vertices */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
ii = adjncy[j];
|
|
||||||
me = where[ii];
|
|
||||||
|
|
||||||
myrinfo = graph->rinfo+ii;
|
|
||||||
if (myrinfo->edegrees == NULL) {
|
|
||||||
myrinfo->edegrees = ctrl->wspace.edegrees+ctrl->wspace.cdegree;
|
|
||||||
ctrl->wspace.cdegree += xadj[ii+1]-xadj[ii];
|
|
||||||
}
|
|
||||||
myedegrees = myrinfo->edegrees;
|
|
||||||
|
|
||||||
ASSERT(CheckRInfo(myrinfo));
|
|
||||||
|
|
||||||
oldgain = (myrinfo->ed-myrinfo->id);
|
|
||||||
|
|
||||||
if (me == from) {
|
|
||||||
INC_DEC(myrinfo->ed, myrinfo->id, adjwgt[j]);
|
|
||||||
|
|
||||||
if (myrinfo->ed-myrinfo->id >= 0 && bndptr[ii] == -1)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, ii);
|
|
||||||
}
|
|
||||||
else if (me == to) {
|
|
||||||
INC_DEC(myrinfo->id, myrinfo->ed, adjwgt[j]);
|
|
||||||
|
|
||||||
if (myrinfo->ed-myrinfo->id < 0 && bndptr[ii] != -1)
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, ii);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove contribution from the .ed of 'from' */
|
|
||||||
if (me != from) {
|
|
||||||
for (k=0; k<myrinfo->ndegrees; k++) {
|
|
||||||
if (myedegrees[k].pid == from) {
|
|
||||||
if (myedegrees[k].ed == adjwgt[j])
|
|
||||||
myedegrees[k] = myedegrees[--myrinfo->ndegrees];
|
|
||||||
else
|
|
||||||
myedegrees[k].ed -= adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add contribution to the .ed of 'to' */
|
|
||||||
if (me != to) {
|
|
||||||
for (k=0; k<myrinfo->ndegrees; k++) {
|
|
||||||
if (myedegrees[k].pid == to) {
|
|
||||||
myedegrees[k].ed += adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k == myrinfo->ndegrees) {
|
|
||||||
myedegrees[myrinfo->ndegrees].pid = to;
|
|
||||||
myedegrees[myrinfo->ndegrees++].ed = adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the queue */
|
|
||||||
if (me == to || me == from) {
|
|
||||||
gain = myrinfo->ed-myrinfo->id;
|
|
||||||
if (moved[ii] == 2) {
|
|
||||||
if (gain >= 0)
|
|
||||||
PQueueUpdate(&queue, ii, oldgain, gain);
|
|
||||||
else {
|
|
||||||
PQueueDelete(&queue, ii, oldgain);
|
|
||||||
moved[ii] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (moved[ii] == -1 && gain >= 0) {
|
|
||||||
PQueueInsert(&queue, ii, gain);
|
|
||||||
moved[ii] = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(myrinfo->ndegrees <= xadj[ii+1]-xadj[ii]);
|
|
||||||
ASSERT(CheckRInfo(myrinfo));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("\t[%6D %6D], Balance: %5.3f, Nb: %6D. Cut: %6D\n",
|
|
||||||
pwgts[idxargmin(nparts, pwgts)], pwgts[idxargmax(nparts, pwgts)],
|
|
||||||
1.0*nparts*pwgts[idxargmax(nparts, pwgts)]/tvwgt, graph->nbnd, graph->mincut));
|
|
||||||
|
|
||||||
if (graph->mincut == oldcut)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
PQueueFree(ctrl, &queue);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function performs k-way refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void Greedy_KWayEdgeBalance(CtrlType *ctrl, GraphType *graph, idxtype nparts, float *tpwgts, float ubfactor, idxtype npasses)
|
|
||||||
{
|
|
||||||
idxtype i, ii, iii, j, jj, k, l, pass, nvtxs, nbnd, tvwgt, myndegrees, oldgain, gain, nmoves;
|
|
||||||
idxtype from, me, to, oldcut, vwgt;
|
|
||||||
idxtype *xadj, *adjncy, *adjwgt;
|
|
||||||
idxtype *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *moved, *itpwgts;
|
|
||||||
EDegreeType *myedegrees;
|
|
||||||
RInfoType *myrinfo;
|
|
||||||
PQueueType queue;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = graph->bndptr;
|
|
||||||
|
|
||||||
where = graph->where;
|
|
||||||
pwgts = graph->pwgts;
|
|
||||||
|
|
||||||
/* Setup the weight intervals of the various subdomains */
|
|
||||||
minwgt = idxwspacemalloc(ctrl, nparts);
|
|
||||||
maxwgt = idxwspacemalloc(ctrl, nparts);
|
|
||||||
itpwgts = idxwspacemalloc(ctrl, nparts);
|
|
||||||
tvwgt = idxsum(nparts, pwgts, 1);
|
|
||||||
ASSERT(tvwgt == idxsum(nvtxs, graph->vwgt, 1));
|
|
||||||
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
itpwgts[i] = tpwgts[i]*tvwgt;
|
|
||||||
maxwgt[i] = tpwgts[i]*tvwgt*ubfactor;
|
|
||||||
minwgt[i] = tpwgts[i]*tvwgt*(1.0/ubfactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
moved = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
|
|
||||||
PQueueInit(ctrl, &queue, nvtxs, graph->adjwgtsum[idxargmax(nvtxs, graph->adjwgtsum)]);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("Partitions: [%6D %6D]-[%6D %6D], Balance: %5.3f, Nv-Nb[%6D %6D]. Cut: %6D [B]\n",
|
|
||||||
pwgts[idxargmin(nparts, pwgts)], pwgts[idxargmax(nparts, pwgts)], minwgt[0], maxwgt[0],
|
|
||||||
1.0*nparts*pwgts[idxargmax(nparts, pwgts)]/tvwgt, graph->nvtxs, graph->nbnd,
|
|
||||||
graph->mincut));
|
|
||||||
|
|
||||||
for (pass=0; pass<npasses; pass++) {
|
|
||||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
|
||||||
|
|
||||||
/* Check to see if things are out of balance, given the tolerance */
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
if (pwgts[i] > maxwgt[i])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == nparts) /* Things are balanced. Return right away */
|
|
||||||
break;
|
|
||||||
|
|
||||||
PQueueReset(&queue);
|
|
||||||
idxset(nvtxs, -1, moved);
|
|
||||||
|
|
||||||
oldcut = graph->mincut;
|
|
||||||
nbnd = graph->nbnd;
|
|
||||||
|
|
||||||
RandomPermute(nbnd, perm, 1);
|
|
||||||
for (ii=0; ii<nbnd; ii++) {
|
|
||||||
i = bndind[perm[ii]];
|
|
||||||
PQueueInsert(&queue, i, graph->rinfo[i].ed - graph->rinfo[i].id);
|
|
||||||
moved[i] = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
nmoves = 0;
|
|
||||||
for (;;) {
|
|
||||||
if ((i = PQueueGetMax(&queue)) == -1)
|
|
||||||
break;
|
|
||||||
moved[i] = 1;
|
|
||||||
|
|
||||||
myrinfo = graph->rinfo+i;
|
|
||||||
from = where[i];
|
|
||||||
vwgt = graph->vwgt[i];
|
|
||||||
|
|
||||||
if (pwgts[from]-vwgt < minwgt[from])
|
|
||||||
continue; /* This cannot be moved! */
|
|
||||||
|
|
||||||
myedegrees = myrinfo->edegrees;
|
|
||||||
myndegrees = myrinfo->ndegrees;
|
|
||||||
|
|
||||||
for (k=0; k<myndegrees; k++) {
|
|
||||||
to = myedegrees[k].pid;
|
|
||||||
if (pwgts[to]+vwgt <= maxwgt[to] || itpwgts[from]*(pwgts[to]+vwgt) <= itpwgts[to]*pwgts[from])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (k == myndegrees)
|
|
||||||
continue; /* break out if you did not find a candidate */
|
|
||||||
|
|
||||||
for (j=k+1; j<myndegrees; j++) {
|
|
||||||
to = myedegrees[j].pid;
|
|
||||||
if (itpwgts[myedegrees[k].pid]*pwgts[to] < itpwgts[to]*pwgts[myedegrees[k].pid])
|
|
||||||
k = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
to = myedegrees[k].pid;
|
|
||||||
|
|
||||||
if (pwgts[from] < maxwgt[from] && pwgts[to] > minwgt[to] && myedegrees[k].ed-myrinfo->id < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*=====================================================================
|
|
||||||
* If we got here, we can now move the vertex from 'from' to 'to'
|
|
||||||
*======================================================================*/
|
|
||||||
graph->mincut -= myedegrees[k].ed-myrinfo->id;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_MOVEINFO, mprintf("\t\tMoving %6D to %3D. Gain: %4D. Cut: %6D\n", i, to, myedegrees[k].ed-myrinfo->id, graph->mincut));
|
|
||||||
|
|
||||||
/* Update where, weight, and ID/ED information of the vertex you moved */
|
|
||||||
where[i] = to;
|
|
||||||
INC_DEC(pwgts[to], pwgts[from], vwgt);
|
|
||||||
myrinfo->ed += myrinfo->id-myedegrees[k].ed;
|
|
||||||
SWAP(myrinfo->id, myedegrees[k].ed, j);
|
|
||||||
if (myedegrees[k].ed == 0)
|
|
||||||
myedegrees[k] = myedegrees[--myrinfo->ndegrees];
|
|
||||||
else
|
|
||||||
myedegrees[k].pid = from;
|
|
||||||
|
|
||||||
if (myrinfo->ed == 0)
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, i);
|
|
||||||
|
|
||||||
/* Update the degrees of adjacent vertices */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
ii = adjncy[j];
|
|
||||||
me = where[ii];
|
|
||||||
|
|
||||||
myrinfo = graph->rinfo+ii;
|
|
||||||
if (myrinfo->edegrees == NULL) {
|
|
||||||
myrinfo->edegrees = ctrl->wspace.edegrees+ctrl->wspace.cdegree;
|
|
||||||
ctrl->wspace.cdegree += xadj[ii+1]-xadj[ii];
|
|
||||||
}
|
|
||||||
myedegrees = myrinfo->edegrees;
|
|
||||||
|
|
||||||
ASSERT(CheckRInfo(myrinfo));
|
|
||||||
|
|
||||||
oldgain = (myrinfo->ed-myrinfo->id);
|
|
||||||
|
|
||||||
if (me == from) {
|
|
||||||
INC_DEC(myrinfo->ed, myrinfo->id, adjwgt[j]);
|
|
||||||
|
|
||||||
if (myrinfo->ed > 0 && bndptr[ii] == -1)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, ii);
|
|
||||||
}
|
|
||||||
else if (me == to) {
|
|
||||||
INC_DEC(myrinfo->id, myrinfo->ed, adjwgt[j]);
|
|
||||||
|
|
||||||
if (myrinfo->ed == 0 && bndptr[ii] != -1)
|
|
||||||
BNDDelete(nbnd, bndind, bndptr, ii);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove contribution from the .ed of 'from' */
|
|
||||||
if (me != from) {
|
|
||||||
for (k=0; k<myrinfo->ndegrees; k++) {
|
|
||||||
if (myedegrees[k].pid == from) {
|
|
||||||
if (myedegrees[k].ed == adjwgt[j])
|
|
||||||
myedegrees[k] = myedegrees[--myrinfo->ndegrees];
|
|
||||||
else
|
|
||||||
myedegrees[k].ed -= adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add contribution to the .ed of 'to' */
|
|
||||||
if (me != to) {
|
|
||||||
for (k=0; k<myrinfo->ndegrees; k++) {
|
|
||||||
if (myedegrees[k].pid == to) {
|
|
||||||
myedegrees[k].ed += adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k == myrinfo->ndegrees) {
|
|
||||||
myedegrees[myrinfo->ndegrees].pid = to;
|
|
||||||
myedegrees[myrinfo->ndegrees++].ed = adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the queue */
|
|
||||||
if (me == to || me == from) {
|
|
||||||
gain = myrinfo->ed-myrinfo->id;
|
|
||||||
if (moved[ii] == 2) {
|
|
||||||
if (myrinfo->ed > 0)
|
|
||||||
PQueueUpdate(&queue, ii, oldgain, gain);
|
|
||||||
else {
|
|
||||||
PQueueDelete(&queue, ii, oldgain);
|
|
||||||
moved[ii] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (moved[ii] == -1 && myrinfo->ed > 0) {
|
|
||||||
PQueueInsert(&queue, ii, gain);
|
|
||||||
moved[ii] = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(myrinfo->ndegrees <= xadj[ii+1]-xadj[ii]);
|
|
||||||
ASSERT(CheckRInfo(myrinfo));
|
|
||||||
}
|
|
||||||
nmoves++;
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_REFINE,
|
|
||||||
mprintf("\t[%6D %6D], Balance: %5.3f, Nb: %6D. Nmoves: %5D, Cut: %6D\n",
|
|
||||||
pwgts[idxargmin(nparts, pwgts)], pwgts[idxargmax(nparts, pwgts)],
|
|
||||||
1.0*nparts*pwgts[idxargmax(nparts, pwgts)]/tvwgt, graph->nbnd, nmoves, graph->mincut));
|
|
||||||
}
|
|
||||||
|
|
||||||
PQueueFree(ctrl, &queue);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,480 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* kwayrefine.c
|
|
||||||
*
|
|
||||||
* This file contains the driving routines for multilevel k-way refinement
|
|
||||||
*
|
|
||||||
* Started 7/28/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: kwayrefine.c,v 1.5 2003/04/01 05:09:37 karypis Exp $
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry point of refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void RefineKWay(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, idxtype nparts, float *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, nlevels, mustfree=0;
|
|
||||||
GraphType *ptr;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr));
|
|
||||||
|
|
||||||
/* Compute the parameters of the coarsest graph */
|
|
||||||
ComputeKWayPartitionParams(ctrl, graph, nparts);
|
|
||||||
|
|
||||||
|
|
||||||
/* Take care any non-contiguity */
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->AuxTmr1));
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) {
|
|
||||||
EliminateComponents(ctrl, graph, nparts, tpwgts, 1.25);
|
|
||||||
EliminateSubDomainEdges(ctrl, graph, nparts, tpwgts);
|
|
||||||
EliminateComponents(ctrl, graph, nparts, tpwgts, 1.25);
|
|
||||||
}
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->AuxTmr1));
|
|
||||||
|
|
||||||
/* Determine how many levels are there */
|
|
||||||
for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++);
|
|
||||||
|
|
||||||
for (i=0; ;i++) {
|
|
||||||
/* PrintSubDomainGraph(graph, nparts, graph->where); */
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN && (i == nlevels/2 || i == nlevels/2+1))
|
|
||||||
EliminateSubDomainEdges(ctrl, graph, nparts, tpwgts);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->RefTmr));
|
|
||||||
|
|
||||||
if (2*i >= nlevels && !IsBalanced(graph->pwgts, nparts, tpwgts, 1.04*ubfactor)) {
|
|
||||||
ComputeKWayBalanceBoundary(ctrl, graph, nparts);
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN)
|
|
||||||
Greedy_KWayEdgeBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 1);
|
|
||||||
else
|
|
||||||
Greedy_KWayEdgeBalance(ctrl, graph, nparts, tpwgts, ubfactor, 1);
|
|
||||||
ComputeKWayBoundary(ctrl, graph, nparts);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ctrl->RType) {
|
|
||||||
case RTYPE_KWAYRANDOM:
|
|
||||||
Random_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 1);
|
|
||||||
break;
|
|
||||||
case RTYPE_KWAYGREEDY:
|
|
||||||
Greedy_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10);
|
|
||||||
break;
|
|
||||||
case RTYPE_KWAYRANDOM_MCONN:
|
|
||||||
Random_KWayEdgeRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->RefTmr));
|
|
||||||
|
|
||||||
if (graph == orggraph)
|
|
||||||
break;
|
|
||||||
|
|
||||||
graph = graph->finer;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->ProjectTmr));
|
|
||||||
if (graph->vwgt == NULL) {
|
|
||||||
graph->vwgt = idxsmalloc(graph->nvtxs, 1, "RefineKWay: graph->vwgt");
|
|
||||||
graph->adjwgt = idxsmalloc(graph->nedges, 1, "RefineKWay: graph->adjwgt");
|
|
||||||
mustfree = 1;
|
|
||||||
}
|
|
||||||
ProjectKWayPartition(ctrl, graph, nparts);
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsBalanced(graph->pwgts, nparts, tpwgts, ubfactor)) {
|
|
||||||
ComputeKWayBalanceBoundary(ctrl, graph, nparts);
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) {
|
|
||||||
Greedy_KWayEdgeBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 8);
|
|
||||||
Random_KWayEdgeRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Greedy_KWayEdgeBalance(ctrl, graph, nparts, tpwgts, ubfactor, 8);
|
|
||||||
Random_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take care any trivial non-contiguity */
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->AuxTmr2));
|
|
||||||
EliminateComponents(ctrl, graph, nparts, tpwgts, ubfactor);
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->AuxTmr2));
|
|
||||||
|
|
||||||
if (mustfree)
|
|
||||||
gk_free((void **)&graph->vwgt, &graph->adjwgt, LTERM);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry point of refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void RefineKWayRefinement(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, idxtype nparts, float *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, nlevels, mustfree=0;
|
|
||||||
GraphType *ptr;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr));
|
|
||||||
|
|
||||||
/* Compute the parameters of the coarsest graph */
|
|
||||||
ComputeKWayPartitionParams(ctrl, graph, nparts);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef XXXX
|
|
||||||
/* Take care any non-contiguity */
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->AuxTmr1));
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) {
|
|
||||||
EliminateComponents(ctrl, graph, nparts, tpwgts, 1.25);
|
|
||||||
EliminateSubDomainEdges(ctrl, graph, nparts, tpwgts);
|
|
||||||
EliminateComponents(ctrl, graph, nparts, tpwgts, 1.25);
|
|
||||||
}
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->AuxTmr1));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Determine how many levels are there */
|
|
||||||
for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++);
|
|
||||||
|
|
||||||
for (i=0; ;i++) {
|
|
||||||
#ifdef XXXX
|
|
||||||
/* PrintSubDomainGraph(graph, nparts, graph->where); */
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN && (i == nlevels/2 || i == nlevels/2+1))
|
|
||||||
EliminateSubDomainEdges(ctrl, graph, nparts, tpwgts);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->RefTmr));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (2*i >= nlevels && !IsBalanced(graph->pwgts, nparts, tpwgts, 1.04*ubfactor)) {
|
|
||||||
ComputeKWayBalanceBoundary(ctrl, graph, nparts);
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN)
|
|
||||||
Greedy_KWayEdgeBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 1);
|
|
||||||
else
|
|
||||||
Greedy_KWayEdgeBalance(ctrl, graph, nparts, tpwgts, ubfactor, 1);
|
|
||||||
ComputeKWayBoundary(ctrl, graph, nparts);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ctrl->RType) {
|
|
||||||
case RTYPE_KWAYRANDOM:
|
|
||||||
Random_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 1);
|
|
||||||
break;
|
|
||||||
case RTYPE_KWAYGREEDY:
|
|
||||||
Greedy_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10);
|
|
||||||
break;
|
|
||||||
case RTYPE_KWAYRANDOM_MCONN:
|
|
||||||
Random_KWayEdgeRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->RefTmr));
|
|
||||||
|
|
||||||
if (graph == orggraph)
|
|
||||||
break;
|
|
||||||
|
|
||||||
graph = graph->finer;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->ProjectTmr));
|
|
||||||
if (graph->vwgt == NULL) {
|
|
||||||
graph->vwgt = idxsmalloc(graph->nvtxs, 1, "RefineKWay: graph->vwgt");
|
|
||||||
graph->adjwgt = idxsmalloc(graph->nedges, 1, "RefineKWay: graph->adjwgt");
|
|
||||||
mustfree = 1;
|
|
||||||
}
|
|
||||||
ProjectKWayPartition(ctrl, graph, nparts);
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsBalanced(graph->pwgts, nparts, tpwgts, ubfactor)) {
|
|
||||||
ComputeKWayBalanceBoundary(ctrl, graph, nparts);
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) {
|
|
||||||
Greedy_KWayEdgeBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 8);
|
|
||||||
Random_KWayEdgeRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Greedy_KWayEdgeBalance(ctrl, graph, nparts, tpwgts, ubfactor, 8);
|
|
||||||
Random_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take care any trivial non-contiguity */
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->AuxTmr2));
|
|
||||||
EliminateComponents(ctrl, graph, nparts, tpwgts, ubfactor);
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->AuxTmr2));
|
|
||||||
|
|
||||||
if (mustfree)
|
|
||||||
gk_free((void **)&graph->vwgt, &graph->adjwgt, LTERM);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function allocates memory for k-way edge refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void AllocateKWayPartitionMemory(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype nvtxs;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
|
|
||||||
graph->pwgts = idxmalloc(nparts, "AllocateKWayPartitionMemory: pwgts");
|
|
||||||
graph->where = idxmalloc(nvtxs, "AllocateKWayPartitionMemory: pwgts");
|
|
||||||
graph->bndptr = idxmalloc(nvtxs, "AllocateKWayPartitionMemory: pwgts");
|
|
||||||
graph->bndind = idxmalloc(nvtxs, "AllocateKWayPartitionMemory: pwgts");
|
|
||||||
graph->rinfo = (RInfoType *)gk_malloc(nvtxs*sizeof(RInfoType), "AllocateKWayPartitionMemory: rinfo");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the initial id/ed
|
|
||||||
**************************************************************************/
|
|
||||||
void ComputeKWayPartitionParams(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, l, nvtxs, nbnd, mincut, me, other;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt, *pwgts, *where, *bndind, *bndptr;
|
|
||||||
RInfoType *rinfo, *myrinfo;
|
|
||||||
EDegreeType *myedegrees;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
where = graph->where;
|
|
||||||
pwgts = idxset(nparts, 0, graph->pwgts);
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = idxset(nvtxs, -1, graph->bndptr);
|
|
||||||
rinfo = graph->rinfo;
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
/ Compute now the id/ed degrees
|
|
||||||
/------------------------------------------------------------*/
|
|
||||||
ctrl->wspace.cdegree = 0;
|
|
||||||
nbnd = mincut = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
me = where[i];
|
|
||||||
pwgts[me] += vwgt[i];
|
|
||||||
|
|
||||||
myrinfo = rinfo+i;
|
|
||||||
myrinfo->id = myrinfo->ed = myrinfo->ndegrees = 0;
|
|
||||||
myrinfo->edegrees = NULL;
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (me != where[adjncy[j]])
|
|
||||||
myrinfo->ed += adjwgt[j];
|
|
||||||
}
|
|
||||||
myrinfo->id = graph->adjwgtsum[i] - myrinfo->ed;
|
|
||||||
|
|
||||||
if (myrinfo->ed > 0)
|
|
||||||
mincut += myrinfo->ed;
|
|
||||||
|
|
||||||
if (myrinfo->ed-myrinfo->id >= 0)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, i);
|
|
||||||
|
|
||||||
/* Time to compute the particular external degrees */
|
|
||||||
if (myrinfo->ed > 0) {
|
|
||||||
myedegrees = myrinfo->edegrees = ctrl->wspace.edegrees+ctrl->wspace.cdegree;
|
|
||||||
ctrl->wspace.cdegree += xadj[i+1]-xadj[i];
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
other = where[adjncy[j]];
|
|
||||||
if (me != other) {
|
|
||||||
for (k=0; k<myrinfo->ndegrees; k++) {
|
|
||||||
if (myedegrees[k].pid == other) {
|
|
||||||
myedegrees[k].ed += adjwgt[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k == myrinfo->ndegrees) {
|
|
||||||
myedegrees[myrinfo->ndegrees].pid = other;
|
|
||||||
myedegrees[myrinfo->ndegrees++].ed = adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(myrinfo->ndegrees <= xadj[i+1]-xadj[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->mincut = mincut/2;
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function projects a partition, and at the same time computes the
|
|
||||||
* parameters for refinement.
|
|
||||||
**************************************************************************/
|
|
||||||
void ProjectKWayPartition(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, nbnd, me, other, istart, iend, ndegrees;
|
|
||||||
idxtype *xadj, *adjncy, *adjwgt, *adjwgtsum;
|
|
||||||
idxtype *cmap, *where, *bndptr, *bndind;
|
|
||||||
idxtype *cwhere;
|
|
||||||
GraphType *cgraph;
|
|
||||||
RInfoType *crinfo, *rinfo, *myrinfo;
|
|
||||||
EDegreeType *myedegrees;
|
|
||||||
idxtype *htable;
|
|
||||||
|
|
||||||
cgraph = graph->coarser;
|
|
||||||
cwhere = cgraph->where;
|
|
||||||
crinfo = cgraph->rinfo;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
cmap = graph->cmap;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
adjwgtsum = graph->adjwgtsum;
|
|
||||||
|
|
||||||
AllocateKWayPartitionMemory(ctrl, graph, nparts);
|
|
||||||
where = graph->where;
|
|
||||||
rinfo = graph->rinfo;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = idxset(nvtxs, -1, graph->bndptr);
|
|
||||||
|
|
||||||
/* Go through and project partition and compute id/ed for the nodes */
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
k = cmap[i];
|
|
||||||
where[i] = cwhere[k];
|
|
||||||
cmap[i] = crinfo[k].ed; /* For optimization */
|
|
||||||
}
|
|
||||||
|
|
||||||
htable = idxset(nparts, -1, idxwspacemalloc(ctrl, nparts));
|
|
||||||
|
|
||||||
ctrl->wspace.cdegree = 0;
|
|
||||||
for (nbnd=0, i=0; i<nvtxs; i++) {
|
|
||||||
me = where[i];
|
|
||||||
|
|
||||||
myrinfo = rinfo+i;
|
|
||||||
myrinfo->id = myrinfo->ed = myrinfo->ndegrees = 0;
|
|
||||||
myrinfo->edegrees = NULL;
|
|
||||||
|
|
||||||
myrinfo->id = adjwgtsum[i];
|
|
||||||
|
|
||||||
if (cmap[i] > 0) { /* If it is an interface node. Note cmap[i] = crinfo[cmap[i]].ed */
|
|
||||||
istart = xadj[i];
|
|
||||||
iend = xadj[i+1];
|
|
||||||
|
|
||||||
myedegrees = myrinfo->edegrees = ctrl->wspace.edegrees+ctrl->wspace.cdegree;
|
|
||||||
ctrl->wspace.cdegree += iend-istart;
|
|
||||||
|
|
||||||
ndegrees = 0;
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
other = where[adjncy[j]];
|
|
||||||
if (me != other) {
|
|
||||||
myrinfo->ed += adjwgt[j];
|
|
||||||
if ((k = htable[other]) == -1) {
|
|
||||||
htable[other] = ndegrees;
|
|
||||||
myedegrees[ndegrees].pid = other;
|
|
||||||
myedegrees[ndegrees++].ed = adjwgt[j];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myedegrees[k].ed += adjwgt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myrinfo->id -= myrinfo->ed;
|
|
||||||
|
|
||||||
/* Remove space for edegrees if it was interior */
|
|
||||||
if (myrinfo->ed == 0) {
|
|
||||||
myrinfo->edegrees = NULL;
|
|
||||||
ctrl->wspace.cdegree -= iend-istart;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (myrinfo->ed-myrinfo->id >= 0)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, i);
|
|
||||||
|
|
||||||
myrinfo->ndegrees = ndegrees;
|
|
||||||
|
|
||||||
for (j=0; j<ndegrees; j++)
|
|
||||||
htable[myedegrees[j].pid] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
idxcopy(nparts, cgraph->pwgts, graph->pwgts);
|
|
||||||
graph->mincut = cgraph->mincut;
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
|
|
||||||
FreeGraph(graph->coarser, 1);
|
|
||||||
graph->coarser = NULL;
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
|
|
||||||
ASSERT(CheckBnd2(graph));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function checks if the partition weights are within the balance
|
|
||||||
* contraints
|
|
||||||
**************************************************************************/
|
|
||||||
idxtype IsBalanced(idxtype *pwgts, idxtype nparts, float *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, j, tvwgt;
|
|
||||||
|
|
||||||
tvwgt = idxsum(nparts, pwgts, 1);
|
|
||||||
for (i=0; i<nparts; i++) {
|
|
||||||
if (pwgts[i] > tpwgts[i]*tvwgt*(ubfactor+0.005))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the boundary definition for balancing
|
|
||||||
**************************************************************************/
|
|
||||||
void ComputeKWayBoundary(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, nvtxs, nbnd;
|
|
||||||
idxtype *bndind, *bndptr;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = idxset(nvtxs, -1, graph->bndptr);
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
/ Compute the new boundary
|
|
||||||
/------------------------------------------------------------*/
|
|
||||||
nbnd = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (graph->rinfo[i].ed-graph->rinfo[i].id >= 0)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the boundary definition for balancing
|
|
||||||
**************************************************************************/
|
|
||||||
void ComputeKWayBalanceBoundary(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, nvtxs, nbnd;
|
|
||||||
idxtype *bndind, *bndptr;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = idxset(nvtxs, -1, graph->bndptr);
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
/ Compute the new boundary
|
|
||||||
/------------------------------------------------------------*/
|
|
||||||
nbnd = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (graph->rinfo[i].ed > 0)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,456 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* kwayvolrefine.c
|
|
||||||
*
|
|
||||||
* This file contains the driving routines for multilevel k-way refinement
|
|
||||||
*
|
|
||||||
* Started 7/28/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: kwayvolrefine.c,v 1.2 2002/08/10 06:29:31 karypis Exp $
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function is the entry point of refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void RefineVolKWay(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, idxtype nparts,
|
|
||||||
float *tpwgts, float ubfactor)
|
|
||||||
{
|
|
||||||
idxtype i, nlevels;
|
|
||||||
GraphType *ptr;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr));
|
|
||||||
|
|
||||||
/* Take care any non-contiguity */
|
|
||||||
if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) {
|
|
||||||
ComputeVolKWayPartitionParams(ctrl, graph, nparts);
|
|
||||||
EliminateVolComponents(ctrl, graph, nparts, tpwgts, 1.25);
|
|
||||||
EliminateVolSubDomainEdges(ctrl, graph, nparts, tpwgts);
|
|
||||||
EliminateVolComponents(ctrl, graph, nparts, tpwgts, 1.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Determine how many levels are there */
|
|
||||||
for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++);
|
|
||||||
|
|
||||||
/* Compute the parameters of the coarsest graph */
|
|
||||||
ComputeVolKWayPartitionParams(ctrl, graph, nparts);
|
|
||||||
|
|
||||||
for (i=0; ;i++) {
|
|
||||||
/*PrintSubDomainGraph(graph, nparts, graph->where);*/
|
|
||||||
MALLOC_CHECK(NULL);
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->RefTmr));
|
|
||||||
|
|
||||||
if (2*i >= nlevels && !IsBalanced(graph->pwgts, nparts, tpwgts, 1.04*ubfactor)) {
|
|
||||||
ComputeVolKWayBalanceBoundary(ctrl, graph, nparts);
|
|
||||||
switch (ctrl->RType) {
|
|
||||||
case RTYPE_KWAYRANDOM:
|
|
||||||
Greedy_KWayVolBalance(ctrl, graph, nparts, tpwgts, ubfactor, 1);
|
|
||||||
break;
|
|
||||||
case RTYPE_KWAYRANDOM_MCONN:
|
|
||||||
Greedy_KWayVolBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ComputeVolKWayBoundary(ctrl, graph, nparts);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ctrl->RType) {
|
|
||||||
case RTYPE_KWAYRANDOM:
|
|
||||||
Random_KWayVolRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0);
|
|
||||||
break;
|
|
||||||
case RTYPE_KWAYRANDOM_MCONN:
|
|
||||||
Random_KWayVolRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->RefTmr));
|
|
||||||
|
|
||||||
if (graph == orggraph)
|
|
||||||
break;
|
|
||||||
|
|
||||||
graph = graph->finer;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->ProjectTmr));
|
|
||||||
ProjectVolKWayPartition(ctrl, graph, nparts);
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsBalanced(graph->pwgts, nparts, tpwgts, ubfactor)) {
|
|
||||||
ComputeVolKWayBalanceBoundary(ctrl, graph, nparts);
|
|
||||||
switch (ctrl->RType) {
|
|
||||||
case RTYPE_KWAYRANDOM:
|
|
||||||
Greedy_KWayVolBalance(ctrl, graph, nparts, tpwgts, ubfactor, 8);
|
|
||||||
Random_KWayVolRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0);
|
|
||||||
break;
|
|
||||||
case RTYPE_KWAYRANDOM_MCONN:
|
|
||||||
Greedy_KWayVolBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 8);
|
|
||||||
Random_KWayVolRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EliminateVolComponents(ctrl, graph, nparts, tpwgts, ubfactor);
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function allocates memory for k-way edge refinement
|
|
||||||
**************************************************************************/
|
|
||||||
void AllocateVolKWayPartitionMemory(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype nvtxs;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
|
|
||||||
graph->pwgts = idxmalloc(nparts, "AllocateVolKWayPartitionMemory: pwgts");
|
|
||||||
graph->where = idxmalloc(nvtxs, "AllocateVolKWayPartitionMemory: pwgts");
|
|
||||||
graph->bndptr = idxmalloc(nvtxs, "AllocateVolKWayPartitionMemory: pwgts");
|
|
||||||
graph->bndind = idxmalloc(nvtxs, "AllocateVolKWayPartitionMemory: pwgts");
|
|
||||||
|
|
||||||
graph->vrinfo = (VRInfoType *)gk_malloc(nvtxs*sizeof(VRInfoType), "AllocateVolKWayPartitionMemory: vrinfo");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the initial id/ed
|
|
||||||
**************************************************************************/
|
|
||||||
void ComputeVolKWayPartitionParams(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, kk, l, nvtxs, nbnd, mincut, minvol, me, other, pid;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt, *pwgts, *where;
|
|
||||||
VRInfoType *rinfo, *myrinfo, *orinfo;
|
|
||||||
VEDegreeType *myedegrees, *oedegrees;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
where = graph->where;
|
|
||||||
pwgts = idxset(nparts, 0, graph->pwgts);
|
|
||||||
rinfo = graph->vrinfo;
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
/ Compute now the id/ed degrees
|
|
||||||
/------------------------------------------------------------*/
|
|
||||||
ctrl->wspace.cdegree = 0;
|
|
||||||
mincut = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
me = where[i];
|
|
||||||
pwgts[me] += vwgt[i];
|
|
||||||
|
|
||||||
myrinfo = rinfo+i;
|
|
||||||
myrinfo->id = myrinfo->ed = myrinfo->nid = myrinfo->ndegrees = 0;
|
|
||||||
myrinfo->edegrees = NULL;
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (me == where[adjncy[j]]) {
|
|
||||||
myrinfo->id += adjwgt[j];
|
|
||||||
myrinfo->nid++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myrinfo->ed = graph->adjwgtsum[i] - myrinfo->id;
|
|
||||||
|
|
||||||
mincut += myrinfo->ed;
|
|
||||||
|
|
||||||
/* Time to compute the particular external degrees */
|
|
||||||
if (myrinfo->ed > 0) {
|
|
||||||
myedegrees = myrinfo->edegrees = ctrl->wspace.vedegrees+ctrl->wspace.cdegree;
|
|
||||||
ctrl->wspace.cdegree += xadj[i+1]-xadj[i];
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
other = where[adjncy[j]];
|
|
||||||
if (me != other) {
|
|
||||||
for (k=0; k<myrinfo->ndegrees; k++) {
|
|
||||||
if (myedegrees[k].pid == other) {
|
|
||||||
myedegrees[k].ed += adjwgt[j];
|
|
||||||
myedegrees[k].ned++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k == myrinfo->ndegrees) {
|
|
||||||
myedegrees[myrinfo->ndegrees].gv = 0;
|
|
||||||
myedegrees[myrinfo->ndegrees].pid = other;
|
|
||||||
myedegrees[myrinfo->ndegrees].ed = adjwgt[j];
|
|
||||||
myedegrees[myrinfo->ndegrees++].ned = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(myrinfo->ndegrees <= xadj[i+1]-xadj[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
graph->mincut = mincut/2;
|
|
||||||
|
|
||||||
|
|
||||||
ComputeKWayVolGains(ctrl, graph, nparts);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the initial id/ed
|
|
||||||
**************************************************************************/
|
|
||||||
void ComputeKWayVolGains(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, kk, l, nvtxs, me, other, pid, myndegrees;
|
|
||||||
idxtype *xadj, *vsize, *adjncy, *adjwgt, *where, *bndind, *bndptr, *ophtable;
|
|
||||||
VRInfoType *rinfo, *myrinfo, *orinfo;
|
|
||||||
VEDegreeType *myedegrees, *oedegrees;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vsize = graph->vsize;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
where = graph->where;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = idxset(nvtxs, -1, graph->bndptr);
|
|
||||||
rinfo = graph->vrinfo;
|
|
||||||
|
|
||||||
ophtable = idxset(nparts, -1, idxwspacemalloc(ctrl, nparts));
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
/ Compute now the iv/ev degrees
|
|
||||||
/------------------------------------------------------------*/
|
|
||||||
graph->minvol = graph->nbnd = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
myrinfo = rinfo+i;
|
|
||||||
myrinfo->gv = -MAXIDX;
|
|
||||||
|
|
||||||
if (myrinfo->ndegrees > 0) {
|
|
||||||
me = where[i];
|
|
||||||
myedegrees = myrinfo->edegrees;
|
|
||||||
myndegrees = myrinfo->ndegrees;
|
|
||||||
|
|
||||||
graph->minvol += myndegrees*vsize[i];
|
|
||||||
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
ii = adjncy[j];
|
|
||||||
other = where[ii];
|
|
||||||
orinfo = rinfo+ii;
|
|
||||||
oedegrees = orinfo->edegrees;
|
|
||||||
|
|
||||||
for (k=0; k<orinfo->ndegrees; k++)
|
|
||||||
ophtable[oedegrees[k].pid] = k;
|
|
||||||
ophtable[other] = 1; /* this is to simplify coding */
|
|
||||||
|
|
||||||
if (me == other) {
|
|
||||||
/* Find which domains 'i' is connected and 'ii' is not and update their gain */
|
|
||||||
for (k=0; k<myndegrees; k++) {
|
|
||||||
if (ophtable[myedegrees[k].pid] == -1)
|
|
||||||
myedegrees[k].gv -= vsize[ii];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ASSERT(ophtable[me] != -1);
|
|
||||||
|
|
||||||
if (oedegrees[ophtable[me]].ned == 1) { /* I'm the only connection of 'ii' in 'me' */
|
|
||||||
/* Increase the gains for all the common domains between 'i' and 'ii' */
|
|
||||||
for (k=0; k<myndegrees; k++) {
|
|
||||||
if (ophtable[myedegrees[k].pid] != -1)
|
|
||||||
myedegrees[k].gv += vsize[ii];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Find which domains 'i' is connected and 'ii' is not and update their gain */
|
|
||||||
for (k=0; k<myndegrees; k++) {
|
|
||||||
if (ophtable[myedegrees[k].pid] == -1)
|
|
||||||
myedegrees[k].gv -= vsize[ii];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (kk=0; kk<orinfo->ndegrees; kk++)
|
|
||||||
ophtable[oedegrees[kk].pid] = -1;
|
|
||||||
ophtable[other] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute the max vgain */
|
|
||||||
for (k=0; k<myndegrees; k++) {
|
|
||||||
if (myedegrees[k].gv > myrinfo->gv)
|
|
||||||
myrinfo->gv = myedegrees[k].gv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myrinfo->ed > 0 && myrinfo->id == 0)
|
|
||||||
myrinfo->gv += vsize[i];
|
|
||||||
|
|
||||||
if (myrinfo->gv >= 0 || myrinfo->ed-myrinfo->id >= 0)
|
|
||||||
BNDInsert(graph->nbnd, bndind, bndptr, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function projects a partition, and at the same time computes the
|
|
||||||
* parameters for refinement.
|
|
||||||
**************************************************************************/
|
|
||||||
void ProjectVolKWayPartition(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, j, k, nvtxs, me, other, istart, iend, ndegrees;
|
|
||||||
idxtype *xadj, *adjncy, *adjwgt, *adjwgtsum;
|
|
||||||
idxtype *cmap, *where;
|
|
||||||
idxtype *cwhere;
|
|
||||||
GraphType *cgraph;
|
|
||||||
VRInfoType *crinfo, *rinfo, *myrinfo;
|
|
||||||
VEDegreeType *myedegrees;
|
|
||||||
idxtype *htable;
|
|
||||||
|
|
||||||
cgraph = graph->coarser;
|
|
||||||
cwhere = cgraph->where;
|
|
||||||
crinfo = cgraph->vrinfo;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
cmap = graph->cmap;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
adjwgtsum = graph->adjwgtsum;
|
|
||||||
|
|
||||||
AllocateVolKWayPartitionMemory(ctrl, graph, nparts);
|
|
||||||
where = graph->where;
|
|
||||||
rinfo = graph->vrinfo;
|
|
||||||
|
|
||||||
/* Go through and project partition and compute id/ed for the nodes */
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
k = cmap[i];
|
|
||||||
where[i] = cwhere[k];
|
|
||||||
cmap[i] = crinfo[k].ed; /* For optimization */
|
|
||||||
}
|
|
||||||
|
|
||||||
htable = idxset(nparts, -1, idxwspacemalloc(ctrl, nparts));
|
|
||||||
|
|
||||||
ctrl->wspace.cdegree = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
me = where[i];
|
|
||||||
|
|
||||||
myrinfo = rinfo+i;
|
|
||||||
myrinfo->id = myrinfo->ed = myrinfo->nid = myrinfo->ndegrees = 0;
|
|
||||||
myrinfo->edegrees = NULL;
|
|
||||||
|
|
||||||
myrinfo->id = adjwgtsum[i];
|
|
||||||
myrinfo->nid = xadj[i+1]-xadj[i];
|
|
||||||
|
|
||||||
if (cmap[i] > 0) { /* If it is an interface node. Note cmap[i] = crinfo[cmap[i]].ed */
|
|
||||||
istart = xadj[i];
|
|
||||||
iend = xadj[i+1];
|
|
||||||
|
|
||||||
myedegrees = myrinfo->edegrees = ctrl->wspace.vedegrees+ctrl->wspace.cdegree;
|
|
||||||
ctrl->wspace.cdegree += iend-istart;
|
|
||||||
|
|
||||||
ndegrees = 0;
|
|
||||||
for (j=istart; j<iend; j++) {
|
|
||||||
other = where[adjncy[j]];
|
|
||||||
if (me != other) {
|
|
||||||
myrinfo->ed += adjwgt[j];
|
|
||||||
myrinfo->nid--;
|
|
||||||
if ((k = htable[other]) == -1) {
|
|
||||||
htable[other] = ndegrees;
|
|
||||||
myedegrees[ndegrees].gv = 0;
|
|
||||||
myedegrees[ndegrees].pid = other;
|
|
||||||
myedegrees[ndegrees].ed = adjwgt[j];
|
|
||||||
myedegrees[ndegrees++].ned = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myedegrees[k].ed += adjwgt[j];
|
|
||||||
myedegrees[k].ned++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myrinfo->id -= myrinfo->ed;
|
|
||||||
|
|
||||||
/* Remove space for edegrees if it was interior */
|
|
||||||
if (myrinfo->ed == 0) {
|
|
||||||
myrinfo->edegrees = NULL;
|
|
||||||
ctrl->wspace.cdegree -= iend-istart;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myrinfo->ndegrees = ndegrees;
|
|
||||||
|
|
||||||
for (j=0; j<ndegrees; j++)
|
|
||||||
htable[myedegrees[j].pid] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputeKWayVolGains(ctrl, graph, nparts);
|
|
||||||
|
|
||||||
idxcopy(nparts, cgraph->pwgts, graph->pwgts);
|
|
||||||
graph->mincut = cgraph->mincut;
|
|
||||||
|
|
||||||
FreeGraph(graph->coarser, 1);
|
|
||||||
graph->coarser = NULL;
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nparts);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the boundary definition for balancing
|
|
||||||
**************************************************************************/
|
|
||||||
void ComputeVolKWayBoundary(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, nvtxs, nbnd;
|
|
||||||
idxtype *bndind, *bndptr;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = idxset(nvtxs, -1, graph->bndptr);
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
/ Compute the new boundary
|
|
||||||
/------------------------------------------------------------*/
|
|
||||||
nbnd = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (graph->vrinfo[i].gv >=0 || graph->vrinfo[i].ed-graph->vrinfo[i].id >= 0)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function computes the boundary definition for balancing
|
|
||||||
**************************************************************************/
|
|
||||||
void ComputeVolKWayBalanceBoundary(CtrlType *ctrl, GraphType *graph, idxtype nparts)
|
|
||||||
{
|
|
||||||
idxtype i, nvtxs, nbnd;
|
|
||||||
idxtype *bndind, *bndptr;
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
bndind = graph->bndind;
|
|
||||||
bndptr = idxset(nvtxs, -1, graph->bndptr);
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
|
||||||
/ Compute the new boundary
|
|
||||||
/------------------------------------------------------------*/
|
|
||||||
nbnd = 0;
|
|
||||||
for (i=0; i<nvtxs; i++) {
|
|
||||||
if (graph->vrinfo[i].ed > 0)
|
|
||||||
BNDInsert(nbnd, bndind, bndptr, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
graph->nbnd = nbnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* macros.h
|
|
||||||
*
|
|
||||||
* This file contains macros used in multilevel
|
|
||||||
*
|
|
||||||
* Started 9/25/94
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: macros.h,v 1.6 2003/04/30 12:42:05 karypis Exp $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* The following macro returns a random number in the specified range
|
|
||||||
**************************************************************************/
|
|
||||||
#define AND(a, b) ((a) < 0 ? ((-(a))&(b)) : ((a)&(b)))
|
|
||||||
#define OR(a, b) ((a) < 0 ? -((-(a))|(b)) : ((a)|(b)))
|
|
||||||
#define XOR(a, b) ((a) < 0 ? -((-(a))^(b)) : ((a)^(b)))
|
|
||||||
|
|
||||||
#define idxcopy(n, a, b) (idxtype *)memcpy((void *)(b), (void *)(a), sizeof(idxtype)*(n))
|
|
||||||
|
|
||||||
#define HASHFCT(key, size) ((key)%(size))
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* Datatype related macros
|
|
||||||
**************************************************************************/
|
|
||||||
#define idxtype_abs(x) ((x) > 0 ? (x) : -(x))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* These macros insert and remove nodes from the boundary list
|
|
||||||
**************************************************************************/
|
|
||||||
#define BNDInsert(nbnd, bndind, bndptr, vtx) \
|
|
||||||
do { \
|
|
||||||
ASSERT(bndptr[vtx] == -1); \
|
|
||||||
bndind[nbnd] = vtx; \
|
|
||||||
bndptr[vtx] = nbnd++;\
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define BNDDelete(nbnd, bndind, bndptr, vtx) \
|
|
||||||
do { \
|
|
||||||
ASSERT(bndptr[vtx] != -1); \
|
|
||||||
bndind[bndptr[vtx]] = bndind[--nbnd]; \
|
|
||||||
bndptr[bndind[nbnd]] = bndptr[vtx]; \
|
|
||||||
bndptr[vtx] = -1; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,267 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1997, Regents of the University of Minnesota
|
|
||||||
*
|
|
||||||
* match.c
|
|
||||||
*
|
|
||||||
* This file contains the code that computes matchings and creates the next
|
|
||||||
* level coarse graph.
|
|
||||||
*
|
|
||||||
* Started 7/23/97
|
|
||||||
* George
|
|
||||||
*
|
|
||||||
* $Id: match.c,v 1.3 2003/07/31 15:49:43 karypis Exp $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <metislib.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function finds a matching using the HEM heuristic
|
|
||||||
**************************************************************************/
|
|
||||||
void Match_RM(CtrlType *ctrl, GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, nvtxs, cnvtxs, maxidx;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt;
|
|
||||||
idxtype *match, *cmap, *perm;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->MatchTmr));
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
cmap = graph->cmap;
|
|
||||||
match = idxset(nvtxs, UNMATCHED, idxwspacemalloc(ctrl, nvtxs));
|
|
||||||
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
RandomPermute(nvtxs, perm, 1);
|
|
||||||
|
|
||||||
cnvtxs = 0;
|
|
||||||
for (ii=0; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
|
|
||||||
if (match[i] == UNMATCHED) { /* Unmatched */
|
|
||||||
maxidx = i;
|
|
||||||
|
|
||||||
/* Find a random matching, subject to maxvwgt constraints */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (match[adjncy[j]] == UNMATCHED && vwgt[i]+vwgt[adjncy[j]] <= ctrl->maxvwgt) {
|
|
||||||
maxidx = adjncy[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmap[i] = cmap[maxidx] = cnvtxs++;
|
|
||||||
match[i] = maxidx;
|
|
||||||
match[maxidx] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->MatchTmr));
|
|
||||||
|
|
||||||
CreateCoarseGraph(ctrl, graph, cnvtxs, match, perm);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function finds a matching using the HEM heuristic
|
|
||||||
**************************************************************************/
|
|
||||||
void Match_RM_NVW(CtrlType *ctrl, GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, nvtxs, cnvtxs, maxidx;
|
|
||||||
idxtype *xadj, *adjncy;
|
|
||||||
idxtype *match, *cmap, *perm;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->MatchTmr));
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
|
|
||||||
cmap = graph->cmap;
|
|
||||||
match = idxset(nvtxs, UNMATCHED, idxwspacemalloc(ctrl, nvtxs));
|
|
||||||
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
RandomPermute(nvtxs, perm, 1);
|
|
||||||
|
|
||||||
cnvtxs = 0;
|
|
||||||
for (ii=0; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
|
|
||||||
if (match[i] == UNMATCHED) { /* Unmatched */
|
|
||||||
maxidx = i;
|
|
||||||
|
|
||||||
/* Find a random matching, subject to maxvwgt constraints */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (match[adjncy[j]] == UNMATCHED) {
|
|
||||||
maxidx = adjncy[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmap[i] = cmap[maxidx] = cnvtxs++;
|
|
||||||
match[i] = maxidx;
|
|
||||||
match[maxidx] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->MatchTmr));
|
|
||||||
|
|
||||||
CreateCoarseGraph_NVW(ctrl, graph, cnvtxs, match, perm);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function finds a matching using the HEM heuristic
|
|
||||||
**************************************************************************/
|
|
||||||
void Match_HEM(CtrlType *ctrl, GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, nvtxs, cnvtxs, maxidx, maxwgt;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt;
|
|
||||||
idxtype *match, *cmap, *perm;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->MatchTmr));
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
cmap = graph->cmap;
|
|
||||||
match = idxset(nvtxs, UNMATCHED, idxwspacemalloc(ctrl, nvtxs));
|
|
||||||
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
RandomPermute(nvtxs, perm, 1);
|
|
||||||
|
|
||||||
cnvtxs = 0;
|
|
||||||
for (ii=0; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
|
|
||||||
if (match[i] == UNMATCHED) { /* Unmatched */
|
|
||||||
maxidx = i;
|
|
||||||
maxwgt = 0;
|
|
||||||
|
|
||||||
/* Find a heavy-edge matching, subject to maxvwgt constraints */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
k = adjncy[j];
|
|
||||||
if (match[k] == UNMATCHED && maxwgt < adjwgt[j] && vwgt[i]+vwgt[k] <= ctrl->maxvwgt) {
|
|
||||||
maxwgt = adjwgt[j];
|
|
||||||
maxidx = adjncy[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmap[i] = cmap[maxidx] = cnvtxs++;
|
|
||||||
match[i] = maxidx;
|
|
||||||
match[maxidx] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->MatchTmr));
|
|
||||||
|
|
||||||
CreateCoarseGraph(ctrl, graph, cnvtxs, match, perm);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
* This function finds a matching using the HEM heuristic
|
|
||||||
**************************************************************************/
|
|
||||||
void Match_SHEM(CtrlType *ctrl, GraphType *graph)
|
|
||||||
{
|
|
||||||
idxtype i, ii, j, k, nvtxs, cnvtxs, maxidx, maxwgt, avgdegree;
|
|
||||||
idxtype *xadj, *vwgt, *adjncy, *adjwgt;
|
|
||||||
idxtype *match, *cmap, *degrees, *perm, *tperm;
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->MatchTmr));
|
|
||||||
|
|
||||||
nvtxs = graph->nvtxs;
|
|
||||||
xadj = graph->xadj;
|
|
||||||
vwgt = graph->vwgt;
|
|
||||||
adjncy = graph->adjncy;
|
|
||||||
adjwgt = graph->adjwgt;
|
|
||||||
|
|
||||||
cmap = graph->cmap;
|
|
||||||
match = idxset(nvtxs, UNMATCHED, idxwspacemalloc(ctrl, nvtxs));
|
|
||||||
|
|
||||||
perm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
tperm = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
degrees = idxwspacemalloc(ctrl, nvtxs);
|
|
||||||
|
|
||||||
RandomPermute(nvtxs, tperm, 1);
|
|
||||||
avgdegree = 0.7*(xadj[nvtxs]/nvtxs);
|
|
||||||
for (i=0; i<nvtxs; i++)
|
|
||||||
degrees[i] = (xadj[i+1]-xadj[i] > avgdegree ? avgdegree : xadj[i+1]-xadj[i]);
|
|
||||||
BucketSortKeysInc(nvtxs, avgdegree, degrees, tperm, perm);
|
|
||||||
|
|
||||||
cnvtxs = 0;
|
|
||||||
|
|
||||||
/* Take care any islands. Islands are matched with non-islands due to coarsening */
|
|
||||||
for (ii=0; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
|
|
||||||
if (match[i] == UNMATCHED) { /* Unmatched */
|
|
||||||
if (xadj[i] < xadj[i+1])
|
|
||||||
break;
|
|
||||||
|
|
||||||
maxidx = i;
|
|
||||||
for (j=nvtxs-1; j>ii; j--) {
|
|
||||||
k = perm[j];
|
|
||||||
if (match[k] == UNMATCHED && xadj[k] < xadj[k+1]) {
|
|
||||||
maxidx = k;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmap[i] = cmap[maxidx] = cnvtxs++;
|
|
||||||
match[i] = maxidx;
|
|
||||||
match[maxidx] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Continue with normal matching */
|
|
||||||
for (; ii<nvtxs; ii++) {
|
|
||||||
i = perm[ii];
|
|
||||||
|
|
||||||
if (match[i] == UNMATCHED) { /* Unmatched */
|
|
||||||
maxidx = i;
|
|
||||||
maxwgt = 0;
|
|
||||||
|
|
||||||
/* Find a heavy-edge matching, subject to maxvwgt constraints */
|
|
||||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
|
||||||
if (match[adjncy[j]] == UNMATCHED && maxwgt < adjwgt[j] && vwgt[i]+vwgt[adjncy[j]] <= ctrl->maxvwgt) {
|
|
||||||
maxwgt = adjwgt[j];
|
|
||||||
maxidx = adjncy[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmap[i] = cmap[maxidx] = cnvtxs++;
|
|
||||||
match[i] = maxidx;
|
|
||||||
match[maxidx] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->MatchTmr));
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nvtxs); /* degrees */
|
|
||||||
idxwspacefree(ctrl, nvtxs); /* tperm */
|
|
||||||
|
|
||||||
CreateCoarseGraph(ctrl, graph, cnvtxs, match, perm);
|
|
||||||
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
idxwspacefree(ctrl, nvtxs);
|
|
||||||
}
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user