moved metis into src/other; moved decomposition libraries into src/

This commit is contained in:
mattijs
2008-05-23 12:08:42 +01:00
parent f0d9dbfbe8
commit 8827ab2df1
453 changed files with 81 additions and 491576 deletions

View File

@ -1,6 +1,6 @@
EXE_INC = \
/* -g -DFULLDEBUG -O0 */ \
-I$(FOAM_UTILITIES)/parallelProcessing/decompositionMethods/decompositionMethods/lnInclude \
-I$(LIB_SRC)/decompositionAgglomeration/decompositionMethods/lnInclude \
-I$(LIB_SRC)/autoMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \

View File

@ -2,8 +2,7 @@ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(FOAM_UTILITIES)/parallelProcessing/decompositionMethods/decompositionMethods/lnInclude
-I$(LIB_SRC)/decompositionAgglomeration/decompositionMethods/lnInclude
EXE_LIBS = \
-lmeshTools \

View File

@ -1,8 +0,0 @@
#!/bin/sh
set -x
(cd decompositionMethods; ./Allwmake)
wmake decomposePar
wmake reconstructPar
wmake reconstructParMesh
wmake redistributeMeshPar

View File

@ -1,5 +1,5 @@
EXE_INC = \
-I../decompositionMethods/decompositionMethods/lnInclude \
-I$(LIB_SRC)/decompositionAgglomeration/decompositionMethods/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude

View File

@ -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)

View File

@ -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.

View File

@ -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).

View File

@ -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

View File

@ -1 +0,0 @@
/*EXE_INC = -Wno-unused-variables*/

View File

@ -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 */

View File

@ -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)

View File

@ -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);
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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); */

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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();
}

View File

@ -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));
}
*/
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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.
-------------------------------------------------------------------------------

View File

@ -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

View File

@ -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 */

View File

@ -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.
**********************************************************************

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -1,3 +0,0 @@
EXE_INC = \
-I../include \
-I../GKlib/trunk

View File

@ -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)

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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");
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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]++;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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