Start 3.0.0 branch, strip out Metis
parent
fec73365d7
commit
cce8e83dd6
18
.cproject
18
.cproject
|
|
@ -1,19 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?>
|
||||
|
||||
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.macosx.base.1359703544">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.macosx.base.1359703544" moduleId="org.eclipse.cdt.core.settings" name="MacOSX GCC">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
|
@ -21,7 +19,7 @@
|
|||
<folderInfo id="cdt.managedbuild.toolchain.gnu.macosx.base.1359703544.2031210194" name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.macosx.base.677243255" name="cdt.managedbuild.toolchain.gnu.macosx.base" superClass="cdt.managedbuild.toolchain.gnu.macosx.base">
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.MachO64" id="cdt.managedbuild.target.gnu.platform.macosx.base.752782918" name="Debug Platform" osList="macosx" superClass="cdt.managedbuild.target.gnu.platform.macosx.base"/>
|
||||
<builder arguments="" buildPath="${ProjDirPath}/build" command="make" id="cdt.managedbuild.target.gnu.builder.macosx.base.319933862" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="5" superClass="cdt.managedbuild.target.gnu.builder.macosx.base"/>
|
||||
<builder arguments="" buildPath="${ProjDirPath}/build-3_0_0" command="make" id="cdt.managedbuild.target.gnu.builder.macosx.base.319933862" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="5" superClass="cdt.managedbuild.target.gnu.builder.macosx.base"/>
|
||||
<tool id="cdt.managedbuild.tool.macosx.c.linker.macosx.base.457360678" name="MacOS X C Linker" superClass="cdt.managedbuild.tool.macosx.c.linker.macosx.base"/>
|
||||
<tool id="cdt.managedbuild.tool.macosx.cpp.linker.macosx.base.1011140787" name="MacOS X C++ Linker" superClass="cdt.managedbuild.tool.macosx.cpp.linker.macosx.base">
|
||||
<option id="macosx.cpp.link.option.paths.451252615" name="Library search path (-L)" superClass="macosx.cpp.link.option.paths"/>
|
||||
|
|
@ -62,13 +60,13 @@
|
|||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.macosx.base.1359703544.1441575890" moduleId="org.eclipse.cdt.core.settings" name="Timing">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
|
@ -118,13 +116,13 @@
|
|||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.macosx.base.1359703544.127261216" moduleId="org.eclipse.cdt.core.settings" name="fast">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
|
|
|||
|
|
@ -25,11 +25,6 @@ if(NOT GTSAM_USE_SYSTEM_EIGEN)
|
|||
FILES_MATCHING PATTERN "*.h")
|
||||
endif()
|
||||
|
||||
option(GTSAM_BUILD_METIS "Build metis library" ON)
|
||||
option(GTSAM_BUILD_METIS_EXECUTABLES "Build metis library executables" OFF)
|
||||
if(GTSAM_BUILD_METIS)
|
||||
add_subdirectory(metis-5.1.0)
|
||||
endif(GTSAM_BUILD_METIS)
|
||||
############ NOTE: When updating GeographicLib be sure to disable building their examples
|
||||
############ and unit tests by commenting out their lines:
|
||||
# add_subdirectory (examples)
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
Building METIS requires CMake 2.8, found at
|
||||
http://www.cmake.org/. CMake generates Visual Studio project files,
|
||||
which then can be built using Visual Studio. There are two ways to
|
||||
generate visual studio files: using the command line and using the
|
||||
CMake GUI.
|
||||
|
||||
Using the command line
|
||||
----------------------
|
||||
|
||||
Open the command prompt and cd to the METIS source directory. Run
|
||||
|
||||
> cmake --help
|
||||
|
||||
and look at the list of generators for the Visual Studio studio you
|
||||
want to build for. For example, the generator for Visual Studio 2010
|
||||
is called "Visual Studio 10".
|
||||
|
||||
After you have found the appropriate generator, run
|
||||
|
||||
> .\vsgen -G "<GENERATOR>"
|
||||
|
||||
to generate the project files. The project files will be placed
|
||||
build\windows.
|
||||
|
||||
|
||||
Using the CMake GUI
|
||||
-------------------
|
||||
|
||||
It is also possible to use the CMake GUI, distributed with CMake. To
|
||||
do this, open the CMake GUI, and browse to the location of METIS'
|
||||
source with the "Browse Source" button. You can also change the binary
|
||||
directory. This is where the Visual Studio project files will be
|
||||
placed. Click "Generate" to select the correct visual studio version
|
||||
and build the project files.
|
||||
|
||||
Using the VS project files
|
||||
--------------------------
|
||||
|
||||
The Visual Studio project will be called METIS.sln. Open it in Visual
|
||||
Studio. If the configuration is not already "Release", set it to
|
||||
"Release". Type F7 to build. The METIS library will be in
|
||||
<BINARY_DIR>\libmetis\Release and the executable programs will be in
|
||||
<BINARY_DIR>\programs\Release. (<BINARY_DIR> will be build\windows if
|
||||
you used the command line or whatever you choose if using the CMake
|
||||
GUI.)
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
------------------------------------------------------------------------------
|
||||
Building METIS requires CMake 2.8, found at http://www.cmake.org/, as
|
||||
well as GNU make. Assumming CMake and GNU make are installed, two
|
||||
commands should suffice to build metis:
|
||||
|
||||
$ make config
|
||||
$ make
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
METIS is primarily configured by passing options to make config. For
|
||||
example:
|
||||
|
||||
$ make config shared=1 cc=gcc-4.2
|
||||
|
||||
would configure metis to be built as a shared library using GCC 4.2.
|
||||
|
||||
Common configuration options are:
|
||||
cc=[compiler] - The C compiler to use [default is determined by CMake]
|
||||
shared=1 - Build a shared library instead of a static one
|
||||
[off by default]
|
||||
prefix=[PATH] - Set the installation prefix [/usr/local/ by default]
|
||||
|
||||
Advanced debugging related options:
|
||||
gdb=1 - Build with support for GDB [off by default]
|
||||
debug=1 - Enable debugging support [off by default]
|
||||
assert=1 - Enable asserts [off by default]
|
||||
assert2=1 - Enable very expensive asserts [off by default]
|
||||
|
||||
METIS' index and real data type size can be configured by editing
|
||||
include/metis.h.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
To install METIS, run
|
||||
|
||||
$ make install
|
||||
|
||||
The default installation prefix is /usr/local. To pick an installation
|
||||
prefix for METIS pass prefix=[path] to make config. For example,
|
||||
|
||||
$ make config prefix=~/myroot/
|
||||
|
||||
will cause METIS to be installed in ~/myroot/ when make install is run.
|
||||
|
||||
|
||||
Other make commands
|
||||
-------------------
|
||||
$ make uninstall
|
||||
Removes all files installed by 'make install'.
|
||||
|
||||
$ make clean
|
||||
Removes all object files but retains the configuration options.
|
||||
|
||||
$ make distclean
|
||||
Performs clean and completely removes the build directory.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
project(METIS)
|
||||
|
||||
# Add flags for currect directory and below
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
add_definitions(-Wno-unused-variable)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 5.0)
|
||||
add_definitions(-Wno-sometimes-uninitialized)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_definitions(-Wno-unknown-pragmas)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.6)
|
||||
add_definitions(-Wno-unused-but-set-variable)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(GKLIB_PATH ${PROJECT_SOURCE_DIR}/GKlib CACHE PATH "path to GKlib")
|
||||
set(SHARED FALSE CACHE BOOL "build a shared library")
|
||||
|
||||
if(MSVC)
|
||||
set(METIS_INSTALL FALSE)
|
||||
else()
|
||||
set(METIS_INSTALL FALSE)
|
||||
endif()
|
||||
|
||||
# Configure libmetis library.
|
||||
if(SHARED)
|
||||
set(METIS_LIBRARY_TYPE SHARED)
|
||||
else()
|
||||
set(METIS_LIBRARY_TYPE STATIC)
|
||||
endif(SHARED)
|
||||
|
||||
include(${GKLIB_PATH}/GKlibSystem.cmake)
|
||||
# Add include directories.
|
||||
include_directories(${GKLIB_PATH})
|
||||
include_directories(include)
|
||||
# Recursively look for CMakeLists.txt in subdirs.
|
||||
add_subdirectory("include")
|
||||
add_subdirectory("libmetis")
|
||||
|
||||
if(GTSAM_BUILD_METIS_EXECUTABLES)
|
||||
add_subdirectory("programs")
|
||||
endif()
|
||||
|
|
@ -1,286 +0,0 @@
|
|||
|
||||
metis-5.1.0
|
||||
------------------------------------------------------------------------
|
||||
r13937 | karypis | 2013-03-29 23:08:21 -0500 (Fri, 29 Mar 2013)
|
||||
|
||||
- Further extended the 2-hop coarsening scheme introduced in 5.0.2 for
|
||||
for graphs with highly variable degree distribution (e.g., power-law).
|
||||
This coarsening scheme is automatically used when the standard
|
||||
1-hop-based scheme leaves a large fraction of the vertices of the
|
||||
graph unmatched. It leads to better quality partitionings, lower
|
||||
memory utilization, and faster execution time. In principle, this
|
||||
scheme will never be triggered for graphs/matrices appearing in
|
||||
scientific computations derived from FE meshes. However, if you
|
||||
notice that the quality of the solutions is significantly worse,
|
||||
this 2-hop matching can be turned off by using the '-no2hop' command
|
||||
line option and the associated options[] parameter (as described
|
||||
in the manual).
|
||||
- Fixed 0/1 numbering issue with mesh partitioning routines (flyspray
|
||||
issue #109)
|
||||
|
||||
|
||||
metis-5.0.3
|
||||
------------------------------------------------------------------------
|
||||
r13822 | karypis | 2013-03-11 14:40:11 -0500 (Mon, 11 Mar 2013)
|
||||
|
||||
- Fixed the bug that was introduced in 5.x for creating nodal graphs
|
||||
from meshes (flyspray issue #107).
|
||||
- Changed the license to Apache Version 2.
|
||||
|
||||
|
||||
metis-5.0.2
|
||||
------------------------------------------------------------------------
|
||||
r10974 | karypis | 2011-10-29 18:24:32 -0500 (Sat, 29 Oct 2011)
|
||||
|
||||
- Fixed issue with high-degree vertices and mask-based compression.
|
||||
- Fixed issue with wrong COARSENING_FRACTION.
|
||||
- Modified coarsening schemes to better support non FE graphs.
|
||||
|
||||
|
||||
metis-5.0.1
|
||||
------------------------------------------------------------------------
|
||||
r10709 | karypis | 2011-08-31 16:07:57 -0500 (Wed, 31 Aug 2011)
|
||||
|
||||
- Fixed critical bug in the mesh partitioning routines.
|
||||
|
||||
|
||||
metis-5.0
|
||||
------------------------------------------------------------------------
|
||||
r10667 | karypis | 2011-08-04 00:35:30 -0500 (Thu, 04 Aug 2011)
|
||||
|
||||
- Updated/corrected error messages.
|
||||
- Addressed some build issues.
|
||||
|
||||
|
||||
metis-5.0rc3
|
||||
------------------------------------------------------------------------
|
||||
r10560 | karypis | 2011-07-13 08:19:10 -0500 (Wed, 13 Jul 2011)
|
||||
|
||||
- Fixed various bugs that were identified by testers.
|
||||
- Some minor performance and quality improvements.
|
||||
- Addressed some build issues.
|
||||
|
||||
|
||||
metis-5.0rc2
|
||||
------------------------------------------------------------------------
|
||||
r10496 | karypis | 2011-07-06 11:04:45 -0500 (Wed, 06 Jul 2011)
|
||||
|
||||
- Various run-time and quality optimizations.
|
||||
- Option error-checking.
|
||||
- Signal-based heap cleanup on error. Metis API routines will not
|
||||
return nicely and cleanup all memory that may have allocated.
|
||||
- Reduced memory requirements.
|
||||
- Fixed various bugs identified in rc1.
|
||||
- Added back Fortran support in the form of alternate API names
|
||||
(see libmetis/frename.h).
|
||||
- Minor code changes to accommodate ParMetis 4.0.
|
||||
|
||||
|
||||
metis-5.0rc1
|
||||
------------------------------------------------------------------------
|
||||
r10227 | karypis | 2011-06-13 23:35:05 -0500 (Mon, 13 Jun 2011)
|
||||
|
||||
- A nearly complete re-write of Metis' code-based that changed expanded
|
||||
the functionality of the command-line programs and API routines.
|
||||
- Multi-constraint partitioning can be used in conjunction with
|
||||
minimization of the total communication volume.
|
||||
- All graph and mesh partitioning routines take as input the target
|
||||
sizes of the partitions, which among others, allow them to compute
|
||||
partitioning solutions that are well-suited for parallel architectures
|
||||
with heterogeneous computing capabilities.
|
||||
- When multi-constraint partitioning is used, the target sizes of the
|
||||
partitions are specified on a per partition-constraint pair.
|
||||
- The multilevel k-way partitioning algorithms can compute a
|
||||
partitioning solution in which each partition is contiguous.
|
||||
- All partitioning and ordering routines can compute multiple different
|
||||
solutions and select the best as the final solution.
|
||||
- The mesh partitioning and mesh-to-graph conversion routines can
|
||||
operate on mixed element meshes.
|
||||
- The command-line programs provide full access to the entire set of
|
||||
capabilities provided by Metis' API.
|
||||
- Re-written the memory management subsystem to reduce overall memory
|
||||
requirements.
|
||||
|
||||
|
||||
|
||||
metis-5.0pre2
|
||||
------------------------------------------------------------------------
|
||||
r1437 | karypis | 2007-04-07 23:16:16 -0500 (Sat, 07 Apr 2007)
|
||||
|
||||
- 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).
|
||||
|
||||
|
||||
METIS 4.0.2, 3/10/04
|
||||
------------------------------------------------------------------------------
|
||||
- Fixed a problem with weighted graphs and ometis.c
|
||||
|
||||
|
||||
METIS 4.0.1, 11/29/98
|
||||
------------------------------------------------------------------------------
|
||||
This is mostly a bug-fix release
|
||||
|
||||
- Fixed some bugs in the multi-constraint partitioning routines
|
||||
- Fixed some bugs in the volume-minimization routines
|
||||
|
||||
|
||||
|
||||
METIS 4.0.0, 9/20/98
|
||||
------------------------------------------------------------------------------
|
||||
METIS 4.0 contains a number of changes over the previous major release (ver
|
||||
3.0.x). Most of these changes are concentrated on the graph and mesh
|
||||
partitioning routines and they do not affect the sparse matrix re-ordering
|
||||
routines. Here is a list of the major changes:
|
||||
|
||||
Multi-Constraint Partitioning
|
||||
-----------------------------
|
||||
METIS now includes partitioning routines that can be used to a partition
|
||||
a graph in the presence of multiple balancing constraints.
|
||||
|
||||
Minimizing the Total Communication Volume
|
||||
-----------------------------------------
|
||||
METIS now includes partitioning routines whose objective is to minimize
|
||||
the total communication volume (as opposed to minimizing the edge-cut).
|
||||
|
||||
Minimizing the Maximum Connectivity of the Subdomains
|
||||
-----------------------------------------------------
|
||||
The k-way partitioning routines in METIS can now directly minimize the number
|
||||
of adjacent subdomains. For most graphs corresponding to finite element
|
||||
meshes, METIS is able to significantly reduce the maximum (and total) number of
|
||||
adjacent subdomains.
|
||||
|
||||
|
||||
|
||||
|
||||
METIS 3.0.6, 1/28/98
|
||||
-------------------------------------------------------------------------------
|
||||
- Fixed some problems when too many partitions were asked, and each partition
|
||||
end up having 0 vertices
|
||||
- Fixed some bugs in the I/O routines
|
||||
- Added support for the g77 compiler under Linux
|
||||
|
||||
|
||||
METIS 3.0.5, 12/22/97
|
||||
-------------------------------------------------------------------------------
|
||||
- Fixed problems on 64-bit architectures (eg., -64 option on SGIs).
|
||||
- Added some options in Makefile.in
|
||||
|
||||
|
||||
METIS 3.0.4, 12/1/97
|
||||
-------------------------------------------------------------------------------
|
||||
Fixed a memory leak in the ordering code.
|
||||
|
||||
|
||||
METIS 3.0.3, 11/5/97
|
||||
-------------------------------------------------------------------------------
|
||||
This is mostly a bug-fix release with just a few additions
|
||||
|
||||
Added functionality
|
||||
- Added support for quadrilateral elements.
|
||||
- Added a routine METIS_EstimateMemory that estimates the amount of
|
||||
memory that will be allocated by METIS. This is useful in determining
|
||||
if a problem can run on your system.
|
||||
- Added hooks to allow PARMETIS to use the orderings produced by METIS.
|
||||
This is hidden from the user but it will be used in the next release
|
||||
of PARMETIS.
|
||||
|
||||
Bug-fixes
|
||||
- Fixed a bug related to memory allocation. This should somewhat reduce the
|
||||
overall memory used by METIS.
|
||||
- Fixed some bugs in the 'graphchk' program in the case of weighted graphs.
|
||||
- Removed some code corresponding to unused options.
|
||||
- Fixed some minor bugs in the node-refinement code
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
METIS 3.0 contains a number of changes over METIS 2.0.
|
||||
The major changes are the following:
|
||||
|
||||
General Changes
|
||||
---------------
|
||||
1. Added code to directly partition finite element meshes.
|
||||
|
||||
2. Added code to convert finite element meshes into graphs so they
|
||||
can be used by METIS.
|
||||
|
||||
1. The names, calling sequences, and options of the routines in
|
||||
METISlib have been changed.
|
||||
|
||||
2. Better support has been added for Fortran programs.
|
||||
|
||||
3. Eliminated the 'metis' program. The only way to tune METIS's
|
||||
behavior is to use METISlib.
|
||||
|
||||
4. Improved memory management. METIS should now only abort if truly
|
||||
there is no more memory left in the system.
|
||||
|
||||
|
||||
Graph Partitioning
|
||||
------------------
|
||||
1. Added partitioning routines that can be used to compute a partition
|
||||
with prescribed partition weights. For example, they can be used to
|
||||
compute a 3-way partition such that partition 1 has 50% of the weight,
|
||||
partition 2 has 20% of the way, and partition 3 has 30% of the weight.
|
||||
|
||||
2. Improved the speed of the k-way partitioning algorithm (kmetis). The
|
||||
new code has better cache locality which dramatically improves the
|
||||
speed for large graphs. A factor of 4 speedup can be obtained for
|
||||
certain graphs. METIS can now partition a 4 million node graph
|
||||
in well under a minute on a MIPS R10000.
|
||||
|
||||
3. Eliminated some of the options that were seldom used.
|
||||
|
||||
|
||||
Fill-Reducing Orderings
|
||||
----------------------
|
||||
1. Added a node based ordering code `onmetis' that greatly improves
|
||||
ordering quality.
|
||||
|
||||
2. Improved the quality of the orderings produced by the original
|
||||
edge-based ordering code (it is now called 'oemetis').
|
||||
|
||||
3. METIS can now analyze the graph and try to compress together
|
||||
nodes with identical sparsity pattern. For some problems, this
|
||||
significantly reduces ordering time
|
||||
|
||||
4. METIS can now prune dense columns prior to ordering. This can be
|
||||
helpful for LP matrices.
|
||||
|
||||
|
||||
Mesh Partitioning
|
||||
-----------------
|
||||
1. METIS can now directly partition the element node array of finite
|
||||
element meshes. It produces two partitioning vectors. One for the
|
||||
elements and one for the nodes. METIS supports the following
|
||||
elements: triangles, tetrahedra, hexahedra
|
||||
|
||||
|
||||
Mesh-To-Graph Conversion Routines
|
||||
---------------------------------
|
||||
1. METIS now includes a number of mesh conversion functions that can
|
||||
be used to create the dual and nodal graphs directly from the
|
||||
element connectivity arrays. These are highly optimized routines.
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
Building GKlib requires CMake 2.8. Once you've installed CMake run
|
||||
|
||||
$ make
|
||||
|
||||
This will build the GKlib library in build/<arch>/. Options can be tweaked by
|
||||
running make config. For example,
|
||||
|
||||
$ make config openmp=ON
|
||||
$ make
|
||||
|
||||
will build GKlib will OpenMP support if it is available.
|
||||
|
||||
GKlib can be installed with
|
||||
|
||||
$ make install
|
||||
|
||||
and uninstalled with
|
||||
|
||||
$ make uninstall
|
||||
|
||||
You can choose the installation prefix with make config:
|
||||
|
||||
$ make config prefix=~/local
|
||||
|
||||
will cause GKlib to be install in the ~/local tree.
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
project(GKlib)
|
||||
|
||||
get_filename_component(abs "." ABSOLUTE)
|
||||
set(GKLIB_PATH ${abs})
|
||||
unset(abs)
|
||||
include(GKlibSystem.cmake)
|
||||
|
||||
include_directories(".")
|
||||
add_library(GKlib STATIC ${GKlib_sources})
|
||||
if(UNIX)
|
||||
target_link_libraries(GKlib m)
|
||||
endif(UNIX)
|
||||
|
||||
include_directories("test")
|
||||
add_subdirectory("test")
|
||||
|
||||
install(TARGETS GKlib
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib)
|
||||
install(FILES ${GKlib_includes} DESTINATION include)
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* GKlib.h
|
||||
*
|
||||
* George's library of most frequently used routines
|
||||
*
|
||||
* $Id: GKlib.h 13005 2012-10-23 22:34:36Z 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
|
||||
#if defined(USE_GKREGEX)
|
||||
#include "gkregex.h"
|
||||
#else
|
||||
#include <regex.h>
|
||||
#endif /* defined(USE_GKREGEX) */
|
||||
#endif /* defined(__WITHPCRE__) */
|
||||
|
||||
|
||||
|
||||
#if defined(__OPENMP__)
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#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_mksort.h>
|
||||
#include <gk_mkblas.h>
|
||||
#include <gk_mkmemory.h>
|
||||
#include <gk_mkpqueue.h>
|
||||
#include <gk_mkpqueue2.h>
|
||||
#include <gk_mkrandom.h>
|
||||
#include <gk_mkutils.h>
|
||||
|
||||
#include <gk_proto.h>
|
||||
|
||||
|
||||
#endif /* GKlib.h */
|
||||
|
||||
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
# Helper modules.
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
|
||||
# Setup options.
|
||||
option(GDB "enable use of GDB" OFF)
|
||||
option(ASSERT "turn asserts on" OFF)
|
||||
option(ASSERT2 "additional assertions" OFF)
|
||||
option(DEBUG "add debugging support" OFF)
|
||||
option(GPROF "add gprof support" OFF)
|
||||
option(OPENMP "enable OpenMP support" OFF)
|
||||
option(PCRE "enable PCRE support" OFF)
|
||||
option(GKREGEX "enable GKREGEX support" OFF)
|
||||
option(GKRAND "enable GKRAND support" OFF)
|
||||
|
||||
# Add compiler flags.
|
||||
if(MSVC)
|
||||
set(GKlib_COPTS "/Ox")
|
||||
set(GKlib_COPTIONS "-DWIN32 -DMSC -D_CRT_SECURE_NO_DEPRECATE -DUSE_GKREGEX")
|
||||
elseif(MINGW)
|
||||
set(GKlib_COPTS "-DUSE_GKREGEX")
|
||||
else()
|
||||
set(GKlib_COPTS "-O3")
|
||||
set(GKlib_COPTIONS "-DLINUX -D_FILE_OFFSET_BITS=64")
|
||||
endif(MSVC)
|
||||
if(CYGWIN)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -DCYGWIN")
|
||||
endif(CYGWIN)
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
# GCC opts.
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -std=c99 -fno-strict-aliasing")
|
||||
if(NOT MINGW)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -fPIC")
|
||||
endif(NOT MINGW)
|
||||
# GCC warnings.
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -Wall -pedantic -Wno-unused-variable -Wno-unknown-pragmas")
|
||||
elseif(${CMAKE_C_COMPILER_ID} MATCHES "Sun")
|
||||
# Sun insists on -xc99.
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -xc99")
|
||||
endif(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
# Find OpenMP if it is requested.
|
||||
if(OPENMP)
|
||||
include(FindOpenMP)
|
||||
if(OPENMP_FOUND)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -D__OPENMP__ ${OpenMP_C_FLAGS}")
|
||||
else()
|
||||
message(WARNING "OpenMP was requested but support was not found")
|
||||
endif(OPENMP_FOUND)
|
||||
endif(OPENMP)
|
||||
|
||||
|
||||
# Add various definitions.
|
||||
if(GDB)
|
||||
set(GKlib_COPTS "${GKlib_COPTS} -g")
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -Werror")
|
||||
endif(GDB)
|
||||
|
||||
|
||||
if(DEBUG)
|
||||
set(GKlib_COPTS "-g")
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -DDEBUG")
|
||||
endif(DEBUG)
|
||||
|
||||
if(GPROF)
|
||||
set(GKlib_COPTS "-pg")
|
||||
endif(GPROF)
|
||||
|
||||
if(NOT ASSERT)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -DNDEBUG")
|
||||
endif(NOT ASSERT)
|
||||
|
||||
if(NOT ASSERT2)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -DNDEBUG2")
|
||||
endif(NOT ASSERT2)
|
||||
|
||||
|
||||
# Add various options
|
||||
if(PCRE)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -D__WITHPCRE__")
|
||||
endif(PCRE)
|
||||
|
||||
if(GKREGEX)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -DUSE_GKREGEX")
|
||||
endif(GKREGEX)
|
||||
|
||||
if(GKRAND)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -DUSE_GKRAND")
|
||||
endif(GKRAND)
|
||||
|
||||
|
||||
# Check for features.
|
||||
check_include_file(execinfo.h HAVE_EXECINFO_H)
|
||||
if(HAVE_EXECINFO_H)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -DHAVE_EXECINFO_H")
|
||||
endif(HAVE_EXECINFO_H)
|
||||
|
||||
check_function_exists(getline HAVE_GETLINE)
|
||||
if(HAVE_GETLINE)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -DHAVE_GETLINE")
|
||||
endif(HAVE_GETLINE)
|
||||
|
||||
|
||||
# Custom check for TLS.
|
||||
if(MSVC)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -D__thread=__declspec(thread)")
|
||||
else()
|
||||
# This if checks if that value is cached or not.
|
||||
if("${HAVE_THREADLOCALSTORAGE}" MATCHES "^${HAVE_THREADLOCALSTORAGE}$")
|
||||
try_compile(HAVE_THREADLOCALSTORAGE
|
||||
${CMAKE_BINARY_DIR}
|
||||
${GKLIB_PATH}/conf/check_thread_storage.c)
|
||||
if(HAVE_THREADLOCALSTORAGE)
|
||||
message(STATUS "checking for thread-local storage - found")
|
||||
else()
|
||||
message(STATUS "checking for thread-local storage - not found")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT HAVE_THREADLOCALSTORAGE)
|
||||
set(GKlib_COPTIONS "${GKlib_COPTIONS} -D__thread=")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Finally set the official C flags.
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GKlib_COPTIONS} ${GKlib_COPTS}")
|
||||
|
||||
# Find GKlib sources.
|
||||
file(GLOB GKlib_sources ${GKLIB_PATH}/*.c)
|
||||
file(GLOB GKlib_includes ${GKLIB_PATH}/*.h)
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
# Configuration options.
|
||||
gdb = not-set
|
||||
assert = not-set
|
||||
assert2 = not-set
|
||||
debug = not-set
|
||||
gprof = not-set
|
||||
openmp = not-set
|
||||
prefix = not-set
|
||||
pcre = not-set
|
||||
gkregex = not-set
|
||||
gkrand = not-set
|
||||
|
||||
|
||||
# Basically proxies everything to the builddir cmake.
|
||||
cputype = $(shell uname -m | sed "s/\\ /_/g")
|
||||
systype = $(shell uname -s)
|
||||
|
||||
BUILDDIR = build/$(systype)-$(cputype)
|
||||
|
||||
# Process configuration options.
|
||||
CONFIG_FLAGS = -DCMAKE_VERBOSE_MAKEFILE=1
|
||||
ifneq ($(gdb), not-set)
|
||||
CONFIG_FLAGS += -DGDB=$(gdb)
|
||||
endif
|
||||
ifneq ($(assert), not-set)
|
||||
CONFIG_FLAGS += -DASSERT=$(assert)
|
||||
endif
|
||||
ifneq ($(assert2), not-set)
|
||||
CONFIG_FLAGS += -DASSERT2=$(assert2)
|
||||
endif
|
||||
ifneq ($(debug), not-set)
|
||||
CONFIG_FLAGS += -DDEBUG=$(debug)
|
||||
endif
|
||||
ifneq ($(gprof), not-set)
|
||||
CONFIG_FLAGS += -DGPROF=$(gprof)
|
||||
endif
|
||||
ifneq ($(openmp), not-set)
|
||||
CONFIG_FLAGS += -DOPENMP=$(openmp)
|
||||
endif
|
||||
ifneq ($(pcre), not-set)
|
||||
CONFIG_FLAGS += -DPCRE=$(pcre)
|
||||
endif
|
||||
ifneq ($(gkregex), not-set)
|
||||
CONFIG_FLAGS += -DGKREGEX=$(pcre)
|
||||
endif
|
||||
ifneq ($(gkrand), not-set)
|
||||
CONFIG_FLAGS += -DGKRAND=$(pcre)
|
||||
endif
|
||||
ifneq ($(prefix), not-set)
|
||||
CONFIG_FLAGS += -DCMAKE_INSTALL_PREFIX=$(prefix)
|
||||
endif
|
||||
|
||||
define run-config
|
||||
mkdir -p $(BUILDDIR)
|
||||
cd $(BUILDDIR) && cmake $(CURDIR) $(CONFIG_FLAGS)
|
||||
endef
|
||||
|
||||
all clean install: $(BUILDDIR)
|
||||
make -C $(BUILDDIR) $@
|
||||
|
||||
uninstall:
|
||||
xargs rm < $(BUILDDIR)/install_manifest.txt
|
||||
|
||||
$(BUILDDIR):
|
||||
$(run-config)
|
||||
|
||||
config: distclean
|
||||
$(run-config)
|
||||
|
||||
distclean:
|
||||
rm -rf $(BUILDDIR)
|
||||
|
||||
remake:
|
||||
find . -name CMakeLists.txt -exec touch {} ';'
|
||||
|
||||
.PHONY: config distclean all clean install uninstall remake
|
||||
|
|
@ -1,95 +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 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
|
||||
\verbatim
|
||||
$Copyright$
|
||||
$License$
|
||||
\endverbatim
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "GKlib.h"
|
||||
|
||||
#define B64OFFSET 48 /* This is the '0' number */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Encode 3 '8-bit' binary bytes as 4 '6-bit' characters
|
||||
*******************************************************************************/
|
||||
void encodeblock(unsigned char *in, unsigned char *out)
|
||||
{
|
||||
out[0] = (in[0] >> 2);
|
||||
out[1] = (((in[0] & 0x03) << 4) | (in[1] >> 4));
|
||||
out[2] = (((in[1] & 0x0f) << 2) | (in[2] >> 6));
|
||||
out[3] = (in[2] & 0x3f);
|
||||
|
||||
out[0] += B64OFFSET;
|
||||
out[1] += B64OFFSET;
|
||||
out[2] += B64OFFSET;
|
||||
out[3] += B64OFFSET;
|
||||
|
||||
// printf("%c %c %c %c %2x %2x %2x %2x %2x %2x %2x\n", out[0], out[1], out[2], out[3], out[0], out[1], out[2], out[3], in[0], in[1], in[2]);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Decode 4 '6-bit' characters into 3 '8-bit' binary bytes
|
||||
*******************************************************************************/
|
||||
void decodeblock(unsigned char *in, unsigned char *out)
|
||||
{
|
||||
in[0] -= B64OFFSET;
|
||||
in[1] -= B64OFFSET;
|
||||
in[2] -= B64OFFSET;
|
||||
in[3] -= B64OFFSET;
|
||||
|
||||
out[0] = (in[0] << 2 | in[1] >> 4);
|
||||
out[1] = (in[1] << 4 | in[2] >> 2);
|
||||
out[2] = (in[2] << 6 | in[3]);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function encodes an input array of bytes into a base64 encoding. Memory
|
||||
* for the output array is assumed to have been allocated by the calling program
|
||||
* and be sufficiently large. The output string is NULL terminated.
|
||||
*******************************************************************************/
|
||||
void GKEncodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (nbytes%3 != 0)
|
||||
gk_errexit(SIGERR, "GKEncodeBase64: Input buffer size should be a multiple of 3! (%d)\n", nbytes);
|
||||
|
||||
for (j=0, i=0; i<nbytes; i+=3, j+=4)
|
||||
encodeblock(inbuffer+i, outbuffer+j);
|
||||
|
||||
//printf("%d %d\n", nbytes, j);
|
||||
outbuffer[j] = '\0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function decodes an input array of base64 characters into their actual
|
||||
* 8-bit codes. Memory * for the output array is assumed to have been allocated
|
||||
* by the calling program and be sufficiently large. The padding is discarded.
|
||||
*******************************************************************************/
|
||||
void GKDecodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (nbytes%4 != 0)
|
||||
gk_errexit(SIGERR, "GKDecodeBase64: Input buffer size should be a multiple of 4! (%d)\n", nbytes);
|
||||
|
||||
for (j=0, i=0; i<nbytes; i+=4, j+=3)
|
||||
decodeblock(inbuffer+i, outbuffer+j);
|
||||
}
|
||||
|
||||
|
|
@ -1,36 +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 11848 2012-04-20 13:47:37Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Use the templates to generate BLAS routines for the scalar data types */
|
||||
/*************************************************************************/
|
||||
GK_MKBLAS(gk_c, char, int)
|
||||
GK_MKBLAS(gk_i, int, int)
|
||||
GK_MKBLAS(gk_i32, int32_t, int32_t)
|
||||
GK_MKBLAS(gk_i64, int64_t, int64_t)
|
||||
GK_MKBLAS(gk_z, ssize_t, ssize_t)
|
||||
GK_MKBLAS(gk_f, float, float)
|
||||
GK_MKBLAS(gk_d, double, double)
|
||||
GK_MKBLAS(gk_idx, gk_idx_t, gk_idx_t)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
extern __thread int x;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,214 +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 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#define _GK_ERROR_C_ /* this is needed to properly declare the gk_jub* variables
|
||||
as an extern function in GKlib.h */
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
/* These are the jmp_buf for the graceful exit in case of severe errors.
|
||||
Multiple buffers are defined to allow for recursive invokation. */
|
||||
#define MAX_JBUFS 128
|
||||
__thread int gk_cur_jbufs=-1;
|
||||
__thread jmp_buf gk_jbufs[MAX_JBUFS];
|
||||
__thread jmp_buf gk_jbuf;
|
||||
|
||||
typedef void (*gksighandler_t)(int);
|
||||
|
||||
/* These are the holders of the old singal handlers for the trapped signals */
|
||||
static __thread gksighandler_t old_SIGMEM_handler; /* Custom signal */
|
||||
static __thread gksighandler_t old_SIGERR_handler; /* Custom signal */
|
||||
static __thread gksighandler_t old_SIGMEM_handlers[MAX_JBUFS]; /* Custom signal */
|
||||
static __thread gksighandler_t old_SIGERR_handlers[MAX_JBUFS]; /* Custom signal */
|
||||
|
||||
/* The following is used to control if the gk_errexit() will actually abort or not.
|
||||
There is always a single copy of this variable */
|
||||
static int gk_exit_on_error = 1;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function sets the gk_exit_on_error variable
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_set_exit_on_error(int value)
|
||||
{
|
||||
gk_exit_on_error = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! 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);
|
||||
|
||||
if (strlen(f_str) == 0 || f_str[strlen(f_str)-1] != '\n')
|
||||
fprintf(stderr,"\n");
|
||||
fflush(stderr);
|
||||
|
||||
if (gk_exit_on_error)
|
||||
exit(-2);
|
||||
|
||||
/* abort(); */
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! 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);
|
||||
|
||||
if (gk_exit_on_error)
|
||||
raise(signum);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/*! This function sets a number of signal handlers and sets the return point
|
||||
of a longjmp
|
||||
*/
|
||||
/***************************************************************************/
|
||||
int gk_sigtrap()
|
||||
{
|
||||
if (gk_cur_jbufs+1 >= MAX_JBUFS)
|
||||
return 0;
|
||||
|
||||
gk_cur_jbufs++;
|
||||
|
||||
old_SIGMEM_handlers[gk_cur_jbufs] = signal(SIGMEM, gk_sigthrow);
|
||||
old_SIGERR_handlers[gk_cur_jbufs] = signal(SIGERR, gk_sigthrow);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/*! This function sets the handlers for the signals to their default handlers
|
||||
*/
|
||||
/***************************************************************************/
|
||||
int gk_siguntrap()
|
||||
{
|
||||
if (gk_cur_jbufs == -1)
|
||||
return 0;
|
||||
|
||||
signal(SIGMEM, old_SIGMEM_handlers[gk_cur_jbufs]);
|
||||
signal(SIGERR, old_SIGERR_handlers[gk_cur_jbufs]);
|
||||
|
||||
gk_cur_jbufs--;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function is the custome signal handler, which all it does is to
|
||||
perform a longjump to the most recent saved environment
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_sigthrow(int signum)
|
||||
{
|
||||
longjmp(gk_jbufs[gk_cur_jbufs], signum);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* This function sets a number of signal handlers and sets the return point
|
||||
* of a longjmp
|
||||
****************************************************************************/
|
||||
void gk_SetSignalHandlers()
|
||||
{
|
||||
old_SIGMEM_handler = signal(SIGMEM, gk_NonLocalExit_Handler);
|
||||
old_SIGERR_handler = signal(SIGERR, gk_NonLocalExit_Handler);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* This function sets the handlers for the signals to their default handlers
|
||||
****************************************************************************/
|
||||
void gk_UnsetSignalHandlers()
|
||||
{
|
||||
signal(SIGMEM, old_SIGMEM_handler);
|
||||
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)
|
||||
{
|
||||
longjmp(gk_jbuf, signum);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! \brief Thread-safe implementation of strerror() */
|
||||
/**************************************************************************/
|
||||
char *gk_strerror(int errnum)
|
||||
{
|
||||
#if defined(WIN32) || defined(__MINGW32__)
|
||||
return strerror(errnum);
|
||||
#else
|
||||
#ifndef SUNOS
|
||||
static __thread char buf[1024];
|
||||
|
||||
strerror_r(errnum, buf, 1024);
|
||||
|
||||
buf[1023] = '\0';
|
||||
return buf;
|
||||
#else
|
||||
return strerror(errnum);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function prints a backtrace of calling functions
|
||||
**************************************************************************/
|
||||
void PrintBackTrace()
|
||||
{
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
void *array[10];
|
||||
int i, size;
|
||||
char **strings;
|
||||
|
||||
size = backtrace(array, 10);
|
||||
strings = backtrace_symbols(array, size);
|
||||
|
||||
printf("Obtained %d stack frames.\n", size);
|
||||
for (i=0; i<size; i++) {
|
||||
printf("%s\n", strings[i]);
|
||||
}
|
||||
free(strings);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
/*!
|
||||
\file evaluate.c
|
||||
\brief Various routines to evaluate classification performance
|
||||
|
||||
\author George
|
||||
\date 9/23/2008
|
||||
\version\verbatim $Id: evaluate.c 13328 2012-12-31 14:57:40Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
/**********************************************************************
|
||||
* This function computes the max accuracy score of a ranked list,
|
||||
* given +1/-1 class list
|
||||
**********************************************************************/
|
||||
float ComputeAccuracy(int n, gk_fkv_t *list)
|
||||
{
|
||||
int i, P, N, TP, FN = 0;
|
||||
float bAccuracy = 0.0;
|
||||
float acc;
|
||||
|
||||
for (P=0, i=0;i<n;i++)
|
||||
P += (list[i].val == 1? 1 : 0);
|
||||
N = n - P;
|
||||
|
||||
TP = FN = 0;
|
||||
|
||||
for(i=0; i<n; i++){
|
||||
if (list[i].val == 1)
|
||||
TP++;
|
||||
else
|
||||
FN++;
|
||||
|
||||
acc = (TP + N - FN) * 100.0/ (P + N) ;
|
||||
if (acc > bAccuracy)
|
||||
bAccuracy = acc;
|
||||
}
|
||||
|
||||
return bAccuracy;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* This function computes the ROC score of a ranked list, given a +1/-1 class
|
||||
* list.
|
||||
******************************************************************************/
|
||||
float ComputeROCn(int n, int maxN, gk_fkv_t *list)
|
||||
{
|
||||
int i, P, TP, FP, TPprev, FPprev, AUC;
|
||||
float prev;
|
||||
|
||||
FP = TP = FPprev = TPprev = AUC = 0;
|
||||
prev = list[0].key -1;
|
||||
|
||||
for (P=0, i=0; i<n; i++)
|
||||
P += (list[i].val == 1 ? 1 : 0);
|
||||
|
||||
for (i=0; i<n && FP < maxN; i++) {
|
||||
if (list[i].key != prev) {
|
||||
AUC += (TP+TPprev)*(FP-FPprev)/2;
|
||||
prev = list[i].key;
|
||||
FPprev = FP;
|
||||
TPprev = TP;
|
||||
}
|
||||
if (list[i].val == 1)
|
||||
TP++;
|
||||
else {
|
||||
FP++;
|
||||
}
|
||||
}
|
||||
AUC += (TP+TPprev)*(FP-FPprev)/2;
|
||||
|
||||
return (TP*FP > 0 ? (float)(1.0*AUC/(P*FP)) : 0.0);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* This function computes the median rate of false positive for each positive
|
||||
* instance.
|
||||
******************************************************************************/
|
||||
float ComputeMedianRFP(int n, gk_fkv_t *list)
|
||||
{
|
||||
int i, P, N, TP, FP;
|
||||
|
||||
P = N = 0;
|
||||
for (i=0; i<n; i++) {
|
||||
if (list[i].val == 1)
|
||||
P++;
|
||||
else
|
||||
N++;
|
||||
}
|
||||
|
||||
FP = TP = 0;
|
||||
for (i=0; i<n && TP < (P+1)/2; i++) {
|
||||
if (list[i].val == 1)
|
||||
TP++;
|
||||
else
|
||||
FP++;
|
||||
}
|
||||
|
||||
return 1.0*FP/N;
|
||||
}
|
||||
|
||||
/*********************************************************
|
||||
* Compute the mean
|
||||
********************************************************/
|
||||
float ComputeMean (int n, float *values)
|
||||
{
|
||||
int i;
|
||||
float mean = 0.0;
|
||||
|
||||
for(i=0; i < n; i++)
|
||||
mean += values[i];
|
||||
|
||||
return 1.0 * mean/ n;
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* Compute the standard deviation
|
||||
********************************************************/
|
||||
float ComputeStdDev(int n, float *values)
|
||||
{
|
||||
int i;
|
||||
float mean = ComputeMean(n, values);
|
||||
float stdDev = 0;
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
stdDev += (values[i] - mean)* (values[i] - mean);
|
||||
}
|
||||
|
||||
return sqrt(1.0 * stdDev/n);
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/*!
|
||||
\file dfkvkselect.c
|
||||
\brief Sorts only the largest k values
|
||||
|
||||
\date Started 7/14/00
|
||||
\author George
|
||||
\version\verbatim $Id: fkvkselect.c 10711 2011-08-31 22:23:04Z 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(size_t n, int topk, gk_fkv_t *cand)
|
||||
{
|
||||
int i, j, lo, hi, mid;
|
||||
gk_fkv_t stmp;
|
||||
float pivot;
|
||||
|
||||
if (n <= topk)
|
||||
return n; /* return if the array has fewer elements than we want */
|
||||
|
||||
for (lo=0, hi=n-1; lo < hi;) {
|
||||
mid = lo + ((hi-lo) >> 1);
|
||||
|
||||
/* select the median */
|
||||
if (cand[lo].key < cand[mid].key)
|
||||
mid = lo;
|
||||
if (cand[hi].key > cand[mid].key)
|
||||
mid = hi;
|
||||
else
|
||||
goto jump_over;
|
||||
if (cand[lo].key < cand[mid].key)
|
||||
mid = lo;
|
||||
|
||||
jump_over:
|
||||
QSSWAP(cand[mid], cand[hi], stmp);
|
||||
pivot = cand[hi].key;
|
||||
|
||||
/* the partitioning algorithm */
|
||||
for (i=lo-1, j=lo; j<hi; j++) {
|
||||
if (cand[j].key >= pivot) {
|
||||
i++;
|
||||
QSSWAP(cand[i], cand[j], stmp);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
QSSWAP(cand[i], cand[hi], stmp);
|
||||
|
||||
|
||||
if (i > topk)
|
||||
hi = i-1;
|
||||
else if (i < topk)
|
||||
lo = i+1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*! This function puts the 'topk' smallest values in the beginning of the array */
|
||||
/*******************************************************************************/
|
||||
int gk_ifkvkselect(size_t n, int topk, gk_fkv_t *cand)
|
||||
{
|
||||
int i, j, lo, hi, mid;
|
||||
gk_fkv_t stmp;
|
||||
float pivot;
|
||||
|
||||
if (n <= topk)
|
||||
return n; /* return if the array has fewer elements than we want */
|
||||
|
||||
for (lo=0, hi=n-1; lo < hi;) {
|
||||
mid = lo + ((hi-lo) >> 1);
|
||||
|
||||
/* select the median */
|
||||
if (cand[lo].key > cand[mid].key)
|
||||
mid = lo;
|
||||
if (cand[hi].key < cand[mid].key)
|
||||
mid = hi;
|
||||
else
|
||||
goto jump_over;
|
||||
if (cand[lo].key > cand[mid].key)
|
||||
mid = lo;
|
||||
|
||||
jump_over:
|
||||
QSSWAP(cand[mid], cand[hi], stmp);
|
||||
pivot = cand[hi].key;
|
||||
|
||||
/* the partitioning algorithm */
|
||||
for (i=lo-1, j=lo; j<hi; j++) {
|
||||
if (cand[j].key <= pivot) {
|
||||
i++;
|
||||
QSSWAP(cand[i], cand[j], stmp);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
QSSWAP(cand[i], cand[hi], stmp);
|
||||
|
||||
|
||||
if (i > topk)
|
||||
hi = i-1;
|
||||
else if (i < topk)
|
||||
lo = i+1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,225 +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 10711 2011-08-31 22:23:04Z 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.
|
||||
\param fname is the name of the file
|
||||
\param r_nlines is the number of lines in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
\param r_ntokens is the number of tokens in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
\param r_max_nlntokens is the maximum number of tokens in any line
|
||||
in the file. If it is NULL this information is not returned.
|
||||
\param r_nbytes is the number of bytes in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_getfilestats(char *fname, size_t *r_nlines, size_t *r_ntokens,
|
||||
size_t *r_max_nlntokens, size_t *r_nbytes)
|
||||
{
|
||||
size_t nlines=0, ntokens=0, max_nlntokens=0, nbytes=0, oldntokens=0, nread;
|
||||
int intoken=0;
|
||||
char buffer[2049], *cptr;
|
||||
FILE *fpin;
|
||||
|
||||
fpin = gk_fopen(fname, "r", "gk_GetFileStats");
|
||||
|
||||
while (!feof(fpin)) {
|
||||
nread = fread(buffer, sizeof(char), 2048, fpin);
|
||||
nbytes += nread;
|
||||
|
||||
buffer[nread] = '\0'; /* There is space for this one */
|
||||
for (cptr=buffer; *cptr!='\0'; cptr++) {
|
||||
if (*cptr == '\n') {
|
||||
nlines++;
|
||||
ntokens += intoken;
|
||||
intoken = 0;
|
||||
if (max_nlntokens < ntokens-oldntokens)
|
||||
max_nlntokens = ntokens-oldntokens;
|
||||
oldntokens = ntokens;
|
||||
}
|
||||
else if (*cptr == ' ' || *cptr == '\t') {
|
||||
ntokens += intoken;
|
||||
intoken = 0;
|
||||
}
|
||||
else {
|
||||
intoken = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ntokens += intoken;
|
||||
if (max_nlntokens < ntokens-oldntokens)
|
||||
max_nlntokens = ntokens-oldntokens;
|
||||
|
||||
gk_fclose(fpin);
|
||||
|
||||
if (r_nlines != NULL)
|
||||
*r_nlines = nlines;
|
||||
if (r_ntokens != NULL)
|
||||
*r_ntokens = ntokens;
|
||||
if (r_max_nlntokens != NULL)
|
||||
*r_max_nlntokens = max_nlntokens;
|
||||
if (r_nbytes != NULL)
|
||||
*r_nbytes = nbytes;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function takes in a potentially full path specification of a file
|
||||
* and just returns a string containing just the basename of the file.
|
||||
* The basename is derived from the actual filename by stripping the last
|
||||
* .ext part.
|
||||
**************************************************************************/
|
||||
char *gk_getbasename(char *path)
|
||||
{
|
||||
char *startptr, *endptr;
|
||||
char *basename;
|
||||
|
||||
if ((startptr = strrchr(path, '/')) == NULL)
|
||||
startptr = path;
|
||||
else
|
||||
startptr = startptr+1;
|
||||
|
||||
basename = gk_strdup(startptr);
|
||||
|
||||
if ((endptr = strrchr(basename, '.')) != NULL)
|
||||
*endptr = '\0';
|
||||
|
||||
return basename;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* This function takes in a potentially full path specification of a file
|
||||
* and just returns a string corresponding to its file extension. The
|
||||
* extension of a file is considered to be the string right after the
|
||||
* last '.' character.
|
||||
**************************************************************************/
|
||||
char *gk_getextname(char *path)
|
||||
{
|
||||
char *startptr;
|
||||
|
||||
if ((startptr = strrchr(path, '.')) == NULL)
|
||||
return gk_strdup(path);
|
||||
else
|
||||
return gk_strdup(startptr+1);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* This function takes in a potentially full path specification of a file
|
||||
* and just returns a string containing just the filename.
|
||||
**************************************************************************/
|
||||
char *gk_getfilename(char *path)
|
||||
{
|
||||
char *startptr;
|
||||
|
||||
if ((startptr = strrchr(path, '/')) == NULL)
|
||||
return gk_strdup(path);
|
||||
else
|
||||
return gk_strdup(startptr+1);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* This function takes in a potentially full path specification of a file
|
||||
* and extracts the directory path component if it exists, otherwise it
|
||||
* returns "./" as the path. The memory for it is dynamically allocated.
|
||||
**************************************************************************/
|
||||
char *getpathname(char *path)
|
||||
{
|
||||
char *endptr, *tmp;
|
||||
|
||||
if ((endptr = strrchr(path, '/')) == NULL) {
|
||||
return gk_strdup(".");
|
||||
}
|
||||
else {
|
||||
tmp = gk_strdup(path);
|
||||
*(strrchr(tmp, '/')) = '\0';
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function creates a path
|
||||
**************************************************************************/
|
||||
int gk_mkpath(char *pathname)
|
||||
{
|
||||
char tmp[2048];
|
||||
|
||||
sprintf(tmp, "mkdir -p %s", pathname);
|
||||
return system(tmp);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function deletes a directory tree and all of its contents
|
||||
**************************************************************************/
|
||||
int gk_rmpath(char *pathname)
|
||||
{
|
||||
char tmp[2048];
|
||||
|
||||
sprintf(tmp, "rm -r %s", pathname);
|
||||
return system(tmp);
|
||||
}
|
||||
|
|
@ -1,854 +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 char *gk_getopt_initialize (int, char **, char *);
|
||||
static int gk_getopt_internal(int argc, char **argv, char *optstring,
|
||||
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 char *gk_getopt_initialize (int argc, char **argv, 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.
|
||||
|
||||
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 **argv, char *optstring,
|
||||
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;
|
||||
struct gk_option *p;
|
||||
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;
|
||||
struct gk_option *p;
|
||||
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, 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 **argv, char *options,
|
||||
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 **argv, char *options,
|
||||
struct gk_option *long_options, int *opt_index)
|
||||
{
|
||||
return gk_getopt_internal(argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
|
|
@ -1,71 +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 10711 2011-08-31 22:23:04Z 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
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __MSC__
|
||||
#include "ms_stdint.h"
|
||||
#include "ms_inttypes.h"
|
||||
#include "ms_stat.h"
|
||||
#else
|
||||
#ifndef SUNOS
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Architecture-specific modifications
|
||||
**************************************************************************/
|
||||
#ifdef WIN32
|
||||
typedef ptrdiff_t ssize_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SUNOS
|
||||
#define PTRDIFF_MAX INT64_MAX
|
||||
#endif
|
||||
|
||||
#ifdef __MSC__
|
||||
/* MSC does not have rint() function */
|
||||
#define rint(x) ((int)((x)+0.5))
|
||||
|
||||
/* MSC does not have INFINITY defined */
|
||||
#ifndef INFINITY
|
||||
#define INFINITY FLT_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,69 +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 12732 2012-09-24 20:54:50Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _GK_DEFS_H_
|
||||
#define _GK_DEFS_H_
|
||||
|
||||
|
||||
#define LTERM (void **) 0 /* List terminator for GKfree() */
|
||||
|
||||
/* mopt_t types */
|
||||
#define GK_MOPT_MARK 1
|
||||
#define GK_MOPT_CORE 2
|
||||
#define GK_MOPT_HEAP 3
|
||||
|
||||
#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
|
||||
|
||||
/* GKlib signals to standard signal mapping */
|
||||
#define SIGMEM SIGABRT
|
||||
#define SIGERR SIGTERM
|
||||
|
||||
|
||||
/* CSR-related defines */
|
||||
#define GK_CSR_ROW 1
|
||||
#define GK_CSR_COL 2
|
||||
|
||||
#define GK_CSR_MAXTF 1
|
||||
#define GK_CSR_SQRT 2
|
||||
#define GK_CSR_POW25 3
|
||||
#define GK_CSR_POW65 4
|
||||
#define GK_CSR_POW75 5
|
||||
#define GK_CSR_POW85 6
|
||||
#define GK_CSR_LOG 7
|
||||
#define GK_CSR_IDF 8
|
||||
#define GK_CSR_IDF2 9
|
||||
#define GK_CSR_MAXTF2 10
|
||||
|
||||
#define GK_CSR_COS 1
|
||||
#define GK_CSR_JAC 2
|
||||
#define GK_CSR_MIN 3
|
||||
#define GK_CSR_AMIN 4
|
||||
|
||||
#define GK_CSR_FMT_CLUTO 1
|
||||
#define GK_CSR_FMT_CSR 2
|
||||
#define GK_CSR_FMT_METIS 3
|
||||
#define GK_CSR_FMT_BINROW 4
|
||||
#define GK_CSR_FMT_BINCOL 5
|
||||
|
||||
#define GK_GRAPH_FMT_METIS 1
|
||||
|
||||
#endif
|
||||
|
|
@ -1,25 +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 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _GK_EXTERNS_H_
|
||||
#define _GK_EXTERNS_H_
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Extern variable definition. Hopefully, the __thread makes them thread-safe.
|
||||
**************************************************************************/
|
||||
#ifndef _GK_ERROR_C_
|
||||
/* declared in error.c */
|
||||
extern __thread int gk_cur_jbufs;
|
||||
extern __thread jmp_buf gk_jbufs[];
|
||||
extern __thread jmp_buf gk_jbuf;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,64 +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 10711 2011-08-31 22:23:04Z 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 {
|
||||
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.
|
||||
*/
|
||||
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, char *__shortopts);
|
||||
extern int gk_getopt_long(int __argc, char **__argv, char *__shortopts,
|
||||
struct gk_option *__longopts, int *__longind);
|
||||
extern int gk_getopt_long_only (int __argc, char **__argv,
|
||||
char *__shortopts, struct gk_option *__longopts, int *__longind);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,153 +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 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _GK_MACROS_H_
|
||||
#define _GK_MACROS_H_
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* Usefull commands
|
||||
*-------------------------------------------------------------*/
|
||||
#define gk_max(a, b) ((a) >= (b) ? (a) : (b))
|
||||
#define gk_min(a, b) ((a) >= (b) ? (b) : (a))
|
||||
#define gk_max3(a, b, c) ((a) >= (b) && (a) >= (c) ? (a) : ((b) >= (a) && (b) >= (c) ? (b) : (c)))
|
||||
#define gk_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 sign(a, b) ((a >= 0 ? b : -b))
|
||||
|
||||
#define ONEOVERRANDMAX (1.0/(RAND_MAX+1.0))
|
||||
#define RandomInRange(u) ((int) (ONEOVERRANDMAX*(u)*rand()))
|
||||
|
||||
#define gk_abs(x) ((x) >= 0 ? (x) : -(x))
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* 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))
|
||||
#define gk_sigcatch() (setjmp(gk_jbufs[gk_cur_jbufs]))
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* 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)
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* ASSERTS that cannot be turned off!
|
||||
*-------------------------------------------------------------*/
|
||||
#define GKASSERT(expr) \
|
||||
if (!(expr)) { \
|
||||
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
|
||||
__LINE__, __FILE__); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define GKASSERTP(expr,msg) \
|
||||
if (!(expr)) { \
|
||||
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
|
||||
__LINE__, __FILE__); \
|
||||
printf msg ; \
|
||||
printf("\n"); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define GKCUASSERT(expr) \
|
||||
if (!(expr)) { \
|
||||
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
|
||||
__LINE__, __FILE__); \
|
||||
}
|
||||
|
||||
#define GKCUASSERTP(expr,msg) \
|
||||
if (!(expr)) { \
|
||||
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
|
||||
__LINE__, __FILE__); \
|
||||
printf msg ; \
|
||||
printf("\n"); \
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* Program Assertions
|
||||
*-------------------------------------------------------------*/
|
||||
#ifndef NDEBUG
|
||||
# define ASSERT(expr) \
|
||||
if (!(expr)) { \
|
||||
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
|
||||
__LINE__, __FILE__); \
|
||||
assert(expr); \
|
||||
}
|
||||
|
||||
# define ASSERTP(expr,msg) \
|
||||
if (!(expr)) { \
|
||||
printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \
|
||||
__LINE__, __FILE__); \
|
||||
printf msg ; \
|
||||
printf("\n"); \
|
||||
assert(expr); \
|
||||
}
|
||||
#else
|
||||
# define ASSERT(expr) ;
|
||||
# define ASSERTP(expr,msg) ;
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG2
|
||||
# define ASSERT2 ASSERT
|
||||
# define ASSERTP2 ASSERTP
|
||||
#else
|
||||
# define ASSERT2(expr) ;
|
||||
# define ASSERTP2(expr,msg) ;
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
/*!
|
||||
\file gk_mkblas.h
|
||||
\brief Templates for BLAS-like routines
|
||||
|
||||
\date Started 3/28/07
|
||||
\author George
|
||||
\version\verbatim $Id: gk_mkblas.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _GK_MKBLAS_H_
|
||||
#define _GK_MKBLAS_H_
|
||||
|
||||
|
||||
#define GK_MKBLAS(PRFX, TYPE, OUTTYPE) \
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?incset()-class of routines */\
|
||||
/*************************************************************************/\
|
||||
TYPE *PRFX ## incset(size_t n, TYPE baseval, TYPE *x)\
|
||||
{\
|
||||
size_t i;\
|
||||
\
|
||||
for (i=0; i<n; i++)\
|
||||
x[i] = baseval+i;\
|
||||
\
|
||||
return x;\
|
||||
}\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?max()-class of routines */\
|
||||
/*************************************************************************/\
|
||||
TYPE PRFX ## max(size_t n, TYPE *x)\
|
||||
{\
|
||||
size_t i, max=0; \
|
||||
\
|
||||
if (n <= 0) return (TYPE) 0;\
|
||||
\
|
||||
for (i=1; i<n; i++)\
|
||||
max = (x[i] > x[max] ? i : max);\
|
||||
\
|
||||
return x[max];\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?min()-class of routines */\
|
||||
/*************************************************************************/\
|
||||
TYPE PRFX ## min(size_t n, TYPE *x)\
|
||||
{\
|
||||
size_t i, min=0;\
|
||||
\
|
||||
if (n <= 0) return (TYPE) 0;\
|
||||
\
|
||||
for (i=1; i<n; i++)\
|
||||
min = (x[i] < x[min] ? i : min);\
|
||||
\
|
||||
return x[min];\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?argmax()-class of routines */\
|
||||
/*************************************************************************/\
|
||||
size_t PRFX ## argmax(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;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?argmin()-class of routines */\
|
||||
/*************************************************************************/\
|
||||
size_t PRFX ## argmin(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;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?argmax_n()-class of routines */\
|
||||
/*************************************************************************/\
|
||||
size_t PRFX ## argmax_n(size_t n, TYPE *x, size_t k)\
|
||||
{\
|
||||
size_t i, max_n;\
|
||||
PRFX ## kv_t *cand;\
|
||||
\
|
||||
cand = PRFX ## kvmalloc(n, "GK_ARGMAX_N: cand");\
|
||||
\
|
||||
for (i=0; i<n; i++) {\
|
||||
cand[i].val = i;\
|
||||
cand[i].key = x[i];\
|
||||
}\
|
||||
PRFX ## kvsortd(n, cand);\
|
||||
\
|
||||
max_n = cand[k-1].val;\
|
||||
\
|
||||
gk_free((void *)&cand, LTERM);\
|
||||
\
|
||||
return max_n;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?sum()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
OUTTYPE PRFX ## sum(size_t n, TYPE *x, size_t incx)\
|
||||
{\
|
||||
size_t i;\
|
||||
OUTTYPE sum = 0;\
|
||||
\
|
||||
for (i=0; i<n; i++, x+=incx)\
|
||||
sum += (*x);\
|
||||
\
|
||||
return sum;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?scale()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
TYPE *PRFX ## scale(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;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?norm2()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
OUTTYPE PRFX ## norm2(size_t n, TYPE *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) : (OUTTYPE)0);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?dot()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
OUTTYPE PRFX ## dot(size_t n, TYPE *x, size_t incx, TYPE *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;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?axpy()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
TYPE *PRFX ## axpy(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_MKBLAS_PROTO(PRFX, TYPE, OUTTYPE) \
|
||||
TYPE *PRFX ## incset(size_t n, TYPE baseval, TYPE *x);\
|
||||
TYPE PRFX ## max(size_t n, TYPE *x);\
|
||||
TYPE PRFX ## min(size_t n, TYPE *x);\
|
||||
size_t PRFX ## argmax(size_t n, TYPE *x);\
|
||||
size_t PRFX ## argmin(size_t n, TYPE *x);\
|
||||
size_t PRFX ## argmax_n(size_t n, TYPE *x, size_t k);\
|
||||
OUTTYPE PRFX ## sum(size_t n, TYPE *x, size_t incx);\
|
||||
TYPE *PRFX ## scale(size_t n, TYPE alpha, TYPE *x, size_t incx);\
|
||||
OUTTYPE PRFX ## norm2(size_t n, TYPE *x, size_t incx);\
|
||||
OUTTYPE PRFX ## dot(size_t n, TYPE *x, size_t incx, TYPE *y, size_t incy);\
|
||||
TYPE *PRFX ## axpy(size_t n, TYPE alpha, TYPE *x, size_t incx, TYPE *y, size_t incy);\
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/*!
|
||||
\file gk_mkmemory.h
|
||||
\brief Templates for memory allocation routines
|
||||
|
||||
\date Started 3/29/07
|
||||
\author George
|
||||
\version\verbatim $Id: gk_mkmemory.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _GK_MKMEMORY_H_
|
||||
#define _GK_MKMEMORY_H_
|
||||
|
||||
|
||||
#define GK_MKALLOC(PRFX, TYPE)\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?malloc()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
TYPE *PRFX ## malloc(size_t n, char *msg)\
|
||||
{\
|
||||
return (TYPE *)gk_malloc(sizeof(TYPE)*n, msg);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?realloc()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
TYPE *PRFX ## realloc(TYPE *ptr, size_t n, char *msg)\
|
||||
{\
|
||||
return (TYPE *)gk_realloc((void *)ptr, sizeof(TYPE)*n, msg);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?smalloc()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
TYPE *PRFX ## smalloc(size_t n, TYPE ival, char *msg)\
|
||||
{\
|
||||
TYPE *ptr;\
|
||||
\
|
||||
ptr = (TYPE *)gk_malloc(sizeof(TYPE)*n, msg);\
|
||||
if (ptr == NULL) \
|
||||
return NULL; \
|
||||
\
|
||||
return PRFX ## set(n, ival, ptr); \
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?set()-class of routines */\
|
||||
/*************************************************************************/\
|
||||
TYPE *PRFX ## set(size_t n, TYPE val, TYPE *x)\
|
||||
{\
|
||||
size_t i;\
|
||||
\
|
||||
for (i=0; i<n; i++)\
|
||||
x[i] = val;\
|
||||
\
|
||||
return x;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?set()-class of routines */\
|
||||
/*************************************************************************/\
|
||||
TYPE *PRFX ## copy(size_t n, TYPE *a, TYPE *b)\
|
||||
{\
|
||||
return (TYPE *)memmove((void *)b, (void *)a, sizeof(TYPE)*n);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?AllocMatrix()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
TYPE **PRFX ## AllocMatrix(size_t ndim1, size_t ndim2, TYPE value, char *errmsg)\
|
||||
{\
|
||||
gk_idx_t i, j;\
|
||||
TYPE **matrix;\
|
||||
\
|
||||
matrix = (TYPE **)gk_malloc(ndim1*sizeof(TYPE *), errmsg);\
|
||||
if (matrix == NULL) \
|
||||
return NULL;\
|
||||
\
|
||||
for (i=0; i<ndim1; i++) { \
|
||||
matrix[i] = PRFX ## smalloc(ndim2, value, errmsg);\
|
||||
if (matrix[i] == NULL) { \
|
||||
for (j=0; j<i; j++) \
|
||||
gk_free((void **)&matrix[j], LTERM); \
|
||||
return NULL; \
|
||||
} \
|
||||
}\
|
||||
\
|
||||
return matrix;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?AllocMatrix()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
void PRFX ## FreeMatrix(TYPE ***r_matrix, size_t ndim1, size_t ndim2)\
|
||||
{\
|
||||
gk_idx_t i;\
|
||||
TYPE **matrix;\
|
||||
\
|
||||
if (*r_matrix == NULL) \
|
||||
return; \
|
||||
\
|
||||
matrix = *r_matrix;\
|
||||
\
|
||||
for (i=0; i<ndim1; i++) \
|
||||
gk_free((void **)&(matrix[i]), LTERM);\
|
||||
\
|
||||
gk_free((void **)r_matrix, LTERM);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?SetMatrix()-class of routines */\
|
||||
/**************************************************************************/\
|
||||
void PRFX ## SetMatrix(TYPE **matrix, size_t ndim1, size_t ndim2, TYPE value)\
|
||||
{\
|
||||
gk_idx_t i, j;\
|
||||
\
|
||||
for (i=0; i<ndim1; i++) {\
|
||||
for (j=0; j<ndim2; j++)\
|
||||
matrix[i][j] = value;\
|
||||
}\
|
||||
}\
|
||||
|
||||
|
||||
#define GK_MKALLOC_PROTO(PRFX, TYPE)\
|
||||
TYPE *PRFX ## malloc(size_t n, char *msg);\
|
||||
TYPE *PRFX ## realloc(TYPE *ptr, size_t n, char *msg);\
|
||||
TYPE *PRFX ## smalloc(size_t n, TYPE ival, char *msg);\
|
||||
TYPE *PRFX ## set(size_t n, TYPE val, TYPE *x);\
|
||||
TYPE *PRFX ## copy(size_t n, TYPE *a, TYPE *b);\
|
||||
TYPE **PRFX ## AllocMatrix(size_t ndim1, size_t ndim2, TYPE value, char *errmsg);\
|
||||
void PRFX ## FreeMatrix(TYPE ***r_matrix, size_t ndim1, size_t ndim2);\
|
||||
void PRFX ## SetMatrix(TYPE **matrix, size_t ndim1, size_t ndim2, TYPE value);\
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,437 +0,0 @@
|
|||
/*!
|
||||
\file gk_mkpqueue.h
|
||||
\brief Templates for priority queues
|
||||
|
||||
\date Started 4/09/07
|
||||
\author George
|
||||
\version\verbatim $Id: gk_mkpqueue.h 13005 2012-10-23 22:34:36Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GK_MKPQUEUE_H
|
||||
#define _GK_MKPQUEUE_H
|
||||
|
||||
|
||||
#define GK_MKPQUEUE(FPRFX, PQT, KVT, KT, VT, KVMALLOC, KMAX, KEY_LT)\
|
||||
/*************************************************************************/\
|
||||
/*! This function creates and initializes a priority queue */\
|
||||
/**************************************************************************/\
|
||||
PQT *FPRFX ## Create(size_t maxnodes)\
|
||||
{\
|
||||
PQT *queue; \
|
||||
\
|
||||
queue = (PQT *)gk_malloc(sizeof(PQT), "gk_pqCreate: queue");\
|
||||
FPRFX ## Init(queue, maxnodes);\
|
||||
\
|
||||
return queue;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function initializes the data structures of the priority queue */\
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## Init(PQT *queue, size_t maxnodes)\
|
||||
{\
|
||||
queue->nnodes = 0;\
|
||||
queue->maxnodes = maxnodes;\
|
||||
\
|
||||
queue->heap = KVMALLOC(maxnodes, "gk_PQInit: heap");\
|
||||
queue->locator = gk_idxsmalloc(maxnodes, -1, "gk_PQInit: locator");\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function resets the priority queue */\
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## Reset(PQT *queue)\
|
||||
{\
|
||||
gk_idx_t i;\
|
||||
gk_idx_t *locator=queue->locator;\
|
||||
KVT *heap=queue->heap;\
|
||||
\
|
||||
for (i=queue->nnodes-1; i>=0; i--)\
|
||||
locator[heap[i].val] = -1;\
|
||||
queue->nnodes = 0;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function frees the internal datastructures of the priority queue */\
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## Free(PQT *queue)\
|
||||
{\
|
||||
if (queue == NULL) return;\
|
||||
gk_free((void **)&queue->heap, &queue->locator, LTERM);\
|
||||
queue->maxnodes = 0;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function frees the internal datastructures of the priority queue \
|
||||
and the queue itself */\
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## Destroy(PQT *queue)\
|
||||
{\
|
||||
if (queue == NULL) return;\
|
||||
FPRFX ## Free(queue);\
|
||||
gk_free((void **)&queue, LTERM);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the length of the queue */\
|
||||
/**************************************************************************/\
|
||||
size_t FPRFX ## Length(PQT *queue)\
|
||||
{\
|
||||
return queue->nnodes;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function adds an item in the priority queue */\
|
||||
/**************************************************************************/\
|
||||
int FPRFX ## Insert(PQT *queue, VT node, KT key)\
|
||||
{\
|
||||
gk_idx_t i, j;\
|
||||
gk_idx_t *locator=queue->locator;\
|
||||
KVT *heap=queue->heap;\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap(queue));\
|
||||
\
|
||||
ASSERT(locator[node] == -1);\
|
||||
\
|
||||
i = queue->nnodes++;\
|
||||
while (i > 0) {\
|
||||
j = (i-1)>>1;\
|
||||
if (KEY_LT(key, heap[j].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;\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap(queue));\
|
||||
\
|
||||
return 0;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function deletes an item from the priority queue */\
|
||||
/**************************************************************************/\
|
||||
int FPRFX ## Delete(PQT *queue, VT node)\
|
||||
{\
|
||||
gk_idx_t i, j, nnodes;\
|
||||
KT newkey, oldkey;\
|
||||
gk_idx_t *locator=queue->locator;\
|
||||
KVT *heap=queue->heap;\
|
||||
\
|
||||
ASSERT(locator[node] != -1);\
|
||||
ASSERT(heap[locator[node]].val == node);\
|
||||
\
|
||||
ASSERT2(FPRFX ## 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 (KEY_LT(newkey, oldkey)) { /* Filter-up */\
|
||||
while (i > 0) {\
|
||||
j = (i-1)>>1;\
|
||||
if (KEY_LT(newkey, heap[j].key)) {\
|
||||
heap[i] = heap[j];\
|
||||
locator[heap[i].val] = i;\
|
||||
i = j;\
|
||||
}\
|
||||
else\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
else { /* Filter down */\
|
||||
nnodes = queue->nnodes;\
|
||||
while ((j=(i<<1)+1) < nnodes) {\
|
||||
if (KEY_LT(heap[j].key, newkey)) {\
|
||||
if (j+1 < nnodes && KEY_LT(heap[j+1].key, heap[j].key))\
|
||||
j++;\
|
||||
heap[i] = heap[j];\
|
||||
locator[heap[i].val] = i;\
|
||||
i = j;\
|
||||
}\
|
||||
else if (j+1 < nnodes && KEY_LT(heap[j+1].key, newkey)) {\
|
||||
j++;\
|
||||
heap[i] = heap[j];\
|
||||
locator[heap[i].val] = i;\
|
||||
i = j;\
|
||||
}\
|
||||
else\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
heap[i].key = newkey;\
|
||||
heap[i].val = node;\
|
||||
locator[node] = i;\
|
||||
}\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap(queue));\
|
||||
\
|
||||
return 0;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function updates the key values associated for a particular item */ \
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## Update(PQT *queue, VT node, KT newkey)\
|
||||
{\
|
||||
gk_idx_t i, j, nnodes;\
|
||||
KT oldkey;\
|
||||
gk_idx_t *locator=queue->locator;\
|
||||
KVT *heap=queue->heap;\
|
||||
\
|
||||
oldkey = heap[locator[node]].key;\
|
||||
\
|
||||
ASSERT(locator[node] != -1);\
|
||||
ASSERT(heap[locator[node]].val == node);\
|
||||
ASSERT2(FPRFX ## CheckHeap(queue));\
|
||||
\
|
||||
i = locator[node];\
|
||||
\
|
||||
if (KEY_LT(newkey, oldkey)) { /* Filter-up */\
|
||||
while (i > 0) {\
|
||||
j = (i-1)>>1;\
|
||||
if (KEY_LT(newkey, heap[j].key)) {\
|
||||
heap[i] = heap[j];\
|
||||
locator[heap[i].val] = i;\
|
||||
i = j;\
|
||||
}\
|
||||
else\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
else { /* Filter down */\
|
||||
nnodes = queue->nnodes;\
|
||||
while ((j=(i<<1)+1) < nnodes) {\
|
||||
if (KEY_LT(heap[j].key, newkey)) {\
|
||||
if (j+1 < nnodes && KEY_LT(heap[j+1].key, heap[j].key))\
|
||||
j++;\
|
||||
heap[i] = heap[j];\
|
||||
locator[heap[i].val] = i;\
|
||||
i = j;\
|
||||
}\
|
||||
else if (j+1 < nnodes && KEY_LT(heap[j+1].key, newkey)) {\
|
||||
j++;\
|
||||
heap[i] = heap[j];\
|
||||
locator[heap[i].val] = i;\
|
||||
i = j;\
|
||||
}\
|
||||
else\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
heap[i].key = newkey;\
|
||||
heap[i].val = node;\
|
||||
locator[node] = i;\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap(queue));\
|
||||
\
|
||||
return;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the item at the top of the queue and removes\
|
||||
it from the priority queue */\
|
||||
/**************************************************************************/\
|
||||
VT FPRFX ## GetTop(PQT *queue)\
|
||||
{\
|
||||
gk_idx_t i, j;\
|
||||
gk_idx_t *locator;\
|
||||
KVT *heap;\
|
||||
VT vtx, node;\
|
||||
KT key;\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap(queue));\
|
||||
\
|
||||
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 (KEY_LT(heap[j].key, key)) {\
|
||||
if (j+1 < queue->nnodes && KEY_LT(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 && KEY_LT(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;\
|
||||
}\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap(queue));\
|
||||
return vtx;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the item at the top of the queue. The item is not\
|
||||
deleted from the queue. */\
|
||||
/**************************************************************************/\
|
||||
VT FPRFX ## SeeTopVal(PQT *queue)\
|
||||
{\
|
||||
return (queue->nnodes == 0 ? -1 : queue->heap[0].val);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the key of the top item. The item is not\
|
||||
deleted from the queue. */\
|
||||
/**************************************************************************/\
|
||||
KT FPRFX ## SeeTopKey(PQT *queue)\
|
||||
{\
|
||||
return (queue->nnodes == 0 ? KMAX : queue->heap[0].key);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the key of a specific item */\
|
||||
/**************************************************************************/\
|
||||
KT FPRFX ## SeeKey(PQT *queue, VT node)\
|
||||
{\
|
||||
gk_idx_t *locator;\
|
||||
KVT *heap;\
|
||||
\
|
||||
heap = queue->heap;\
|
||||
locator = queue->locator;\
|
||||
\
|
||||
return heap[locator[node]].key;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the first item in a breadth-first traversal of\
|
||||
the heap whose key is less than maxwgt. This function is here due to\
|
||||
hMETIS and is not general!*/\
|
||||
/**************************************************************************/\
|
||||
/*\
|
||||
VT FPRFX ## SeeConstraintTop(PQT *queue, KT maxwgt, KT *wgts)\
|
||||
{\
|
||||
gk_idx_t i;\
|
||||
\
|
||||
if (queue->nnodes == 0)\
|
||||
return -1;\
|
||||
\
|
||||
if (maxwgt <= 1000)\
|
||||
return FPRFX ## SeeTopVal(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 functions checks the consistency of the heap */\
|
||||
/**************************************************************************/\
|
||||
int FPRFX ## CheckHeap(PQT *queue)\
|
||||
{\
|
||||
gk_idx_t i, j;\
|
||||
size_t nnodes;\
|
||||
gk_idx_t *locator;\
|
||||
KVT *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++) {\
|
||||
ASSERT(locator[heap[i].val] == i);\
|
||||
ASSERT(!KEY_LT(heap[i].key, heap[(i-1)/2].key));\
|
||||
}\
|
||||
for (i=1; i<nnodes; i++)\
|
||||
ASSERT(!KEY_LT(heap[i].key, heap[0].key));\
|
||||
\
|
||||
for (j=i=0; i<queue->maxnodes; i++) {\
|
||||
if (locator[i] != -1)\
|
||||
j++;\
|
||||
}\
|
||||
ASSERTP(j == nnodes, ("%jd %jd\n", (intmax_t)j, (intmax_t)nnodes));\
|
||||
\
|
||||
return 1;\
|
||||
}\
|
||||
|
||||
|
||||
#define GK_MKPQUEUE_PROTO(FPRFX, PQT, KT, VT)\
|
||||
PQT * FPRFX ## Create(size_t maxnodes);\
|
||||
void FPRFX ## Init(PQT *queue, size_t maxnodes);\
|
||||
void FPRFX ## Reset(PQT *queue);\
|
||||
void FPRFX ## Free(PQT *queue);\
|
||||
void FPRFX ## Destroy(PQT *queue);\
|
||||
size_t FPRFX ## Length(PQT *queue);\
|
||||
int FPRFX ## Insert(PQT *queue, VT node, KT key);\
|
||||
int FPRFX ## Delete(PQT *queue, VT node);\
|
||||
void FPRFX ## Update(PQT *queue, VT node, KT newkey);\
|
||||
VT FPRFX ## GetTop(PQT *queue);\
|
||||
VT FPRFX ## SeeTopVal(PQT *queue);\
|
||||
KT FPRFX ## SeeTopKey(PQT *queue);\
|
||||
KT FPRFX ## SeeKey(PQT *queue, VT node);\
|
||||
VT FPRFX ## SeeConstraintTop(PQT *queue, KT maxwgt, KT *wgts);\
|
||||
int FPRFX ## CheckHeap(PQT *queue);\
|
||||
|
||||
|
||||
/* This is how these macros are used
|
||||
GK_MKPQUEUE(gk_dkvPQ, gk_dkvPQ_t, double, gk_idx_t, gk_dkvmalloc, DBL_MAX)
|
||||
GK_MKPQUEUE_PROTO(gk_dkvPQ, gk_dkvPQ_t, double, gk_idx_t)
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
/*!
|
||||
\file gk_mkpqueue2.h
|
||||
\brief Templates for priority queues that do not utilize locators and as such
|
||||
they can use different types of values.
|
||||
|
||||
\date Started 4/09/07
|
||||
\author George
|
||||
\version\verbatim $Id: gk_mkpqueue2.h 13005 2012-10-23 22:34:36Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GK_MKPQUEUE2_H
|
||||
#define _GK_MKPQUEUE2_H
|
||||
|
||||
|
||||
#define GK_MKPQUEUE2(FPRFX, PQT, KT, VT, KMALLOC, VMALLOC, KMAX, KEY_LT)\
|
||||
/*************************************************************************/\
|
||||
/*! This function creates and initializes a priority queue */\
|
||||
/**************************************************************************/\
|
||||
PQT *FPRFX ## Create2(ssize_t maxnodes)\
|
||||
{\
|
||||
PQT *queue; \
|
||||
\
|
||||
if ((queue = (PQT *)gk_malloc(sizeof(PQT), "gk_pqCreate2: queue")) != NULL) {\
|
||||
memset(queue, 0, sizeof(PQT));\
|
||||
queue->nnodes = 0;\
|
||||
queue->maxnodes = maxnodes;\
|
||||
queue->keys = KMALLOC(maxnodes, "gk_pqCreate2: keys");\
|
||||
queue->vals = VMALLOC(maxnodes, "gk_pqCreate2: vals");\
|
||||
\
|
||||
if (queue->keys == NULL || queue->vals == NULL)\
|
||||
gk_free((void **)&queue->keys, &queue->vals, &queue, LTERM);\
|
||||
}\
|
||||
\
|
||||
return queue;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function resets the priority queue */\
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## Reset2(PQT *queue)\
|
||||
{\
|
||||
queue->nnodes = 0;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function frees the internal datastructures of the priority queue */\
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## Destroy2(PQT **r_queue)\
|
||||
{\
|
||||
PQT *queue = *r_queue; \
|
||||
if (queue == NULL) return;\
|
||||
gk_free((void **)&queue->keys, &queue->vals, &queue, LTERM);\
|
||||
*r_queue = NULL;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the length of the queue */\
|
||||
/**************************************************************************/\
|
||||
size_t FPRFX ## Length2(PQT *queue)\
|
||||
{\
|
||||
return queue->nnodes;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function adds an item in the priority queue. */\
|
||||
/**************************************************************************/\
|
||||
int FPRFX ## Insert2(PQT *queue, VT val, KT key)\
|
||||
{\
|
||||
ssize_t i, j;\
|
||||
KT *keys=queue->keys;\
|
||||
VT *vals=queue->vals;\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap2(queue));\
|
||||
\
|
||||
if (queue->nnodes == queue->maxnodes) \
|
||||
return 0;\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap2(queue));\
|
||||
\
|
||||
i = queue->nnodes++;\
|
||||
while (i > 0) {\
|
||||
j = (i-1)>>1;\
|
||||
if (KEY_LT(key, keys[j])) {\
|
||||
keys[i] = keys[j];\
|
||||
vals[i] = vals[j];\
|
||||
i = j;\
|
||||
}\
|
||||
else\
|
||||
break;\
|
||||
}\
|
||||
ASSERT(i >= 0);\
|
||||
keys[i] = key;\
|
||||
vals[i] = val;\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap2(queue));\
|
||||
\
|
||||
return 1;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the item at the top of the queue and removes\
|
||||
it from the priority queue */\
|
||||
/**************************************************************************/\
|
||||
int FPRFX ## GetTop2(PQT *queue, VT *r_val)\
|
||||
{\
|
||||
ssize_t i, j;\
|
||||
KT key, *keys=queue->keys;\
|
||||
VT val, *vals=queue->vals;\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap2(queue));\
|
||||
\
|
||||
if (queue->nnodes == 0)\
|
||||
return 0;\
|
||||
\
|
||||
queue->nnodes--;\
|
||||
\
|
||||
*r_val = vals[0];\
|
||||
\
|
||||
if ((i = queue->nnodes) > 0) {\
|
||||
key = keys[i];\
|
||||
val = vals[i];\
|
||||
i = 0;\
|
||||
while ((j=2*i+1) < queue->nnodes) {\
|
||||
if (KEY_LT(keys[j], key)) {\
|
||||
if (j+1 < queue->nnodes && KEY_LT(keys[j+1], keys[j]))\
|
||||
j = j+1;\
|
||||
keys[i] = keys[j];\
|
||||
vals[i] = vals[j];\
|
||||
i = j;\
|
||||
}\
|
||||
else if (j+1 < queue->nnodes && KEY_LT(keys[j+1], key)) {\
|
||||
j = j+1;\
|
||||
keys[i] = keys[j];\
|
||||
vals[i] = vals[j];\
|
||||
i = j;\
|
||||
}\
|
||||
else\
|
||||
break;\
|
||||
}\
|
||||
\
|
||||
keys[i] = key;\
|
||||
vals[i] = val;\
|
||||
}\
|
||||
\
|
||||
ASSERT2(FPRFX ## CheckHeap2(queue));\
|
||||
\
|
||||
return 1;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the item at the top of the queue. The item is not\
|
||||
deleted from the queue. */\
|
||||
/**************************************************************************/\
|
||||
int FPRFX ## SeeTopVal2(PQT *queue, VT *r_val)\
|
||||
{\
|
||||
if (queue->nnodes == 0) \
|
||||
return 0;\
|
||||
\
|
||||
*r_val = queue->vals[0];\
|
||||
\
|
||||
return 1;\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This function returns the key of the top item. The item is not\
|
||||
deleted from the queue. */\
|
||||
/**************************************************************************/\
|
||||
KT FPRFX ## SeeTopKey2(PQT *queue)\
|
||||
{\
|
||||
return (queue->nnodes == 0 ? KMAX : queue->keys[0]);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! This functions checks the consistency of the heap */\
|
||||
/**************************************************************************/\
|
||||
int FPRFX ## CheckHeap2(PQT *queue)\
|
||||
{\
|
||||
ssize_t i;\
|
||||
KT *keys=queue->keys;\
|
||||
\
|
||||
if (queue->nnodes == 0)\
|
||||
return 1;\
|
||||
\
|
||||
for (i=1; i<queue->nnodes; i++) {\
|
||||
ASSERT(!KEY_LT(keys[i], keys[(i-1)/2]));\
|
||||
}\
|
||||
for (i=1; i<queue->nnodes; i++)\
|
||||
ASSERT(!KEY_LT(keys[i], keys[0]));\
|
||||
\
|
||||
return 1;\
|
||||
}\
|
||||
|
||||
|
||||
#define GK_MKPQUEUE2_PROTO(FPRFX, PQT, KT, VT)\
|
||||
PQT * FPRFX ## Create2(ssize_t maxnodes);\
|
||||
void FPRFX ## Reset2(PQT *queue);\
|
||||
void FPRFX ## Destroy2(PQT **r_queue);\
|
||||
size_t FPRFX ## Length2(PQT *queue);\
|
||||
int FPRFX ## Insert2(PQT *queue, VT node, KT key);\
|
||||
int FPRFX ## GetTop2(PQT *queue, VT *r_val);\
|
||||
int FPRFX ## SeeTopVal2(PQT *queue, VT *r_val);\
|
||||
KT FPRFX ## SeeTopKey2(PQT *queue);\
|
||||
int FPRFX ## CheckHeap2(PQT *queue);\
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Templates for portable random number generation
|
||||
|
||||
\date Started 5/17/07
|
||||
\author George
|
||||
\version\verbatim $Id: gk_mkrandom.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GK_MKRANDOM_H
|
||||
#define _GK_MKRANDOM_H
|
||||
|
||||
/*************************************************************************/\
|
||||
/*! The generator for the rand() related routines. \
|
||||
\params RNGT the datatype that defines the range of values over which\
|
||||
random numbers will be generated\
|
||||
\params VALT the datatype that defines the contents of the array to \
|
||||
be permuted by randArrayPermute() \
|
||||
\params FPRFX the function prefix \
|
||||
*/\
|
||||
/**************************************************************************/\
|
||||
#define GK_MKRANDOM(FPRFX, RNGT, VALT)\
|
||||
/*************************************************************************/\
|
||||
/*! Initializes the generator */ \
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## srand(RNGT seed) \
|
||||
{\
|
||||
gk_randinit((uint64_t) seed);\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! Returns a random number */ \
|
||||
/**************************************************************************/\
|
||||
RNGT FPRFX ## rand() \
|
||||
{\
|
||||
if (sizeof(RNGT) <= sizeof(int32_t)) \
|
||||
return (RNGT)gk_randint32(); \
|
||||
else \
|
||||
return (RNGT)gk_randint64(); \
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! Returns a random number between [0, max) */ \
|
||||
/**************************************************************************/\
|
||||
RNGT FPRFX ## randInRange(RNGT max) \
|
||||
{\
|
||||
return (RNGT)((FPRFX ## rand())%max); \
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! Randomly permutes the elements of an array p[]. \
|
||||
flag == 1, p[i] = i prior to permutation, \
|
||||
flag == 0, p[] is not initialized. */\
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## randArrayPermute(RNGT n, VALT *p, RNGT nshuffles, int flag)\
|
||||
{\
|
||||
RNGT i, u, v;\
|
||||
VALT tmp;\
|
||||
\
|
||||
if (flag == 1) {\
|
||||
for (i=0; i<n; i++)\
|
||||
p[i] = (VALT)i;\
|
||||
}\
|
||||
\
|
||||
if (n < 10) {\
|
||||
for (i=0; i<n; i++) {\
|
||||
v = FPRFX ## randInRange(n);\
|
||||
u = FPRFX ## randInRange(n);\
|
||||
gk_SWAP(p[v], p[u], tmp);\
|
||||
}\
|
||||
}\
|
||||
else {\
|
||||
for (i=0; i<nshuffles; i++) {\
|
||||
v = FPRFX ## randInRange(n-3);\
|
||||
u = FPRFX ## randInRange(n-3);\
|
||||
/*gk_SWAP(p[v+0], p[u+0], tmp);*/\
|
||||
/*gk_SWAP(p[v+1], p[u+1], tmp);*/\
|
||||
/*gk_SWAP(p[v+2], p[u+2], tmp);*/\
|
||||
/*gk_SWAP(p[v+3], p[u+3], tmp);*/\
|
||||
gk_SWAP(p[v+0], p[u+2], tmp);\
|
||||
gk_SWAP(p[v+1], p[u+3], tmp);\
|
||||
gk_SWAP(p[v+2], p[u+0], tmp);\
|
||||
gk_SWAP(p[v+3], p[u+1], tmp);\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
\
|
||||
/*************************************************************************/\
|
||||
/*! Randomly permutes the elements of an array p[]. \
|
||||
flag == 1, p[i] = i prior to permutation, \
|
||||
flag == 0, p[] is not initialized. */\
|
||||
/**************************************************************************/\
|
||||
void FPRFX ## randArrayPermuteFine(RNGT n, VALT *p, int flag)\
|
||||
{\
|
||||
RNGT i, v;\
|
||||
VALT tmp;\
|
||||
\
|
||||
if (flag == 1) {\
|
||||
for (i=0; i<n; i++)\
|
||||
p[i] = (VALT)i;\
|
||||
}\
|
||||
\
|
||||
for (i=0; i<n; i++) {\
|
||||
v = FPRFX ## randInRange(n);\
|
||||
gk_SWAP(p[i], p[v], tmp);\
|
||||
}\
|
||||
}\
|
||||
|
||||
|
||||
#define GK_MKRANDOM_PROTO(FPRFX, RNGT, VALT)\
|
||||
void FPRFX ## srand(RNGT seed); \
|
||||
RNGT FPRFX ## rand(); \
|
||||
RNGT FPRFX ## randInRange(RNGT max); \
|
||||
void FPRFX ## randArrayPermute(RNGT n, VALT *p, RNGT nshuffles, int flag);\
|
||||
void FPRFX ## randArrayPermuteFine(RNGT n, VALT *p, int flag);\
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,273 +0,0 @@
|
|||
/*!
|
||||
\file gk_mksort.h
|
||||
\brief Templates for the qsort routine
|
||||
|
||||
\date Started 3/28/07
|
||||
\author George
|
||||
\version\verbatim $Id: gk_mksort.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GK_MKSORT_H_
|
||||
#define _GK_MKSORT_H_
|
||||
|
||||
/* $Id: gk_mksort.h 10711 2011-08-31 22:23:04Z 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 GK_MKQSORT(GKQSORT_TYPE,GKQSORT_BASE,GKQSORT_NELT,GKQSORT_LT) \
|
||||
{ \
|
||||
GKQSORT_TYPE *const _base = (GKQSORT_BASE); \
|
||||
const size_t _elems = (GKQSORT_NELT); \
|
||||
GKQSORT_TYPE _hold; \
|
||||
\
|
||||
if (_elems == 0) \
|
||||
return; \
|
||||
\
|
||||
/* Don't declare two variables of type GKQSORT_TYPE in a single \
|
||||
* statement: eg `TYPE a, b;', in case if TYPE is a pointer, \
|
||||
* expands to `type* a, b;' wich isn't what we want. \
|
||||
*/ \
|
||||
\
|
||||
if (_elems > _GKQSORT_MAX_THRESH) { \
|
||||
GKQSORT_TYPE *_lo = _base; \
|
||||
GKQSORT_TYPE *_hi = _lo + _elems - 1; \
|
||||
struct { \
|
||||
GKQSORT_TYPE *_hi; GKQSORT_TYPE *_lo; \
|
||||
} _stack[_GKQSORT_STACK_SIZE], *_top = _stack + 1; \
|
||||
\
|
||||
while (_GKQSORT_STACK_NOT_EMPTY) { \
|
||||
GKQSORT_TYPE *_left_ptr; GKQSORT_TYPE *_right_ptr; \
|
||||
\
|
||||
/* Select median value from among LO, MID, and HI. Rearrange \
|
||||
LO and HI so the three values are sorted. This lowers the \
|
||||
probability of picking a pathological pivot value and \
|
||||
skips a comparison for both the LEFT_PTR and RIGHT_PTR in \
|
||||
the while loops. */ \
|
||||
\
|
||||
GKQSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); \
|
||||
\
|
||||
if (GKQSORT_LT (_mid, _lo)) \
|
||||
_GKQSORT_SWAP (_mid, _lo, _hold); \
|
||||
if (GKQSORT_LT (_hi, _mid)) \
|
||||
_GKQSORT_SWAP (_mid, _hi, _hold); \
|
||||
else \
|
||||
goto _jump_over; \
|
||||
if (GKQSORT_LT (_mid, _lo)) \
|
||||
_GKQSORT_SWAP (_mid, _lo, _hold); \
|
||||
_jump_over:; \
|
||||
\
|
||||
_left_ptr = _lo + 1; \
|
||||
_right_ptr = _hi - 1; \
|
||||
\
|
||||
/* Here's the famous ``collapse the walls'' section of quicksort. \
|
||||
Gotta like those tight inner loops! They are the main reason \
|
||||
that this algorithm runs much faster than others. */ \
|
||||
do { \
|
||||
while (GKQSORT_LT (_left_ptr, _mid)) \
|
||||
++_left_ptr; \
|
||||
\
|
||||
while (GKQSORT_LT (_mid, _right_ptr)) \
|
||||
--_right_ptr; \
|
||||
\
|
||||
if (_left_ptr < _right_ptr) { \
|
||||
_GKQSORT_SWAP (_left_ptr, _right_ptr, _hold); \
|
||||
if (_mid == _left_ptr) \
|
||||
_mid = _right_ptr; \
|
||||
else if (_mid == _right_ptr) \
|
||||
_mid = _left_ptr; \
|
||||
++_left_ptr; \
|
||||
--_right_ptr; \
|
||||
} \
|
||||
else if (_left_ptr == _right_ptr) { \
|
||||
++_left_ptr; \
|
||||
--_right_ptr; \
|
||||
break; \
|
||||
} \
|
||||
} while (_left_ptr <= _right_ptr); \
|
||||
\
|
||||
/* Set up pointers for next iteration. First determine whether \
|
||||
left and right partitions are below the threshold size. If so, \
|
||||
ignore one or both. Otherwise, push the larger partition's \
|
||||
bounds on the stack and continue sorting the smaller one. */ \
|
||||
\
|
||||
if (_right_ptr - _lo <= _GKQSORT_MAX_THRESH) { \
|
||||
if (_hi - _left_ptr <= _GKQSORT_MAX_THRESH) \
|
||||
/* Ignore both small partitions. */ \
|
||||
_GKQSORT_POP (_lo, _hi, _top); \
|
||||
else \
|
||||
/* Ignore small left partition. */ \
|
||||
_lo = _left_ptr; \
|
||||
} \
|
||||
else if (_hi - _left_ptr <= _GKQSORT_MAX_THRESH) \
|
||||
/* Ignore small right partition. */ \
|
||||
_hi = _right_ptr; \
|
||||
else if (_right_ptr - _lo > _hi - _left_ptr) { \
|
||||
/* Push larger left partition indices. */ \
|
||||
_GKQSORT_PUSH (_top, _lo, _right_ptr); \
|
||||
_lo = _left_ptr; \
|
||||
} \
|
||||
else { \
|
||||
/* Push larger right partition indices. */ \
|
||||
_GKQSORT_PUSH (_top, _left_ptr, _hi); \
|
||||
_hi = _right_ptr; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* Once the BASE array is partially sorted by quicksort the rest \
|
||||
is completely sorted using insertion sort, since this is efficient \
|
||||
for partitions below MAX_THRESH size. BASE points to the \
|
||||
beginning of the array to sort, and END_PTR points at the very \
|
||||
last element in the array (*not* one beyond it!). */ \
|
||||
\
|
||||
{ \
|
||||
GKQSORT_TYPE *const _end_ptr = _base + _elems - 1; \
|
||||
GKQSORT_TYPE *_tmp_ptr = _base; \
|
||||
register GKQSORT_TYPE *_run_ptr; \
|
||||
GKQSORT_TYPE *_thresh; \
|
||||
\
|
||||
_thresh = _base + _GKQSORT_MAX_THRESH; \
|
||||
if (_thresh > _end_ptr) \
|
||||
_thresh = _end_ptr; \
|
||||
\
|
||||
/* Find smallest element in first threshold and place it at the \
|
||||
array's beginning. This is the smallest array element, \
|
||||
and the operation speeds up insertion sort's inner loop. */ \
|
||||
\
|
||||
for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) \
|
||||
if (GKQSORT_LT (_run_ptr, _tmp_ptr)) \
|
||||
_tmp_ptr = _run_ptr; \
|
||||
\
|
||||
if (_tmp_ptr != _base) \
|
||||
_GKQSORT_SWAP (_tmp_ptr, _base, _hold); \
|
||||
\
|
||||
/* Insertion sort, running from left-hand-side \
|
||||
* up to right-hand-side. */ \
|
||||
\
|
||||
_run_ptr = _base + 1; \
|
||||
while (++_run_ptr <= _end_ptr) { \
|
||||
_tmp_ptr = _run_ptr - 1; \
|
||||
while (GKQSORT_LT (_run_ptr, _tmp_ptr)) \
|
||||
--_tmp_ptr; \
|
||||
\
|
||||
++_tmp_ptr; \
|
||||
if (_tmp_ptr != _run_ptr) { \
|
||||
GKQSORT_TYPE *_trav = _run_ptr + 1; \
|
||||
while (--_trav >= _run_ptr) { \
|
||||
GKQSORT_TYPE *_hi; GKQSORT_TYPE *_lo; \
|
||||
_hold = *_trav; \
|
||||
\
|
||||
for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) \
|
||||
*_hi = *_lo; \
|
||||
*_hi = _hold; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Templates for various utility routines
|
||||
|
||||
\date Started 5/28/07
|
||||
\author George
|
||||
\version\verbatim $Id: gk_mkutils.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _GK_MKUTILS_H_
|
||||
#define _GK_MKUTILS_H_
|
||||
|
||||
|
||||
#define GK_MKARRAY2CSR(PRFX, TYPE)\
|
||||
/*************************************************************************/\
|
||||
/*! The macro for gk_?array2csr() routine */\
|
||||
/**************************************************************************/\
|
||||
void PRFX ## array2csr(TYPE n, TYPE range, TYPE *array, TYPE *ptr, TYPE *ind)\
|
||||
{\
|
||||
TYPE i;\
|
||||
\
|
||||
for (i=0; i<=range; i++)\
|
||||
ptr[i] = 0;\
|
||||
\
|
||||
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);\
|
||||
}
|
||||
|
||||
|
||||
#define GK_MKARRAY2CSR_PROTO(PRFX, TYPE)\
|
||||
void PRFX ## array2csr(TYPE n, TYPE range, TYPE *array, TYPE *ptr, TYPE *ind);\
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,381 +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 12591 2012-09-01 19:03:15Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _GK_PROTO_H_
|
||||
#define _GK_PROTO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* blas.c
|
||||
*-------------------------------------------------------------*/
|
||||
GK_MKBLAS_PROTO(gk_c, char, int)
|
||||
GK_MKBLAS_PROTO(gk_i, int, int)
|
||||
GK_MKBLAS_PROTO(gk_i32, int32_t, int32_t)
|
||||
GK_MKBLAS_PROTO(gk_i64, int64_t, int64_t)
|
||||
GK_MKBLAS_PROTO(gk_z, ssize_t, ssize_t)
|
||||
GK_MKBLAS_PROTO(gk_f, float, float)
|
||||
GK_MKBLAS_PROTO(gk_d, double, double)
|
||||
GK_MKBLAS_PROTO(gk_idx, gk_idx_t, gk_idx_t)
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* io.c
|
||||
*-------------------------------------------------------------*/
|
||||
FILE *gk_fopen(char *, char *, const char *);
|
||||
void gk_fclose(FILE *);
|
||||
gk_idx_t gk_getline(char **lineptr, size_t *n, FILE *stream);
|
||||
char **gk_readfile(char *fname, gk_idx_t *r_nlines);
|
||||
int32_t *gk_i32readfile(char *fname, gk_idx_t *r_nlines);
|
||||
int64_t *gk_i64readfile(char *fname, gk_idx_t *r_nlines);
|
||||
int32_t *gk_i32readfilebin(char *fname, ssize_t *r_nelmnts);
|
||||
int64_t *gk_i64readfilebin(char *fname, ssize_t *r_nelmnts);
|
||||
float *gk_freadfilebin(char *fname, ssize_t *r_nelmnts);
|
||||
size_t gk_fwritefilebin(char *fname, size_t n, float *a);
|
||||
double *gk_dreadfilebin(char *fname, ssize_t *r_nelmnts);
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* fs.c
|
||||
*-------------------------------------------------------------*/
|
||||
int gk_fexists(char *);
|
||||
int gk_dexists(char *);
|
||||
intmax_t gk_getfsize(char *);
|
||||
void gk_getfilestats(char *fname, size_t *r_nlines, size_t *r_ntokens,
|
||||
size_t *r_max_nlntokens, size_t *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_MKALLOC_PROTO(gk_c, char)
|
||||
GK_MKALLOC_PROTO(gk_i, int)
|
||||
GK_MKALLOC_PROTO(gk_i32, int32_t)
|
||||
GK_MKALLOC_PROTO(gk_i64, int64_t)
|
||||
GK_MKALLOC_PROTO(gk_z, ssize_t)
|
||||
GK_MKALLOC_PROTO(gk_f, float)
|
||||
GK_MKALLOC_PROTO(gk_d, double)
|
||||
GK_MKALLOC_PROTO(gk_idx, gk_idx_t)
|
||||
|
||||
GK_MKALLOC_PROTO(gk_ckv, gk_ckv_t)
|
||||
GK_MKALLOC_PROTO(gk_ikv, gk_ikv_t)
|
||||
GK_MKALLOC_PROTO(gk_i32kv, gk_i32kv_t)
|
||||
GK_MKALLOC_PROTO(gk_i64kv, gk_i64kv_t)
|
||||
GK_MKALLOC_PROTO(gk_zkv, gk_zkv_t)
|
||||
GK_MKALLOC_PROTO(gk_fkv, gk_fkv_t)
|
||||
GK_MKALLOC_PROTO(gk_dkv, gk_dkv_t)
|
||||
GK_MKALLOC_PROTO(gk_skv, gk_skv_t)
|
||||
GK_MKALLOC_PROTO(gk_idxkv, gk_idxkv_t)
|
||||
|
||||
void gk_AllocMatrix(void ***, size_t, size_t , size_t);
|
||||
void gk_FreeMatrix(void ***, size_t, size_t);
|
||||
int gk_malloc_init();
|
||||
void gk_malloc_cleanup(int showstats);
|
||||
void *gk_malloc(size_t nbytes, char *msg);
|
||||
void *gk_realloc(void *oldptr, size_t nbytes, char *msg);
|
||||
void gk_free(void **ptr1,...);
|
||||
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 gk_set_exit_on_error(int value);
|
||||
void errexit(char *,...);
|
||||
void gk_errexit(int signum, char *,...);
|
||||
int gk_sigtrap();
|
||||
int gk_siguntrap();
|
||||
void gk_sigthrow(int signum);
|
||||
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);
|
||||
int gk_strrcmp(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_csorti(size_t, char *);
|
||||
void gk_csortd(size_t, char *);
|
||||
void gk_isorti(size_t, int *);
|
||||
void gk_isortd(size_t, int *);
|
||||
void gk_fsorti(size_t, float *);
|
||||
void gk_fsortd(size_t, float *);
|
||||
void gk_dsorti(size_t, double *);
|
||||
void gk_dsortd(size_t, double *);
|
||||
void gk_idxsorti(size_t, gk_idx_t *);
|
||||
void gk_idxsortd(size_t, gk_idx_t *);
|
||||
void gk_ckvsorti(size_t, gk_ckv_t *);
|
||||
void gk_ckvsortd(size_t, gk_ckv_t *);
|
||||
void gk_ikvsorti(size_t, gk_ikv_t *);
|
||||
void gk_ikvsortd(size_t, gk_ikv_t *);
|
||||
void gk_i32kvsorti(size_t, gk_i32kv_t *);
|
||||
void gk_i32kvsortd(size_t, gk_i32kv_t *);
|
||||
void gk_i64kvsorti(size_t, gk_i64kv_t *);
|
||||
void gk_i64kvsortd(size_t, gk_i64kv_t *);
|
||||
void gk_zkvsorti(size_t, gk_zkv_t *);
|
||||
void gk_zkvsortd(size_t, gk_zkv_t *);
|
||||
void gk_fkvsorti(size_t, gk_fkv_t *);
|
||||
void gk_fkvsortd(size_t, gk_fkv_t *);
|
||||
void gk_dkvsorti(size_t, gk_dkv_t *);
|
||||
void gk_dkvsortd(size_t, gk_dkv_t *);
|
||||
void gk_skvsorti(size_t, gk_skv_t *);
|
||||
void gk_skvsortd(size_t, gk_skv_t *);
|
||||
void gk_idxkvsorti(size_t, gk_idxkv_t *);
|
||||
void gk_idxkvsortd(size_t, gk_idxkv_t *);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* Selection routines
|
||||
*-------------------------------------------------------------*/
|
||||
int gk_dfkvkselect(size_t, int, gk_fkv_t *);
|
||||
int gk_ifkvkselect(size_t, int, gk_fkv_t *);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* Priority queue
|
||||
*-------------------------------------------------------------*/
|
||||
GK_MKPQUEUE_PROTO(gk_ipq, gk_ipq_t, int, gk_idx_t)
|
||||
GK_MKPQUEUE_PROTO(gk_i32pq, gk_i32pq_t, int32_t, gk_idx_t)
|
||||
GK_MKPQUEUE_PROTO(gk_i64pq, gk_i64pq_t, int64_t, gk_idx_t)
|
||||
GK_MKPQUEUE_PROTO(gk_fpq, gk_fpq_t, float, gk_idx_t)
|
||||
GK_MKPQUEUE_PROTO(gk_dpq, gk_dpq_t, double, gk_idx_t)
|
||||
GK_MKPQUEUE_PROTO(gk_idxpq, gk_idxpq_t, gk_idx_t, gk_idx_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);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* random.c
|
||||
*-------------------------------------------------------------*/
|
||||
GK_MKRANDOM_PROTO(gk_c, size_t, char)
|
||||
GK_MKRANDOM_PROTO(gk_i, size_t, int)
|
||||
GK_MKRANDOM_PROTO(gk_f, size_t, float)
|
||||
GK_MKRANDOM_PROTO(gk_d, size_t, double)
|
||||
GK_MKRANDOM_PROTO(gk_idx, size_t, gk_idx_t)
|
||||
GK_MKRANDOM_PROTO(gk_z, size_t, ssize_t)
|
||||
void gk_randinit(uint64_t);
|
||||
uint64_t gk_randint64(void);
|
||||
uint32_t gk_randint32(void);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* 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__ */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* CSR-related functions
|
||||
*-------------------------------------------------------------*/
|
||||
gk_csr_t *gk_csr_Create();
|
||||
void gk_csr_Init(gk_csr_t *mat);
|
||||
void gk_csr_Free(gk_csr_t **mat);
|
||||
void gk_csr_FreeContents(gk_csr_t *mat);
|
||||
gk_csr_t *gk_csr_Dup(gk_csr_t *mat);
|
||||
gk_csr_t *gk_csr_ExtractSubmatrix(gk_csr_t *mat, int rstart, int nrows);
|
||||
gk_csr_t *gk_csr_ExtractRows(gk_csr_t *mat, int nrows, int *rind);
|
||||
gk_csr_t *gk_csr_ExtractPartition(gk_csr_t *mat, int *part, int pid);
|
||||
gk_csr_t **gk_csr_Split(gk_csr_t *mat, int *color);
|
||||
gk_csr_t *gk_csr_Read(char *filename, int format, int readvals, int numbering);
|
||||
void gk_csr_Write(gk_csr_t *mat, char *filename, int format, int writevals, int numbering);
|
||||
gk_csr_t *gk_csr_Prune(gk_csr_t *mat, int what, int minf, int maxf);
|
||||
gk_csr_t *gk_csr_LowFilter(gk_csr_t *mat, int what, int norm, float fraction);
|
||||
gk_csr_t *gk_csr_TopKPlusFilter(gk_csr_t *mat, int what, int topk, float keepval);
|
||||
gk_csr_t *gk_csr_ZScoreFilter(gk_csr_t *mat, int what, float zscore);
|
||||
void gk_csr_CompactColumns(gk_csr_t *mat);
|
||||
void gk_csr_SortIndices(gk_csr_t *mat, int what);
|
||||
void gk_csr_CreateIndex(gk_csr_t *mat, int what);
|
||||
void gk_csr_Normalize(gk_csr_t *mat, int what, int norm);
|
||||
void gk_csr_Scale(gk_csr_t *mat, int type);
|
||||
void gk_csr_ComputeSums(gk_csr_t *mat, int what);
|
||||
void gk_csr_ComputeSquaredNorms(gk_csr_t *mat, int what);
|
||||
float gk_csr_ComputeSimilarity(gk_csr_t *mat, int i1, int i2, int what, int simtype);
|
||||
int gk_csr_GetSimilarRows(gk_csr_t *mat, int nqterms, int *qind, float *qval,
|
||||
int simtype, int nsim, float minsim, gk_fkv_t *hits, int *_imarker,
|
||||
gk_fkv_t *i_cand);
|
||||
|
||||
|
||||
|
||||
/* itemsets.c */
|
||||
void gk_find_frequent_itemsets(int ntrans, ssize_t *tranptr, int *tranind,
|
||||
int minfreq, int maxfreq, int minlen, int maxlen,
|
||||
void (*process_itemset)(void *stateptr, int nitems, int *itemind,
|
||||
int ntrans, int *tranind),
|
||||
void *stateptr);
|
||||
|
||||
|
||||
/* evaluate.c */
|
||||
float ComputeAccuracy(int n, gk_fkv_t *list);
|
||||
float ComputeROCn(int n, int maxN, gk_fkv_t *list);
|
||||
float ComputeMedianRFP(int n, gk_fkv_t *list);
|
||||
float ComputeMean (int n, float *values);
|
||||
float ComputeStdDev(int n, float *values);
|
||||
|
||||
|
||||
/* mcore.c */
|
||||
gk_mcore_t *gk_mcoreCreate(size_t coresize);
|
||||
gk_mcore_t *gk_gkmcoreCreate();
|
||||
void gk_mcoreDestroy(gk_mcore_t **r_mcore, int showstats);
|
||||
void gk_gkmcoreDestroy(gk_mcore_t **r_mcore, int showstats);
|
||||
void *gk_mcoreMalloc(gk_mcore_t *mcore, size_t nbytes);
|
||||
void gk_mcorePush(gk_mcore_t *mcore);
|
||||
void gk_gkmcorePush(gk_mcore_t *mcore);
|
||||
void gk_mcorePop(gk_mcore_t *mcore);
|
||||
void gk_gkmcorePop(gk_mcore_t *mcore);
|
||||
void gk_mcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr);
|
||||
void gk_gkmcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr);
|
||||
void gk_mcoreDel(gk_mcore_t *mcore, void *ptr);
|
||||
void gk_gkmcoreDel(gk_mcore_t *mcore, void *ptr);
|
||||
|
||||
/* rw.c */
|
||||
int gk_rw_PageRank(gk_csr_t *mat, float lamda, float eps, int max_niter, float *pr);
|
||||
|
||||
|
||||
/* graph.c */
|
||||
gk_graph_t *gk_graph_Create();
|
||||
void gk_graph_Init(gk_graph_t *graph);
|
||||
void gk_graph_Free(gk_graph_t **graph);
|
||||
void gk_graph_FreeContents(gk_graph_t *graph);
|
||||
gk_graph_t *gk_graph_Read(char *filename, int format, int isfewgts,
|
||||
int isfvwgts, int isfvsizes);
|
||||
void gk_graph_Write(gk_graph_t *graph, char *filename, int format);
|
||||
gk_graph_t *gk_graph_Dup(gk_graph_t *graph);
|
||||
gk_graph_t *gk_graph_ExtractSubgraph(gk_graph_t *graph, int vstart, int nvtxs);
|
||||
gk_graph_t *gk_graph_Reorder(gk_graph_t *graph, int32_t *perm, int32_t *iperm);
|
||||
int gk_graph_FindComponents(gk_graph_t *graph, int32_t *cptr, int32_t *cind);
|
||||
void gk_graph_ComputeBFSOrdering(gk_graph_t *graph, int v, int32_t **r_perm,
|
||||
int32_t **r_iperm);
|
||||
void gk_graph_ComputeBestFOrdering0(gk_graph_t *graph, int v, int type,
|
||||
int32_t **r_perm, int32_t **r_iperm);
|
||||
void gk_graph_ComputeBestFOrdering(gk_graph_t *graph, int v, int type,
|
||||
int32_t **r_perm, int32_t **r_iperm);
|
||||
void gk_graph_SingleSourceShortestPaths(gk_graph_t *graph, int v, void **r_sps);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,268 +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 13005 2012-10-23 22:34:36Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _GK_STRUCT_H_
|
||||
#define _GK_STRUCT_H_
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*! Generator for gk_??KeyVal_t data structure */
|
||||
/********************************************************************/
|
||||
#define GK_MKKEYVALUE_T(NAME, KEYTYPE, VALTYPE) \
|
||||
typedef struct {\
|
||||
KEYTYPE key;\
|
||||
VALTYPE val;\
|
||||
} NAME;\
|
||||
|
||||
/* The actual KeyVal data structures */
|
||||
GK_MKKEYVALUE_T(gk_ckv_t, char, ssize_t)
|
||||
GK_MKKEYVALUE_T(gk_ikv_t, int, ssize_t)
|
||||
GK_MKKEYVALUE_T(gk_i32kv_t, int32_t, ssize_t)
|
||||
GK_MKKEYVALUE_T(gk_i64kv_t, int64_t, ssize_t)
|
||||
GK_MKKEYVALUE_T(gk_zkv_t, ssize_t, ssize_t)
|
||||
GK_MKKEYVALUE_T(gk_fkv_t, float, ssize_t)
|
||||
GK_MKKEYVALUE_T(gk_dkv_t, double, ssize_t)
|
||||
GK_MKKEYVALUE_T(gk_skv_t, char *, ssize_t)
|
||||
GK_MKKEYVALUE_T(gk_idxkv_t, gk_idx_t, gk_idx_t)
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*! Generator for gk_?pq_t data structure */
|
||||
/********************************************************************/
|
||||
#define GK_MKPQUEUE_T(NAME, KVTYPE)\
|
||||
typedef struct {\
|
||||
gk_idx_t nnodes;\
|
||||
gk_idx_t maxnodes;\
|
||||
\
|
||||
/* Heap version of the data structure */ \
|
||||
KVTYPE *heap;\
|
||||
gk_idx_t *locator;\
|
||||
} NAME;\
|
||||
|
||||
GK_MKPQUEUE_T(gk_ipq_t, gk_ikv_t)
|
||||
GK_MKPQUEUE_T(gk_i32pq_t, gk_i32kv_t)
|
||||
GK_MKPQUEUE_T(gk_i64pq_t, gk_i64kv_t)
|
||||
GK_MKPQUEUE_T(gk_fpq_t, gk_fkv_t)
|
||||
GK_MKPQUEUE_T(gk_dpq_t, gk_dkv_t)
|
||||
GK_MKPQUEUE_T(gk_idxpq_t, gk_idxkv_t)
|
||||
|
||||
|
||||
#define GK_MKPQUEUE2_T(NAME, KTYPE, VTYPE)\
|
||||
typedef struct {\
|
||||
ssize_t nnodes;\
|
||||
ssize_t maxnodes;\
|
||||
\
|
||||
/* Heap version of the data structure */ \
|
||||
KTYPE *keys;\
|
||||
VTYPE *vals;\
|
||||
} NAME;\
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* The following data structure stores a sparse CSR format
|
||||
*-------------------------------------------------------------*/
|
||||
typedef struct gk_csr_t {
|
||||
int32_t nrows, ncols;
|
||||
ssize_t *rowptr, *colptr;
|
||||
int32_t *rowind, *colind;
|
||||
int32_t *rowids, *colids;
|
||||
float *rowval, *colval;
|
||||
float *rnorms, *cnorms;
|
||||
float *rsums, *csums;
|
||||
float *rsizes, *csizes;
|
||||
float *rvols, *cvols;
|
||||
float *rwgts, *cwgts;
|
||||
} gk_csr_t;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* The following data structure stores a sparse graph
|
||||
*-------------------------------------------------------------*/
|
||||
typedef struct gk_graph_t {
|
||||
int32_t nvtxs; /*!< The number of vertices in the graph */
|
||||
ssize_t *xadj; /*!< The ptr-structure of the adjncy list */
|
||||
int32_t *adjncy; /*!< The adjacency list of the graph */
|
||||
int32_t *iadjwgt; /*!< The integer edge weights */
|
||||
float *fadjwgt; /*!< The floating point edge weights */
|
||||
int32_t *ivwgts; /*!< The integer vertex weights */
|
||||
float *fvwgts; /*!< The floating point vertex weights */
|
||||
int32_t *ivsizes; /*!< The integer vertex sizes */
|
||||
float *fvsizes; /*!< The floating point vertex sizes */
|
||||
int32_t *vlabels; /*!< The labels of the vertices */
|
||||
} gk_graph_t;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* The following data structure stores stores a string as a
|
||||
* pair of its allocated buffer and the buffer itself.
|
||||
*-------------------------------------------------------------*/
|
||||
typedef struct gk_str_t {
|
||||
size_t len;
|
||||
char *buf;
|
||||
} gk_str_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------
|
||||
* The following data structure implements a string-2-int mapping
|
||||
* table used for parsing command-line options
|
||||
*-------------------------------------------------------------*/
|
||||
typedef struct gk_StringMap_t {
|
||||
char *name;
|
||||
int id;
|
||||
} gk_StringMap_t;
|
||||
|
||||
|
||||
/*------------------------------------------------------------
|
||||
* This structure implements a simple hash table
|
||||
*------------------------------------------------------------*/
|
||||
typedef struct gk_HTable_t {
|
||||
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 gk_Tokens_t {
|
||||
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 atom {
|
||||
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 center of mass for
|
||||
* a single residue.
|
||||
*------------------------------------------------------------*/
|
||||
typedef struct center_of_mass {
|
||||
char name;
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} center_of_mass;
|
||||
|
||||
|
||||
/*------------------------------------------------------------
|
||||
* This structure implements storage for a pdb protein
|
||||
*------------------------------------------------------------*/
|
||||
typedef struct pdbf {
|
||||
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 */
|
||||
char **threeresSeq; /* three-letter residue sequence */
|
||||
atom *atoms;
|
||||
atom **bbs;
|
||||
atom **cas;
|
||||
center_of_mass *cm;
|
||||
} pdbf;
|
||||
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* Localization Structures for converting characters to integers
|
||||
**************************************************************/
|
||||
typedef struct gk_i2cc2i_t {
|
||||
int n;
|
||||
char *i2c;
|
||||
int *c2i;
|
||||
} gk_i2cc2i_t;
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*This structure implements storage of a protein sequence
|
||||
* *****************************************************************/
|
||||
typedef struct gk_seq_t {
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! The following data structure stores information about a memory
|
||||
allocation operation that can either be served from gk_mcore_t or by
|
||||
a gk_malloc if not sufficient workspace memory is available. */
|
||||
/*************************************************************************/
|
||||
typedef struct gk_mop_t {
|
||||
int type;
|
||||
ssize_t nbytes;
|
||||
void *ptr;
|
||||
} gk_mop_t;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! The following structure stores information used by Metis */
|
||||
/*************************************************************************/
|
||||
typedef struct gk_mcore_t {
|
||||
/* Workspace information */
|
||||
size_t coresize; /*!< The amount of core memory that has been allocated */
|
||||
size_t corecpos; /*!< Index of the first free location in core */
|
||||
void *core; /*!< Pointer to the core itself */
|
||||
|
||||
/* These are for implementing a stack-based allocation scheme using both
|
||||
core and also dynamically allocated memory */
|
||||
size_t nmops; /*!< The number of maop_t entries that have been allocated */
|
||||
size_t cmop; /*!< Index of the first free location in maops */
|
||||
gk_mop_t *mops; /*!< The array recording the maop_t operations */
|
||||
|
||||
/* These are for keeping various statistics for wspacemalloc */
|
||||
size_t num_callocs; /*!< The number of core mallocs */
|
||||
size_t num_hallocs; /*!< The number of heap mallocs */
|
||||
size_t size_callocs; /*!< The total # of bytes in core mallocs */
|
||||
size_t size_hallocs; /*!< The total # of bytes in heap mallocs */
|
||||
size_t cur_callocs; /*!< The current # of bytes in core mallocs */
|
||||
size_t cur_hallocs; /*!< The current # of bytes in heap mallocs */
|
||||
size_t max_callocs; /*!< The maximum # of bytes in core mallocs at any given time */
|
||||
size_t max_hallocs; /*!< The maximum # of bytes in heap mallocs at any given time */
|
||||
|
||||
} gk_mcore_t;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,38 +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 10711 2011-08-31 22:23:04Z 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_idx_t; */ /* index variable */
|
||||
typedef ssize_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 double gk_wclock_t; /* wall-clock time */
|
||||
|
||||
/*#define GK_IDX_MAX PTRDIFF_MAX*/
|
||||
#define GK_IDX_MAX ((SIZE_MAX>>1)-2)
|
||||
|
||||
#define PRIGKIDX "zd"
|
||||
#define SCNGKIDX "zd"
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,556 +0,0 @@
|
|||
/* Definitions for data structures and routines for the regular
|
||||
expression library.
|
||||
Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006
|
||||
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. */
|
||||
|
||||
#ifndef _REGEX_H
|
||||
#define _REGEX_H 1
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Allow the use in C++ code. */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* The following two types have to be signed and unsigned integer type
|
||||
wide enough to hold a value of a pointer. For most ANSI compilers
|
||||
ptrdiff_t and size_t should be likely OK. Still size of these two
|
||||
types is 2 for Microsoft C. Ugh... */
|
||||
typedef long int s_reg_t;
|
||||
typedef unsigned long int active_reg_t;
|
||||
|
||||
/* The following bits are used to determine the regexp syntax we
|
||||
recognize. The set/not-set meanings are chosen so that Emacs syntax
|
||||
remains the value 0. The bits are given in alphabetical order, and
|
||||
the definitions shifted by one from the previous bit; thus, when we
|
||||
add or remove a bit, only one other definition need change. */
|
||||
typedef unsigned long int reg_syntax_t;
|
||||
|
||||
/* If this bit is not set, then \ inside a bracket expression is literal.
|
||||
If set, then such a \ quotes the following character. */
|
||||
#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
|
||||
|
||||
/* If this bit is not set, then + and ? are operators, and \+ and \? are
|
||||
literals.
|
||||
If set, then \+ and \? are operators and + and ? are literals. */
|
||||
#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
|
||||
|
||||
/* If this bit is set, then character classes are supported. They are:
|
||||
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
|
||||
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
|
||||
If not set, then character classes are not supported. */
|
||||
#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
|
||||
|
||||
/* If this bit is set, then ^ and $ are always anchors (outside bracket
|
||||
expressions, of course).
|
||||
If this bit is not set, then it depends:
|
||||
^ is an anchor if it is at the beginning of a regular
|
||||
expression or after an open-group or an alternation operator;
|
||||
$ is an anchor if it is at the end of a regular expression, or
|
||||
before a close-group or an alternation operator.
|
||||
|
||||
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
|
||||
POSIX draft 11.2 says that * etc. in leading positions is undefined.
|
||||
We already implemented a previous draft which made those constructs
|
||||
invalid, though, so we haven't changed the code back. */
|
||||
#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
|
||||
|
||||
/* If this bit is set, then special characters are always special
|
||||
regardless of where they are in the pattern.
|
||||
If this bit is not set, then special characters are special only in
|
||||
some contexts; otherwise they are ordinary. Specifically,
|
||||
* + ? and intervals are only special when not after the beginning,
|
||||
open-group, or alternation operator. */
|
||||
#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
|
||||
|
||||
/* If this bit is set, then *, +, ?, and { cannot be first in an re or
|
||||
immediately after an alternation or begin-group operator. */
|
||||
#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
|
||||
|
||||
/* If this bit is set, then . matches newline.
|
||||
If not set, then it doesn't. */
|
||||
#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
|
||||
|
||||
/* If this bit is set, then . doesn't match NUL.
|
||||
If not set, then it does. */
|
||||
#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
|
||||
|
||||
/* If this bit is set, nonmatching lists [^...] do not match newline.
|
||||
If not set, they do. */
|
||||
#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
|
||||
|
||||
/* If this bit is set, either \{...\} or {...} defines an
|
||||
interval, depending on RE_NO_BK_BRACES.
|
||||
If not set, \{, \}, {, and } are literals. */
|
||||
#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
|
||||
|
||||
/* If this bit is set, +, ? and | aren't recognized as operators.
|
||||
If not set, they are. */
|
||||
#define RE_LIMITED_OPS (RE_INTERVALS << 1)
|
||||
|
||||
/* If this bit is set, newline is an alternation operator.
|
||||
If not set, newline is literal. */
|
||||
#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
|
||||
|
||||
/* If this bit is set, then `{...}' defines an interval, and \{ and \}
|
||||
are literals.
|
||||
If not set, then `\{...\}' defines an interval. */
|
||||
#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
|
||||
|
||||
/* If this bit is set, (...) defines a group, and \( and \) are literals.
|
||||
If not set, \(...\) defines a group, and ( and ) are literals. */
|
||||
#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
|
||||
|
||||
/* If this bit is set, then \<digit> matches <digit>.
|
||||
If not set, then \<digit> is a back-reference. */
|
||||
#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
|
||||
|
||||
/* If this bit is set, then | is an alternation operator, and \| is literal.
|
||||
If not set, then \| is an alternation operator, and | is literal. */
|
||||
#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
|
||||
|
||||
/* If this bit is set, then an ending range point collating higher
|
||||
than the starting range point, as in [z-a], is invalid.
|
||||
If not set, then when ending range point collates higher than the
|
||||
starting range point, the range is ignored. */
|
||||
#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
|
||||
|
||||
/* If this bit is set, then an unmatched ) is ordinary.
|
||||
If not set, then an unmatched ) is invalid. */
|
||||
#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
|
||||
|
||||
/* If this bit is set, succeed as soon as we match the whole pattern,
|
||||
without further backtracking. */
|
||||
#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
|
||||
|
||||
/* If this bit is set, do not process the GNU regex operators.
|
||||
If not set, then the GNU regex operators are recognized. */
|
||||
#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
|
||||
|
||||
/* If this bit is set, turn on internal regex debugging.
|
||||
If not set, and debugging was on, turn it off.
|
||||
This only works if regex.c is compiled -DDEBUG.
|
||||
We define this bit always, so that all that's needed to turn on
|
||||
debugging is to recompile regex.c; the calling code can always have
|
||||
this bit set, and it won't affect anything in the normal case. */
|
||||
#define RE_DEBUG (RE_NO_GNU_OPS << 1)
|
||||
|
||||
/* If this bit is set, a syntactically invalid interval is treated as
|
||||
a string of ordinary characters. For example, the ERE 'a{1' is
|
||||
treated as 'a\{1'. */
|
||||
#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
|
||||
|
||||
/* If this bit is set, then ignore case when matching.
|
||||
If not set, then case is significant. */
|
||||
#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
|
||||
|
||||
/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
|
||||
for ^, because it is difficult to scan the regex backwards to find
|
||||
whether ^ should be special. */
|
||||
#define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
|
||||
|
||||
/* If this bit is set, then \{ cannot be first in an bre or
|
||||
immediately after an alternation or begin-group operator. */
|
||||
#define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
|
||||
|
||||
/* If this bit is set, then no_sub will be set to 1 during
|
||||
re_compile_pattern. */
|
||||
#define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
|
||||
|
||||
/* This global variable defines the particular regexp syntax to use (for
|
||||
some interfaces). When a regexp is compiled, the syntax used is
|
||||
stored in the pattern buffer, so changing this does not affect
|
||||
already-compiled regexps. */
|
||||
extern reg_syntax_t re_syntax_options;
|
||||
|
||||
/* Define combinations of the above bits for the standard possibilities.
|
||||
(The [[[ comments delimit what gets put into the Texinfo file, so
|
||||
don't delete them!) */
|
||||
/* [[[begin syntaxes]]] */
|
||||
#define RE_SYNTAX_EMACS 0
|
||||
|
||||
#define RE_SYNTAX_AWK \
|
||||
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
|
||||
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
|
||||
| RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
|
||||
|
||||
#define RE_SYNTAX_GNU_AWK \
|
||||
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
|
||||
& ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \
|
||||
| RE_CONTEXT_INVALID_OPS ))
|
||||
|
||||
#define RE_SYNTAX_POSIX_AWK \
|
||||
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
|
||||
| RE_INTERVALS | RE_NO_GNU_OPS)
|
||||
|
||||
#define RE_SYNTAX_GREP \
|
||||
(RE_BK_PLUS_QM | RE_CHAR_CLASSES \
|
||||
| RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
|
||||
| RE_NEWLINE_ALT)
|
||||
|
||||
#define RE_SYNTAX_EGREP \
|
||||
(RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
|
||||
| RE_NEWLINE_ALT | RE_NO_BK_PARENS \
|
||||
| RE_NO_BK_VBAR)
|
||||
|
||||
#define RE_SYNTAX_POSIX_EGREP \
|
||||
(RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \
|
||||
| RE_INVALID_INTERVAL_ORD)
|
||||
|
||||
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
|
||||
#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
|
||||
|
||||
#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
|
||||
|
||||
/* Syntax bits common to both basic and extended POSIX regex syntax. */
|
||||
#define _RE_SYNTAX_POSIX_COMMON \
|
||||
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
|
||||
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
|
||||
|
||||
#define RE_SYNTAX_POSIX_BASIC \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
|
||||
|
||||
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
|
||||
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
|
||||
isn't minimal, since other operators, such as \`, aren't disabled. */
|
||||
#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
|
||||
|
||||
#define RE_SYNTAX_POSIX_EXTENDED \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
|
||||
| RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
|
||||
|
||||
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
|
||||
removed and RE_NO_BK_REFS is added. */
|
||||
#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
|
||||
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
|
||||
/* [[[end syntaxes]]] */
|
||||
|
||||
/* Maximum number of duplicates an interval can allow. Some systems
|
||||
(erroneously) define this in other header files, but we want our
|
||||
value, so remove any previous define. */
|
||||
#ifdef RE_DUP_MAX
|
||||
# undef RE_DUP_MAX
|
||||
#endif
|
||||
/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
|
||||
#define RE_DUP_MAX (0x7fff)
|
||||
|
||||
|
||||
/* POSIX `cflags' bits (i.e., information for `regcomp'). */
|
||||
|
||||
/* If this bit is set, then use extended regular expression syntax.
|
||||
If not set, then use basic regular expression syntax. */
|
||||
#define REG_EXTENDED 1
|
||||
|
||||
/* If this bit is set, then ignore case when matching.
|
||||
If not set, then case is significant. */
|
||||
#define REG_ICASE (REG_EXTENDED << 1)
|
||||
|
||||
/* If this bit is set, then anchors do not match at newline
|
||||
characters in the string.
|
||||
If not set, then anchors do match at newlines. */
|
||||
#define REG_NEWLINE (REG_ICASE << 1)
|
||||
|
||||
/* If this bit is set, then report only success or fail in regexec.
|
||||
If not set, then returns differ between not matching and errors. */
|
||||
#define REG_NOSUB (REG_NEWLINE << 1)
|
||||
|
||||
|
||||
/* POSIX `eflags' bits (i.e., information for regexec). */
|
||||
|
||||
/* If this bit is set, then the beginning-of-line operator doesn't match
|
||||
the beginning of the string (presumably because it's not the
|
||||
beginning of a line).
|
||||
If not set, then the beginning-of-line operator does match the
|
||||
beginning of the string. */
|
||||
#define REG_NOTBOL 1
|
||||
|
||||
/* Like REG_NOTBOL, except for the end-of-line. */
|
||||
#define REG_NOTEOL (1 << 1)
|
||||
|
||||
/* Use PMATCH[0] to delimit the start and end of the search in the
|
||||
buffer. */
|
||||
#define REG_STARTEND (1 << 2)
|
||||
|
||||
|
||||
/* If any error codes are removed, changed, or added, update the
|
||||
`re_error_msg' table in regex.c. */
|
||||
typedef enum
|
||||
{
|
||||
#ifdef _XOPEN_SOURCE
|
||||
REG_ENOSYS = -1, /* This will never happen for this implementation. */
|
||||
#endif
|
||||
|
||||
REG_NOERROR = 0, /* Success. */
|
||||
REG_NOMATCH, /* Didn't find a match (for regexec). */
|
||||
|
||||
/* POSIX regcomp return error codes. (In the order listed in the
|
||||
standard.) */
|
||||
REG_BADPAT, /* Invalid pattern. */
|
||||
REG_ECOLLATE, /* Inalid collating element. */
|
||||
REG_ECTYPE, /* Invalid character class name. */
|
||||
REG_EESCAPE, /* Trailing backslash. */
|
||||
REG_ESUBREG, /* Invalid back reference. */
|
||||
REG_EBRACK, /* Unmatched left bracket. */
|
||||
REG_EPAREN, /* Parenthesis imbalance. */
|
||||
REG_EBRACE, /* Unmatched \{. */
|
||||
REG_BADBR, /* Invalid contents of \{\}. */
|
||||
REG_ERANGE, /* Invalid range end. */
|
||||
REG_ESPACE, /* Ran out of memory. */
|
||||
REG_BADRPT, /* No preceding re for repetition op. */
|
||||
|
||||
/* Error codes we've added. */
|
||||
REG_EEND, /* Premature end. */
|
||||
REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
|
||||
REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
|
||||
} reg_errcode_t;
|
||||
|
||||
/* This data structure represents a compiled pattern. Before calling
|
||||
the pattern compiler, the fields `buffer', `allocated', `fastmap',
|
||||
`translate', and `no_sub' can be set. After the pattern has been
|
||||
compiled, the `re_nsub' field is available. All other fields are
|
||||
private to the regex routines. */
|
||||
|
||||
#ifndef RE_TRANSLATE_TYPE
|
||||
# define RE_TRANSLATE_TYPE unsigned char *
|
||||
#endif
|
||||
|
||||
struct re_pattern_buffer
|
||||
{
|
||||
/* Space that holds the compiled pattern. It is declared as
|
||||
`unsigned char *' because its elements are sometimes used as
|
||||
array indexes. */
|
||||
unsigned char *buffer;
|
||||
|
||||
/* Number of bytes to which `buffer' points. */
|
||||
unsigned long int allocated;
|
||||
|
||||
/* Number of bytes actually used in `buffer'. */
|
||||
unsigned long int used;
|
||||
|
||||
/* Syntax setting with which the pattern was compiled. */
|
||||
reg_syntax_t syntax;
|
||||
|
||||
/* Pointer to a fastmap, if any, otherwise zero. re_search uses the
|
||||
fastmap, if there is one, to skip over impossible starting points
|
||||
for matches. */
|
||||
char *fastmap;
|
||||
|
||||
/* Either a translate table to apply to all characters before
|
||||
comparing them, or zero for no translation. The translation is
|
||||
applied to a pattern when it is compiled and to a string when it
|
||||
is matched. */
|
||||
RE_TRANSLATE_TYPE translate;
|
||||
|
||||
/* Number of subexpressions found by the compiler. */
|
||||
size_t re_nsub;
|
||||
|
||||
/* Zero if this pattern cannot match the empty string, one else.
|
||||
Well, in truth it's used only in `re_search_2', to see whether or
|
||||
not we should use the fastmap, so we don't set this absolutely
|
||||
perfectly; see `re_compile_fastmap' (the `duplicate' case). */
|
||||
unsigned can_be_null : 1;
|
||||
|
||||
/* If REGS_UNALLOCATED, allocate space in the `regs' structure
|
||||
for `max (RE_NREGS, re_nsub + 1)' groups.
|
||||
If REGS_REALLOCATE, reallocate space if necessary.
|
||||
If REGS_FIXED, use what's there. */
|
||||
#define REGS_UNALLOCATED 0
|
||||
#define REGS_REALLOCATE 1
|
||||
#define REGS_FIXED 2
|
||||
unsigned regs_allocated : 2;
|
||||
|
||||
/* Set to zero when `regex_compile' compiles a pattern; set to one
|
||||
by `re_compile_fastmap' if it updates the fastmap. */
|
||||
unsigned fastmap_accurate : 1;
|
||||
|
||||
/* If set, `re_match_2' does not return information about
|
||||
subexpressions. */
|
||||
unsigned no_sub : 1;
|
||||
|
||||
/* If set, a beginning-of-line anchor doesn't match at the beginning
|
||||
of the string. */
|
||||
unsigned not_bol : 1;
|
||||
|
||||
/* Similarly for an end-of-line anchor. */
|
||||
unsigned not_eol : 1;
|
||||
|
||||
/* If true, an anchor at a newline matches. */
|
||||
unsigned newline_anchor : 1;
|
||||
};
|
||||
|
||||
typedef struct re_pattern_buffer regex_t;
|
||||
|
||||
/* Type for byte offsets within the string. POSIX mandates this. */
|
||||
typedef int regoff_t;
|
||||
|
||||
|
||||
/* This is the structure we store register match data in. See
|
||||
regex.texinfo for a full description of what registers match. */
|
||||
struct re_registers
|
||||
{
|
||||
unsigned num_regs;
|
||||
regoff_t *start;
|
||||
regoff_t *end;
|
||||
};
|
||||
|
||||
|
||||
/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
|
||||
`re_match_2' returns information about at least this many registers
|
||||
the first time a `regs' structure is passed. */
|
||||
#ifndef RE_NREGS
|
||||
# define RE_NREGS 30
|
||||
#endif
|
||||
|
||||
|
||||
/* POSIX specification for registers. Aside from the different names than
|
||||
`re_registers', POSIX uses an array of structures, instead of a
|
||||
structure of arrays. */
|
||||
typedef struct
|
||||
{
|
||||
regoff_t rm_so; /* Byte offset from string's start to substring's start. */
|
||||
regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
|
||||
} regmatch_t;
|
||||
|
||||
/* Declarations for routines. */
|
||||
|
||||
/* Sets the current default syntax to SYNTAX, and return the old syntax.
|
||||
You can also simply assign to the `re_syntax_options' variable. */
|
||||
extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
|
||||
|
||||
/* Compile the regular expression PATTERN, with length LENGTH
|
||||
and syntax given by the global `re_syntax_options', into the buffer
|
||||
BUFFER. Return NULL if successful, and an error string if not. */
|
||||
extern const char *re_compile_pattern (const char *__pattern, size_t __length,
|
||||
struct re_pattern_buffer *__buffer);
|
||||
|
||||
|
||||
/* Compile a fastmap for the compiled pattern in BUFFER; used to
|
||||
accelerate searches. Return 0 if successful and -2 if was an
|
||||
internal error. */
|
||||
extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
|
||||
|
||||
|
||||
/* Search in the string STRING (with length LENGTH) for the pattern
|
||||
compiled into BUFFER. Start searching at position START, for RANGE
|
||||
characters. Return the starting position of the match, -1 for no
|
||||
match, or -2 for an internal error. Also return register
|
||||
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
|
||||
extern int re_search (struct re_pattern_buffer *__buffer, const char *__string,
|
||||
int __length, int __start, int __range,
|
||||
struct re_registers *__regs);
|
||||
|
||||
|
||||
/* Like `re_search', but search in the concatenation of STRING1 and
|
||||
STRING2. Also, stop searching at index START + STOP. */
|
||||
extern int re_search_2 (struct re_pattern_buffer *__buffer,
|
||||
const char *__string1, int __length1,
|
||||
const char *__string2, int __length2, int __start,
|
||||
int __range, struct re_registers *__regs, int __stop);
|
||||
|
||||
|
||||
/* Like `re_search', but return how many characters in STRING the regexp
|
||||
in BUFFER matched, starting at position START. */
|
||||
extern int re_match (struct re_pattern_buffer *__buffer, const char *__string,
|
||||
int __length, int __start, struct re_registers *__regs);
|
||||
|
||||
|
||||
/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
|
||||
extern int re_match_2 (struct re_pattern_buffer *__buffer,
|
||||
const char *__string1, int __length1,
|
||||
const char *__string2, int __length2, int __start,
|
||||
struct re_registers *__regs, int __stop);
|
||||
|
||||
|
||||
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
|
||||
ENDS. Subsequent matches using BUFFER and REGS will use this memory
|
||||
for recording register information. STARTS and ENDS must be
|
||||
allocated with malloc, and must each be at least `NUM_REGS * sizeof
|
||||
(regoff_t)' bytes long.
|
||||
|
||||
If NUM_REGS == 0, then subsequent matches should allocate their own
|
||||
register data.
|
||||
|
||||
Unless this function is called, the first search or match using
|
||||
PATTERN_BUFFER will allocate its own register data, without
|
||||
freeing the old data. */
|
||||
extern void re_set_registers (struct re_pattern_buffer *__buffer,
|
||||
struct re_registers *__regs,
|
||||
unsigned int __num_regs,
|
||||
regoff_t *__starts, regoff_t *__ends);
|
||||
|
||||
#if defined _REGEX_RE_COMP || defined _LIBC
|
||||
# ifndef _CRAY
|
||||
/* 4.2 bsd compatibility. */
|
||||
extern char *re_comp (const char *);
|
||||
extern int re_exec (const char *);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* GCC 2.95 and later have "__restrict"; C99 compilers have
|
||||
"restrict", and "configure" may have defined "restrict". */
|
||||
#ifndef __restrict
|
||||
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
|
||||
# if defined restrict || 199901L <= __STDC_VERSION__
|
||||
# define __restrict restrict
|
||||
# else
|
||||
# define __restrict
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
/* gcc 3.1 and up support the [restrict] syntax. */
|
||||
#ifndef __restrict_arr
|
||||
# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \
|
||||
&& !defined __GNUG__
|
||||
# define __restrict_arr __restrict
|
||||
# else
|
||||
# define __restrict_arr
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* POSIX compatibility. */
|
||||
extern int regcomp (regex_t *__restrict __preg,
|
||||
const char *__restrict __pattern,
|
||||
int __cflags);
|
||||
|
||||
extern int regexec (const regex_t *__restrict __preg,
|
||||
const char *__restrict __string, size_t __nmatch,
|
||||
regmatch_t __pmatch[__restrict_arr],
|
||||
int __eflags);
|
||||
|
||||
extern size_t regerror (int __errcode, const regex_t *__restrict __preg,
|
||||
char *__restrict __errbuf, size_t __errbuf_size);
|
||||
|
||||
extern void regfree (regex_t *__preg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* C++ */
|
||||
|
||||
#endif /* regex.h */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,247 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, Regents of the University of Minnesota
|
||||
*
|
||||
* This file contains routines for manipulating a direct-access hash table
|
||||
*
|
||||
* Started 3/22/04
|
||||
* George
|
||||
*
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
/******************************************************************************
|
||||
* This function creates the hash-table
|
||||
*******************************************************************************/
|
||||
gk_HTable_t *HTable_Create(int nelements)
|
||||
{
|
||||
gk_HTable_t *htable;
|
||||
|
||||
htable = gk_malloc(sizeof(gk_HTable_t), "HTable_Create: htable");
|
||||
htable->harray = gk_ikvmalloc(nelements, "HTable_Create: harray");
|
||||
htable->nelements = nelements;
|
||||
|
||||
HTable_Reset(htable);
|
||||
|
||||
return htable;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function resets the data-structures associated with the hash-table
|
||||
*******************************************************************************/
|
||||
void HTable_Reset(gk_HTable_t *htable)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<htable->nelements; i++)
|
||||
htable->harray[i].key = HTABLE_EMPTY;
|
||||
htable->htsize = 0;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* This function resizes the hash-table
|
||||
*******************************************************************************/
|
||||
void HTable_Resize(gk_HTable_t *htable, int nelements)
|
||||
{
|
||||
int i, old_nelements;
|
||||
gk_ikv_t *old_harray;
|
||||
|
||||
old_nelements = htable->nelements;
|
||||
old_harray = htable->harray;
|
||||
|
||||
/* prepare larger hash */
|
||||
htable->nelements = nelements;
|
||||
htable->htsize = 0;
|
||||
htable->harray = gk_ikvmalloc(nelements, "HTable_Resize: harray");
|
||||
for (i=0; i<nelements; i++)
|
||||
htable->harray[i].key = HTABLE_EMPTY;
|
||||
|
||||
/* reassign the values */
|
||||
for (i=0; i<old_nelements; i++)
|
||||
if (old_harray[i].key != HTABLE_EMPTY)
|
||||
HTable_Insert(htable, old_harray[i].key, old_harray[i].val);
|
||||
|
||||
/* remove old harray */
|
||||
gk_free((void **)&old_harray, LTERM);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function inserts a key-value pair in the array
|
||||
*******************************************************************************/
|
||||
void HTable_Insert(gk_HTable_t *htable, int key, int val)
|
||||
{
|
||||
int i, first;
|
||||
|
||||
if (htable->htsize > htable->nelements/2)
|
||||
HTable_Resize(htable, 2*htable->nelements);
|
||||
|
||||
first = HTable_HFunction(htable->nelements, key);
|
||||
|
||||
for (i=first; i<htable->nelements; i++) {
|
||||
if (htable->harray[i].key == HTABLE_EMPTY || htable->harray[i].key == HTABLE_DELETED) {
|
||||
htable->harray[i].key = key;
|
||||
htable->harray[i].val = val;
|
||||
htable->htsize++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<first; i++) {
|
||||
if (htable->harray[i].key == HTABLE_EMPTY || htable->harray[i].key == HTABLE_DELETED) {
|
||||
htable->harray[i].key = key;
|
||||
htable->harray[i].val = val;
|
||||
htable->htsize++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function deletes key from the htable
|
||||
*******************************************************************************/
|
||||
void HTable_Delete(gk_HTable_t *htable, int key)
|
||||
{
|
||||
int i, first;
|
||||
|
||||
first = HTable_HFunction(htable->nelements, key);
|
||||
|
||||
for (i=first; i<htable->nelements; i++) {
|
||||
if (htable->harray[i].key == key) {
|
||||
htable->harray[i].key = HTABLE_DELETED;
|
||||
htable->htsize--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<first; i++) {
|
||||
if (htable->harray[i].key == key) {
|
||||
htable->harray[i].key = HTABLE_DELETED;
|
||||
htable->htsize--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function returns the data associated with the key in the hastable
|
||||
*******************************************************************************/
|
||||
int HTable_Search(gk_HTable_t *htable, int key)
|
||||
{
|
||||
int i, first;
|
||||
|
||||
first = HTable_HFunction(htable->nelements, key);
|
||||
|
||||
for (i=first; i<htable->nelements; i++) {
|
||||
if (htable->harray[i].key == key)
|
||||
return htable->harray[i].val;
|
||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i<first; i++) {
|
||||
if (htable->harray[i].key == key)
|
||||
return htable->harray[i].val;
|
||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function returns the next key/val
|
||||
*******************************************************************************/
|
||||
int HTable_GetNext(gk_HTable_t *htable, int key, int *r_val, int type)
|
||||
{
|
||||
int i;
|
||||
static int first, last;
|
||||
|
||||
if (type == HTABLE_FIRST)
|
||||
first = last = HTable_HFunction(htable->nelements, key);
|
||||
|
||||
if (first > last) {
|
||||
for (i=first; i<htable->nelements; i++) {
|
||||
if (htable->harray[i].key == key) {
|
||||
*r_val = htable->harray[i].val;
|
||||
first = i+1;
|
||||
return 1;
|
||||
}
|
||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
||||
return -1;
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
|
||||
for (i=first; i<last; i++) {
|
||||
if (htable->harray[i].key == key) {
|
||||
*r_val = htable->harray[i].val;
|
||||
first = i+1;
|
||||
return 1;
|
||||
}
|
||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function returns the data associated with the key in the hastable
|
||||
*******************************************************************************/
|
||||
int HTable_SearchAndDelete(gk_HTable_t *htable, int key)
|
||||
{
|
||||
int i, first;
|
||||
|
||||
first = HTable_HFunction(htable->nelements, key);
|
||||
|
||||
for (i=first; i<htable->nelements; i++) {
|
||||
if (htable->harray[i].key == key) {
|
||||
htable->harray[i].key = HTABLE_DELETED;
|
||||
htable->htsize--;
|
||||
return htable->harray[i].val;
|
||||
}
|
||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
||||
gk_errexit(SIGERR, "HTable_SearchAndDelete: Failed to find the key!\n");
|
||||
}
|
||||
|
||||
for (i=0; i<first; i++) {
|
||||
if (htable->harray[i].key == key) {
|
||||
htable->harray[i].key = HTABLE_DELETED;
|
||||
htable->htsize--;
|
||||
return htable->harray[i].val;
|
||||
}
|
||||
else if (htable->harray[i].key == HTABLE_EMPTY)
|
||||
gk_errexit(SIGERR, "HTable_SearchAndDelete: Failed to find the key!\n");
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This function destroys the data structures associated with the hash-table
|
||||
*******************************************************************************/
|
||||
void HTable_Destroy(gk_HTable_t *htable)
|
||||
{
|
||||
gk_free((void **)&htable->harray, &htable, LTERM);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* This is the hash-function. Based on multiplication
|
||||
*******************************************************************************/
|
||||
int HTable_HFunction(int nelements, int key)
|
||||
{
|
||||
return (int)(key%nelements);
|
||||
}
|
||||
|
|
@ -1,384 +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 12591 2012-09-01 19:03:15Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifdef HAVE_GETLINE
|
||||
/* Get getline to be defined. */
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#undef _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#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.
|
||||
\returns -1 if the EOF has been reached, otherwise it returns the
|
||||
number of bytes read.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
gk_idx_t gk_getline(char **lineptr, size_t *n, FILE *stream)
|
||||
{
|
||||
#ifdef HAVE_GETLINE
|
||||
return getline(lineptr, n, stream);
|
||||
#else
|
||||
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 */
|
||||
i = 0;
|
||||
while ((ch = getc(stream)) != EOF) {
|
||||
(*lineptr)[i++] = (char)ch;
|
||||
|
||||
/* reallocate memory if reached at the end of the buffer. The +1 is for '\0' */
|
||||
if (i+1 == *n) {
|
||||
*n = 2*(*n);
|
||||
*lineptr = gk_realloc(*lineptr, (*n)*sizeof(char), "gk_getline: lineptr");
|
||||
}
|
||||
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
(*lineptr)[i] = '\0';
|
||||
|
||||
return (i == 0 ? -1 : i);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function reads the contents of a text file and returns it in the
|
||||
form of an array of strings.
|
||||
\param fname is the name of the file
|
||||
\param r_nlines is the number of lines in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
char **gk_readfile(char *fname, gk_idx_t *r_nlines)
|
||||
{
|
||||
size_t lnlen, nlines;
|
||||
char *line=NULL, **lines=NULL;
|
||||
FILE *fpin;
|
||||
|
||||
gk_getfilestats(fname, &nlines, NULL, NULL, NULL);
|
||||
if (nlines > 0) {
|
||||
lines = (char **)gk_malloc(nlines*sizeof(char *), "gk_readfile: lines");
|
||||
|
||||
fpin = gk_fopen(fname, "r", "gk_readfile");
|
||||
nlines = 0;
|
||||
while (gk_getline(&line, &lnlen, fpin) != -1) {
|
||||
gk_strtprune(line, "\n\r");
|
||||
lines[nlines++] = gk_strdup(line);
|
||||
}
|
||||
gk_fclose(fpin);
|
||||
}
|
||||
|
||||
gk_free((void **)&line, LTERM);
|
||||
|
||||
if (r_nlines != NULL)
|
||||
*r_nlines = nlines;
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function reads the contents of a file and returns it in the
|
||||
form of an array of int32_t.
|
||||
\param fname is the name of the file
|
||||
\param r_nlines is the number of lines in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int32_t *gk_i32readfile(char *fname, gk_idx_t *r_nlines)
|
||||
{
|
||||
size_t lnlen, nlines;
|
||||
char *line=NULL;
|
||||
int32_t *array=NULL;
|
||||
FILE *fpin;
|
||||
|
||||
gk_getfilestats(fname, &nlines, NULL, NULL, NULL);
|
||||
if (nlines > 0) {
|
||||
array = gk_i32malloc(nlines, "gk_i32readfile: array");
|
||||
|
||||
fpin = gk_fopen(fname, "r", "gk_readfile");
|
||||
nlines = 0;
|
||||
|
||||
while (gk_getline(&line, &lnlen, fpin) != -1) {
|
||||
sscanf(line, "%"SCNd32, &array[nlines++]);
|
||||
}
|
||||
|
||||
gk_fclose(fpin);
|
||||
}
|
||||
|
||||
gk_free((void **)&line, LTERM);
|
||||
|
||||
if (r_nlines != NULL)
|
||||
*r_nlines = nlines;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function reads the contents of a file and returns it in the
|
||||
form of an array of int64_t.
|
||||
\param fname is the name of the file
|
||||
\param r_nlines is the number of lines in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int64_t *gk_i64readfile(char *fname, gk_idx_t *r_nlines)
|
||||
{
|
||||
size_t lnlen, nlines;
|
||||
char *line=NULL;
|
||||
int64_t *array=NULL;
|
||||
FILE *fpin;
|
||||
|
||||
gk_getfilestats(fname, &nlines, NULL, NULL, NULL);
|
||||
if (nlines > 0) {
|
||||
array = gk_i64malloc(nlines, "gk_i64readfile: array");
|
||||
|
||||
fpin = gk_fopen(fname, "r", "gk_readfile");
|
||||
nlines = 0;
|
||||
|
||||
while (gk_getline(&line, &lnlen, fpin) != -1) {
|
||||
sscanf(line, "%"SCNd64, &array[nlines++]);
|
||||
}
|
||||
|
||||
gk_fclose(fpin);
|
||||
}
|
||||
|
||||
gk_free((void **)&line, LTERM);
|
||||
|
||||
if (r_nlines != NULL)
|
||||
*r_nlines = nlines;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function reads the contents of a binary file and returns it in the
|
||||
form of an array of int32_t.
|
||||
\param fname is the name of the file
|
||||
\param r_nlines is the number of lines in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int32_t *gk_i32readfilebin(char *fname, ssize_t *r_nelmnts)
|
||||
{
|
||||
ssize_t fsize, nelmnts;
|
||||
int32_t *array=NULL;
|
||||
FILE *fpin;
|
||||
|
||||
*r_nelmnts = -1;
|
||||
|
||||
fsize = (ssize_t) gk_getfsize(fname);
|
||||
if (fsize%sizeof(int32_t) != 0) {
|
||||
gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(int32_t).\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nelmnts = fsize/sizeof(int32_t);
|
||||
array = gk_i32malloc(nelmnts, "gk_i32readfilebin: array");
|
||||
|
||||
fpin = gk_fopen(fname, "rb", "gk_i32readfilebin");
|
||||
|
||||
if (fread(array, sizeof(int32_t), nelmnts, fpin) != nelmnts) {
|
||||
gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts);
|
||||
gk_free((void **)&array, LTERM);
|
||||
return NULL;
|
||||
}
|
||||
gk_fclose(fpin);
|
||||
|
||||
*r_nelmnts = nelmnts;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function reads the contents of a binary file and returns it in the
|
||||
form of an array of int64_t.
|
||||
\param fname is the name of the file
|
||||
\param r_nlines is the number of lines in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int64_t *gk_i64readfilebin(char *fname, ssize_t *r_nelmnts)
|
||||
{
|
||||
ssize_t fsize, nelmnts;
|
||||
int64_t *array=NULL;
|
||||
FILE *fpin;
|
||||
|
||||
*r_nelmnts = -1;
|
||||
|
||||
fsize = (ssize_t) gk_getfsize(fname);
|
||||
if (fsize%sizeof(int64_t) != 0) {
|
||||
gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(int64_t).\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nelmnts = fsize/sizeof(int64_t);
|
||||
array = gk_i64malloc(nelmnts, "gk_i64readfilebin: array");
|
||||
|
||||
fpin = gk_fopen(fname, "rb", "gk_i64readfilebin");
|
||||
|
||||
if (fread(array, sizeof(int64_t), nelmnts, fpin) != nelmnts) {
|
||||
gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts);
|
||||
gk_free((void **)&array, LTERM);
|
||||
return NULL;
|
||||
}
|
||||
gk_fclose(fpin);
|
||||
|
||||
*r_nelmnts = nelmnts;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function reads the contents of a binary file and returns it in the
|
||||
form of an array of float.
|
||||
\param fname is the name of the file
|
||||
\param r_nlines is the number of lines in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
float *gk_freadfilebin(char *fname, ssize_t *r_nelmnts)
|
||||
{
|
||||
ssize_t fsize, nelmnts;
|
||||
float *array=NULL;
|
||||
FILE *fpin;
|
||||
|
||||
*r_nelmnts = -1;
|
||||
|
||||
fsize = (ssize_t) gk_getfsize(fname);
|
||||
if (fsize%sizeof(float) != 0) {
|
||||
gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(float).\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nelmnts = fsize/sizeof(float);
|
||||
array = gk_fmalloc(nelmnts, "gk_freadfilebin: array");
|
||||
|
||||
fpin = gk_fopen(fname, "rb", "gk_freadfilebin");
|
||||
|
||||
if (fread(array, sizeof(float), nelmnts, fpin) != nelmnts) {
|
||||
gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts);
|
||||
gk_free((void **)&array, LTERM);
|
||||
return NULL;
|
||||
}
|
||||
gk_fclose(fpin);
|
||||
|
||||
*r_nelmnts = nelmnts;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function writes the contents of an array into a binary file.
|
||||
\param fname is the name of the file
|
||||
\param n the number of elements in the array.
|
||||
\param a the array to be written out.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
size_t gk_fwritefilebin(char *fname, size_t n, float *a)
|
||||
{
|
||||
size_t fsize;
|
||||
FILE *fp;
|
||||
|
||||
fp = gk_fopen(fname, "wb", "gk_fwritefilebin");
|
||||
|
||||
fsize = fwrite(a, sizeof(float), n, fp);
|
||||
|
||||
gk_fclose(fp);
|
||||
|
||||
return fsize;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function reads the contents of a binary file and returns it in the
|
||||
form of an array of double.
|
||||
\param fname is the name of the file
|
||||
\param r_nlines is the number of lines in the file. If it is NULL,
|
||||
this information is not returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
double *gk_dreadfilebin(char *fname, ssize_t *r_nelmnts)
|
||||
{
|
||||
ssize_t fsize, nelmnts;
|
||||
double *array=NULL;
|
||||
FILE *fpin;
|
||||
|
||||
*r_nelmnts = -1;
|
||||
|
||||
fsize = (ssize_t) gk_getfsize(fname);
|
||||
if (fsize%sizeof(double) != 0) {
|
||||
gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(double).\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nelmnts = fsize/sizeof(double);
|
||||
array = gk_dmalloc(nelmnts, "gk_dreadfilebin: array");
|
||||
|
||||
fpin = gk_fopen(fname, "rb", "gk_dreadfilebin");
|
||||
|
||||
if (fread(array, sizeof(double), nelmnts, fpin) != nelmnts) {
|
||||
gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts);
|
||||
gk_free((void **)&array, LTERM);
|
||||
return NULL;
|
||||
}
|
||||
gk_fclose(fpin);
|
||||
|
||||
*r_nelmnts = nelmnts;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
/*!
|
||||
* \file
|
||||
* \brief Frequent/Closed itemset discovery routines
|
||||
*
|
||||
* This file contains the code for finding frequent/closed itemests. These routines
|
||||
* are implemented using a call-back mechanism to deal with the discovered itemsets.
|
||||
*
|
||||
* \date 6/13/2008
|
||||
* \author George Karypis
|
||||
* \version\verbatim $Id: itemsets.c 11075 2011-11-11 22:31:52Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*! Data structures for use within this module */
|
||||
/*-------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
int minfreq; /* the minimum frequency of a pattern */
|
||||
int maxfreq; /* the maximum frequency of a pattern */
|
||||
int minlen; /* the minimum length of the requested pattern */
|
||||
int maxlen; /* the maximum length of the requested pattern */
|
||||
int tnitems; /* the initial range of the item space */
|
||||
|
||||
/* the call-back function */
|
||||
void (*callback)(void *stateptr, int nitems, int *itemids, int ntrans, int *transids);
|
||||
void *stateptr; /* the user-supplied pointer to pass to the callback */
|
||||
|
||||
/* workspace variables */
|
||||
int *rmarker;
|
||||
gk_ikv_t *cand;
|
||||
} isparams_t;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*! Prototypes for this module */
|
||||
/*-------------------------------------------------------------*/
|
||||
void itemsets_find_frequent_itemsets(isparams_t *params, gk_csr_t *mat,
|
||||
int preflen, int *prefix);
|
||||
gk_csr_t *itemsets_project_matrix(isparams_t *param, gk_csr_t *mat, int cid);
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! The entry point of the frequent itemset discovery code */
|
||||
/*************************************************************************/
|
||||
void gk_find_frequent_itemsets(int ntrans, ssize_t *tranptr, int *tranind,
|
||||
int minfreq, int maxfreq, int minlen, int maxlen,
|
||||
void (*process_itemset)(void *stateptr, int nitems, int *itemids,
|
||||
int ntrans, int *transids),
|
||||
void *stateptr)
|
||||
{
|
||||
ssize_t i;
|
||||
gk_csr_t *mat, *pmat;
|
||||
isparams_t params;
|
||||
int *pattern;
|
||||
|
||||
/* Create the matrix */
|
||||
mat = gk_csr_Create();
|
||||
mat->nrows = ntrans;
|
||||
mat->ncols = tranind[gk_iargmax(tranptr[ntrans], tranind)]+1;
|
||||
mat->rowptr = gk_zcopy(ntrans+1, tranptr, gk_zmalloc(ntrans+1, "gk_find_frequent_itemsets: mat.rowptr"));
|
||||
mat->rowind = gk_icopy(tranptr[ntrans], tranind, gk_imalloc(tranptr[ntrans], "gk_find_frequent_itemsets: mat.rowind"));
|
||||
mat->colids = gk_iincset(mat->ncols, 0, gk_imalloc(mat->ncols, "gk_find_frequent_itemsets: mat.colids"));
|
||||
|
||||
/* Setup the parameters */
|
||||
params.minfreq = minfreq;
|
||||
params.maxfreq = (maxfreq == -1 ? mat->nrows : maxfreq);
|
||||
params.minlen = minlen;
|
||||
params.maxlen = (maxlen == -1 ? mat->ncols : maxlen);
|
||||
params.tnitems = mat->ncols;
|
||||
params.callback = process_itemset;
|
||||
params.stateptr = stateptr;
|
||||
params.rmarker = gk_ismalloc(mat->nrows, 0, "gk_find_frequent_itemsets: rmarker");
|
||||
params.cand = gk_ikvmalloc(mat->ncols, "gk_find_frequent_itemsets: cand");
|
||||
|
||||
/* Perform the initial projection */
|
||||
gk_csr_CreateIndex(mat, GK_CSR_COL);
|
||||
pmat = itemsets_project_matrix(¶ms, mat, -1);
|
||||
gk_csr_Free(&mat);
|
||||
|
||||
pattern = gk_imalloc(pmat->ncols, "gk_find_frequent_itemsets: pattern");
|
||||
itemsets_find_frequent_itemsets(¶ms, pmat, 0, pattern);
|
||||
|
||||
gk_csr_Free(&pmat);
|
||||
gk_free((void **)&pattern, ¶ms.rmarker, ¶ms.cand, LTERM);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! The recursive routine for DFS-based frequent pattern discovery */
|
||||
/*************************************************************************/
|
||||
void itemsets_find_frequent_itemsets(isparams_t *params, gk_csr_t *mat,
|
||||
int preflen, int *prefix)
|
||||
{
|
||||
ssize_t i;
|
||||
gk_csr_t *cmat;
|
||||
|
||||
/* Project each frequent column */
|
||||
for (i=0; i<mat->ncols; i++) {
|
||||
prefix[preflen] = mat->colids[i];
|
||||
|
||||
if (preflen+1 >= params->minlen)
|
||||
(*params->callback)(params->stateptr, preflen+1, prefix,
|
||||
mat->colptr[i+1]-mat->colptr[i], mat->colind+mat->colptr[i]);
|
||||
|
||||
if (preflen+1 < params->maxlen) {
|
||||
cmat = itemsets_project_matrix(params, mat, i);
|
||||
itemsets_find_frequent_itemsets(params, cmat, preflen+1, prefix);
|
||||
gk_csr_Free(&cmat);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*! This function projects a matrix w.r.t. to a particular column.
|
||||
It performs the following steps:
|
||||
- Determines the length of each column that is remaining
|
||||
- Sorts the columns in increasing length
|
||||
- Creates a column-based version of the matrix with the proper
|
||||
column ordering and renamed rowids.
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
gk_csr_t *itemsets_project_matrix(isparams_t *params, gk_csr_t *mat, int cid)
|
||||
{
|
||||
ssize_t i, j, k, ii, pnnz;
|
||||
int nrows, ncols, pnrows, pncols;
|
||||
ssize_t *colptr, *pcolptr;
|
||||
int *colind, *colids, *pcolind, *pcolids, *rmarker;
|
||||
gk_csr_t *pmat;
|
||||
gk_ikv_t *cand;
|
||||
|
||||
nrows = mat->nrows;
|
||||
ncols = mat->ncols;
|
||||
colptr = mat->colptr;
|
||||
colind = mat->colind;
|
||||
colids = mat->colids;
|
||||
|
||||
rmarker = params->rmarker;
|
||||
cand = params->cand;
|
||||
|
||||
|
||||
/* Allocate space for the projected matrix based on what you know thus far */
|
||||
pmat = gk_csr_Create();
|
||||
pmat->nrows = pnrows = (cid == -1 ? nrows : colptr[cid+1]-colptr[cid]);
|
||||
|
||||
|
||||
/* Mark the rows that will be kept and determine the prowids */
|
||||
if (cid == -1) { /* Initial projection */
|
||||
gk_iset(nrows, 1, rmarker);
|
||||
}
|
||||
else { /* The other projections */
|
||||
for (i=colptr[cid]; i<colptr[cid+1]; i++)
|
||||
rmarker[colind[i]] = 1;
|
||||
}
|
||||
|
||||
|
||||
/* Determine the length of each column that will be left in the projected matrix */
|
||||
for (pncols=0, pnnz=0, i=cid+1; i<ncols; i++) {
|
||||
for (k=0, j=colptr[i]; j<colptr[i+1]; j++) {
|
||||
k += rmarker[colind[j]];
|
||||
}
|
||||
if (k >= params->minfreq && k <= params->maxfreq) {
|
||||
cand[pncols].val = i;
|
||||
cand[pncols++].key = k;
|
||||
pnnz += k;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort the columns in increasing order */
|
||||
gk_ikvsorti(pncols, cand);
|
||||
|
||||
|
||||
/* Allocate space for the remaining fields of the projected matrix */
|
||||
pmat->ncols = pncols;
|
||||
pmat->colids = pcolids = gk_imalloc(pncols, "itemsets_project_matrix: pcolids");
|
||||
pmat->colptr = pcolptr = gk_zmalloc(pncols+1, "itemsets_project_matrix: pcolptr");
|
||||
pmat->colind = pcolind = gk_imalloc(pnnz, "itemsets_project_matrix: pcolind");
|
||||
|
||||
|
||||
/* Populate the projected matrix */
|
||||
pcolptr[0] = 0;
|
||||
for (pnnz=0, ii=0; ii<pncols; ii++) {
|
||||
i = cand[ii].val;
|
||||
for (j=colptr[i]; j<colptr[i+1]; j++) {
|
||||
if (rmarker[colind[j]])
|
||||
pcolind[pnnz++] = colind[j];
|
||||
}
|
||||
|
||||
pcolids[ii] = colids[i];
|
||||
pcolptr[ii+1] = pnnz;
|
||||
}
|
||||
|
||||
|
||||
/* Reset the rmarker array */
|
||||
if (cid == -1) { /* Initial projection */
|
||||
gk_iset(nrows, 0, rmarker);
|
||||
}
|
||||
else { /* The other projections */
|
||||
for (i=colptr[cid]; i<colptr[cid+1]; i++)
|
||||
rmarker[colind[i]] = 0;
|
||||
}
|
||||
|
||||
|
||||
return pmat;
|
||||
}
|
||||
|
|
@ -1,393 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Functions dealing with creating and allocating mcores
|
||||
|
||||
\date Started 5/30/11
|
||||
\author George
|
||||
\author Copyright 1997-2011, Regents of the University of Minnesota
|
||||
\version $Id: mcore.c 13953 2013-03-30 16:20:07Z karypis $
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function creates an mcore
|
||||
*/
|
||||
/*************************************************************************/
|
||||
gk_mcore_t *gk_mcoreCreate(size_t coresize)
|
||||
{
|
||||
gk_mcore_t *mcore;
|
||||
|
||||
mcore = (gk_mcore_t *)gk_malloc(sizeof(gk_mcore_t), "gk_mcoreCreate: mcore");
|
||||
memset(mcore, 0, sizeof(gk_mcore_t));
|
||||
|
||||
mcore->coresize = coresize;
|
||||
mcore->corecpos = 0;
|
||||
|
||||
mcore->core = (coresize == 0 ? NULL : gk_malloc(mcore->coresize, "gk_mcoreCreate: core"));
|
||||
|
||||
/* allocate the memory for keeping track of malloc ops */
|
||||
mcore->nmops = 2048;
|
||||
mcore->cmop = 0;
|
||||
mcore->mops = (gk_mop_t *)gk_malloc(mcore->nmops*sizeof(gk_mop_t), "gk_mcoreCreate: mcore->mops");
|
||||
|
||||
return mcore;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function creates an mcore. This version is used for gkmcore.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
gk_mcore_t *gk_gkmcoreCreate()
|
||||
{
|
||||
gk_mcore_t *mcore;
|
||||
|
||||
if ((mcore = (gk_mcore_t *)malloc(sizeof(gk_mcore_t))) == NULL)
|
||||
return NULL;
|
||||
memset(mcore, 0, sizeof(gk_mcore_t));
|
||||
|
||||
/* allocate the memory for keeping track of malloc ops */
|
||||
mcore->nmops = 2048;
|
||||
mcore->cmop = 0;
|
||||
if ((mcore->mops = (gk_mop_t *)malloc(mcore->nmops*sizeof(gk_mop_t))) == NULL) {
|
||||
free(mcore);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mcore;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function destroys an mcore.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_mcoreDestroy(gk_mcore_t **r_mcore, int showstats)
|
||||
{
|
||||
gk_mcore_t *mcore = *r_mcore;
|
||||
|
||||
if (mcore == NULL)
|
||||
return;
|
||||
|
||||
if (showstats)
|
||||
printf("\n gk_mcore statistics\n"
|
||||
" coresize: %12zu nmops: %12zu cmop: %6zu\n"
|
||||
" num_callocs: %12zu num_hallocs: %12zu\n"
|
||||
" size_callocs: %12zu size_hallocs: %12zu\n"
|
||||
" cur_callocs: %12zu cur_hallocs: %12zu\n"
|
||||
" max_callocs: %12zu max_hallocs: %12zu\n",
|
||||
mcore->coresize, mcore->nmops, mcore->cmop,
|
||||
mcore->num_callocs, mcore->num_hallocs,
|
||||
mcore->size_callocs, mcore->size_hallocs,
|
||||
mcore->cur_callocs, mcore->cur_hallocs,
|
||||
mcore->max_callocs, mcore->max_hallocs);
|
||||
|
||||
if (mcore->cur_callocs != 0 || mcore->cur_hallocs != 0 || mcore->cmop != 0) {
|
||||
printf("***Warning: mcore memory was not fully freed when destroyed.\n"
|
||||
" cur_callocs: %6zu cur_hallocs: %6zu cmop: %6zu\n",
|
||||
mcore->cur_callocs, mcore->cur_hallocs, mcore->cmop);
|
||||
}
|
||||
|
||||
gk_free((void **)&mcore->core, &mcore->mops, &mcore, LTERM);
|
||||
|
||||
*r_mcore = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function destroys an mcore. This version is for gkmcore.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_gkmcoreDestroy(gk_mcore_t **r_mcore, int showstats)
|
||||
{
|
||||
gk_mcore_t *mcore = *r_mcore;
|
||||
|
||||
if (mcore == NULL)
|
||||
return;
|
||||
|
||||
if (showstats)
|
||||
printf("\n gk_mcore statistics\n"
|
||||
" nmops: %12zu cmop: %6zu\n"
|
||||
" num_hallocs: %12zu\n"
|
||||
" size_hallocs: %12zu\n"
|
||||
" cur_hallocs: %12zu\n"
|
||||
" max_hallocs: %12zu\n",
|
||||
mcore->nmops, mcore->cmop,
|
||||
mcore->num_hallocs,
|
||||
mcore->size_hallocs,
|
||||
mcore->cur_hallocs,
|
||||
mcore->max_hallocs);
|
||||
|
||||
if (mcore->cur_hallocs != 0 || mcore->cmop != 0) {
|
||||
printf("***Warning: mcore memory was not fully freed when destroyed.\n"
|
||||
" cur_hallocs: %6zu cmop: %6zu\n",
|
||||
mcore->cur_hallocs, mcore->cmop);
|
||||
}
|
||||
|
||||
free(mcore->mops);
|
||||
free(mcore);
|
||||
|
||||
*r_mcore = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function allocate space from the core/heap
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void *gk_mcoreMalloc(gk_mcore_t *mcore, size_t nbytes)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
/* pad to make pointers 8-byte aligned */
|
||||
nbytes += (nbytes%8 == 0 ? 0 : 8 - nbytes%8);
|
||||
|
||||
if (mcore->corecpos + nbytes < mcore->coresize) {
|
||||
/* service this request from the core */
|
||||
ptr = ((char *)mcore->core)+mcore->corecpos;
|
||||
mcore->corecpos += nbytes;
|
||||
|
||||
gk_mcoreAdd(mcore, GK_MOPT_CORE, nbytes, ptr);
|
||||
}
|
||||
else {
|
||||
/* service this request from the heap */
|
||||
ptr = gk_malloc(nbytes, "gk_mcoremalloc: ptr");
|
||||
|
||||
gk_mcoreAdd(mcore, GK_MOPT_HEAP, nbytes, ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
printf("MCMALLOC: %zu %d %8zu\n", mcore->cmop-1,
|
||||
mcore->mops[mcore->cmop-1].type, mcore->mops[mcore->cmop-1].nbytes);
|
||||
*/
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function sets a marker in the stack of malloc ops to be used
|
||||
subsequently for freeing purposes
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_mcorePush(gk_mcore_t *mcore)
|
||||
{
|
||||
gk_mcoreAdd(mcore, GK_MOPT_MARK, 0, NULL);
|
||||
/* printf("MCPPUSH: %zu\n", mcore->cmop-1); */
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function sets a marker in the stack of malloc ops to be used
|
||||
subsequently for freeing purposes. This is the gkmcore version.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_gkmcorePush(gk_mcore_t *mcore)
|
||||
{
|
||||
gk_gkmcoreAdd(mcore, GK_MOPT_MARK, 0, NULL);
|
||||
/* printf("MCPPUSH: %zu\n", mcore->cmop-1); */
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function frees all mops since the last push
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_mcorePop(gk_mcore_t *mcore)
|
||||
{
|
||||
while (mcore->cmop > 0) {
|
||||
mcore->cmop--;
|
||||
switch (mcore->mops[mcore->cmop].type) {
|
||||
case GK_MOPT_MARK: /* push marker */
|
||||
goto DONE;
|
||||
break;
|
||||
|
||||
case GK_MOPT_CORE: /* core free */
|
||||
if (mcore->corecpos < mcore->mops[mcore->cmop].nbytes)
|
||||
errexit("Internal Error: wspace's core is about to be over-freed [%zu, %zu, %zd]\n",
|
||||
mcore->coresize, mcore->corecpos, mcore->mops[mcore->cmop].nbytes);
|
||||
|
||||
mcore->corecpos -= mcore->mops[mcore->cmop].nbytes;
|
||||
mcore->cur_callocs -= mcore->mops[mcore->cmop].nbytes;
|
||||
break;
|
||||
|
||||
case GK_MOPT_HEAP: /* heap free */
|
||||
gk_free((void **)&mcore->mops[mcore->cmop].ptr, LTERM);
|
||||
mcore->cur_hallocs -= mcore->mops[mcore->cmop].nbytes;
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGMEM, "Unknown mop type of %d\n", mcore->mops[mcore->cmop].type);
|
||||
}
|
||||
}
|
||||
|
||||
DONE:
|
||||
;
|
||||
/*printf("MCPPOP: %zu\n", mcore->cmop); */
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function frees all mops since the last push. This version is
|
||||
for poping the gkmcore and it uses free instead of gk_free.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_gkmcorePop(gk_mcore_t *mcore)
|
||||
{
|
||||
while (mcore->cmop > 0) {
|
||||
mcore->cmop--;
|
||||
switch (mcore->mops[mcore->cmop].type) {
|
||||
case GK_MOPT_MARK: /* push marker */
|
||||
goto DONE;
|
||||
break;
|
||||
|
||||
case GK_MOPT_HEAP: /* heap free */
|
||||
free(mcore->mops[mcore->cmop].ptr);
|
||||
mcore->cur_hallocs -= mcore->mops[mcore->cmop].nbytes;
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGMEM, "Unknown mop type of %d\n", mcore->mops[mcore->cmop].type);
|
||||
}
|
||||
}
|
||||
|
||||
DONE:
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Adds a memory allocation at the end of the list.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_mcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr)
|
||||
{
|
||||
if (mcore->cmop == mcore->nmops) {
|
||||
mcore->nmops *= 2;
|
||||
mcore->mops = realloc(mcore->mops, mcore->nmops*sizeof(gk_mop_t));
|
||||
if (mcore->mops == NULL)
|
||||
gk_errexit(SIGMEM, "***Memory allocation for gkmcore failed.\n");
|
||||
}
|
||||
|
||||
mcore->mops[mcore->cmop].type = type;
|
||||
mcore->mops[mcore->cmop].nbytes = nbytes;
|
||||
mcore->mops[mcore->cmop].ptr = ptr;
|
||||
mcore->cmop++;
|
||||
|
||||
switch (type) {
|
||||
case GK_MOPT_MARK:
|
||||
break;
|
||||
|
||||
case GK_MOPT_CORE:
|
||||
mcore->num_callocs++;
|
||||
mcore->size_callocs += nbytes;
|
||||
mcore->cur_callocs += nbytes;
|
||||
if (mcore->max_callocs < mcore->cur_callocs)
|
||||
mcore->max_callocs = mcore->cur_callocs;
|
||||
break;
|
||||
|
||||
case GK_MOPT_HEAP:
|
||||
mcore->num_hallocs++;
|
||||
mcore->size_hallocs += nbytes;
|
||||
mcore->cur_hallocs += nbytes;
|
||||
if (mcore->max_hallocs < mcore->cur_hallocs)
|
||||
mcore->max_hallocs = mcore->cur_hallocs;
|
||||
break;
|
||||
default:
|
||||
gk_errexit(SIGMEM, "Incorrect mcore type operation.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Adds a memory allocation at the end of the list. This is the gkmcore
|
||||
version.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_gkmcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr)
|
||||
{
|
||||
if (mcore->cmop == mcore->nmops) {
|
||||
mcore->nmops *= 2;
|
||||
mcore->mops = realloc(mcore->mops, mcore->nmops*sizeof(gk_mop_t));
|
||||
if (mcore->mops == NULL)
|
||||
gk_errexit(SIGMEM, "***Memory allocation for gkmcore failed.\n");
|
||||
}
|
||||
|
||||
mcore->mops[mcore->cmop].type = type;
|
||||
mcore->mops[mcore->cmop].nbytes = nbytes;
|
||||
mcore->mops[mcore->cmop].ptr = ptr;
|
||||
mcore->cmop++;
|
||||
|
||||
switch (type) {
|
||||
case GK_MOPT_MARK:
|
||||
break;
|
||||
|
||||
case GK_MOPT_HEAP:
|
||||
mcore->num_hallocs++;
|
||||
mcore->size_hallocs += nbytes;
|
||||
mcore->cur_hallocs += nbytes;
|
||||
if (mcore->max_hallocs < mcore->cur_hallocs)
|
||||
mcore->max_hallocs = mcore->cur_hallocs;
|
||||
break;
|
||||
default:
|
||||
gk_errexit(SIGMEM, "Incorrect mcore type operation.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function deletes the mop associated with the supplied pointer.
|
||||
The mop has to be a heap allocation, otherwise it fails violently.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_mcoreDel(gk_mcore_t *mcore, void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=mcore->cmop-1; i>=0; i--) {
|
||||
if (mcore->mops[i].type == GK_MOPT_MARK)
|
||||
gk_errexit(SIGMEM, "Could not find pointer %p in mcore\n", ptr);
|
||||
|
||||
if (mcore->mops[i].ptr == ptr) {
|
||||
if (mcore->mops[i].type != GK_MOPT_HEAP)
|
||||
gk_errexit(SIGMEM, "Trying to delete a non-HEAP mop.\n");
|
||||
|
||||
mcore->cur_hallocs -= mcore->mops[i].nbytes;
|
||||
mcore->mops[i] = mcore->mops[--mcore->cmop];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gk_errexit(SIGMEM, "mcoreDel should never have been here!\n");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function deletes the mop associated with the supplied pointer.
|
||||
The mop has to be a heap allocation, otherwise it fails violently.
|
||||
This is the gkmcore version.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_gkmcoreDel(gk_mcore_t *mcore, void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=mcore->cmop-1; i>=0; i--) {
|
||||
if (mcore->mops[i].type == GK_MOPT_MARK)
|
||||
gk_errexit(SIGMEM, "Could not find pointer %p in mcore\n", ptr);
|
||||
|
||||
if (mcore->mops[i].ptr == ptr) {
|
||||
if (mcore->mops[i].type != GK_MOPT_HEAP)
|
||||
gk_errexit(SIGMEM, "Trying to delete a non-HEAP mop.\n");
|
||||
|
||||
mcore->cur_hallocs -= mcore->mops[i].nbytes;
|
||||
mcore->mops[i] = mcore->mops[--mcore->cmop];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gk_errexit(SIGMEM, "gkmcoreDel should never have been here!\n");
|
||||
}
|
||||
|
||||
|
|
@ -1,252 +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 10783 2011-09-21 23:19:56Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
/* This is for the global mcore that tracks all heap allocations */
|
||||
static __thread gk_mcore_t *gkmcore = NULL;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Define the set of memory allocation routines for each data type */
|
||||
/**************************************************************************/
|
||||
GK_MKALLOC(gk_c, char)
|
||||
GK_MKALLOC(gk_i, int)
|
||||
GK_MKALLOC(gk_i32, int32_t)
|
||||
GK_MKALLOC(gk_i64, int64_t)
|
||||
GK_MKALLOC(gk_z, ssize_t)
|
||||
GK_MKALLOC(gk_f, float)
|
||||
GK_MKALLOC(gk_d, double)
|
||||
GK_MKALLOC(gk_idx, gk_idx_t)
|
||||
|
||||
GK_MKALLOC(gk_ckv, gk_ckv_t)
|
||||
GK_MKALLOC(gk_ikv, gk_ikv_t)
|
||||
GK_MKALLOC(gk_i32kv, gk_i32kv_t)
|
||||
GK_MKALLOC(gk_i64kv, gk_i64kv_t)
|
||||
GK_MKALLOC(gk_zkv, gk_zkv_t)
|
||||
GK_MKALLOC(gk_fkv, gk_fkv_t)
|
||||
GK_MKALLOC(gk_dkv, gk_dkv_t)
|
||||
GK_MKALLOC(gk_skv, gk_skv_t)
|
||||
GK_MKALLOC(gk_idxkv, gk_idxkv_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, j;
|
||||
void **matrix;
|
||||
|
||||
*r_matrix = NULL;
|
||||
|
||||
if ((matrix = (void **)gk_malloc(ndim1*sizeof(void *), "gk_AllocMatrix: matrix")) == NULL)
|
||||
return;
|
||||
|
||||
for (i=0; i<ndim1; i++) {
|
||||
if ((matrix[i] = (void *)gk_malloc(ndim2*elmlen, "gk_AllocMatrix: matrix[i]")) == NULL) {
|
||||
for (j=0; j<i; j++)
|
||||
gk_free((void **)&matrix[j], LTERM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*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;
|
||||
|
||||
if ((matrix = *r_matrix) == NULL)
|
||||
return;
|
||||
|
||||
for (i=0; i<ndim1; i++)
|
||||
gk_free((void **)&matrix[i], LTERM);
|
||||
|
||||
gk_free((void **)r_matrix, LTERM);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function initializes tracking of heap allocations.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int gk_malloc_init()
|
||||
{
|
||||
if (gkmcore == NULL)
|
||||
gkmcore = gk_gkmcoreCreate();
|
||||
|
||||
if (gkmcore == NULL)
|
||||
return 0;
|
||||
|
||||
gk_gkmcorePush(gkmcore);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function frees the memory that has been allocated since the
|
||||
last call to gk_malloc_init().
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void gk_malloc_cleanup(int showstats)
|
||||
{
|
||||
if (gkmcore != NULL) {
|
||||
gk_gkmcorePop(gkmcore);
|
||||
if (gkmcore->cmop == 0) {
|
||||
gk_gkmcoreDestroy(&gkmcore, showstats);
|
||||
gkmcore = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function is my wrapper around malloc that provides the following
|
||||
enhancements over malloc:
|
||||
* It always allocates one byte of memory, even if 0 bytes are requested.
|
||||
This is to ensure that checks of returned values do not lead to NULL
|
||||
due to 0 bytes requested.
|
||||
* It zeros-out the memory that is allocated. This is for a quick init
|
||||
of the underlying datastructures.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void *gk_malloc(size_t nbytes, char *msg)
|
||||
{
|
||||
void *ptr=NULL;
|
||||
|
||||
if (nbytes == 0)
|
||||
nbytes++; /* Force mallocs to actually allocate some memory */
|
||||
|
||||
ptr = (void *)malloc(nbytes);
|
||||
|
||||
if (ptr == NULL) {
|
||||
fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed());
|
||||
fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed());
|
||||
gk_errexit(SIGMEM, "***Memory allocation failed for %s. Requested size: %zu bytes",
|
||||
msg, nbytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add this memory allocation */
|
||||
if (gkmcore != NULL) gk_gkmcoreAdd(gkmcore, GK_MOPT_HEAP, nbytes, ptr);
|
||||
|
||||
/* zero-out the allocated space */
|
||||
#ifndef NDEBUG
|
||||
memset(ptr, 0, nbytes);
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function is my wrapper around realloc
|
||||
**************************************************************************/
|
||||
void *gk_realloc(void *oldptr, size_t nbytes, char *msg)
|
||||
{
|
||||
void *ptr=NULL;
|
||||
|
||||
if (nbytes == 0)
|
||||
nbytes++; /* Force mallocs to actually allocate some memory */
|
||||
|
||||
/* remove this memory de-allocation */
|
||||
if (gkmcore != NULL && oldptr != NULL) gk_gkmcoreDel(gkmcore, oldptr);
|
||||
|
||||
ptr = (void *)realloc(oldptr, nbytes);
|
||||
|
||||
if (ptr == NULL) {
|
||||
fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed());
|
||||
fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed());
|
||||
gk_errexit(SIGMEM, "***Memory realloc failed for %s. " "Requested size: %zu bytes",
|
||||
msg, nbytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add this memory allocation */
|
||||
if (gkmcore != NULL) gk_gkmcoreAdd(gkmcore, GK_MOPT_HEAP, nbytes, ptr);
|
||||
|
||||
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) {
|
||||
free(*ptr1);
|
||||
|
||||
/* remove this memory de-allocation */
|
||||
if (gkmcore != NULL) gk_gkmcoreDel(gkmcore, *ptr1);
|
||||
}
|
||||
*ptr1 = NULL;
|
||||
|
||||
va_start(plist, ptr1);
|
||||
while ((ptr = va_arg(plist, void **)) != LTERM) {
|
||||
if (*ptr != NULL) {
|
||||
free(*ptr);
|
||||
|
||||
/* remove this memory de-allocation */
|
||||
if (gkmcore != NULL) gk_gkmcoreDel(gkmcore, *ptr);
|
||||
}
|
||||
*ptr = NULL;
|
||||
}
|
||||
va_end(plist);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function returns the current ammount of dynamically allocated
|
||||
* memory that is used by the system
|
||||
**************************************************************************/
|
||||
size_t gk_GetCurMemoryUsed()
|
||||
{
|
||||
if (gkmcore == NULL)
|
||||
return 0;
|
||||
else
|
||||
return gkmcore->cur_hallocs;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function returns the maximum ammount of dynamically allocated
|
||||
* memory that was used by the system
|
||||
**************************************************************************/
|
||||
size_t gk_GetMaxMemoryUsed()
|
||||
{
|
||||
if (gkmcore == NULL)
|
||||
return 0;
|
||||
else
|
||||
return gkmcore->max_hallocs;
|
||||
}
|
||||
|
|
@ -1,301 +0,0 @@
|
|||
// ISO C9x compliant inttypes.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_INTTYPES_H_ // [
|
||||
#define _MSC_INTTYPES_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "ms_stdint.h"
|
||||
|
||||
// 7.8 Format conversion of integer types
|
||||
|
||||
typedef struct {
|
||||
intmax_t quot;
|
||||
intmax_t rem;
|
||||
} imaxdiv_t;
|
||||
|
||||
// 7.8.1 Macros for format specifiers
|
||||
|
||||
// The fprintf macros for signed integers are:
|
||||
#define PRId8 "d"
|
||||
#define PRIi8 "i"
|
||||
#define PRIdLEAST8 "d"
|
||||
#define PRIiLEAST8 "i"
|
||||
#define PRIdFAST8 "d"
|
||||
#define PRIiFAST8 "i"
|
||||
|
||||
#define PRId16 "hd"
|
||||
#define PRIi16 "hi"
|
||||
#define PRIdLEAST16 "hd"
|
||||
#define PRIiLEAST16 "hi"
|
||||
#define PRIdFAST16 "hd"
|
||||
#define PRIiFAST16 "hi"
|
||||
|
||||
#define PRId32 "I32d"
|
||||
#define PRIi32 "I32i"
|
||||
#define PRIdLEAST32 "I32d"
|
||||
#define PRIiLEAST32 "I32i"
|
||||
#define PRIdFAST32 "I32d"
|
||||
#define PRIiFAST32 "I32i"
|
||||
|
||||
#define PRId64 "I64d"
|
||||
#define PRIi64 "I64i"
|
||||
#define PRIdLEAST64 "I64d"
|
||||
#define PRIiLEAST64 "I64i"
|
||||
#define PRIdFAST64 "I64d"
|
||||
#define PRIiFAST64 "I64i"
|
||||
|
||||
#define PRIdMAX "I64d"
|
||||
#define PRIiMAX "I64i"
|
||||
|
||||
#define PRIdPTR "Id"
|
||||
#define PRIiPTR "Ii"
|
||||
|
||||
// The fprintf macros for unsigned integers are:
|
||||
#define PRIo8 "o"
|
||||
#define PRIu8 "u"
|
||||
#define PRIx8 "x"
|
||||
#define PRIX8 "X"
|
||||
#define PRIoLEAST8 "o"
|
||||
#define PRIuLEAST8 "u"
|
||||
#define PRIxLEAST8 "x"
|
||||
#define PRIXLEAST8 "X"
|
||||
#define PRIoFAST8 "o"
|
||||
#define PRIuFAST8 "u"
|
||||
#define PRIxFAST8 "x"
|
||||
#define PRIXFAST8 "X"
|
||||
|
||||
#define PRIo16 "ho"
|
||||
#define PRIu16 "hu"
|
||||
#define PRIx16 "hx"
|
||||
#define PRIX16 "hX"
|
||||
#define PRIoLEAST16 "ho"
|
||||
#define PRIuLEAST16 "hu"
|
||||
#define PRIxLEAST16 "hx"
|
||||
#define PRIXLEAST16 "hX"
|
||||
#define PRIoFAST16 "ho"
|
||||
#define PRIuFAST16 "hu"
|
||||
#define PRIxFAST16 "hx"
|
||||
#define PRIXFAST16 "hX"
|
||||
|
||||
#define PRIo32 "I32o"
|
||||
#define PRIu32 "I32u"
|
||||
#define PRIx32 "I32x"
|
||||
#define PRIX32 "I32X"
|
||||
#define PRIoLEAST32 "I32o"
|
||||
#define PRIuLEAST32 "I32u"
|
||||
#define PRIxLEAST32 "I32x"
|
||||
#define PRIXLEAST32 "I32X"
|
||||
#define PRIoFAST32 "I32o"
|
||||
#define PRIuFAST32 "I32u"
|
||||
#define PRIxFAST32 "I32x"
|
||||
#define PRIXFAST32 "I32X"
|
||||
|
||||
#define PRIo64 "I64o"
|
||||
#define PRIu64 "I64u"
|
||||
#define PRIx64 "I64x"
|
||||
#define PRIX64 "I64X"
|
||||
#define PRIoLEAST64 "I64o"
|
||||
#define PRIuLEAST64 "I64u"
|
||||
#define PRIxLEAST64 "I64x"
|
||||
#define PRIXLEAST64 "I64X"
|
||||
#define PRIoFAST64 "I64o"
|
||||
#define PRIuFAST64 "I64u"
|
||||
#define PRIxFAST64 "I64x"
|
||||
#define PRIXFAST64 "I64X"
|
||||
|
||||
#define PRIoMAX "I64o"
|
||||
#define PRIuMAX "I64u"
|
||||
#define PRIxMAX "I64x"
|
||||
#define PRIXMAX "I64X"
|
||||
|
||||
#define PRIoPTR "Io"
|
||||
#define PRIuPTR "Iu"
|
||||
#define PRIxPTR "Ix"
|
||||
#define PRIXPTR "IX"
|
||||
|
||||
// The fscanf macros for signed integers are:
|
||||
#define SCNd8 "d"
|
||||
#define SCNi8 "i"
|
||||
#define SCNdLEAST8 "d"
|
||||
#define SCNiLEAST8 "i"
|
||||
#define SCNdFAST8 "d"
|
||||
#define SCNiFAST8 "i"
|
||||
|
||||
#define SCNd16 "hd"
|
||||
#define SCNi16 "hi"
|
||||
#define SCNdLEAST16 "hd"
|
||||
#define SCNiLEAST16 "hi"
|
||||
#define SCNdFAST16 "hd"
|
||||
#define SCNiFAST16 "hi"
|
||||
|
||||
#define SCNd32 "ld"
|
||||
#define SCNi32 "li"
|
||||
#define SCNdLEAST32 "ld"
|
||||
#define SCNiLEAST32 "li"
|
||||
#define SCNdFAST32 "ld"
|
||||
#define SCNiFAST32 "li"
|
||||
|
||||
#define SCNd64 "I64d"
|
||||
#define SCNi64 "I64i"
|
||||
#define SCNdLEAST64 "I64d"
|
||||
#define SCNiLEAST64 "I64i"
|
||||
#define SCNdFAST64 "I64d"
|
||||
#define SCNiFAST64 "I64i"
|
||||
|
||||
#define SCNdMAX "I64d"
|
||||
#define SCNiMAX "I64i"
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define SCNdPTR "I64d"
|
||||
# define SCNiPTR "I64i"
|
||||
#else // _WIN64 ][
|
||||
# define SCNdPTR "ld"
|
||||
# define SCNiPTR "li"
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// The fscanf macros for unsigned integers are:
|
||||
#define SCNo8 "o"
|
||||
#define SCNu8 "u"
|
||||
#define SCNx8 "x"
|
||||
#define SCNX8 "X"
|
||||
#define SCNoLEAST8 "o"
|
||||
#define SCNuLEAST8 "u"
|
||||
#define SCNxLEAST8 "x"
|
||||
#define SCNXLEAST8 "X"
|
||||
#define SCNoFAST8 "o"
|
||||
#define SCNuFAST8 "u"
|
||||
#define SCNxFAST8 "x"
|
||||
#define SCNXFAST8 "X"
|
||||
|
||||
#define SCNo16 "ho"
|
||||
#define SCNu16 "hu"
|
||||
#define SCNx16 "hx"
|
||||
#define SCNX16 "hX"
|
||||
#define SCNoLEAST16 "ho"
|
||||
#define SCNuLEAST16 "hu"
|
||||
#define SCNxLEAST16 "hx"
|
||||
#define SCNXLEAST16 "hX"
|
||||
#define SCNoFAST16 "ho"
|
||||
#define SCNuFAST16 "hu"
|
||||
#define SCNxFAST16 "hx"
|
||||
#define SCNXFAST16 "hX"
|
||||
|
||||
#define SCNo32 "lo"
|
||||
#define SCNu32 "lu"
|
||||
#define SCNx32 "lx"
|
||||
#define SCNX32 "lX"
|
||||
#define SCNoLEAST32 "lo"
|
||||
#define SCNuLEAST32 "lu"
|
||||
#define SCNxLEAST32 "lx"
|
||||
#define SCNXLEAST32 "lX"
|
||||
#define SCNoFAST32 "lo"
|
||||
#define SCNuFAST32 "lu"
|
||||
#define SCNxFAST32 "lx"
|
||||
#define SCNXFAST32 "lX"
|
||||
|
||||
#define SCNo64 "I64o"
|
||||
#define SCNu64 "I64u"
|
||||
#define SCNx64 "I64x"
|
||||
#define SCNX64 "I64X"
|
||||
#define SCNoLEAST64 "I64o"
|
||||
#define SCNuLEAST64 "I64u"
|
||||
#define SCNxLEAST64 "I64x"
|
||||
#define SCNXLEAST64 "I64X"
|
||||
#define SCNoFAST64 "I64o"
|
||||
#define SCNuFAST64 "I64u"
|
||||
#define SCNxFAST64 "I64x"
|
||||
#define SCNXFAST64 "I64X"
|
||||
|
||||
#define SCNoMAX "I64o"
|
||||
#define SCNuMAX "I64u"
|
||||
#define SCNxMAX "I64x"
|
||||
#define SCNXMAX "I64X"
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define SCNoPTR "I64o"
|
||||
# define SCNuPTR "I64u"
|
||||
# define SCNxPTR "I64x"
|
||||
# define SCNXPTR "I64X"
|
||||
#else // _WIN64 ][
|
||||
# define SCNoPTR "lo"
|
||||
# define SCNuPTR "lu"
|
||||
# define SCNxPTR "lx"
|
||||
# define SCNXPTR "lX"
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.8.2 Functions for greatest-width integer types
|
||||
|
||||
// 7.8.2.1 The imaxabs function
|
||||
#define imaxabs _abs64
|
||||
|
||||
// 7.8.2.2 The imaxdiv function
|
||||
|
||||
// This is modified version of div() function from Microsoft's div.c found
|
||||
// in %MSVC.NET%\crt\src\div.c
|
||||
#ifdef STATIC_IMAXDIV // [
|
||||
static
|
||||
#else // STATIC_IMAXDIV ][
|
||||
_inline
|
||||
#endif // STATIC_IMAXDIV ]
|
||||
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
|
||||
{
|
||||
imaxdiv_t result;
|
||||
|
||||
result.quot = numer / denom;
|
||||
result.rem = numer % denom;
|
||||
|
||||
if (numer < 0 && result.rem > 0) {
|
||||
// did division wrong; must fix up
|
||||
++result.quot;
|
||||
result.rem -= denom;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 7.8.2.3 The strtoimax and strtoumax functions
|
||||
#define strtoimax _strtoi64
|
||||
#define strtoumax _strtoui64
|
||||
|
||||
// 7.8.2.4 The wcstoimax and wcstoumax functions
|
||||
#define wcstoimax _wcstoi64
|
||||
#define wcstoumax _wcstoui64
|
||||
|
||||
|
||||
#endif // _MSC_INTTYPES_H_ ]
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MS_STAT_H_
|
||||
#define _MS_STAT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
/* Test macros for file types. */
|
||||
|
||||
#define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask))
|
||||
|
||||
#define S_ISDIR(mode) __S_ISTYPE((mode), S_IFDIR)
|
||||
#define S_ISCHR(mode) __S_ISTYPE((mode), S_IFCHR)
|
||||
#define S_ISBLK(mode) __S_ISTYPE((mode), S_IFBLK)
|
||||
#define S_ISREG(mode) __S_ISTYPE((mode), S_IFREG)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#if (_MSC_VER < 1300) && defined(__cplusplus)
|
||||
extern "C++" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#if (_MSC_VER < 1300) && defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
|
|
@ -1,27 +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>
|
||||
|
||||
#ifdef GK_NOOPENMP /* remove those for now */
|
||||
#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 0; }
|
||||
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
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,460 +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 10711 2011-08-31 22:23:04Z karypis $
|
||||
*/
|
||||
/************************************************************************/
|
||||
#include <GKlib.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);
|
||||
}
|
||||
for(i=0; i<p->nresidues; i++) {
|
||||
gk_free((void *)&p->threeresSeq[i], 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, &p->cm, &p->threeresSeq, 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 avgx;
|
||||
double avgy;
|
||||
double avgz;
|
||||
double opcy;
|
||||
double tmpt;
|
||||
char line[MAXLINELEN];
|
||||
int corruption=0;
|
||||
int nresatoms;
|
||||
|
||||
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->threeresSeq = (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");
|
||||
toFill->cm = (center_of_mass *)gk_malloc(residues*sizeof(center_of_mass),"center of mass");
|
||||
res=0; firstres=1; cas=0; bbs=0; i=0;
|
||||
avgx = 0.0; avgy = 0.0; avgz = 0.0;
|
||||
nresatoms = 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);
|
||||
toFill->threeresSeq[res] = gk_strdup(rname);
|
||||
oldRserial = rserial;
|
||||
res++;
|
||||
firstres = 0;
|
||||
}
|
||||
if(oldRserial != rserial) {
|
||||
/* we're changing residues. store the center of mass from the last one & reset */
|
||||
toFill->cm[res-1].x = avgx/nresatoms;
|
||||
toFill->cm[res-1].y = avgy/nresatoms;
|
||||
toFill->cm[res-1].z = avgz/nresatoms;
|
||||
avgx = 0.0; avgy = 0.0; avgz = 0.0;
|
||||
nresatoms = 0;
|
||||
toFill->cm[res-1].name = toFill->resSeq[res-1];
|
||||
|
||||
toFill->threeresSeq[res] = gk_strdup(rname);
|
||||
toFill->resSeq[res] = gk_threetoone(rname);
|
||||
res++;
|
||||
oldRserial = rserial;
|
||||
}
|
||||
avgx += x;
|
||||
avgy += y;
|
||||
avgz += z;
|
||||
nresatoms++;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* get that last average */
|
||||
toFill->cm[res-1].x = avgx/nresatoms;
|
||||
toFill->cm[res-1].y = avgy/nresatoms;
|
||||
toFill->cm[res-1].z = avgz/nresatoms;
|
||||
/* 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 *FPOUT;
|
||||
|
||||
FPOUT = gk_fopen(fname,"w",fname);
|
||||
fprintf(FPOUT,"> %s\n",fname);
|
||||
|
||||
for(i=0; i<pb->nresidues; i++)
|
||||
fprintf(FPOUT,"%c",pb->resSeq[i]);
|
||||
|
||||
fprintf(FPOUT,"\n");
|
||||
fclose(FPOUT);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/*! \brief Writes all centers of mass in pdb-format to file fname.
|
||||
|
||||
This function takes a pdbf structure and writes out the calculated
|
||||
mass center information to file fname as though each one was a c-alpha.
|
||||
|
||||
\param p is the pdbf structure to write out
|
||||
\param fname is the file name to be written
|
||||
*/
|
||||
/************************************************************************/
|
||||
void gk_writecentersofmass(pdbf *p, char *fname) {
|
||||
int i;
|
||||
FILE *FPIN;
|
||||
FPIN = gk_fopen(fname,"w",fname);
|
||||
for(i=0; i<p->nresidues; i++) {
|
||||
fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n",
|
||||
"ATOM ",i,"CA",' ',p->threeresSeq[i],' ',i,' ',p->cm[i].x,p->cm[i].y,p->cm[i].z,1.0,-37.0);
|
||||
}
|
||||
fclose(FPIN);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/*! \brief Writes all atoms in p in pdb-format to file fname.
|
||||
|
||||
This function takes a pdbf structure and writes out all the atom
|
||||
information to file fname.
|
||||
|
||||
\param p is the pdbf structure to write out
|
||||
\param fname is the file name to be written
|
||||
*/
|
||||
/************************************************************************/
|
||||
void gk_writefullatom(pdbf *p, char *fname) {
|
||||
int i;
|
||||
FILE *FPIN;
|
||||
FPIN = gk_fopen(fname,"w",fname);
|
||||
for(i=0; i<p->natoms; i++) {
|
||||
fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n",
|
||||
"ATOM ",p->atoms[i].serial,p->atoms[i].name,p->atoms[i].altLoc,p->atoms[i].resname,p->atoms[i].chainid,p->atoms[i].rserial,p->atoms[i].icode,p->atoms[i].x,p->atoms[i].y,p->atoms[i].z,p->atoms[i].opcy,p->atoms[i].tmpt);
|
||||
}
|
||||
fclose(FPIN);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/*! \brief Writes out all the backbone atoms of a structure in pdb format
|
||||
|
||||
This function takes a pdbf structure p and writes only the backbone atoms
|
||||
to a filename fname.
|
||||
|
||||
\param p is the pdb structure to write out.
|
||||
\param fname is the file name to be written.
|
||||
*/
|
||||
/************************************************************************/
|
||||
void gk_writebackbone(pdbf *p, char *fname) {
|
||||
int i;
|
||||
FILE *FPIN;
|
||||
FPIN = gk_fopen(fname,"w",fname);
|
||||
for(i=0; i<p->nbbs; i++) {
|
||||
fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n",
|
||||
"ATOM ",p->bbs[i]->serial,p->bbs[i]->name,p->bbs[i]->altLoc,p->bbs[i]->resname,p->bbs[i]->chainid,p->bbs[i]->rserial,p->bbs[i]->icode,p->bbs[i]->x,p->bbs[i]->y,p->bbs[i]->z,p->bbs[i]->opcy,p->bbs[i]->tmpt);
|
||||
}
|
||||
fclose(FPIN);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/*! \brief Writes out all the alpha carbon atoms of a structure
|
||||
|
||||
This function takes a pdbf structure p and writes only the alpha carbon
|
||||
atoms to a filename fname.
|
||||
|
||||
\param p is the pdb structure to write out.
|
||||
\param fname is the file name to be written.
|
||||
*/
|
||||
/************************************************************************/
|
||||
void gk_writealphacarbons(pdbf *p, char *fname) {
|
||||
int i;
|
||||
FILE *FPIN;
|
||||
FPIN = gk_fopen(fname,"w",fname);
|
||||
for(i=0; i<p->ncas; i++) {
|
||||
fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n",
|
||||
"ATOM ",p->cas[i]->serial,p->cas[i]->name,p->cas[i]->altLoc,p->cas[i]->resname,p->cas[i]->chainid,p->cas[i]->rserial,p->cas[i]->icode,p->cas[i]->x,p->cas[i]->y,p->cas[i]->z,p->cas[i]->opcy,p->cas[i]->tmpt);
|
||||
}
|
||||
fclose(FPIN);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/*! \brief Decodes the corruption bitswitch and prints any problems
|
||||
|
||||
Due to the totally unreliable nature of the pdb format, reading a pdb
|
||||
file stores a corruption bitswitch, and this function decodes that switch
|
||||
and prints the result on stdout.
|
||||
|
||||
\param p is the pdb structure to write out.
|
||||
\param fname is the file name to be written.
|
||||
*/
|
||||
/************************************************************************/
|
||||
void gk_showcorruption(pdbf *p) {
|
||||
int corruption = p->corruption;
|
||||
if(corruption&CRP_ALTLOCS)
|
||||
printf("Multiple coordinate sets for at least one atom\n");
|
||||
if(corruption&CRP_MISSINGCA)
|
||||
printf("Missing coordiantes for at least one CA atom\n");
|
||||
if(corruption&CRP_MISSINGBB)
|
||||
printf("Missing coordiantes for at least one backbone atom (N,CA,C,O)\n");
|
||||
if(corruption&CRP_MULTICHAIN)
|
||||
printf("File contains coordinates for multiple chains\n");
|
||||
if(corruption&CRP_MULTICA)
|
||||
printf("Multiple CA atoms found for the same residue (could be alternate locators)\n");
|
||||
if(corruption&CRP_MULTICA)
|
||||
printf("Multiple copies of backbone atoms found for the same residue (could be alternate locators)\n");
|
||||
}
|
||||
/* sscanf(line, "%6s%5d%*1c%4s%1c%3s%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf%*6c%4s%2s%2s\n",
|
||||
linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,segId,element,charge);
|
||||
printf(".%s.%s.%s.\n",segId,element,charge);
|
||||
printf("%-6s%5d%-1s%-4s%1c%3s%1s%1c%4d%1c%3s%8.3lf%8.3lf%8.3lf%6.2f%6.2f%6s%4s%2s%2s\n",
|
||||
linetype,aserial," ",aname,altLoc,rname," ",chainid,rserial,icode," ",x,y,z,opcy,tmpt," ",segId,element,charge); */
|
||||
|
||||
/* and we could probably get away with this using astral files, */
|
||||
/* sscanf(line, "%6s%5d%*1c%4s%1c%3s%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf%*6c%6s\n",
|
||||
linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,element);
|
||||
printf("%-6s%5d%-1s%-4s%1c%3s%1s%1c%4d%1c%3s%8.3lf%8.3lf%8.3lf%6.2f%6.2f%6s%6s\n",
|
||||
linetype,aserial," ",aname,altLoc,rname," ",chainid,rserial,icode," ",x,y,z,opcy,tmpt," ",element); */
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
/*!
|
||||
\file pqueue.c
|
||||
\brief This file implements various max-priority queues.
|
||||
|
||||
The priority queues are generated using the GK_MKPQUEUE macro.
|
||||
|
||||
\date Started 3/27/2007
|
||||
\author George
|
||||
\version\verbatim $Id: pqueue.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Create the various max priority queues */
|
||||
/*************************************************************************/
|
||||
#define key_gt(a, b) ((a) > (b))
|
||||
GK_MKPQUEUE(gk_ipq, gk_ipq_t, gk_ikv_t, int, gk_idx_t, gk_ikvmalloc, INT_MAX, key_gt)
|
||||
GK_MKPQUEUE(gk_i32pq, gk_i32pq_t, gk_i32kv_t, int32_t, gk_idx_t, gk_i32kvmalloc, INT32_MAX, key_gt)
|
||||
GK_MKPQUEUE(gk_i64pq, gk_i64pq_t, gk_i64kv_t, int64_t, gk_idx_t, gk_i64kvmalloc, INT64_MAX, key_gt)
|
||||
GK_MKPQUEUE(gk_fpq, gk_fpq_t, gk_fkv_t, float, gk_idx_t, gk_fkvmalloc, FLT_MAX, key_gt)
|
||||
GK_MKPQUEUE(gk_dpq, gk_dpq_t, gk_dkv_t, double, gk_idx_t, gk_dkvmalloc, DBL_MAX, key_gt)
|
||||
GK_MKPQUEUE(gk_idxpq, gk_idxpq_t, gk_idxkv_t, gk_idx_t, gk_idx_t, gk_idxkvmalloc, GK_IDX_MAX, key_gt)
|
||||
#undef key_gt
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Various routines for providing portable 32 and 64 bit random number
|
||||
generators.
|
||||
|
||||
\date Started 5/17/2007
|
||||
\author George
|
||||
\version\verbatim $Id: random.c 11793 2012-04-04 21:03:02Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Create the various random number functions */
|
||||
/*************************************************************************/
|
||||
GK_MKRANDOM(gk_c, size_t, char)
|
||||
GK_MKRANDOM(gk_i, size_t, int)
|
||||
GK_MKRANDOM(gk_f, size_t, float)
|
||||
GK_MKRANDOM(gk_d, size_t, double)
|
||||
GK_MKRANDOM(gk_idx, size_t, gk_idx_t)
|
||||
GK_MKRANDOM(gk_z, size_t, ssize_t)
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! GKlib's built in random number generator for portability across
|
||||
different architectures */
|
||||
/*************************************************************************/
|
||||
#ifdef USE_GKRAND
|
||||
/*
|
||||
A C-program for MT19937-64 (2004/9/29 version).
|
||||
Coded by Takuji Nishimura and Makoto Matsumoto.
|
||||
|
||||
This is a 64-bit version of Mersenne Twister pseudorandom number
|
||||
generator.
|
||||
|
||||
Before using, initialize the state by using init_genrand64(seed)
|
||||
or init_by_array64(init_key, key_length).
|
||||
|
||||
Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura,
|
||||
All rights reserved.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define NN 312
|
||||
#define MM 156
|
||||
#define MATRIX_A 0xB5026F5AA96619E9ULL
|
||||
#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */
|
||||
#define LM 0x7FFFFFFFULL /* Least significant 31 bits */
|
||||
|
||||
|
||||
/* The array for the state vector */
|
||||
static uint64_t mt[NN];
|
||||
/* mti==NN+1 means mt[NN] is not initialized */
|
||||
static int mti=NN+1;
|
||||
#endif /* USE_GKRAND */
|
||||
|
||||
/* initializes mt[NN] with a seed */
|
||||
void gk_randinit(uint64_t seed)
|
||||
{
|
||||
#ifdef USE_GKRAND
|
||||
mt[0] = seed;
|
||||
for (mti=1; mti<NN; mti++)
|
||||
mt[mti] = (6364136223846793005ULL * (mt[mti-1] ^ (mt[mti-1] >> 62)) + mti);
|
||||
#else
|
||||
srand((unsigned int) seed);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* generates a random number on [0, 2^64-1]-interval */
|
||||
uint64_t gk_randint64(void)
|
||||
{
|
||||
#ifdef USE_GKRAND
|
||||
int i;
|
||||
unsigned long long x;
|
||||
static uint64_t mag01[2]={0ULL, MATRIX_A};
|
||||
|
||||
if (mti >= NN) { /* generate NN words at one time */
|
||||
/* if init_genrand64() has not been called, */
|
||||
/* a default initial seed is used */
|
||||
if (mti == NN+1)
|
||||
gk_randinit(5489ULL);
|
||||
|
||||
for (i=0; i<NN-MM; i++) {
|
||||
x = (mt[i]&UM)|(mt[i+1]&LM);
|
||||
mt[i] = mt[i+MM] ^ (x>>1) ^ mag01[(int)(x&1ULL)];
|
||||
}
|
||||
for (; i<NN-1; i++) {
|
||||
x = (mt[i]&UM)|(mt[i+1]&LM);
|
||||
mt[i] = mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x&1ULL)];
|
||||
}
|
||||
x = (mt[NN-1]&UM)|(mt[0]&LM);
|
||||
mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)];
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
x = mt[mti++];
|
||||
|
||||
x ^= (x >> 29) & 0x5555555555555555ULL;
|
||||
x ^= (x << 17) & 0x71D67FFFEDA60000ULL;
|
||||
x ^= (x << 37) & 0xFFF7EEE000000000ULL;
|
||||
x ^= (x >> 43);
|
||||
|
||||
return x & 0x7FFFFFFFFFFFFFFF;
|
||||
#else
|
||||
return (uint64_t)(((uint64_t) rand()) << 32 | ((uint64_t) rand()));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* generates a random number on [0, 2^32-1]-interval */
|
||||
uint32_t gk_randint32(void)
|
||||
{
|
||||
#ifdef USE_GKRAND
|
||||
return (uint32_t)(gk_randint64() & 0x7FFFFFFF);
|
||||
#else
|
||||
return (uint32_t)rand();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Various routines that perform random-walk based operations
|
||||
on graphs stored as gk_csr_t matrices.
|
||||
*
|
||||
* \author George Karypis
|
||||
* \version\verbatim $Id: rw.c 11078 2011-11-12 00:20:44Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Computes the (personalized) page-rank of the vertices in a graph.
|
||||
|
||||
\param mat is the matrix storing the graph.
|
||||
\param lamda is the restart probability.
|
||||
\param eps is the error tolerance for convergance.
|
||||
\param max_niter is the maximum number of allowed iterations.
|
||||
\param pr on entry stores the restart distribution of the vertices.
|
||||
This allows for the computation of personalized page-rank scores
|
||||
by appropriately setting that parameter.
|
||||
On return, pr stores the computed page ranks.
|
||||
|
||||
\returns the number of iterations that were performed.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
int gk_rw_PageRank(gk_csr_t *mat, float lamda, float eps, int max_niter, float *pr)
|
||||
{
|
||||
ssize_t i, j, k, iter, nrows;
|
||||
double *rscale, *prold, *prnew, *prtmp;
|
||||
double fromsinks, error;
|
||||
ssize_t *rowptr;
|
||||
int *rowind;
|
||||
float *rowval;
|
||||
|
||||
nrows = mat->nrows;
|
||||
rowptr = mat->rowptr;
|
||||
rowind = mat->rowind;
|
||||
rowval = mat->rowval;
|
||||
|
||||
prold = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: prnew");
|
||||
prnew = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: prold");
|
||||
rscale = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: rscale");
|
||||
|
||||
/* compute the scaling factors to get adjacency weights into transition
|
||||
probabilities */
|
||||
for (i=0; i<nrows; i++) {
|
||||
for (j=rowptr[i]; j<rowptr[i+1]; j++)
|
||||
rscale[i] += rowval[j];
|
||||
if (rscale[i] > 0)
|
||||
rscale[i] = 1.0/rscale[i];
|
||||
}
|
||||
|
||||
/* the restart distribution is the initial pr scores */
|
||||
for (i=0; i<nrows; i++)
|
||||
prnew[i] = pr[i];
|
||||
|
||||
/* get into the PR iteration */
|
||||
for (iter=0; iter<max_niter; iter++) {
|
||||
gk_SWAP(prnew, prold, prtmp);
|
||||
gk_dset(nrows, 0.0, prnew);
|
||||
|
||||
/* determine the total current PR score of the sinks so that you
|
||||
can distribute them to all nodes according to the restart
|
||||
distribution. */
|
||||
for (fromsinks=0.0, i=0; i<nrows; i++) {
|
||||
if (rscale[i] == 0)
|
||||
fromsinks += prold[i];
|
||||
}
|
||||
|
||||
/* push random-walk scores to the outlinks */
|
||||
for (i=0; i<nrows; i++) {
|
||||
for (j=rowptr[i]; j<rowptr[i+1]; j++)
|
||||
prnew[rowind[j]] += prold[i]*rscale[i]*rowval[j];
|
||||
}
|
||||
|
||||
/* apply the restart conditions */
|
||||
for (i=0; i<nrows; i++) {
|
||||
prnew[i] = lamda*(fromsinks*pr[i]+prnew[i]) + (1.0-lamda)*pr[i];
|
||||
}
|
||||
|
||||
/* compute the error */
|
||||
for (error=0.0, i=0; i<nrows; i++)
|
||||
error = (fabs(prnew[i]-prold[i]) > error ? fabs(prnew[i]-prold[i]) : error);
|
||||
|
||||
//printf("nrm1: %le maxfabserr: %le\n", gk_dsum(nrows, prnew, 1), error);
|
||||
|
||||
if (error < eps)
|
||||
break;
|
||||
}
|
||||
|
||||
/* store the computed pr scores into pr for output */
|
||||
for (i=0; i<nrows; i++)
|
||||
pr[i] = prnew[i];
|
||||
|
||||
gk_free((void **)&prnew, &prold, &rscale, LTERM);
|
||||
|
||||
return (int)(iter+1);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,174 +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_idx_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_idx_t i, j, ii;
|
||||
size_t ntokens, nbytes, len;
|
||||
FILE *fpin;
|
||||
|
||||
|
||||
gk_Tokens_t tokens;
|
||||
static char *AAORDER = "ARNDCQEGHILKMFPSTWYVBZX*";
|
||||
static int PSSMWIDTH = 20;
|
||||
char *header, line[MAXLINELEN];
|
||||
gk_i2cc2i_t *converter;
|
||||
|
||||
header = gk_cmalloc(PSSMWIDTH, "gk_seq_ReadGKMODPSSM: header");
|
||||
|
||||
converter = gk_i2cc2i_create_common(AAORDER);
|
||||
|
||||
gk_getfilestats(filename, &len, &ntokens, NULL, &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 */
|
||||
if (fgets(line, MAXLINELEN-1, fpin) == NULL)
|
||||
errexit("Unexpected end of file: %s\n", filename);
|
||||
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++) {
|
||||
if (fgets(line, MAXLINELEN-1, fpin) == NULL)
|
||||
errexit("Unexpected end of file: %s\n", filename);
|
||||
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_free((void **)&header, LTERM);
|
||||
gk_fclose(fpin);
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*! \brief This function frees the memory allocated to the seq structure.
|
||||
|
||||
\param gk_seq_t
|
||||
\returns nothing
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void gk_seq_free(gk_seq_t *seq)
|
||||
{
|
||||
gk_iFreeMatrix(&seq->pssm, seq->len, seq->nsymbols);
|
||||
gk_iFreeMatrix(&seq->psfm, seq->len, seq->nsymbols);
|
||||
gk_free((void **)&seq->name, &seq->sequence, LTERM);
|
||||
//gk_free((void **)&seq, LTERM);
|
||||
gk_free((void **) &seq, LTERM);
|
||||
|
||||
}
|
||||
|
|
@ -1,327 +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 10796 2011-09-23 21:33:09Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of chars in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_csorti(size_t n, char *base)
|
||||
{
|
||||
#define char_lt(a, b) ((*a) < (*b))
|
||||
GK_MKQSORT(char, base, n, char_lt);
|
||||
#undef char_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of chars in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_csortd(size_t n, char *base)
|
||||
{
|
||||
#define char_gt(a, b) ((*a) > (*b))
|
||||
GK_MKQSORT(char, base, n, char_gt);
|
||||
#undef char_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of integers in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_isorti(size_t n, int *base)
|
||||
{
|
||||
#define int_lt(a, b) ((*a) < (*b))
|
||||
GK_MKQSORT(int, base, n, int_lt);
|
||||
#undef int_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of integers in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_isortd(size_t n, int *base)
|
||||
{
|
||||
#define int_gt(a, b) ((*a) > (*b))
|
||||
GK_MKQSORT(int, base, n, int_gt);
|
||||
#undef int_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of floats in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_fsorti(size_t n, float *base)
|
||||
{
|
||||
#define float_lt(a, b) ((*a) < (*b))
|
||||
GK_MKQSORT(float, base, n, float_lt);
|
||||
#undef float_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of floats in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_fsortd(size_t n, float *base)
|
||||
{
|
||||
#define float_gt(a, b) ((*a) > (*b))
|
||||
GK_MKQSORT(float, base, n, float_gt);
|
||||
#undef float_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of doubles in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_dsorti(size_t n, double *base)
|
||||
{
|
||||
#define double_lt(a, b) ((*a) < (*b))
|
||||
GK_MKQSORT(double, base, n, double_lt);
|
||||
#undef double_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of doubles in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_dsortd(size_t n, double *base)
|
||||
{
|
||||
#define double_gt(a, b) ((*a) > (*b))
|
||||
GK_MKQSORT(double, base, n, double_gt);
|
||||
#undef double_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_idx_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_idxsorti(size_t n, gk_idx_t *base)
|
||||
{
|
||||
#define idx_lt(a, b) ((*a) < (*b))
|
||||
GK_MKQSORT(gk_idx_t, base, n, idx_lt);
|
||||
#undef idx_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_idx_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_idxsortd(size_t n, gk_idx_t *base)
|
||||
{
|
||||
#define idx_gt(a, b) ((*a) > (*b))
|
||||
GK_MKQSORT(gk_idx_t, base, n, idx_gt);
|
||||
#undef idx_gt
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_ckv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_ckvsorti(size_t n, gk_ckv_t *base)
|
||||
{
|
||||
#define ckey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(gk_ckv_t, base, n, ckey_lt);
|
||||
#undef ckey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_ckv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_ckvsortd(size_t n, gk_ckv_t *base)
|
||||
{
|
||||
#define ckey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(gk_ckv_t, base, n, ckey_gt);
|
||||
#undef ckey_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_ikv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_ikvsorti(size_t n, gk_ikv_t *base)
|
||||
{
|
||||
#define ikey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(gk_ikv_t, base, n, ikey_lt);
|
||||
#undef ikey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_ikv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_ikvsortd(size_t n, gk_ikv_t *base)
|
||||
{
|
||||
#define ikey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(gk_ikv_t, base, n, ikey_gt);
|
||||
#undef ikey_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_i32kv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_i32kvsorti(size_t n, gk_i32kv_t *base)
|
||||
{
|
||||
#define ikey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(gk_i32kv_t, base, n, ikey_lt);
|
||||
#undef ikey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_i32kv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_i32kvsortd(size_t n, gk_i32kv_t *base)
|
||||
{
|
||||
#define ikey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(gk_i32kv_t, base, n, ikey_gt);
|
||||
#undef ikey_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_i64kv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_i64kvsorti(size_t n, gk_i64kv_t *base)
|
||||
{
|
||||
#define ikey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(gk_i64kv_t, base, n, ikey_lt);
|
||||
#undef ikey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_i64kv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_i64kvsortd(size_t n, gk_i64kv_t *base)
|
||||
{
|
||||
#define ikey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(gk_i64kv_t, base, n, ikey_gt);
|
||||
#undef ikey_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_zkv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_zkvsorti(size_t n, gk_zkv_t *base)
|
||||
{
|
||||
#define zkey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(gk_zkv_t, base, n, zkey_lt);
|
||||
#undef zkey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_zkv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_zkvsortd(size_t n, gk_zkv_t *base)
|
||||
{
|
||||
#define zkey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(gk_zkv_t, base, n, zkey_gt);
|
||||
#undef zkey_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_fkv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_fkvsorti(size_t n, gk_fkv_t *base)
|
||||
{
|
||||
#define fkey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(gk_fkv_t, base, n, fkey_lt);
|
||||
#undef fkey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_fkv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_fkvsortd(size_t n, gk_fkv_t *base)
|
||||
{
|
||||
#define fkey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(gk_fkv_t, base, n, fkey_gt);
|
||||
#undef fkey_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_dkv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_dkvsorti(size_t n, gk_dkv_t *base)
|
||||
{
|
||||
#define dkey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(gk_dkv_t, base, n, dkey_lt);
|
||||
#undef dkey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_fkv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_dkvsortd(size_t n, gk_dkv_t *base)
|
||||
{
|
||||
#define dkey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(gk_dkv_t, base, n, dkey_gt);
|
||||
#undef dkey_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_skv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_skvsorti(size_t n, gk_skv_t *base)
|
||||
{
|
||||
#define skey_lt(a, b) (strcmp((a)->key, (b)->key) < 0)
|
||||
GK_MKQSORT(gk_skv_t, base, n, skey_lt);
|
||||
#undef skey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_skv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_skvsortd(size_t n, gk_skv_t *base)
|
||||
{
|
||||
#define skey_gt(a, b) (strcmp((a)->key, (b)->key) > 0)
|
||||
GK_MKQSORT(gk_skv_t, base, n, skey_gt);
|
||||
#undef skey_gt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_idxkv_t in increasing order */
|
||||
/*************************************************************************/
|
||||
void gk_idxkvsorti(size_t n, gk_idxkv_t *base)
|
||||
{
|
||||
#define idxkey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(gk_idxkv_t, base, n, idxkey_lt);
|
||||
#undef idxkey_lt
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorts an array of gk_idxkv_t in decreasing order */
|
||||
/*************************************************************************/
|
||||
void gk_idxkvsortd(size_t n, gk_idxkv_t *base)
|
||||
{
|
||||
#define idxkey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(gk_idxkv_t, base, n, idxkey_gt);
|
||||
#undef idxkey_gt
|
||||
}
|
||||
|
|
@ -1,529 +0,0 @@
|
|||
/************************************************************************/
|
||||
/*! \file
|
||||
|
||||
\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 10711 2011-08-31 22:23:04Z 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 Compare two strings in revere order
|
||||
|
||||
This function is similar to strcmp but it performs the comparison as
|
||||
if the two strings were reversed.
|
||||
|
||||
\param s1 is the first string to be compared.
|
||||
\param s2 is the second string to be compared.
|
||||
\retval -1, 0, 1, if the s1 < s2, s1 == s2, or s1 > s2.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int gk_strrcmp(char *s1, char *s2)
|
||||
{
|
||||
int i1 = strlen(s1)-1;
|
||||
int i2 = strlen(s2)-1;
|
||||
|
||||
while ((i1 >= 0) && (i2 >= 0)) {
|
||||
if (s1[i1] != s2[i2])
|
||||
return (s1[i1] - s2[i2]);
|
||||
i1--;
|
||||
i2--;
|
||||
}
|
||||
|
||||
/* i1 == -1 and/or i2 == -1 */
|
||||
|
||||
if (i1 < i2)
|
||||
return -1;
|
||||
if (i1 > i2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/*! \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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if !defined(WIN32) && !defined(__MINGW32__)
|
||||
/************************************************************************/
|
||||
/*! \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);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function returns the ID of a particular string based on the
|
||||
* supplied StringMap array
|
||||
**************************************************************************/
|
||||
int gk_GetStringID(gk_StringMap_t *strmap, char *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; strmap[i].name; i++) {
|
||||
if (gk_strcasecmp(key, strmap[i].name))
|
||||
return strmap[i].id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
# Where the header files reside
|
||||
#include_directories(../)
|
||||
|
||||
# Build program.
|
||||
add_executable(strings strings.c)
|
||||
add_executable(gksort gksort.c)
|
||||
add_executable(fis fis.c)
|
||||
add_executable(rw rw.c)
|
||||
add_executable(gkgraph gkgraph.c)
|
||||
foreach(prog strings gksort fis rw gkgraph)
|
||||
target_link_libraries(${prog} GKlib)
|
||||
endforeach(prog)
|
||||
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
#*************************************************************************
|
||||
# Global flags
|
||||
#*************************************************************************
|
||||
gdb = yes
|
||||
debug = no
|
||||
memdbg = no
|
||||
openmp = no
|
||||
x86compiler = gcc
|
||||
|
||||
VERNUM = 0.1.0
|
||||
|
||||
|
||||
|
||||
#*************************************************************************
|
||||
# System-specific compilation flags
|
||||
#*************************************************************************
|
||||
# Get some basic information about the system that you are working on
|
||||
cputype = $(shell uname -m | sed "s/\\ /_/g")
|
||||
systype = $(shell uname)
|
||||
ifeq ($(findstring CYGWIN, $(systype)),CYGWIN)
|
||||
# systype = CYGWIN
|
||||
systype = MSWIN
|
||||
cputype = x86
|
||||
endif
|
||||
|
||||
|
||||
GKLIBINCDIR = $(HOME)/work/algorithms/GKlib/trunk/
|
||||
GKLIBBUILDDIR = $(HOME)/work/algorithms/GKlib/builds/$(systype)-$(cputype)
|
||||
|
||||
|
||||
ifeq ($(systype),MSWIN)
|
||||
#-------------------------------------------------------------------
|
||||
# These defs are very much Visual Studio Specific
|
||||
#-------------------------------------------------------------------
|
||||
#Compiler information
|
||||
CC = cl
|
||||
OPTFLAGS = /Ox
|
||||
COPTIONS = -DWIN32 -DMSC -D_CRT_SECURE_NO_DEPRECATE
|
||||
|
||||
#Compile input/output file specification
|
||||
SOURCEFILE = /c $<
|
||||
OUTPUTFILE = /Fo$@
|
||||
|
||||
#Output specification for executables
|
||||
EXEOUTPUTFILE = /Fe$@ # This option is when cl is used for linking
|
||||
#EXEOUTPUTFILE = /OUT:$@ # This option is used when link is used for linking
|
||||
|
||||
#Linker information
|
||||
LDOPTIONS = /MT
|
||||
#LD = /cygdrive/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/VC/BIN/link
|
||||
LD = cl
|
||||
MERGEMANIFEST =
|
||||
|
||||
#Library creation information
|
||||
AR = lib /OUT:$@
|
||||
RANLIB =
|
||||
|
||||
ifeq ($(openmp),yes)
|
||||
COPTIONS += -D__OPENMP__ /openmp
|
||||
LDOPTIONS += /openmp
|
||||
MERGEMANIFEST = vc_mt -manifest $@.manifest -outputresource:$@\;1
|
||||
endif
|
||||
|
||||
#Library information
|
||||
ifeq ($(cputype),i386)
|
||||
LIBPLOTDIR = ../Libplot/Win32
|
||||
else
|
||||
LIBPLOTDIR = ../Libplot/Win64
|
||||
endif
|
||||
LIBS = $(LIBPLOTDIR)/libplot.lib $(BUILDDIR)/libcluto.lib $(GKLIBBUILDDIR)/libGKlib.lib
|
||||
|
||||
# Standard file extensions
|
||||
OBJEXT = .obj
|
||||
LIBEXT = .lib
|
||||
EXEEXT = .exe
|
||||
else
|
||||
ifeq ($(systype),Linux)
|
||||
ifeq ($(x86compiler),gcc)
|
||||
#Compiler information
|
||||
CC = gcc
|
||||
OPTFLAGS = -O6
|
||||
COPTIONS = -DLINUX -D_FILE_OFFSET_BITS=64 -pedantic -std=c99 -pthread
|
||||
|
||||
#Linker information
|
||||
LDOPTIONS =
|
||||
LD = gcc
|
||||
|
||||
MERGEMANIFEST =
|
||||
|
||||
#Library creation information
|
||||
AR = ar rv
|
||||
RANLIB = ar -ts
|
||||
else
|
||||
#Compiler information
|
||||
CC = icc
|
||||
OPTFLAGS = -O3
|
||||
COPTIONS = -DLINUX -D_FILE_OFFSET_BITS=64 -std=c99
|
||||
|
||||
#Linker information
|
||||
LDOPTIONS =
|
||||
LD = icc
|
||||
|
||||
#Library creation information
|
||||
AR = ar rv
|
||||
RANLIB = ar -ts
|
||||
|
||||
ifeq ($(openmp),yes)
|
||||
COPTIONS += -D__OPENMP__ -openmp -openmp-report2
|
||||
LDOPTIONS += -openmp
|
||||
endif
|
||||
endif
|
||||
|
||||
#Library information
|
||||
ifeq ($(cputype),x86_64)
|
||||
LIBPLOTDIR = ../Libplot/Linux64
|
||||
else
|
||||
LIBPLOTDIR = ../Libplot/Linux32
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(systype),SunOS)
|
||||
#Compiler information
|
||||
CC = /opt/SUNWspro/bin/cc
|
||||
OPTFLAGS = -xO4
|
||||
COPTIONS =-DSUNOS
|
||||
|
||||
#Linker information
|
||||
LDOPTIONS =
|
||||
LD = /opt/SUNWspro/bin/cc
|
||||
|
||||
|
||||
#Library creation information
|
||||
AR = ar rv
|
||||
RANLIB = ar -ts
|
||||
|
||||
#Library information
|
||||
LIBPLOTDIR = ../Libplot/SunOS
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(systype),Darwin)
|
||||
#Compiler information
|
||||
CC = gcc
|
||||
OPTFLAGS = -O6
|
||||
COPTIONS = -DDARWIN -D_FILE_OFFSET_BITS=64 -pedantic -std=c99
|
||||
|
||||
#Linker information
|
||||
LDOPTIONS = -fvisibility=default
|
||||
LD = gcc
|
||||
|
||||
#Library creation information
|
||||
AR = ar rv
|
||||
RANLIB = ar -ts
|
||||
|
||||
#Library information
|
||||
ifeq ($(cputype),i386)
|
||||
LIBPLOTDIR = ../Libplot/Darwini386
|
||||
else
|
||||
LIBPLOTDIR = ../Libplot/DarwinPPC
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(systype),CYGWIN)
|
||||
#Compiler information
|
||||
CC = gcc
|
||||
OPTFLAGS = -O6
|
||||
COPTIONS = -DCYGWIN -DWIN32 -D_FILE_OFFSET_BITS=64 -Wall -std=c99 -pedantic -mno-cygwin
|
||||
|
||||
#Linker information
|
||||
LDOPTIONS = -mno-cygwin
|
||||
LD = gcc
|
||||
|
||||
#Library creation information
|
||||
AR = ar crv
|
||||
RANLIB = ar -ts
|
||||
|
||||
#Library information
|
||||
LIBPLOTDIR = ../Libplot/CYGWIN
|
||||
endif
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# These defs are common among the GNU/GCC based systems
|
||||
#-------------------------------------------------------------------
|
||||
#Compile input/output file specification
|
||||
SOURCEFILE = -c $<
|
||||
OUTPUTFILE = -o $@
|
||||
|
||||
#Output specification for executables
|
||||
EXEOUTPUTFILE = -o $@
|
||||
|
||||
#Library creation information
|
||||
AR = ar crv $@
|
||||
RANLIB = ar -ts $@
|
||||
|
||||
#Libraries needed for linking
|
||||
LIBSDIR = -L$(BUILDDIR) -L$(GKLIBBUILDDIR) -L$(HOME)/local/lib
|
||||
LIBS = -lGKlib -lpcreposix -lpcre -lz -lm
|
||||
|
||||
# Standard file extensions
|
||||
OBJEXT = .o
|
||||
LIBEXT = .a
|
||||
EXEEXT =
|
||||
endif
|
||||
|
||||
|
||||
#**************************************************************************
|
||||
DMALLOCINC =
|
||||
DMALLOCFLAGS =
|
||||
DEBUGFLAGS =
|
||||
|
||||
ifeq ($(dmalloc),yes)
|
||||
DMALLOCINC = -I$(HOME)/local/include
|
||||
DMALLOCFLAGS = -DDMALLOC
|
||||
OPTFLAGS = -g
|
||||
endif
|
||||
|
||||
ifeq ($(debug),yes)
|
||||
DEBUGFLAGS = -DDEBUG
|
||||
OPTFLAGS = -g
|
||||
endif
|
||||
|
||||
ifeq ($(gdb),yes)
|
||||
OPTFLAGS += -g
|
||||
endif
|
||||
#**************************************************************************
|
||||
|
||||
|
||||
#**************************************************************************
|
||||
# Create the build directory if it does not exist
|
||||
#**************************************************************************
|
||||
ifeq ($(systype),Darwin)
|
||||
BINDIR = $(HOME)
|
||||
else
|
||||
BINDIR = $(HOME)/work/bin/$(systype)-$(cputype)
|
||||
$(shell mkdir -p $(BINDIR))
|
||||
endif
|
||||
|
||||
ifeq ($(openmp),no)
|
||||
BUILDDIR = ./builds/$(systype)-$(cputype)
|
||||
else
|
||||
BUILDDIR = ./builds/$(systype)-$(cputype)-openmp
|
||||
endif
|
||||
|
||||
LIBBUILDDIR = $(BUILDDIR)/lib
|
||||
PRGBUILDDIR = $(BUILDDIR)/prg
|
||||
$(shell mkdir -p $(BUILDDIR))
|
||||
$(shell mkdir -p $(LIBBUILDDIR))
|
||||
$(shell mkdir -p $(PRGBUILDDIR))
|
||||
|
||||
|
||||
|
||||
|
||||
INCLUDES = -I./ -I$(GKLIBINCDIR) -I$(LIBPLOTDIR) -I$(HOME)/local/include
|
||||
CFLAGS = $(COPTIONS) $(OPTFLAGS) $(DEBUGFLAGS) $(INCLUDES)
|
||||
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
include Makefile.in
|
||||
|
||||
STRINGSOBJS = $(PRGBUILDDIR)/strings$(OBJEXT)
|
||||
GKSORTOBJS = $(PRGBUILDDIR)/gksort$(OBJEXT)
|
||||
FISOBJS = $(PRGBUILDDIR)/fis$(OBJEXT)
|
||||
|
||||
HEADERS = $(wildcard $(GKLIBINCDIR)/*.h)
|
||||
|
||||
|
||||
default: $(BUILDDIR)/strings$(EXEEXT) $(BUILDDIR)/gksort$(EXEEXT) $(BUILDDIR)/fis$(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 $@
|
||||
|
||||
$(BUILDDIR)/fis$(EXEEXT): $(FISOBJS) $(GKLIBBUILDDIR)/libGKlib.a
|
||||
$(LD) $(LDOPTIONS) $(EXEOUTPUTFILE) $(FISOBJS) $(LIBSDIR) $(LIBS) ; $(MERGEMANIFEST)
|
||||
chmod 744 $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf $(PRGBUILDDIR)
|
||||
|
||||
realclean:
|
||||
rm -rf $(PRGBUILDDIR) ;\
|
||||
rm -rf $(BUILDDIR) ;
|
||||
|
||||
|
||||
$(STRINGSOBJS) : $(HEADERS) Makefile.in Makefile $(GKLIBBUILDDIR)/libGKlib.a
|
||||
|
||||
|
||||
$(PRGBUILDDIR)/%$(OBJEXT) : %.c
|
||||
$(CC) $(CFLAGS) $(SOURCEFILE) $(OUTPUTFILE)
|
||||
|
||||
|
|
@ -1,286 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief A simple frequent itemset discovery program to test GKlib's routines
|
||||
|
||||
\date 6/12/2008
|
||||
\author George
|
||||
\version \verbatim $Id: fis.c 11075 2011-11-11 22:31:52Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Data structures for the code */
|
||||
/*************************************************************************/
|
||||
typedef struct {
|
||||
ssize_t minlen, maxlen;
|
||||
ssize_t minfreq, maxfreq;
|
||||
char *filename;
|
||||
int silent;
|
||||
ssize_t nitemsets;
|
||||
char *clabelfile;
|
||||
char **clabels;
|
||||
} params_t;
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Constants */
|
||||
/*************************************************************************/
|
||||
#define CMD_MINLEN 1
|
||||
#define CMD_MAXLEN 2
|
||||
#define CMD_MINFREQ 3
|
||||
#define CMD_MAXFREQ 4
|
||||
#define CMD_SILENT 5
|
||||
#define CMD_CLABELFILE 6
|
||||
#define CMD_HELP 10
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Local variables */
|
||||
/*************************************************************************/
|
||||
static struct gk_option long_options[] = {
|
||||
{"minlen", 1, 0, CMD_MINLEN},
|
||||
{"maxlen", 1, 0, CMD_MAXLEN},
|
||||
{"minfreq", 1, 0, CMD_MINFREQ},
|
||||
{"maxfreq", 1, 0, CMD_MAXFREQ},
|
||||
{"silent", 0, 0, CMD_SILENT},
|
||||
{"clabels", 1, 0, CMD_CLABELFILE},
|
||||
{"help", 0, 0, CMD_HELP},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* Mini help */
|
||||
/*-------------------------------------------------------------------*/
|
||||
static char helpstr[][100] = {
|
||||
" ",
|
||||
"Usage: fis [options] <mat-file>",
|
||||
" ",
|
||||
" Required parameters",
|
||||
" mat-file",
|
||||
" The name of the file storing the transactions. The file is in ",
|
||||
" Cluto's .mat format.",
|
||||
" ",
|
||||
" Optional parameters",
|
||||
" -minlen=int",
|
||||
" Specifies the minimum length of the patterns. [default: 1]",
|
||||
" ",
|
||||
" -maxlen=int",
|
||||
" Specifies the maximum length of the patterns. [default: none]",
|
||||
" ",
|
||||
" -minfreq=int",
|
||||
" Specifies the minimum frequency of the patterns. [default: 10]",
|
||||
" ",
|
||||
" -maxfreq=int",
|
||||
" Specifies the maximum frequency of the patterns. [default: none]",
|
||||
" ",
|
||||
" -silent",
|
||||
" Does not print the discovered itemsets.",
|
||||
" ",
|
||||
" -clabels=filename",
|
||||
" Specifies the name of the file that stores the column labels.",
|
||||
" ",
|
||||
" -help",
|
||||
" Prints this message.",
|
||||
""
|
||||
};
|
||||
|
||||
static char shorthelpstr[][100] = {
|
||||
" ",
|
||||
" Usage: fis [options] <mat-file>",
|
||||
" use 'fis -help' for a summary of the options.",
|
||||
""
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Function prototypes */
|
||||
/*************************************************************************/
|
||||
void print_init_info(params_t *params, gk_csr_t *mat);
|
||||
void print_final_info(params_t *params);
|
||||
params_t *parse_cmdline(int argc, char *argv[]);
|
||||
void print_an_itemset(void *stateptr, int nitems, int *itemind,
|
||||
int ntrans, int *tranind);
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! the entry point */
|
||||
/**************************************************************************/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
ssize_t i;
|
||||
char line[8192];
|
||||
FILE *fpin;
|
||||
params_t *params;
|
||||
gk_csr_t *mat;
|
||||
|
||||
params = parse_cmdline(argc, argv);
|
||||
params->nitemsets = 0;
|
||||
|
||||
/* read the data */
|
||||
mat = gk_csr_Read(params->filename, GK_CSR_FMT_CLUTO, 1, 1);
|
||||
gk_csr_CreateIndex(mat, GK_CSR_COL);
|
||||
|
||||
/* read the column labels */
|
||||
params->clabels = (char **)gk_malloc(mat->ncols*sizeof(char *), "main: clabels");
|
||||
if (params->clabelfile == NULL) {
|
||||
for (i=0; i<mat->ncols; i++) {
|
||||
sprintf(line, "%zd", i);
|
||||
params->clabels[i] = gk_strdup(line);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fpin = gk_fopen(params->clabelfile, "r", "main: fpin");
|
||||
for (i=0; i<mat->ncols; i++) {
|
||||
if (fgets(line, 8192, fpin) == NULL)
|
||||
errexit("Failed on fgets.\n");
|
||||
params->clabels[i] = gk_strdup(gk_strtprune(line, " \n\t"));
|
||||
}
|
||||
gk_fclose(fpin);
|
||||
}
|
||||
|
||||
|
||||
print_init_info(params, mat);
|
||||
|
||||
gk_find_frequent_itemsets(mat->nrows, mat->rowptr, mat->rowind,
|
||||
params->minfreq, params->maxfreq, params->minlen, params->maxlen,
|
||||
&print_an_itemset, (void *)params);
|
||||
|
||||
printf("Total itemsets found: %zd\n", params->nitemsets);
|
||||
|
||||
print_final_info(params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function prints run parameters */
|
||||
/*************************************************************************/
|
||||
void print_init_info(params_t *params, gk_csr_t *mat)
|
||||
{
|
||||
printf("*******************************************************************************\n");
|
||||
printf(" fis\n\n");
|
||||
printf("Matrix Information ---------------------------------------------------------\n");
|
||||
printf(" input file=%s, [%d, %d, %zd]\n",
|
||||
params->filename, mat->nrows, mat->ncols, mat->rowptr[mat->nrows]);
|
||||
|
||||
printf("\n");
|
||||
printf("Options --------------------------------------------------------------------\n");
|
||||
printf(" minlen=%zd, maxlen=%zd, minfeq=%zd, maxfreq=%zd\n",
|
||||
params->minlen, params->maxlen, params->minfreq, params->maxfreq);
|
||||
|
||||
printf("\n");
|
||||
printf("Finding patterns... -----------------------------------------------------\n");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function prints final statistics */
|
||||
/*************************************************************************/
|
||||
void print_final_info(params_t *params)
|
||||
{
|
||||
printf("\n");
|
||||
printf("Memory Usage Information -----------------------------------------------------\n");
|
||||
printf(" Maximum memory used: %10zd bytes\n", (ssize_t) gk_GetMaxMemoryUsed());
|
||||
printf(" Current memory used: %10zd bytes\n", (ssize_t) gk_GetCurMemoryUsed());
|
||||
printf("********************************************************************************\n");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This is the entry point of the command-line argument parser */
|
||||
/*************************************************************************/
|
||||
params_t *parse_cmdline(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int c, option_index;
|
||||
params_t *params;
|
||||
|
||||
params = (params_t *)gk_malloc(sizeof(params_t), "parse_cmdline: params");
|
||||
|
||||
/* initialize the params data structure */
|
||||
params->minlen = 1;
|
||||
params->maxlen = -1;
|
||||
params->minfreq = 10;
|
||||
params->maxfreq = -1;
|
||||
params->silent = 0;
|
||||
params->filename = NULL;
|
||||
params->clabelfile = NULL;
|
||||
|
||||
|
||||
/* Parse the command line arguments */
|
||||
while ((c = gk_getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
case CMD_MINLEN:
|
||||
if (gk_optarg) params->minlen = atoi(gk_optarg);
|
||||
break;
|
||||
case CMD_MAXLEN:
|
||||
if (gk_optarg) params->maxlen = atoi(gk_optarg);
|
||||
break;
|
||||
case CMD_MINFREQ:
|
||||
if (gk_optarg) params->minfreq = atoi(gk_optarg);
|
||||
break;
|
||||
case CMD_MAXFREQ:
|
||||
if (gk_optarg) params->maxfreq = atoi(gk_optarg);
|
||||
break;
|
||||
|
||||
case CMD_SILENT:
|
||||
params->silent = 1;
|
||||
break;
|
||||
|
||||
case CMD_CLABELFILE:
|
||||
if (gk_optarg) params->clabelfile = gk_strdup(gk_optarg);
|
||||
break;
|
||||
|
||||
case CMD_HELP:
|
||||
for (i=0; strlen(helpstr[i]) > 0; i++)
|
||||
printf("%s\n", helpstr[i]);
|
||||
exit(0);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
printf("Illegal command-line option(s)\nUse %s -help for a summary of the options.\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc-gk_optind != 1) {
|
||||
printf("Unrecognized parameters.");
|
||||
for (i=0; strlen(shorthelpstr[i]) > 0; i++)
|
||||
printf("%s\n", shorthelpstr[i]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
params->filename = gk_strdup(argv[gk_optind++]);
|
||||
|
||||
if (!gk_fexists(params->filename))
|
||||
errexit("input file %s does not exist.\n", params->filename);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This is the callback function for the itemset discovery routine */
|
||||
/*************************************************************************/
|
||||
void print_an_itemset(void *stateptr, int nitems, int *itemids, int ntrans,
|
||||
int *transids)
|
||||
{
|
||||
ssize_t i;
|
||||
params_t *params;
|
||||
|
||||
params = (params_t *)stateptr;
|
||||
params->nitemsets++;
|
||||
|
||||
if (!params->silent) {
|
||||
printf("%4zd %4d %4d => ", params->nitemsets, nitems, ntrans);
|
||||
for (i=0; i<nitems; i++)
|
||||
printf(" %s", params->clabels[itemids[i]]);
|
||||
printf("\n");
|
||||
for (i=0; i<ntrans; i++)
|
||||
printf(" %d\n", transids[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief A simple frequent itemset discovery program to test GKlib's routines
|
||||
|
||||
\date 6/12/2008
|
||||
\author George
|
||||
\version \verbatim $Id: gkgraph.c 11408 2012-01-25 15:05:58Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Data structures for the code */
|
||||
/*************************************************************************/
|
||||
typedef struct {
|
||||
int type;
|
||||
int niter;
|
||||
float eps;
|
||||
float lamda;
|
||||
|
||||
char *infile;
|
||||
char *outfile;
|
||||
} params_t;
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Constants */
|
||||
/*************************************************************************/
|
||||
#define CMD_NITER 1
|
||||
#define CMD_EPS 2
|
||||
#define CMD_LAMDA 3
|
||||
#define CMD_TYPE 4
|
||||
#define CMD_HELP 10
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Local variables */
|
||||
/*************************************************************************/
|
||||
static struct gk_option long_options[] = {
|
||||
{"type", 1, 0, CMD_TYPE},
|
||||
{"niter", 1, 0, CMD_NITER},
|
||||
{"lamda", 1, 0, CMD_LAMDA},
|
||||
{"eps", 1, 0, CMD_EPS},
|
||||
{"help", 0, 0, CMD_HELP},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* Mini help */
|
||||
/*-------------------------------------------------------------------*/
|
||||
static char helpstr[][100] = {
|
||||
" ",
|
||||
"Usage: gkgraph [options] <graph-file> [<out-file>]",
|
||||
" ",
|
||||
" Required parameters",
|
||||
" graph-file",
|
||||
" The name of the file storing the graph. The file is in ",
|
||||
" Metis' graph format.",
|
||||
" ",
|
||||
" Optional parameters",
|
||||
" -niter=int",
|
||||
" Specifies the maximum number of iterations. [default: 100]",
|
||||
" ",
|
||||
" -lamda=float",
|
||||
" Specifies the follow-the-adjacent-links probability. [default: 0.80]",
|
||||
" ",
|
||||
" -eps=float",
|
||||
" Specifies the error tollerance. [default: 1e-10]",
|
||||
" ",
|
||||
" -help",
|
||||
" Prints this message.",
|
||||
""
|
||||
};
|
||||
|
||||
static char shorthelpstr[][100] = {
|
||||
" ",
|
||||
" Usage: gkgraph [options] <graph-file> [<out-file>]",
|
||||
" use 'gkgraph -help' for a summary of the options.",
|
||||
""
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Function prototypes */
|
||||
/*************************************************************************/
|
||||
double compute_compactness(params_t *params, gk_graph_t *graph, int32_t *perm);
|
||||
void reorder_centroid(params_t *params, gk_graph_t *graph, int32_t *perm);
|
||||
void print_init_info(params_t *params, gk_graph_t *graph);
|
||||
void print_final_info(params_t *params);
|
||||
params_t *parse_cmdline(int argc, char *argv[]);
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! the entry point */
|
||||
/**************************************************************************/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
ssize_t i, j, v;
|
||||
params_t *params;
|
||||
gk_graph_t *graph, *pgraph;
|
||||
int32_t *perm;
|
||||
|
||||
/* get command-line options */
|
||||
params = parse_cmdline(argc, argv);
|
||||
|
||||
/* read the data */
|
||||
graph = gk_graph_Read(params->infile, GK_GRAPH_FMT_METIS, 0, 0, 0);
|
||||
|
||||
/* display some basic stats */
|
||||
print_init_info(params, graph);
|
||||
|
||||
|
||||
/* determine the initial compactness of the graph */
|
||||
printf("Initial compactness: %le\n", compute_compactness(params, graph, NULL));
|
||||
|
||||
/* compute the BFS ordering and re-order the graph */
|
||||
//for (i=0; i<params->niter; i++) {
|
||||
for (i=0; i<1; i++) {
|
||||
v = RandomInRange(graph->nvtxs);
|
||||
gk_graph_ComputeBFSOrdering(graph, v, &perm, NULL);
|
||||
printf("BFS from %8d. Compactness: %le\n",
|
||||
(int) v, compute_compactness(params, graph, perm));
|
||||
|
||||
pgraph = gk_graph_Reorder(graph, perm, NULL);
|
||||
gk_graph_Write(pgraph, "bfs.metis", GK_GRAPH_FMT_METIS);
|
||||
gk_graph_Free(&pgraph);
|
||||
|
||||
gk_graph_ComputeBestFOrdering(graph, v, params->type, &perm, NULL);
|
||||
printf("BestF from %8d. Compactness: %le\n",
|
||||
(int) v, compute_compactness(params, graph, perm));
|
||||
|
||||
pgraph = gk_graph_Reorder(graph, perm, NULL);
|
||||
gk_graph_Write(pgraph, "bestf.metis", GK_GRAPH_FMT_METIS);
|
||||
gk_graph_Free(&pgraph);
|
||||
|
||||
#ifdef XXX
|
||||
for (j=0; j<params->niter; j++) {
|
||||
reorder_centroid(params, graph, perm);
|
||||
printf("\tAfter centroid; Compactness: %le\n",
|
||||
compute_compactness(params, graph, perm));
|
||||
}
|
||||
|
||||
pgraph = gk_graph_Reorder(graph, perm, NULL);
|
||||
gk_graph_Write(pgraph, "centroid.metis", GK_GRAPH_FMT_METIS);
|
||||
gk_graph_Free(&pgraph);
|
||||
#endif
|
||||
gk_free((void **)&perm, LTERM);
|
||||
}
|
||||
|
||||
gk_graph_Free(&graph);
|
||||
//gk_graph_Free(&pgraph);
|
||||
|
||||
print_final_info(params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes the compactness of the graph's adjacency list */
|
||||
/*************************************************************************/
|
||||
double compute_compactness(params_t *params, gk_graph_t *graph, int32_t *perm)
|
||||
{
|
||||
int i, v, u, nvtxs;
|
||||
ssize_t j, *xadj;
|
||||
int32_t *adjncy;
|
||||
double compactness=0.0;
|
||||
int *freq;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
|
||||
freq = gk_ismalloc(nvtxs, 0, "compute_compactness: freq");
|
||||
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
v = (perm == NULL ? i : perm[i]);
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
u = (perm == NULL ? adjncy[j] : perm[adjncy[j]]);
|
||||
compactness += fabs(v-u);
|
||||
freq[gk_abs(v-u)]++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (freq[i] > 0)
|
||||
printf("%7d %6d\n", i, freq[i]);
|
||||
}
|
||||
*/
|
||||
printf("\tnsmall: %d\n", freq[1]+freq[2]+freq[3]);
|
||||
|
||||
return compactness/xadj[nvtxs];
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function uses a centroid-based approach to refine the ordering */
|
||||
/*************************************************************************/
|
||||
void reorder_centroid(params_t *params, gk_graph_t *graph, int32_t *perm)
|
||||
{
|
||||
int i, v, u, nvtxs;
|
||||
ssize_t j, *xadj;
|
||||
int32_t *adjncy;
|
||||
gk_fkv_t *cand;
|
||||
double displacement;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
|
||||
cand = gk_fkvmalloc(nvtxs, "reorder_centroid: cand");
|
||||
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
v = perm[i];
|
||||
displacement = 0.0;
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
u = perm[adjncy[j]];
|
||||
displacement += u-v;
|
||||
//displacement += sign(u-v, sqrt(fabs(u-v)));
|
||||
}
|
||||
|
||||
cand[i].val = i;
|
||||
cand[i].key = v + displacement*params->lamda/(xadj[i+1]-xadj[i]);
|
||||
}
|
||||
|
||||
/* sort them based on the target position in increasing order */
|
||||
gk_fkvsorti(nvtxs, cand);
|
||||
|
||||
|
||||
/* derive the permutation from the ordered list */
|
||||
gk_i32set(nvtxs, -1, perm);
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (perm[cand[i].val] != -1)
|
||||
errexit("Resetting perm[%d] = %d\n", cand[i].val, perm[cand[i].val]);
|
||||
perm[cand[i].val] = i;
|
||||
}
|
||||
|
||||
gk_free((void **)&cand, LTERM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function prints run parameters */
|
||||
/*************************************************************************/
|
||||
void print_init_info(params_t *params, gk_graph_t *graph)
|
||||
{
|
||||
printf("*******************************************************************************\n");
|
||||
printf(" gkgraph\n\n");
|
||||
printf("Graph Information ----------------------------------------------------------\n");
|
||||
printf(" input file=%s, [%d, %zd]\n",
|
||||
params->infile, graph->nvtxs, graph->xadj[graph->nvtxs]);
|
||||
|
||||
printf("\n");
|
||||
printf("Options --------------------------------------------------------------------\n");
|
||||
printf(" type=%d, niter=%d, lamda=%f, eps=%e\n",
|
||||
params->type, params->niter, params->lamda, params->eps);
|
||||
|
||||
printf("\n");
|
||||
printf("Working... -----------------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function prints final statistics */
|
||||
/*************************************************************************/
|
||||
void print_final_info(params_t *params)
|
||||
{
|
||||
printf("\n");
|
||||
printf("Memory Usage Information -----------------------------------------------------\n");
|
||||
printf(" Maximum memory used: %10zd bytes\n", (ssize_t) gk_GetMaxMemoryUsed());
|
||||
printf(" Current memory used: %10zd bytes\n", (ssize_t) gk_GetCurMemoryUsed());
|
||||
printf("********************************************************************************\n");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This is the entry point of the command-line argument parser */
|
||||
/*************************************************************************/
|
||||
params_t *parse_cmdline(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int c, option_index;
|
||||
params_t *params;
|
||||
|
||||
params = (params_t *)gk_malloc(sizeof(params_t), "parse_cmdline: params");
|
||||
|
||||
/* initialize the params data structure */
|
||||
params->type = 1;
|
||||
params->niter = 1;
|
||||
params->eps = 1e-10;
|
||||
params->lamda = 0.20;
|
||||
params->infile = NULL;
|
||||
|
||||
|
||||
/* Parse the command line arguments */
|
||||
while ((c = gk_getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
case CMD_TYPE:
|
||||
if (gk_optarg) params->type = atoi(gk_optarg);
|
||||
break;
|
||||
case CMD_NITER:
|
||||
if (gk_optarg) params->niter = atoi(gk_optarg);
|
||||
break;
|
||||
case CMD_EPS:
|
||||
if (gk_optarg) params->eps = atof(gk_optarg);
|
||||
break;
|
||||
case CMD_LAMDA:
|
||||
if (gk_optarg) params->lamda = atof(gk_optarg);
|
||||
break;
|
||||
|
||||
case CMD_HELP:
|
||||
for (i=0; strlen(helpstr[i]) > 0; i++)
|
||||
printf("%s\n", helpstr[i]);
|
||||
exit(0);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
printf("Illegal command-line option(s)\nUse %s -help for a summary of the options.\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc-gk_optind != 1) {
|
||||
printf("Unrecognized parameters.");
|
||||
for (i=0; strlen(shorthelpstr[i]) > 0; i++)
|
||||
printf("%s\n", shorthelpstr[i]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
params->infile = gk_strdup(argv[gk_optind++]);
|
||||
|
||||
if (argc-gk_optind > 0)
|
||||
params->outfile = gk_strdup(argv[gk_optind++]);
|
||||
else
|
||||
params->outfile = gk_strdup("gkgraph.out");
|
||||
|
||||
if (!gk_fexists(params->infile))
|
||||
errexit("input file %s does not exist.\n", params->infile);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
|
@ -1,346 +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 11058 2011-11-10 00:02:50Z 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_isorti(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i] > array[i+1])
|
||||
printf("gk_isorti 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_isortd(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i] < array[i+1])
|
||||
printf("gk_isortd 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_fsorti(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i] > array[i+1])
|
||||
printf("gk_fsorti 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_fsortd(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i] < array[i+1])
|
||||
printf("gk_fsortd 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 idxsorti...\n");
|
||||
for (i=0; i<N; i++)
|
||||
array[i] = RandomInRange(123432);
|
||||
|
||||
gk_idxsorti(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i] > array[i+1])
|
||||
printf("gk_idxsorti error at index %zd [%zd %zd]\n", (ssize_t)i, (ssize_t)array[i], (ssize_t)array[i+1]);
|
||||
}
|
||||
|
||||
|
||||
/* test the decreasing sort */
|
||||
printf("Testing idxsortd...\n");
|
||||
for (i=0; i<N; i++)
|
||||
array[i] = RandomInRange(123432);
|
||||
|
||||
gk_idxsortd(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i] < array[i+1])
|
||||
printf("gk_idxsortd error at index %zd [%zd %zd]\n", (ssize_t)i, (ssize_t)array[i], (ssize_t)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 ikvsorti...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
array[i].key = RandomInRange(123432);
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_ikvsorti(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i].key > array[i+1].key)
|
||||
printf("gk_ikvsorti 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 ikvsortd...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
array[i].key = RandomInRange(123432);
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_ikvsortd(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i].key < array[i+1].key)
|
||||
printf("gk_ikvsortd 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 fkvsorti...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
array[i].key = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_fkvsorti(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i].key > array[i+1].key)
|
||||
printf("gk_fkvsorti 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 fkvsortd...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
array[i].key = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_fkvsortd(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i].key < array[i+1].key)
|
||||
printf("gk_fkvsortd 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 dkvsorti...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
array[i].key = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_dkvsorti(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i].key > array[i+1].key)
|
||||
printf("gk_dkvsorti 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 dkvsortd...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
array[i].key = RandomInRange(123432)/(1.0+RandomInRange(645323));
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_dkvsortd(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i].key < array[i+1].key)
|
||||
printf("gk_dkvsortd 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 skvsorti...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
sprintf(line, "%d", RandomInRange(123432));
|
||||
array[i].key = gk_strdup(line);
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_skvsorti(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (strcmp(array[i].key, array[i+1].key) > 0)
|
||||
printf("gk_skvsorti 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 skvsortd...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
sprintf(line, "%d", RandomInRange(123432));
|
||||
array[i].key = gk_strdup(line);
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_skvsortd(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_skvsortd 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 idxkvsorti...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
array[i].key = RandomInRange(123432);
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_idxkvsorti(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i].key > array[i+1].key)
|
||||
printf("gk_idxkvsorti error at index %zd [%zd %zd] [%zd %zd]\n",
|
||||
(ssize_t)i, (ssize_t)array[i].key, (ssize_t)array[i+1].key,
|
||||
(ssize_t)array[i].val, (ssize_t)array[i+1].val);
|
||||
}
|
||||
|
||||
|
||||
/* test the decreasing sort */
|
||||
printf("Testing idxkvsortd...\n");
|
||||
for (i=0; i<N; i++) {
|
||||
array[i].key = RandomInRange(123432);
|
||||
array[i].val = i;
|
||||
}
|
||||
|
||||
gk_idxkvsortd(N, array);
|
||||
|
||||
for (i=0; i<N-1; i++) {
|
||||
if (array[i].key < array[i+1].key)
|
||||
printf("gk_idxkvsortd error at index %zd [%zd %zd] [%zd %zd]\n",
|
||||
(ssize_t)i, (ssize_t)array[i].key, (ssize_t)array[i+1].key,
|
||||
(ssize_t)array[i].val, (ssize_t)array[i+1].val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test_isort();
|
||||
test_fsort();
|
||||
test_idxsort();
|
||||
|
||||
test_ikvsort();
|
||||
test_fkvsort();
|
||||
test_dkvsort();
|
||||
test_skvsort();
|
||||
test_idxkvsort();
|
||||
}
|
||||
|
||||
|
|
@ -1,307 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief A simple frequent itemset discovery program to test GKlib's routines
|
||||
|
||||
\date 6/12/2008
|
||||
\author George
|
||||
\version \verbatim $Id: rw.c 11387 2012-01-21 23:36:23Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Data structures for the code */
|
||||
/*************************************************************************/
|
||||
typedef struct {
|
||||
int niter;
|
||||
int ntvs;
|
||||
int ppr;
|
||||
float eps;
|
||||
float lamda;
|
||||
char *infile;
|
||||
char *outfile;
|
||||
} params_t;
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Constants */
|
||||
/*************************************************************************/
|
||||
#define CMD_NITER 1
|
||||
#define CMD_EPS 2
|
||||
#define CMD_LAMDA 3
|
||||
#define CMD_PPR 4
|
||||
#define CMD_NTVS 5
|
||||
#define CMD_HELP 10
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Local variables */
|
||||
/*************************************************************************/
|
||||
static struct gk_option long_options[] = {
|
||||
{"niter", 1, 0, CMD_NITER},
|
||||
{"lamda", 1, 0, CMD_LAMDA},
|
||||
{"eps", 1, 0, CMD_EPS},
|
||||
{"ppr", 1, 0, CMD_PPR},
|
||||
{"ntvs", 1, 0, CMD_NTVS},
|
||||
{"help", 0, 0, CMD_HELP},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* Mini help */
|
||||
/*-------------------------------------------------------------------*/
|
||||
static char helpstr[][100] = {
|
||||
" ",
|
||||
"Usage: rw [options] <graph-file> <out-file>",
|
||||
" ",
|
||||
" Required parameters",
|
||||
" graph-file",
|
||||
" The name of the file storing the transactions. The file is in ",
|
||||
" Metis' graph format.",
|
||||
" ",
|
||||
" Optional parameters",
|
||||
" -niter=int",
|
||||
" Specifies the maximum number of iterations. [default: 100]",
|
||||
" ",
|
||||
" -lamda=float",
|
||||
" Specifies the follow-the-adjacent-links probability. [default: 0.80]",
|
||||
" ",
|
||||
" -eps=float",
|
||||
" Specifies the error tollerance. [default: 1e-10]",
|
||||
" ",
|
||||
" -ppr=int",
|
||||
" Specifies the source of the personalized PR. [default: -1]",
|
||||
" ",
|
||||
" -ntvs=int",
|
||||
" Specifies the number of test-vectors to compute. [default: -1]",
|
||||
" ",
|
||||
" -help",
|
||||
" Prints this message.",
|
||||
""
|
||||
};
|
||||
|
||||
static char shorthelpstr[][100] = {
|
||||
" ",
|
||||
" Usage: rw [options] <graph-file> <out-file>",
|
||||
" use 'rw -help' for a summary of the options.",
|
||||
""
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Function prototypes */
|
||||
/*************************************************************************/
|
||||
void print_init_info(params_t *params, gk_csr_t *mat);
|
||||
void print_final_info(params_t *params);
|
||||
params_t *parse_cmdline(int argc, char *argv[]);
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! the entry point */
|
||||
/**************************************************************************/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
ssize_t i, j, niter;
|
||||
params_t *params;
|
||||
gk_csr_t *mat;
|
||||
FILE *fpout;
|
||||
|
||||
/* get command-line options */
|
||||
params = parse_cmdline(argc, argv);
|
||||
|
||||
/* read the data */
|
||||
mat = gk_csr_Read(params->infile, GK_CSR_FMT_METIS, 1, 1);
|
||||
|
||||
/* display some basic stats */
|
||||
print_init_info(params, mat);
|
||||
|
||||
|
||||
|
||||
if (params->ntvs != -1) {
|
||||
/* compute the pr for different randomly generated restart-distribution vectors */
|
||||
float **prs;
|
||||
|
||||
prs = gk_fAllocMatrix(params->ntvs, mat->nrows, 0.0, "main: prs");
|
||||
|
||||
/* generate the random restart vectors */
|
||||
for (j=0; j<params->ntvs; j++) {
|
||||
for (i=0; i<mat->nrows; i++)
|
||||
prs[j][i] = RandomInRange(931);
|
||||
gk_fscale(mat->nrows, 1.0/gk_fsum(mat->nrows, prs[j], 1), prs[j], 1);
|
||||
|
||||
niter = gk_rw_PageRank(mat, params->lamda, params->eps, params->niter, prs[j]);
|
||||
printf("tvs#: %zd; niters: %zd\n", j, niter);
|
||||
}
|
||||
|
||||
/* output the computed pr scores */
|
||||
fpout = gk_fopen(params->outfile, "w", "main: outfile");
|
||||
for (i=0; i<mat->nrows; i++) {
|
||||
for (j=0; j<params->ntvs; j++)
|
||||
fprintf(fpout, "%.4e ", prs[j][i]);
|
||||
fprintf(fpout, "\n");
|
||||
}
|
||||
gk_fclose(fpout);
|
||||
|
||||
gk_fFreeMatrix(&prs, params->ntvs, mat->nrows);
|
||||
}
|
||||
else if (params->ppr != -1) {
|
||||
/* compute the personalized pr from the specified vertex */
|
||||
float *pr;
|
||||
|
||||
pr = gk_fsmalloc(mat->nrows, 0.0, "main: pr");
|
||||
|
||||
pr[params->ppr-1] = 1.0;
|
||||
|
||||
niter = gk_rw_PageRank(mat, params->lamda, params->eps, params->niter, pr);
|
||||
printf("ppr: %d; niters: %zd\n", params->ppr, niter);
|
||||
|
||||
/* output the computed pr scores */
|
||||
fpout = gk_fopen(params->outfile, "w", "main: outfile");
|
||||
for (i=0; i<mat->nrows; i++)
|
||||
fprintf(fpout, "%.4e\n", pr[i]);
|
||||
gk_fclose(fpout);
|
||||
|
||||
gk_free((void **)&pr, LTERM);
|
||||
}
|
||||
else {
|
||||
/* compute the standard pr */
|
||||
int jmax;
|
||||
float diff, maxdiff;
|
||||
float *pr;
|
||||
|
||||
pr = gk_fsmalloc(mat->nrows, 1.0/mat->nrows, "main: pr");
|
||||
|
||||
niter = gk_rw_PageRank(mat, params->lamda, params->eps, params->niter, pr);
|
||||
printf("pr; niters: %zd\n", niter);
|
||||
|
||||
/* output the computed pr scores */
|
||||
fpout = gk_fopen(params->outfile, "w", "main: outfile");
|
||||
for (i=0; i<mat->nrows; i++) {
|
||||
for (jmax=i, maxdiff=0.0, j=mat->rowptr[i]; j<mat->rowptr[i+1]; j++) {
|
||||
if ((diff = fabs(pr[i]-pr[mat->rowind[j]])) > maxdiff) {
|
||||
maxdiff = diff;
|
||||
jmax = mat->rowind[j];
|
||||
}
|
||||
}
|
||||
fprintf(fpout, "%.4e %10zd %.4e %10d\n", pr[i],
|
||||
mat->rowptr[i+1]-mat->rowptr[i], maxdiff, jmax+1);
|
||||
}
|
||||
gk_fclose(fpout);
|
||||
|
||||
gk_free((void **)&pr, LTERM);
|
||||
}
|
||||
|
||||
gk_csr_Free(&mat);
|
||||
|
||||
/* display some final stats */
|
||||
print_final_info(params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function prints run parameters */
|
||||
/*************************************************************************/
|
||||
void print_init_info(params_t *params, gk_csr_t *mat)
|
||||
{
|
||||
printf("*******************************************************************************\n");
|
||||
printf(" fis\n\n");
|
||||
printf("Matrix Information ---------------------------------------------------------\n");
|
||||
printf(" input file=%s, [%d, %d, %zd]\n",
|
||||
params->infile, mat->nrows, mat->ncols, mat->rowptr[mat->nrows]);
|
||||
|
||||
printf("\n");
|
||||
printf("Options --------------------------------------------------------------------\n");
|
||||
printf(" niter=%d, ntvs=%d, ppr=%d, lamda=%f, eps=%e\n",
|
||||
params->niter, params->ntvs, params->ppr, params->lamda, params->eps);
|
||||
|
||||
printf("\n");
|
||||
printf("Performing random walks... ----------------------------------------------\n");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function prints final statistics */
|
||||
/*************************************************************************/
|
||||
void print_final_info(params_t *params)
|
||||
{
|
||||
printf("\n");
|
||||
printf("Memory Usage Information -----------------------------------------------------\n");
|
||||
printf(" Maximum memory used: %10zd bytes\n", (ssize_t) gk_GetMaxMemoryUsed());
|
||||
printf(" Current memory used: %10zd bytes\n", (ssize_t) gk_GetCurMemoryUsed());
|
||||
printf("********************************************************************************\n");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This is the entry point of the command-line argument parser */
|
||||
/*************************************************************************/
|
||||
params_t *parse_cmdline(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int c, option_index;
|
||||
params_t *params;
|
||||
|
||||
params = (params_t *)gk_malloc(sizeof(params_t), "parse_cmdline: params");
|
||||
|
||||
/* initialize the params data structure */
|
||||
params->niter = 100;
|
||||
params->ppr = -1;
|
||||
params->ntvs = -1;
|
||||
params->eps = 1e-10;
|
||||
params->lamda = 0.80;
|
||||
params->infile = NULL;
|
||||
params->outfile = NULL;
|
||||
|
||||
|
||||
/* Parse the command line arguments */
|
||||
while ((c = gk_getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
case CMD_NITER:
|
||||
if (gk_optarg) params->niter = atoi(gk_optarg);
|
||||
break;
|
||||
case CMD_NTVS:
|
||||
if (gk_optarg) params->ntvs = atoi(gk_optarg);
|
||||
break;
|
||||
case CMD_PPR:
|
||||
if (gk_optarg) params->ppr = atoi(gk_optarg);
|
||||
break;
|
||||
case CMD_EPS:
|
||||
if (gk_optarg) params->eps = atof(gk_optarg);
|
||||
break;
|
||||
case CMD_LAMDA:
|
||||
if (gk_optarg) params->lamda = atof(gk_optarg);
|
||||
break;
|
||||
|
||||
case CMD_HELP:
|
||||
for (i=0; strlen(helpstr[i]) > 0; i++)
|
||||
printf("%s\n", helpstr[i]);
|
||||
exit(0);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
printf("Illegal command-line option(s)\nUse %s -help for a summary of the options.\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc-gk_optind != 2) {
|
||||
printf("Unrecognized parameters.");
|
||||
for (i=0; strlen(shorthelpstr[i]) > 0; i++)
|
||||
printf("%s\n", shorthelpstr[i]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
params->infile = gk_strdup(argv[gk_optind++]);
|
||||
params->outfile = gk_strdup(argv[gk_optind++]);
|
||||
|
||||
if (!gk_fexists(params->infile))
|
||||
errexit("input file %s does not exist.\n", params->infile);
|
||||
|
||||
if (params->ppr != -1 && params->ntvs != -1)
|
||||
errexit("Only one of the -ppr and -ntvs options can be specified.\n");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
|
@ -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 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Testing module for gk_strstr_replace() */
|
||||
/*************************************************************************/
|
||||
void test_strstr_replace()
|
||||
{
|
||||
char *new_str;
|
||||
int rc;
|
||||
|
||||
rc = gk_strstr_replace("This is a simple string", "s", "S", "", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
|
||||
rc = gk_strstr_replace("This is a simple string", "s", "S", "g", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
|
||||
rc = gk_strstr_replace("This is a simple SS & ss string", "s", "T", "g", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
|
||||
rc = gk_strstr_replace("This is a simple SS & ss string", "s", "T", "ig", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
rc = gk_strstr_replace("This is a simple SS & ss string", "\\b\\w(\\w+)\\w\\b", "$1", "ig", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
rc = gk_strstr_replace("This is a simple SS & ss string", "\\b\\w+\\b", "word", "ig", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4",
|
||||
"(http://www\\.cs\\.umn\\.edu/)(.*)-T(\\d+)", "$1$2-P$3", "g", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4",
|
||||
"(\\d+)", "number:$1", "ig", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
|
||||
rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4",
|
||||
"(http://www\\.cs\\.umn\\.edu/)", "[$1]", "g", &new_str);
|
||||
printf("%d, %s.\n", rc, new_str);
|
||||
gk_free((void **)&new_str, LTERM);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test_strstr_replace();
|
||||
|
||||
/*
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<1000; i++)
|
||||
printf("%d\n", RandomInRange(3));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*!
|
||||
\file timers.c
|
||||
\brief Various timing functions
|
||||
|
||||
\date Started 4/12/2007
|
||||
\author George
|
||||
\version\verbatim $Id: timers.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function returns the CPU seconds
|
||||
**************************************************************************/
|
||||
double gk_WClockSeconds(void)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
struct timeval ctime;
|
||||
|
||||
gettimeofday(&ctime, NULL);
|
||||
|
||||
return (double)ctime.tv_sec + (double).000001*ctime.tv_usec;
|
||||
#else
|
||||
return (double)time(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function returns the CPU seconds
|
||||
**************************************************************************/
|
||||
double gk_CPUSeconds(void)
|
||||
{
|
||||
//#ifdef __OPENMP__
|
||||
#ifdef __OPENMPXXXX__
|
||||
return omp_get_wtime();
|
||||
#else
|
||||
#if defined(WIN32) || defined(__MINGW32__)
|
||||
return((double) clock()/CLOCKS_PER_SEC);
|
||||
#else
|
||||
struct rusage r;
|
||||
|
||||
getrusage(RUSAGE_SELF, &r);
|
||||
return ((r.ru_utime.tv_sec + r.ru_stime.tv_sec) + 1.0e-6*(r.ru_utime.tv_usec + r.ru_stime.tv_usec));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*!
|
||||
\file tokenizer.c
|
||||
\brief String tokenization routines
|
||||
|
||||
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.
|
||||
|
||||
\date Started 11/23/04
|
||||
\author George
|
||||
\version\verbatim $Id: tokenizer.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#include <GKlib.h>
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This function tokenizes a string based on the user-supplied delimiters
|
||||
* list. The resulting tokens are returned into an array of strings.
|
||||
*************************************************************************/
|
||||
void gk_strtokenize(char *str, char *delim, gk_Tokens_t *tokens)
|
||||
{
|
||||
int i, ntoks, slen;
|
||||
|
||||
tokens->strbuf = gk_strdup(str);
|
||||
|
||||
slen = strlen(str);
|
||||
str = tokens->strbuf;
|
||||
|
||||
/* Scan once to determine the number of tokens */
|
||||
for (ntoks=0, i=0; i<slen;) {
|
||||
/* Consume all the consecutive characters from the delimiters list */
|
||||
while (i<slen && strchr(delim, str[i]))
|
||||
i++;
|
||||
|
||||
if (i == slen)
|
||||
break;
|
||||
|
||||
ntoks++;
|
||||
|
||||
/* Consume all the consecutive characters from the token */
|
||||
while (i<slen && !strchr(delim, str[i]))
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
tokens->ntoks = ntoks;
|
||||
tokens->list = (char **)gk_malloc(ntoks*sizeof(char *), "strtokenize: tokens->list");
|
||||
|
||||
|
||||
/* Scan a second time to mark and link the tokens */
|
||||
for (ntoks=0, i=0; i<slen;) {
|
||||
/* Consume all the consecutive characters from the delimiters list */
|
||||
while (i<slen && strchr(delim, str[i]))
|
||||
str[i++] = '\0';
|
||||
|
||||
if (i == slen)
|
||||
break;
|
||||
|
||||
tokens->list[ntoks++] = str+i;
|
||||
|
||||
/* Consume all the consecutive characters from the token */
|
||||
while (i<slen && !strchr(delim, str[i]))
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This function frees the memory associated with a gk_Tokens_t
|
||||
*************************************************************************/
|
||||
void gk_freetokenslist(gk_Tokens_t *tokens)
|
||||
{
|
||||
gk_free((void *)&tokens->list, &tokens->strbuf, LTERM);
|
||||
}
|
||||
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
/*!
|
||||
\file util.c
|
||||
\brief Various utility routines
|
||||
|
||||
\date Started 4/12/2007
|
||||
\author George
|
||||
\version\verbatim $Id: util.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#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);
|
||||
gk_SWAP(p[v], p[u], tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
\brief Converts an element-based set membership into a CSR-format set-based
|
||||
membership.
|
||||
|
||||
For example, 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.
|
||||
|
||||
\param n
|
||||
the number of elements in the array (e.g., # of vertices)
|
||||
\param range
|
||||
the cardinality of the set (e.g., # of partitions)
|
||||
\param array
|
||||
the array that stores the per-element set membership
|
||||
\param ptr
|
||||
the array that will store the starting indices in ind for
|
||||
the elements of each set. This is filled by the routine and
|
||||
its size should be at least range+1.
|
||||
\param ind
|
||||
the array that stores consecutively which elements belong to
|
||||
each set. The size of this array should be n.
|
||||
*/
|
||||
/************************************************************************/
|
||||
void gk_array2csr(size_t n, size_t range, int *array, int *ptr, int *ind)
|
||||
{
|
||||
gk_idx_t i;
|
||||
|
||||
gk_iset(range+1, 0, ptr);
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
ptr[array[i]]++;
|
||||
|
||||
/* Compute the ptr, ind structure */
|
||||
MAKECSR(i, range, ptr);
|
||||
for (i=0; i<n; i++)
|
||||
ind[ptr[array[i]]++] = i;
|
||||
SHIFTCSR(i, range, ptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function returns the log2(x)
|
||||
**************************************************************************/
|
||||
int gk_log2(int a)
|
||||
{
|
||||
gk_idx_t i;
|
||||
|
||||
for (i=1; a > 1; i++, a = a>>1);
|
||||
return i-1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function checks if the argument is a power of 2
|
||||
**************************************************************************/
|
||||
int gk_ispow2(int a)
|
||||
{
|
||||
return (a == (1<<gk_log2(a)));
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function returns the log2(x)
|
||||
**************************************************************************/
|
||||
float gk_flog2(float a)
|
||||
{
|
||||
return log(a)/log(2.0);
|
||||
}
|
||||
|
||||
|
|
@ -1,25 +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. You need to have GNU make and CMake 2.8 (http://www.cmake.org/) installed.
|
||||
|
||||
3. 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.
|
||||
|
||||
|
||||
4. At the top of Metis' directory execute 'make' and follow the instructions.
|
||||
|
||||
make
|
||||
|
||||
5. To build on windows using Visual Studio follow the instructions in the
|
||||
file BUILD-Windows.txt.
|
||||
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
Copyright & License Notice
|
||||
---------------------------
|
||||
|
||||
Copyright 1995-2013, Regents of the University of Minnesota
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
# Configuration options.
|
||||
gdb = not-set
|
||||
assert = not-set
|
||||
assert2 = not-set
|
||||
debug = not-set
|
||||
gprof = not-set
|
||||
openmp = not-set
|
||||
prefix = not-set
|
||||
gklib_path = not-set
|
||||
shared = not-set
|
||||
cc = not-set
|
||||
|
||||
|
||||
# Basically proxies everything to the builddir cmake.
|
||||
|
||||
cputype = $(shell uname -m | sed "s/\\ /_/g")
|
||||
systype = $(shell uname -s)
|
||||
|
||||
BUILDDIR = build/$(systype)-$(cputype)
|
||||
|
||||
# Process configuration options.
|
||||
CONFIG_FLAGS = -DCMAKE_VERBOSE_MAKEFILE=1
|
||||
ifeq ($(gklib_path), not-set)
|
||||
gklib_path = GKlib
|
||||
endif
|
||||
CONFIG_FLAGS += -DGKLIB_PATH=$(abspath $(gklib_path))
|
||||
ifneq ($(gdb), not-set)
|
||||
CONFIG_FLAGS += -DGDB=$(gdb)
|
||||
endif
|
||||
ifneq ($(assert), not-set)
|
||||
CONFIG_FLAGS += -DASSERT=$(assert)
|
||||
endif
|
||||
ifneq ($(assert2), not-set)
|
||||
CONFIG_FLAGS += -DASSERT2=$(assert2)
|
||||
endif
|
||||
ifneq ($(debug), not-set)
|
||||
CONFIG_FLAGS += -DDEBUG=$(debug)
|
||||
endif
|
||||
ifneq ($(gprof), not-set)
|
||||
CONFIG_FLAGS += -DGPROF=$(gprof)
|
||||
endif
|
||||
ifneq ($(openmp), not-set)
|
||||
CONFIG_FLAGS += -DOPENMP=$(openmp)
|
||||
endif
|
||||
ifneq ($(prefix), not-set)
|
||||
CONFIG_FLAGS += -DCMAKE_INSTALL_PREFIX=$(prefix)
|
||||
endif
|
||||
ifneq ($(shared), not-set)
|
||||
CONFIG_FLAGS += -DSHARED=1
|
||||
endif
|
||||
ifneq ($(cc), not-set)
|
||||
CONFIG_FLAGS += -DCMAKE_C_COMPILER=$(cc)
|
||||
endif
|
||||
|
||||
VERNUM=5.1.0
|
||||
PKGNAME=metis-$(VERNUM)
|
||||
|
||||
define run-config
|
||||
mkdir -p $(BUILDDIR)
|
||||
cd $(BUILDDIR) && cmake $(CURDIR) $(CONFIG_FLAGS)
|
||||
endef
|
||||
|
||||
all clean install:
|
||||
@if [ ! -f $(BUILDDIR)/Makefile ]; then \
|
||||
more BUILD.txt; \
|
||||
else \
|
||||
make -C $(BUILDDIR) $@ $(MAKEFLAGS); \
|
||||
fi
|
||||
|
||||
uninstall:
|
||||
xargs rm < $(BUILDDIR)/install_manifest.txt
|
||||
|
||||
config: distclean
|
||||
$(run-config)
|
||||
|
||||
distclean:
|
||||
rm -rf $(BUILDDIR)
|
||||
|
||||
remake:
|
||||
find . -name CMakeLists.txt -exec touch {} ';'
|
||||
|
||||
dist:
|
||||
utils/mkdist.sh $(PKGNAME)
|
||||
|
||||
.PHONY: config distclean all clean install uninstall remake dist
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,19 +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. They can be used as inputs to gpmetis and ndmetis.
|
||||
|
||||
test.mgraph
|
||||
This is a very small graph with two vertex weights (multi-constraint).
|
||||
Can be used as input to gpmetis.
|
||||
|
||||
metis.mesh
|
||||
This is a small 2D mesh (It is a triangulation of 'METIS').
|
||||
Can be used as input to mpmetis and m2gmetis.
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,770 +0,0 @@
|
|||
%% graph file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% 1st line: n, m
|
||||
%% ff lines: vwgt1, vwgt2, adjacencies
|
||||
766 1314 010 2
|
||||
1 1 479 389 571 2
|
||||
2 2 395 1 534 4
|
||||
4 4 148 207 409 498
|
||||
4 4 2 729 6 695
|
||||
4 4 572 6 708 393
|
||||
2 2 571 727 4 5
|
||||
2 2 746 397 575 573
|
||||
24 8 152 733 638 746
|
||||
1 1 573 524 11 13
|
||||
1 1 11 497 532 14
|
||||
2 2 12 531 10 9
|
||||
4 4 754 490 616 11
|
||||
1 1 9 706 403 14
|
||||
1 1 13 10 18 15
|
||||
1 1 14 402 530 20
|
||||
24 8 742 692 17 581
|
||||
4 4 16 109 116 620
|
||||
1 1 14 512 535 20
|
||||
1 1 20 404 408 24
|
||||
1 1 18 15 19 22
|
||||
38 8 645 628 148 536
|
||||
1 1 20 527 421 24
|
||||
24 8 179 28 629 30
|
||||
1 1 19 22 513 27
|
||||
24 8 742 159 174 28
|
||||
0 0 411 440 539 442
|
||||
1 1 24 411 410 538
|
||||
24 8 25 254 23 29
|
||||
4 4 174 28 750 30
|
||||
4 4 596 23 29 745
|
||||
52 8 645 192 581 525
|
||||
1 1 51 332 406
|
||||
1 1 577 330 51
|
||||
1 1 418 682 423
|
||||
68 8 711 36 606
|
||||
68 8 626 35 153
|
||||
0 0 52 333 420
|
||||
2 2 422 358 419
|
||||
1 1 58 345 578
|
||||
1 1 59 348 58
|
||||
68 8 208 144 734
|
||||
68 8 143 483 484
|
||||
1 1 64 349 425
|
||||
2 2 66 334 426
|
||||
68 8 579 141 427
|
||||
0 0 420 50 339
|
||||
68 8 764 48 564
|
||||
68 8 587 47 443
|
||||
2 2 62 673 687
|
||||
0 0 578 46 565
|
||||
1 1 33 584 32
|
||||
0 0 406 429 37
|
||||
68 8 485 335 731
|
||||
68 8 758 55 519
|
||||
68 8 586 54 183
|
||||
1 1 426 64 577
|
||||
0 0 552 630
|
||||
1 1 40 429 39
|
||||
1 1 425 584 40
|
||||
0 0 462
|
||||
68 8 308 162 647
|
||||
4 4 690 431 49
|
||||
68 8 161 672 305
|
||||
1 1 687 56 43
|
||||
68 8 588 168 253
|
||||
4 4 368 431 44
|
||||
68 8 560 68 709
|
||||
68 8 500 67 196
|
||||
68 8 566 170 433
|
||||
68 8 724 163 366
|
||||
1 1 113 97
|
||||
1 1 177 79
|
||||
1 1 601 142
|
||||
24 8 92 738 739
|
||||
24 8 454 644 595
|
||||
1 1 545 146 502
|
||||
1 1 591 351 435
|
||||
1 1 344 436 437
|
||||
1 1 146 72 487 434
|
||||
1 1 103 354 439
|
||||
2 2 437 463 115
|
||||
1 1 601 304
|
||||
2 2 109 174 592
|
||||
0 0 110 355 440
|
||||
1 1 112 353 441
|
||||
0 0 440 442 593
|
||||
0 0 263
|
||||
1 1 444 381 111
|
||||
0 0 91 442 357
|
||||
8 8 594 740 732
|
||||
0 0 445 446 89
|
||||
24 8 595 447 74
|
||||
8 8 763 741 744
|
||||
1 1 757 667 448
|
||||
1 1 453 436 108
|
||||
52 8 130 686 208
|
||||
1 1 71 268
|
||||
1 1 304 157
|
||||
0 0 101 100
|
||||
0 0 474 99 126
|
||||
0 0 474 630 99
|
||||
1 1 117 383 107
|
||||
1 1 441 449 80
|
||||
2 2 116 207 338
|
||||
52 8 763 187 205 692
|
||||
24 8 713 447 763
|
||||
1 1 102 449 444
|
||||
2 2 95 388 450
|
||||
4 4 742 17 83
|
||||
1 1 439 451 84
|
||||
1 1 88 451 445
|
||||
1 1 435 452 85
|
||||
1 1 309 71 282
|
||||
0 0 743
|
||||
4 4 81 119 454
|
||||
4 4 744 17 104
|
||||
1 1 448 452 102
|
||||
1 1 178 600
|
||||
4 4 450 115 661
|
||||
1 1 356 178
|
||||
1 1 601 602
|
||||
0 0 123 460
|
||||
0 0 663 122 248
|
||||
24 8 222 253
|
||||
24 8 603 461
|
||||
0 0 100 248
|
||||
4 4 220 218 604
|
||||
1 1 549 685
|
||||
0 0 529 234 567 151
|
||||
68 8 606 96
|
||||
0 0 607 261 462
|
||||
68 8 417 711
|
||||
1 1 550 608 267
|
||||
1 1 649 214
|
||||
1 1 235 611 704
|
||||
1 1 280 219 613
|
||||
0 0 654 221
|
||||
1 1 266 211 615
|
||||
24 8 736 176
|
||||
24 8 579 558
|
||||
68 8 676 45 518
|
||||
1 1 177 73 542
|
||||
68 8 42 526 191
|
||||
68 8 179 41 629
|
||||
0 0 224 621
|
||||
1 1 76 79 258
|
||||
68 8 468 747 731
|
||||
8 8 391 392 21 3
|
||||
4 4 346 556
|
||||
2 2 639 229 232
|
||||
0 0 464 129
|
||||
24 8 526 191 8 412
|
||||
52 8 36 738 712 167
|
||||
68 8 466 194 526
|
||||
52 8 496 695 753 748
|
||||
2 2 350 623
|
||||
1 1 98 465 309
|
||||
1 1 233 217 238
|
||||
52 8 167 190 179 25
|
||||
68 8 644 595 626
|
||||
52 8 390 63 308
|
||||
68 8 697 61 749
|
||||
68 8 628 70 725
|
||||
4 4 225 674
|
||||
68 8 629 726 191
|
||||
4 4 710 328 169 318
|
||||
68 8 153 739 159
|
||||
68 8 631 65 751
|
||||
4 4 721 166 398 490
|
||||
68 8 632 69 637
|
||||
0 0 657 226
|
||||
68 8 253 603
|
||||
68 8 468 200 640
|
||||
4 4 25 83 413 29
|
||||
0 0 203 469 470
|
||||
52 8 564 139 609 240
|
||||
1 1 142 72 438
|
||||
1 1 455 120 118
|
||||
52 8 159 144 180 23
|
||||
24 8 190 179 208 596
|
||||
4 4 237 659
|
||||
68 8 183 205 628
|
||||
64 8 55 568 735 182
|
||||
68 8 748 209 715
|
||||
1 1 227 471
|
||||
1 1 231 310
|
||||
68 8 447 105 739
|
||||
1 1 215 650
|
||||
68 8 707 209 619
|
||||
24 8 159 686 180 413
|
||||
52 8 143 165 752 152
|
||||
68 8 31 726 618
|
||||
68 8 599 595 447
|
||||
68 8 624 154 733
|
||||
1 1 241 635
|
||||
68 8 68 210 632
|
||||
8 8 651 756 662
|
||||
24 8 387 683 651
|
||||
52 8 749 651 758 586
|
||||
68 8 641 173 528
|
||||
0 0 252 239 256
|
||||
68 8 213 642 546
|
||||
0 0 696 250 175
|
||||
24 8 759 694 386
|
||||
68 8 105 182 645
|
||||
0 0 246 322
|
||||
4 4 391 407 104 3
|
||||
52 8 96 41 180 223
|
||||
68 8 189 184 617
|
||||
68 8 546 196 624
|
||||
1 1 646 138 354
|
||||
68 8 647 758
|
||||
68 8 475 202 648
|
||||
1 1 134 610 233 330
|
||||
1 1 290 260 472 188
|
||||
68 8 519 694
|
||||
1 1 330 158 332
|
||||
4 4 612 652 127
|
||||
1 1 653 136 353
|
||||
2 2 704 297 127
|
||||
0 0 137 243 657
|
||||
24 8 604 588 124
|
||||
24 8 208 734 350
|
||||
0 0 655 145 270 355
|
||||
4 4 295 249 164 278
|
||||
0 0 467 171 262 339
|
||||
1 1 327 185 681 517
|
||||
1 1 471 259 456
|
||||
4 4 271 150 334
|
||||
4 4 461 561 639
|
||||
1 1 659 244 186
|
||||
1 1 150 299 649
|
||||
1 1 214 291 158
|
||||
0 0 593 129 462
|
||||
1 1 602 236 135
|
||||
1 1 633 235 491
|
||||
8 8 558 242 181
|
||||
1 1 158 301 654
|
||||
0 0 540 201 319
|
||||
24 8 176 718 579
|
||||
1 1 310 247 195
|
||||
24 8 427 518 237 504
|
||||
0 0 614 221 313 333
|
||||
2 2 307 292 231 658
|
||||
0 0 416 460 567
|
||||
0 0 319 256 477 206
|
||||
1 1 241 660 289 635
|
||||
0 0 126 264 123
|
||||
2 2 650 312 225
|
||||
0 0 503 565 203
|
||||
1 1 542 255 465
|
||||
1 1 541 300 201
|
||||
52 8 124 65 172 554
|
||||
24 8 581 28 726 750
|
||||
1 1 478 251 523
|
||||
0 0 201 562 246
|
||||
0 0 265 481 263
|
||||
1 1 146 327 478
|
||||
1 1 523 228 455
|
||||
1 1 482 285 215
|
||||
0 0 363 131 460
|
||||
0 0 226 316 627
|
||||
0 0 257 470 87
|
||||
0 0 480 663 343 248
|
||||
0 0 570 257
|
||||
1 1 613 360 138
|
||||
1 1 133 361 549
|
||||
1 1 97 282 597
|
||||
0 0 671 287
|
||||
1 1 615 362 224
|
||||
24 8 582 315 229
|
||||
1 1 670 284
|
||||
0 0 621 688 547
|
||||
68 8 427 483
|
||||
1 1 352 293
|
||||
68 8 734 484
|
||||
68 8 335 764
|
||||
8 8 225 580 656 674
|
||||
2 2 643 384
|
||||
1 1 668 765 136
|
||||
68 8 485 414
|
||||
1 1 113 356 458 268
|
||||
4 4 486 387
|
||||
1 1 272 665 381 348
|
||||
1 1 487 260 590
|
||||
24 8 724 430 643
|
||||
0 0 269 345 570
|
||||
24 8 324 636 320
|
||||
1 1 488 247 321
|
||||
1 1 548 365 215
|
||||
1 1 537 233 329
|
||||
2 2 318 244 634
|
||||
1 1 428 275 383 349
|
||||
2 2 491 341 297
|
||||
2 2 650 723 225
|
||||
24 8 680 631 331
|
||||
4 4 294 220 563
|
||||
1 1 458 597 358 388
|
||||
1 1 398 232 492
|
||||
1 1 493 252 562
|
||||
1 1 329 238 494
|
||||
8 8 755 473 561
|
||||
1 1 590 341 495
|
||||
1 1 82 98 418
|
||||
68 8 63 761
|
||||
1 1 492 317 537
|
||||
4 4 504 659 675 244
|
||||
68 8 161 61
|
||||
1 1 113 157 422
|
||||
1 1 186 677 241
|
||||
24 8 676 473 559
|
||||
4 4 495 249 669
|
||||
0 0 494 326 243
|
||||
1 1 635 374 540
|
||||
52 8 566 271 368
|
||||
0 0 499 262 760
|
||||
1 1 634 306 488
|
||||
4 4 702 166 292
|
||||
0 0 239 378 246
|
||||
24 8 288 475 678
|
||||
1 1 289 501 493
|
||||
0 0 206 679 474
|
||||
68 8 366 433
|
||||
24 8 669 432 288
|
||||
1 1 550 471 361
|
||||
0 0 313 562 499
|
||||
1 1 502 258 227
|
||||
2 2 561 166 398
|
||||
1 1 291 501 301
|
||||
1 1 214 33 217
|
||||
24 8 296 475 751
|
||||
1 1 217 32 654
|
||||
0 0 243 37 657 467
|
||||
2 2 229 44 649
|
||||
52 8 585 53 277
|
||||
1 1 602 682 611
|
||||
24 8 483 340 569
|
||||
1 1 104 544 757
|
||||
0 0 226 46 503
|
||||
24 8 484 337 372
|
||||
2 2 303 727 294 708
|
||||
0 0 343 469 416
|
||||
0 0 720 264 342
|
||||
1 1 608 78 549
|
||||
1 1 671 39 700 287
|
||||
2 2 685 463 149
|
||||
24 8 556 644 594
|
||||
1 1 284 40 671
|
||||
1 1 293 43 670
|
||||
4 4 596 223 156 745
|
||||
1 1 623 77 653
|
||||
1 1 384 673 275
|
||||
1 1 219 85 646
|
||||
1 1 211 80 655
|
||||
0 0 224 84 621 666
|
||||
1 1 120 282 453
|
||||
0 0 89 470 464
|
||||
2 2 298 38 486
|
||||
0 0 370 679 663
|
||||
1 1 689 266 377
|
||||
1 1 325 267 505
|
||||
1 1 506 270 379
|
||||
0 0 364 507 261
|
||||
0 0 508 688 363
|
||||
1 1 681 290 511
|
||||
52 8 70 323 430 698
|
||||
2 2 505 691 369
|
||||
24 8 433 315 66
|
||||
4 4 367 509 701
|
||||
0 0 510 507 359
|
||||
2 2 372 765 376
|
||||
4 4 340 396 693 371
|
||||
2 2 511 691 723
|
||||
1 1 385 314 405
|
||||
1 1 399 677 514
|
||||
1 1 371 380 689
|
||||
1 1 360 400 506
|
||||
0 0 515 319 510
|
||||
0 0 362 382 508
|
||||
1 1 693 376 399
|
||||
1 1 284 88 671
|
||||
0 0 405 379 515
|
||||
1 1 293 102 670
|
||||
1 1 279 667 352
|
||||
1 1 514 400 374
|
||||
24 8 401 204 766 407
|
||||
24 8 283 664 749 198
|
||||
2 2 298 108 486
|
||||
1 1 517 1 516 505
|
||||
24 8 419 496 697 161
|
||||
8 8 401 744 148 207
|
||||
38 8 401 628 766 148
|
||||
24 8 5 468 707 619
|
||||
52 8 695 622 753 641
|
||||
1 1 523 521 522 2
|
||||
4 4 752 412 372 575
|
||||
2 2 553 7 435 524
|
||||
2 2 639 328 169 299
|
||||
1 1 737 380 375 574
|
||||
1 1 512 377 385 404
|
||||
24 8 735 392 386 391
|
||||
1 1 449 15 444 408
|
||||
1 1 452 13 441 449
|
||||
1 1 400 19 506 405
|
||||
1 1 374 404 513 382
|
||||
1 1 32 421 614 52
|
||||
4 4 386 207 409
|
||||
1 1 402 439 19 451
|
||||
4 4 766 407 3 643
|
||||
1 1 429 27 578 420
|
||||
1 1 451 27 445 26
|
||||
4 4 152 717 396 746
|
||||
4 4 190 174 596
|
||||
68 8 281 415 417
|
||||
52 8 701 424 640 414
|
||||
0 0 459 529 342 245
|
||||
52 8 556 414 132
|
||||
1 1 304 589 465 34
|
||||
4 4 423 38 390
|
||||
0 0 37 410 467 46
|
||||
1 1 584 406 22 429
|
||||
1 1 309 458 522 38
|
||||
2 2 522 34 419 729
|
||||
24 8 463 415 625 556
|
||||
1 1 43 530 665 59
|
||||
1 1 44 531 532 56
|
||||
52 8 45 558 274 242
|
||||
1 1 673 448 687 293
|
||||
1 1 421 58 52 410
|
||||
24 8 366 286 690
|
||||
4 4 533 66 62 531
|
||||
24 8 563 520 324 617
|
||||
52 8 323 69 368 533
|
||||
1 1 478 79 438 699
|
||||
1 1 77 397 653 112
|
||||
1 1 521 78 95 534
|
||||
1 1 78 605 534 81
|
||||
1 1 542 177 434 633
|
||||
1 1 80 408 655 110
|
||||
0 0 84 26 666 86
|
||||
1 1 85 403 646 103
|
||||
0 0 26 89 86 529
|
||||
52 8 636 48 564 678
|
||||
1 1 107 665 402 88
|
||||
1 1 111 700 411 91
|
||||
0 0 700 570 91 481
|
||||
52 8 193 106 92 187
|
||||
1 1 94 524 428 117
|
||||
1 1 403 107 402 103
|
||||
4 4 534 108 622 119
|
||||
1 1 408 111 110 411
|
||||
1 1 524 112 117 403
|
||||
1 1 356 521 458 95
|
||||
24 8 115 625 528 75
|
||||
1 1 178 259 521 600
|
||||
1 1 228 550 600
|
||||
24 8 483 504 526 675
|
||||
1 1 282 422 453 298
|
||||
0 0 507 416 663 460
|
||||
0 0 459 261 245 122
|
||||
24 8 560 125 582 230
|
||||
0 0 131 234 567 60
|
||||
4 4 509 81 346 424
|
||||
0 0 529 357 469 151
|
||||
1 1 157 251 418 522
|
||||
52 8 518 154 702 504
|
||||
0 0 333 499 420 226
|
||||
52 8 393 730 173 147
|
||||
0 0 342 175 464
|
||||
0 0 481 357 175 263
|
||||
1 1 228 185 517 325
|
||||
1 1 215 511 705 650
|
||||
24 8 546 311 302 710
|
||||
0 0 322 101 480 100
|
||||
52 8 617 320 331 213
|
||||
1 1 502 548 681
|
||||
0 0 246 510 499 679
|
||||
1 1 258 255 434 479
|
||||
1 1 517 478 523 1
|
||||
0 0 679 760 474 264
|
||||
0 0 446 565 257 470
|
||||
1 1 545 548 260
|
||||
52 8 274 42 457 337
|
||||
52 8 42 276 752 340
|
||||
52 8 701 53 281
|
||||
4 4 358 388 664 283
|
||||
1 1 545 79 285
|
||||
1 1 317 660 289 535
|
||||
4 4 643 498 690 667
|
||||
2 2 169 12 634 492
|
||||
1 1 236 703 294 704
|
||||
1 1 299 490 497 306
|
||||
1 1 321 541 300 527
|
||||
1 1 301 527 614 313
|
||||
2 2 705 303 312 708
|
||||
24 8 729 390 155 672
|
||||
1 1 492 610 10 537
|
||||
4 4 3 536 757 489
|
||||
0 0 326 467 477 316
|
||||
52 8 648 755 68 546
|
||||
1 1 535 329 321 527
|
||||
1 1 76 476 327
|
||||
0 0 339 627 250
|
||||
24 8 242 457 466 307
|
||||
1 1 361 389 605 367
|
||||
1 1 377 615 404 362
|
||||
0 0 539 370 363 459
|
||||
0 0 379 666 539 364
|
||||
2 2 605 685 369 463
|
||||
0 0 378 538 477 370
|
||||
1 1 365 516 472 373
|
||||
1 1 574 514 18 400
|
||||
1 1 405 540 24 515
|
||||
1 1 375 512 660 385
|
||||
0 0 513 382 378 538
|
||||
2 2 389 511 572 691
|
||||
1 1 479 227 471 389
|
||||
52 8 141 559 466 242
|
||||
52 8 756 54 759 216
|
||||
24 8 708 669 619 432
|
||||
1 1 455 453 395 436
|
||||
1 1 465 422 395 423
|
||||
1 1 259 255 479 395
|
||||
1 1 397 448 9 452
|
||||
24 8 31 536 618 598
|
||||
52 8 143 154 457 152
|
||||
1 1 501 22 494 493
|
||||
52 8 661 454 200 599
|
||||
0 0 442 416 464 129
|
||||
1 1 577 425 15 584
|
||||
2 2 431 11 426 687
|
||||
1 1 426 610 10 577
|
||||
24 8 433 698 637 431
|
||||
2 2 436 2 437 450
|
||||
1 1 537 488 18 501
|
||||
24 8 21 525 725 498
|
||||
1 1 306 497 291 535
|
||||
0 0 515 27 539 510
|
||||
0 0 538 508 26 507
|
||||
1 1 314 541 513 239
|
||||
1 1 635 493 252 540
|
||||
1 1 142 251 438 589
|
||||
1 1 592 544 591
|
||||
2 2 620 338 598 543
|
||||
1 1 76 487 482
|
||||
52 8 202 500 473 210
|
||||
0 0 273 607
|
||||
1 1 476 482 290
|
||||
1 1 267 344 605 128
|
||||
1 1 456 325 133
|
||||
0 0 743 552 696
|
||||
0 0 57 551 720
|
||||
4 4 638 591 598 397
|
||||
24 8 253 555 603
|
||||
24 8 751 554 755
|
||||
24 8 149 424 417 347
|
||||
8 8 674 636 736
|
||||
24 8 140 427 237
|
||||
24 8 311 518 702
|
||||
52 8 603 67 755 461
|
||||
4 4 302 230 328
|
||||
0 0 300 326 256
|
||||
8 8 297 432 680
|
||||
52 8 736 47 443 176
|
||||
0 0 50 481 250
|
||||
68 8 709 315 69
|
||||
0 0 245 129 462
|
||||
32 8 583 741 763 183
|
||||
4 4 337 675 693
|
||||
0 0 287 446 265
|
||||
1 1 699 1 572 6
|
||||
2 2 571 705 516 5
|
||||
1 1 7 616 9 706
|
||||
1 1 399 706 689 512
|
||||
2 2 396 668 7 765
|
||||
52 8 715 604 761 588
|
||||
1 1 56 532 33 530
|
||||
1 1 39 410 700 50
|
||||
52 8 609 240 45 140
|
||||
24 8 278 585 587 764
|
||||
24 8 16 254 31 620
|
||||
24 8 461 709 271 639
|
||||
52 8 651 713 586 568
|
||||
1 1 51 530 59 421
|
||||
24 8 723 731 335 580
|
||||
68 8 199 583 55
|
||||
52 8 580 656 747 48
|
||||
52 8 576 631 222 65
|
||||
1 1 601 542 418 714
|
||||
1 1 285 699 705 303
|
||||
2 2 750 543 553 77
|
||||
2 2 620 83 750 543
|
||||
0 0 86 607 234
|
||||
24 8 347 711 90 626
|
||||
52 8 75 193 92 160
|
||||
4 4 180 413 30 350
|
||||
1 1 268 298
|
||||
4 4 525 544 757 553
|
||||
68 8 528 713 193
|
||||
1 1 118 456 455 608
|
||||
1 1 73 82 121 589
|
||||
1 1 121 714 235 336
|
||||
52 8 172 554 125 560
|
||||
24 8 127 576 652 222
|
||||
1 1 549 505 437 509
|
||||
52 8 740 35 712 130
|
||||
0 0 688 547 593 131
|
||||
1 1 600 133 344
|
||||
68 8 176 579
|
||||
1 1 649 497 532 214
|
||||
1 1 336 135 612
|
||||
2 2 611 719 704 218
|
||||
1 1 136 722 646 266
|
||||
1 1 654 494 406 243
|
||||
1 1 138 506 655 270
|
||||
2 2 746 12 737 573
|
||||
52 8 432 680 209 475
|
||||
52 8 192 716 525 638
|
||||
52 8 393 520 747 189
|
||||
4 4 17 581 592 544
|
||||
0 0 145 355 273
|
||||
24 8 450 394 664 661
|
||||
2 2 745 351 156 668
|
||||
52 8 210 194 710 721
|
||||
52 8 454 424 640 644
|
||||
52 8 594 160 36 738
|
||||
0 0 262 503 696 743
|
||||
64 8 182 392 163 21
|
||||
52 8 144 165 23 762
|
||||
0 0 760 101 57
|
||||
52 8 715 588 296 168
|
||||
52 8 196 170 709 721
|
||||
1 1 438 714 236 703
|
||||
1 1 292 490 658 317
|
||||
1 1 247 195 314 541
|
||||
24 8 656 557 288 443
|
||||
52 8 170 728 754 533
|
||||
24 8 726 618 8 553
|
||||
4 4 230 582 398 150
|
||||
68 8 173 415 625
|
||||
68 8 707 394 200
|
||||
68 8 678 202 676
|
||||
4 4 409 286 279 489
|
||||
52 8 625 75 347 160
|
||||
52 8 205 692 21 31
|
||||
1 1 353 613 441 211
|
||||
52 8 749 61 212
|
||||
68 8 751 213 500
|
||||
1 1 232 334 610 134
|
||||
1 1 188 472 295 249
|
||||
24 8 198 199 197 583
|
||||
24 8 218 761 604
|
||||
1 1 351 668 435 219
|
||||
1 1 238 332 614 137
|
||||
1 1 354 615 439 224
|
||||
24 8 278 669 587 636
|
||||
0 0 221 333 171
|
||||
1 1 244 737 634 677
|
||||
2 2 181 307 231
|
||||
1 1 677 488 247 514
|
||||
24 8 119 622 528 683
|
||||
8 8 197 741 759
|
||||
0 0 359 459 264 123
|
||||
24 8 486 697 622 387
|
||||
1 1 670 444 425 284
|
||||
0 0 355 508 440 688
|
||||
2 2 489 384 94 673
|
||||
2 2 623 575 653 280
|
||||
24 8 312 520 656 324
|
||||
1 1 383 349 665 272
|
||||
1 1 348 381 269 345
|
||||
52 8 496 761 63 748
|
||||
2 2 667 49 352 428
|
||||
8 8 278 164 684 557
|
||||
4 4 457 569 307 717
|
||||
52 8 642 718 141 311
|
||||
1 1 658 310 375 660
|
||||
52 8 443 320 642 718
|
||||
0 0 477 322 359 480
|
||||
24 8 563 715 617 296
|
||||
1 1 476 227 365
|
||||
1 1 714 34 336 719
|
||||
24 8 661 198 713
|
||||
24 8 674 764 736
|
||||
1 1 128 509 346
|
||||
24 8 712 96 190
|
||||
1 1 49 531 428 64
|
||||
0 0 273 666 364 607
|
||||
1 1 376 722 574 360
|
||||
8 8 430 698 489 62
|
||||
4 4 367 516 373 730
|
||||
24 8 105 744 16 645
|
||||
2 2 569 372 717 380
|
||||
52 8 216 204 724
|
||||
24 8 4 394 155 707
|
||||
0 0 627 720 203 551
|
||||
52 8 390 664 753 162
|
||||
24 8 366 725 533 690
|
||||
1 1 434 571 590 727
|
||||
1 1 345 445 578 446
|
||||
24 8 369 730 415 485
|
||||
24 8 559 710 466 318
|
||||
1 1 633 727 719 491
|
||||
1 1 135 491 612 220
|
||||
1 1 590 472 572 495
|
||||
1 1 573 722 574 13
|
||||
52 8 695 393 641 189
|
||||
4 4 495 5 341 520
|
||||
52 8 67 566 582 632
|
||||
24 8 473 624 702 166
|
||||
52 8 594 132 740 35
|
||||
24 8 606 732 153 686
|
||||
52 8 683 599 106 583
|
||||
1 1 589 602 633 682
|
||||
52 8 576 680 184 631
|
||||
68 8 728 618 733
|
||||
2 2 675 412 693 737
|
||||
24 8 678 240 676
|
||||
2 2 682 703 729 612
|
||||
0 0 760 696 343 552
|
||||
24 8 624 632 754 169
|
||||
1 1 765 706 689 613
|
||||
4 4 373 295 585
|
||||
52 8 694 70 766 286
|
||||
52 8 163 728 536 698
|
||||
52 8 192 165 254 638
|
||||
1 1 699 703 6 341
|
||||
68 8 716 725 637
|
||||
4 4 423 4 719 496
|
||||
24 8 691 701 468 731
|
||||
52 8 730 585 53 147
|
||||
8 8 90 738 712
|
||||
52 8 194 716 754 8
|
||||
52 8 41 276 223 762
|
||||
38 8 183 759 741 401
|
||||
24 8 684 557 564 139
|
||||
1 1 717 658 616 399
|
||||
24 8 626 732 74 153
|
||||
52 8 74 187 167 742
|
||||
24 8 711 90 606
|
||||
8 8 568 662 93 735
|
||||
24 8 739 109 16 25
|
||||
0 0 627 114 551
|
||||
8 8 93 692 116 391
|
||||
4 4 30 350 762 623
|
||||
4 4 8 412 616 7
|
||||
68 8 147 619 587
|
||||
68 8 155 672 184
|
||||
52 8 387 647 162 199
|
||||
4 4 592 254 29 591
|
||||
52 8 168 331 648 555
|
||||
24 8 191 484 762 396
|
||||
68 8 155 697 394
|
||||
24 8 721 733 637 12
|
||||
24 8 555 500 560 302
|
||||
24 8 758 197 519
|
||||
2 2 498 338 598 94
|
||||
52 8 199 212 756 54
|
||||
24 8 519 662 735 204
|
||||
0 0 316 480 630 720
|
||||
52 8 672 652 305 576
|
||||
24 8 629 734 752 745
|
||||
24 8 106 568 93 105
|
||||
52 8 580 684 277 47
|
||||
1 1 575 371 280 722
|
||||
24 8 386 392 724 409
|
||||
|
|
@ -1 +0,0 @@
|
|||
install(FILES metis.h DESTINATION include/gtsam/3rdparty/metis)
|
||||
|
|
@ -1,350 +0,0 @@
|
|||
/*!
|
||||
\file metis.h
|
||||
\brief This file contains function prototypes and constant definitions for METIS
|
||||
*
|
||||
\author George
|
||||
\date Started 8/9/02
|
||||
\version\verbatim $Id$\endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _METIS_H_
|
||||
#define _METIS_H_
|
||||
|
||||
/****************************************************************************
|
||||
* 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 the data type that will hold floating-point style information.
|
||||
|
||||
Possible values:
|
||||
32 : single precission floating point (float)
|
||||
64 : double precission floating point (double)
|
||||
--------------------------------------------------------------------------*/
|
||||
#define REALTYPEWIDTH 32
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
|
||||
/* Include c99 int definitions and need constants. When building the library,
|
||||
* these are already defined by GKlib; hence the test for _GKLIB_H_ */
|
||||
#ifndef _GKLIB_H_
|
||||
#ifdef COMPILER_MSC
|
||||
#include <limits.h>
|
||||
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
#define PRId32 "I32d"
|
||||
#define PRId64 "I64d"
|
||||
#define SCNd32 "ld"
|
||||
#define SCNd64 "I64d"
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* Setup the basic datatypes
|
||||
*-------------------------------------------------------------------------*/
|
||||
#if IDXTYPEWIDTH == 32
|
||||
typedef int32_t idx_t;
|
||||
|
||||
#define IDX_MAX INT32_MAX
|
||||
#define IDX_MIN INT32_MIN
|
||||
|
||||
#define SCIDX SCNd32
|
||||
#define PRIDX PRId32
|
||||
|
||||
#define strtoidx strtol
|
||||
#define iabs abs
|
||||
#elif IDXTYPEWIDTH == 64
|
||||
typedef int64_t idx_t;
|
||||
|
||||
#define IDX_MAX INT64_MAX
|
||||
#define IDX_MIN INT64_MIN
|
||||
|
||||
#define SCIDX SCNd64
|
||||
#define PRIDX PRId64
|
||||
|
||||
#ifdef COMPILER_MSC
|
||||
#define strtoidx _strtoi64
|
||||
#else
|
||||
#define strtoidx strtoll
|
||||
#endif
|
||||
#define iabs labs
|
||||
#else
|
||||
#error "Incorrect user-supplied value fo IDXTYPEWIDTH"
|
||||
#endif
|
||||
|
||||
|
||||
#if REALTYPEWIDTH == 32
|
||||
typedef float real_t;
|
||||
|
||||
#define SCREAL "f"
|
||||
#define PRREAL "f"
|
||||
#define REAL_MAX FLT_MAX
|
||||
#define REAL_MIN FLT_MIN
|
||||
#define REAL_EPSILON FLT_EPSILON
|
||||
|
||||
#define rabs fabsf
|
||||
#define REALEQ(x,y) ((rabs((x)-(y)) <= FLT_EPSILON))
|
||||
|
||||
#ifdef COMPILER_MSC
|
||||
#define strtoreal (float)strtod
|
||||
#else
|
||||
#define strtoreal strtof
|
||||
#endif
|
||||
#elif REALTYPEWIDTH == 64
|
||||
typedef double real_t;
|
||||
|
||||
#define SCREAL "lf"
|
||||
#define PRREAL "lf"
|
||||
#define REAL_MAX DBL_MAX
|
||||
#define REAL_MIN DBL_MIN
|
||||
#define REAL_EPSILON DBL_EPSILON
|
||||
|
||||
#define rabs fabs
|
||||
#define REALEQ(x,y) ((rabs((x)-(y)) <= DBL_EPSILON))
|
||||
|
||||
#define strtoreal strtod
|
||||
#else
|
||||
#error "Incorrect user-supplied value for REALTYPEWIDTH"
|
||||
#endif
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* Constant definitions
|
||||
*-------------------------------------------------------------------------*/
|
||||
/* Metis's version number */
|
||||
#define METIS_VER_MAJOR 5
|
||||
#define METIS_VER_MINOR 1
|
||||
#define METIS_VER_SUBMINOR 0
|
||||
|
||||
/* The maximum length of the options[] array */
|
||||
#define METIS_NOPTIONS 40
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* Function prototypes
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef _WINDLL
|
||||
#define METIS_API(type) __declspec(dllexport) type __cdecl
|
||||
#elif defined(__cdecl)
|
||||
#define METIS_API(type) type __cdecl
|
||||
#else
|
||||
#define METIS_API(type) type
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
METIS_API(int) METIS_PartGraphRecursive(idx_t *nvtxs, idx_t *ncon, idx_t *xadj,
|
||||
idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt,
|
||||
idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options,
|
||||
idx_t *edgecut, idx_t *part);
|
||||
|
||||
METIS_API(int) METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj,
|
||||
idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt,
|
||||
idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options,
|
||||
idx_t *edgecut, idx_t *part);
|
||||
|
||||
METIS_API(int) METIS_MeshToDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind,
|
||||
idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy);
|
||||
|
||||
METIS_API(int) METIS_MeshToNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind,
|
||||
idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy);
|
||||
|
||||
METIS_API(int) METIS_PartMeshNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind,
|
||||
idx_t *vwgt, idx_t *vsize, idx_t *nparts, real_t *tpwgts,
|
||||
idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart);
|
||||
|
||||
METIS_API(int) METIS_PartMeshDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind,
|
||||
idx_t *vwgt, idx_t *vsize, idx_t *ncommon, idx_t *nparts,
|
||||
real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart,
|
||||
idx_t *npart);
|
||||
|
||||
METIS_API(int) METIS_NodeND(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt,
|
||||
idx_t *options, idx_t *perm, idx_t *iperm);
|
||||
|
||||
METIS_API(int) METIS_Free(void *ptr);
|
||||
|
||||
METIS_API(int) METIS_SetDefaultOptions(idx_t *options);
|
||||
|
||||
|
||||
/* These functions are used by ParMETIS */
|
||||
|
||||
METIS_API(int) METIS_NodeNDP(idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt,
|
||||
idx_t npes, idx_t *options, idx_t *perm, idx_t *iperm,
|
||||
idx_t *sizes);
|
||||
|
||||
METIS_API(int) METIS_ComputeVertexSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy,
|
||||
idx_t *vwgt, idx_t *options, idx_t *sepsize, idx_t *part);
|
||||
|
||||
METIS_API(int) METIS_NodeRefine(idx_t nvtxs, idx_t *xadj, idx_t *vwgt, idx_t *adjncy,
|
||||
idx_t *where, idx_t *hmarker, real_t ubfactor);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* Enum type definitions
|
||||
*-------------------------------------------------------------------------*/
|
||||
/*! Return codes */
|
||||
typedef enum {
|
||||
METIS_OK = 1, /*!< Returned normally */
|
||||
METIS_ERROR_INPUT = -2, /*!< Returned due to erroneous inputs and/or options */
|
||||
METIS_ERROR_MEMORY = -3, /*!< Returned due to insufficient memory */
|
||||
METIS_ERROR = -4 /*!< Some other errors */
|
||||
} rstatus_et;
|
||||
|
||||
|
||||
/*! Operation type codes */
|
||||
typedef enum {
|
||||
METIS_OP_PMETIS,
|
||||
METIS_OP_KMETIS,
|
||||
METIS_OP_OMETIS
|
||||
} moptype_et;
|
||||
|
||||
|
||||
/*! Options codes (i.e., options[]) */
|
||||
typedef enum {
|
||||
METIS_OPTION_PTYPE,
|
||||
METIS_OPTION_OBJTYPE,
|
||||
METIS_OPTION_CTYPE,
|
||||
METIS_OPTION_IPTYPE,
|
||||
METIS_OPTION_RTYPE,
|
||||
METIS_OPTION_DBGLVL,
|
||||
METIS_OPTION_NITER,
|
||||
METIS_OPTION_NCUTS,
|
||||
METIS_OPTION_SEED,
|
||||
METIS_OPTION_NO2HOP,
|
||||
METIS_OPTION_MINCONN,
|
||||
METIS_OPTION_CONTIG,
|
||||
METIS_OPTION_COMPRESS,
|
||||
METIS_OPTION_CCORDER,
|
||||
METIS_OPTION_PFACTOR,
|
||||
METIS_OPTION_NSEPS,
|
||||
METIS_OPTION_UFACTOR,
|
||||
METIS_OPTION_NUMBERING,
|
||||
|
||||
/* Used for command-line parameter purposes */
|
||||
METIS_OPTION_HELP,
|
||||
METIS_OPTION_TPWGTS,
|
||||
METIS_OPTION_NCOMMON,
|
||||
METIS_OPTION_NOOUTPUT,
|
||||
METIS_OPTION_BALANCE,
|
||||
METIS_OPTION_GTYPE,
|
||||
METIS_OPTION_UBVEC
|
||||
} moptions_et;
|
||||
|
||||
|
||||
/*! Partitioning Schemes */
|
||||
typedef enum {
|
||||
METIS_PTYPE_RB,
|
||||
METIS_PTYPE_KWAY
|
||||
} mptype_et;
|
||||
|
||||
/*! Graph types for meshes */
|
||||
typedef enum {
|
||||
METIS_GTYPE_DUAL,
|
||||
METIS_GTYPE_NODAL
|
||||
} mgtype_et;
|
||||
|
||||
/*! Coarsening Schemes */
|
||||
typedef enum {
|
||||
METIS_CTYPE_RM,
|
||||
METIS_CTYPE_SHEM
|
||||
} mctype_et;
|
||||
|
||||
/*! Initial partitioning schemes */
|
||||
typedef enum {
|
||||
METIS_IPTYPE_GROW,
|
||||
METIS_IPTYPE_RANDOM,
|
||||
METIS_IPTYPE_EDGE,
|
||||
METIS_IPTYPE_NODE,
|
||||
METIS_IPTYPE_METISRB
|
||||
} miptype_et;
|
||||
|
||||
|
||||
/*! Refinement schemes */
|
||||
typedef enum {
|
||||
METIS_RTYPE_FM,
|
||||
METIS_RTYPE_GREEDY,
|
||||
METIS_RTYPE_SEP2SIDED,
|
||||
METIS_RTYPE_SEP1SIDED
|
||||
} mrtype_et;
|
||||
|
||||
|
||||
/*! Debug Levels */
|
||||
typedef enum {
|
||||
METIS_DBG_INFO = 1, /*!< Shows various diagnostic messages */
|
||||
METIS_DBG_TIME = 2, /*!< Perform timing analysis */
|
||||
METIS_DBG_COARSEN = 4, /*!< Show the coarsening progress */
|
||||
METIS_DBG_REFINE = 8, /*!< Show the refinement progress */
|
||||
METIS_DBG_IPART = 16, /*!< Show info on initial partitioning */
|
||||
METIS_DBG_MOVEINFO = 32, /*!< Show info on vertex moves during refinement */
|
||||
METIS_DBG_SEPINFO = 64, /*!< Show info on vertex moves during sep refinement */
|
||||
METIS_DBG_CONNINFO = 128, /*!< Show info on minimization of subdomain connectivity */
|
||||
METIS_DBG_CONTIGINFO = 256, /*!< Show info on elimination of connected components */
|
||||
METIS_DBG_MEMORY = 2048, /*!< Show info related to wspace allocation */
|
||||
} mdbglvl_et;
|
||||
|
||||
|
||||
/* Types of objectives */
|
||||
typedef enum {
|
||||
METIS_OBJTYPE_CUT,
|
||||
METIS_OBJTYPE_VOL,
|
||||
METIS_OBJTYPE_NODE
|
||||
} mobjtype_et;
|
||||
|
||||
|
||||
|
||||
#endif /* _METIS_H_ */
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
# Add this directory for internal users.
|
||||
include_directories(.)
|
||||
# Find sources.
|
||||
file(GLOB metis_sources *.c)
|
||||
# Build libmetis.
|
||||
add_library(metis ${METIS_LIBRARY_TYPE} ${GKlib_sources} ${metis_sources})
|
||||
if(UNIX)
|
||||
target_link_libraries(metis m)
|
||||
endif()
|
||||
|
||||
|
||||
install(TARGETS metis
|
||||
LIBRARY DESTINATION include/gtsam/3rdparty/metis/lib
|
||||
RUNTIME DESTINATION include/gtsam/3rdparty/metis/lib
|
||||
ARCHIVE DESTINATION include/gtsam/3rdparty/metis/lib)
|
||||
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/**
|
||||
\file
|
||||
\brief This file contains various helper API routines for using METIS.
|
||||
|
||||
\date Started 5/12/2011
|
||||
\author George
|
||||
\author Copyright 1997-2009, Regents of the University of Minnesota
|
||||
\version\verbatim $Id: auxapi.c 10409 2011-06-25 16:58:34Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function free memory that was allocated by METIS and retuned
|
||||
to the application.
|
||||
|
||||
\param ptr points to the memory that was previously allocated by
|
||||
METIS.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int METIS_Free(void *ptr)
|
||||
{
|
||||
if (ptr != NULL) free(ptr);
|
||||
return METIS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function sets the default values for the options.
|
||||
|
||||
\param options points to an array of size at least METIS_NOPTIONS.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int METIS_SetDefaultOptions(idx_t *options)
|
||||
{
|
||||
iset(METIS_NOPTIONS, -1, options);
|
||||
|
||||
return METIS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,498 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Functions for the edge-based balancing
|
||||
|
||||
\date Started 7/23/97
|
||||
\author George
|
||||
\author Copyright 1997-2011, Regents of the University of Minnesota
|
||||
\version\verbatim $Id: balance.c 10187 2011-06-13 13:46:57Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
/*************************************************************************
|
||||
* This function is the entry poidx_t of the bisection balancing algorithms.
|
||||
**************************************************************************/
|
||||
void Balance2Way(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts)
|
||||
{
|
||||
if (ComputeLoadImbalanceDiff(graph, 2, ctrl->pijbm, ctrl->ubfactors) <= 0)
|
||||
return;
|
||||
|
||||
if (graph->ncon == 1) {
|
||||
/* return right away if the balance is OK */
|
||||
if (iabs(ntpwgts[0]*graph->tvwgt[0]-graph->pwgts[0]) < 3*graph->tvwgt[0]/graph->nvtxs)
|
||||
return;
|
||||
|
||||
if (graph->nbnd > 0)
|
||||
Bnd2WayBalance(ctrl, graph, ntpwgts);
|
||||
else
|
||||
General2WayBalance(ctrl, graph, ntpwgts);
|
||||
}
|
||||
else {
|
||||
McGeneral2WayBalance(ctrl, graph, ntpwgts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function balances two partitions by moving boundary nodes
|
||||
* from the domain that is overweight to the one that is underweight.
|
||||
**************************************************************************/
|
||||
void Bnd2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts)
|
||||
{
|
||||
idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, tmp;
|
||||
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts;
|
||||
idx_t *moved, *perm;
|
||||
rpq_t *queue;
|
||||
idx_t higain, mincut, mindiff;
|
||||
idx_t tpwgts[2];
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
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 = iwspacemalloc(ctrl, nvtxs);
|
||||
perm = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
/* Determine from which domain you will be moving data */
|
||||
tpwgts[0] = graph->tvwgt[0]*ntpwgts[0];
|
||||
tpwgts[1] = graph->tvwgt[0] - tpwgts[0];
|
||||
mindiff = iabs(tpwgts[0]-pwgts[0]);
|
||||
from = (pwgts[0] < tpwgts[0] ? 1 : 0);
|
||||
to = (from+1)%2;
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
|
||||
printf("Partitions: [%6"PRIDX" %6"PRIDX"] T[%6"PRIDX" %6"PRIDX"], Nv-Nb[%6"PRIDX" %6"PRIDX"]. ICut: %6"PRIDX" [B]\n",
|
||||
pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd,
|
||||
graph->mincut));
|
||||
|
||||
queue = rpqCreate(nvtxs);
|
||||
|
||||
iset(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;
|
||||
irandArrayPermute(nbnd, perm, nbnd/5, 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)
|
||||
rpqInsert(queue, bndind[i], ed[bndind[i]]-id[bndind[i]]);
|
||||
}
|
||||
|
||||
mincut = graph->mincut;
|
||||
for (nswaps=0; nswaps<nvtxs; nswaps++) {
|
||||
if ((higain = rpqGetTop(queue)) == -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, METIS_DBG_MOVEINFO,
|
||||
printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\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];
|
||||
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 */
|
||||
rpqDelete(queue, k);
|
||||
}
|
||||
else { /* If it has not been moved, update its position in the queue */
|
||||
if (moved[k] == -1 && where[k] == from && vwgt[k] <= mindiff)
|
||||
rpqUpdate(queue, k, 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)
|
||||
rpqInsert(queue, k, ed[k]-id[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
|
||||
printf("\tMinimum cut: %6"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, pwgts[0], pwgts[1], nbnd));
|
||||
|
||||
graph->mincut = mincut;
|
||||
graph->nbnd = nbnd;
|
||||
|
||||
rpqDestroy(queue);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* 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(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts)
|
||||
{
|
||||
idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, tmp;
|
||||
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts;
|
||||
idx_t *moved, *perm;
|
||||
rpq_t *queue;
|
||||
idx_t higain, mincut, mindiff;
|
||||
idx_t tpwgts[2];
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
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 = iwspacemalloc(ctrl, nvtxs);
|
||||
perm = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
/* Determine from which domain you will be moving data */
|
||||
tpwgts[0] = graph->tvwgt[0]*ntpwgts[0];
|
||||
tpwgts[1] = graph->tvwgt[0] - tpwgts[0];
|
||||
mindiff = iabs(tpwgts[0]-pwgts[0]);
|
||||
from = (pwgts[0] < tpwgts[0] ? 1 : 0);
|
||||
to = (from+1)%2;
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
|
||||
printf("Partitions: [%6"PRIDX" %6"PRIDX"] T[%6"PRIDX" %6"PRIDX"], Nv-Nb[%6"PRIDX" %6"PRIDX"]. ICut: %6"PRIDX" [B]\n",
|
||||
pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd, graph->mincut));
|
||||
|
||||
queue = rpqCreate(nvtxs);
|
||||
|
||||
iset(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 */
|
||||
irandArrayPermute(nvtxs, perm, nvtxs/5, 1);
|
||||
for (ii=0; ii<nvtxs; ii++) {
|
||||
i = perm[ii];
|
||||
if (where[i] == from && vwgt[i] <= mindiff)
|
||||
rpqInsert(queue, i, ed[i]-id[i]);
|
||||
}
|
||||
|
||||
mincut = graph->mincut;
|
||||
nbnd = graph->nbnd;
|
||||
for (nswaps=0; nswaps<nvtxs; nswaps++) {
|
||||
if ((higain = rpqGetTop(queue)) == -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, METIS_DBG_MOVEINFO,
|
||||
printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\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];
|
||||
|
||||
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)
|
||||
rpqUpdate(queue, k, 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, METIS_DBG_REFINE,
|
||||
printf("\tMinimum cut: %6"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, pwgts[0], pwgts[1], nbnd));
|
||||
|
||||
graph->mincut = mincut;
|
||||
graph->nbnd = nbnd;
|
||||
|
||||
rpqDestroy(queue);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function performs an edge-based FM refinement
|
||||
**************************************************************************/
|
||||
void McGeneral2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts)
|
||||
{
|
||||
idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, pass,
|
||||
me, limit, tmp, cnum;
|
||||
idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts, *id, *ed, *bndptr, *bndind;
|
||||
idx_t *moved, *swaps, *perm, *qnum, *qsizes;
|
||||
idx_t higain, mincut, newcut, mincutorder;
|
||||
real_t *invtvwgt, *minbalv, *newbalv, minbal, newbal;
|
||||
rpq_t **queues;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
ncon = graph->ncon;
|
||||
xadj = graph->xadj;
|
||||
vwgt = graph->vwgt;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
invtvwgt = graph->invtvwgt;
|
||||
where = graph->where;
|
||||
id = graph->id;
|
||||
ed = graph->ed;
|
||||
pwgts = graph->pwgts;
|
||||
bndptr = graph->bndptr;
|
||||
bndind = graph->bndind;
|
||||
|
||||
moved = iwspacemalloc(ctrl, nvtxs);
|
||||
swaps = iwspacemalloc(ctrl, nvtxs);
|
||||
perm = iwspacemalloc(ctrl, nvtxs);
|
||||
qnum = iwspacemalloc(ctrl, nvtxs);
|
||||
newbalv = rwspacemalloc(ctrl, ncon);
|
||||
minbalv = rwspacemalloc(ctrl, ncon);
|
||||
qsizes = iwspacemalloc(ctrl, 2*ncon);
|
||||
|
||||
limit = gk_min(gk_max(0.01*nvtxs, 15), 100);
|
||||
|
||||
/* Initialize the queues */
|
||||
queues = (rpq_t **)wspacemalloc(ctrl, 2*ncon*sizeof(rpq_t *));
|
||||
for (i=0; i<2*ncon; i++) {
|
||||
queues[i] = rpqCreate(nvtxs);
|
||||
qsizes[i] = 0;
|
||||
}
|
||||
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
qnum[i] = iargmax_nrm(ncon, vwgt+i*ncon, invtvwgt);
|
||||
qsizes[2*qnum[i]+where[i]]++;
|
||||
}
|
||||
|
||||
|
||||
/* for the empty queues, move into them vertices from other queues */
|
||||
for (from=0; from<2; from++) {
|
||||
for (j=0; j<ncon; j++) {
|
||||
if (qsizes[2*j+from] == 0) {
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (where[i] != from)
|
||||
continue;
|
||||
|
||||
k = iargmax2_nrm(ncon, vwgt+i*ncon, invtvwgt);
|
||||
if (k == j &&
|
||||
qsizes[2*qnum[i]+from] > qsizes[2*j+from] &&
|
||||
vwgt[i*ncon+qnum[i]]*invtvwgt[qnum[i]] < 1.3*vwgt[i*ncon+j]*invtvwgt[j]) {
|
||||
qsizes[2*qnum[i]+from]--;
|
||||
qsizes[2*j+from]++;
|
||||
qnum[i] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
minbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ctrl->ubfactors, minbalv);
|
||||
ASSERT(minbal > 0.0);
|
||||
|
||||
newcut = mincut = graph->mincut;
|
||||
mincutorder = -1;
|
||||
|
||||
if (ctrl->dbglvl&METIS_DBG_REFINE) {
|
||||
printf("Parts: [");
|
||||
for (l=0; l<ncon; l++)
|
||||
printf("(%6"PRIDX" %6"PRIDX" %.3"PRREAL" %.3"PRREAL") ",
|
||||
pwgts[l], pwgts[ncon+l], ntpwgts[l], ntpwgts[ncon+l]);
|
||||
printf("] Nv-Nb[%5"PRIDX", %5"PRIDX"]. ICut: %6"PRIDX", LB: %+.3"PRREAL" [B]\n",
|
||||
graph->nvtxs, graph->nbnd, graph->mincut, minbal);
|
||||
}
|
||||
|
||||
iset(nvtxs, -1, moved);
|
||||
|
||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
||||
ASSERT(CheckBnd(graph));
|
||||
|
||||
/* Insert all nodes in the priority queues */
|
||||
nbnd = graph->nbnd;
|
||||
irandArrayPermute(nvtxs, perm, nvtxs/10, 1);
|
||||
for (ii=0; ii<nvtxs; ii++) {
|
||||
i = perm[ii];
|
||||
rpqInsert(queues[2*qnum[i]+where[i]], i, ed[i]-id[i]);
|
||||
}
|
||||
|
||||
for (nswaps=0; nswaps<nvtxs; nswaps++) {
|
||||
if (minbal <= 0.0)
|
||||
break;
|
||||
|
||||
SelectQueue(graph, ctrl->pijbm, ctrl->ubfactors, queues, &from, &cnum);
|
||||
to = (from+1)%2;
|
||||
|
||||
if (from == -1 || (higain = rpqGetTop(queues[2*cnum+from])) == -1)
|
||||
break;
|
||||
|
||||
newcut -= (ed[higain]-id[higain]);
|
||||
|
||||
iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1);
|
||||
iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1);
|
||||
newbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ctrl->ubfactors, newbalv);
|
||||
|
||||
if (newbal < minbal || (newbal == minbal &&
|
||||
(newcut < mincut ||
|
||||
(newcut == mincut && BetterBalance2Way(ncon, minbalv, newbalv))))) {
|
||||
mincut = newcut;
|
||||
minbal = newbal;
|
||||
mincutorder = nswaps;
|
||||
rcopy(ncon, newbalv, minbalv);
|
||||
}
|
||||
else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */
|
||||
newcut += (ed[higain]-id[higain]);
|
||||
iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1);
|
||||
iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
where[higain] = to;
|
||||
moved[higain] = nswaps;
|
||||
swaps[nswaps] = higain;
|
||||
|
||||
if (ctrl->dbglvl&METIS_DBG_MOVEINFO) {
|
||||
printf("Moved %6"PRIDX" from %"PRIDX"(%"PRIDX"). Gain: %5"PRIDX", "
|
||||
"Cut: %5"PRIDX", NPwgts: ", higain, from, cnum, ed[higain]-id[higain], newcut);
|
||||
for (l=0; l<ncon; l++)
|
||||
printf("(%6"PRIDX", %6"PRIDX") ", pwgts[l], pwgts[ncon+l]);
|
||||
printf(", %+.3"PRREAL" LB: %+.3"PRREAL"\n", minbal, newbal);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
* 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];
|
||||
|
||||
kwgt = (to == where[k] ? adjwgt[j] : -adjwgt[j]);
|
||||
INC_DEC(id[k], ed[k], kwgt);
|
||||
|
||||
/* Update the queue position */
|
||||
if (moved[k] == -1)
|
||||
rpqUpdate(queues[2*qnum[k]+where[k]], k, 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Roll back computations
|
||||
*****************************************************************/
|
||||
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);
|
||||
|
||||
iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1);
|
||||
iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+((to+1)%2)*ncon, 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctrl->dbglvl&METIS_DBG_REFINE) {
|
||||
printf("\tMincut: %6"PRIDX" at %5"PRIDX", NBND: %6"PRIDX", NPwgts: [",
|
||||
mincut, mincutorder, nbnd);
|
||||
for (l=0; l<ncon; l++)
|
||||
printf("(%6"PRIDX", %6"PRIDX") ", pwgts[l], pwgts[ncon+l]);
|
||||
printf("], LB: %.3"PRREAL"\n", ComputeLoadImbalance(graph, 2, ctrl->pijbm));
|
||||
}
|
||||
|
||||
graph->mincut = mincut;
|
||||
graph->nbnd = nbnd;
|
||||
|
||||
|
||||
for (i=0; i<2*ncon; i++)
|
||||
rpqDestroy(queues[i]);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
|
@ -1,44 +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 arsumed to start from
|
||||
* 0 and they are positive. This sorting is used during matching.
|
||||
**************************************************************************/
|
||||
void BucketSortKeysInc(ctrl_t *ctrl, idx_t n, idx_t max, idx_t *keys,
|
||||
idx_t *tperm, idx_t *perm)
|
||||
{
|
||||
idx_t i, ii;
|
||||
idx_t *counts;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
counts = iset(max+2, 0, iwspacemalloc(ctrl, max+2));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
|
@ -1,263 +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. A valid graph must satisfy
|
||||
the following constraints:
|
||||
- It should contain no self-edges.
|
||||
- It should be undirected; i.e., (u,v) and (v,u) should be present.
|
||||
- The adjacency list should not contain multiple edges to the same
|
||||
other vertex.
|
||||
|
||||
\param graph is the graph to be checked, whose numbering starts from 0.
|
||||
\param numflag is 0 if error reporting will be done using 0 as the
|
||||
numbering, or 1 if the reporting should be done using 1.
|
||||
\param verbose is 1 the identified errors will be displayed, or 0, if
|
||||
it should run silently.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int CheckGraph(graph_t *graph, int numflag, int verbose)
|
||||
{
|
||||
idx_t i, j, k, l;
|
||||
idx_t nvtxs, err=0;
|
||||
idx_t minedge, maxedge, minewgt, maxewgt;
|
||||
idx_t *xadj, *adjncy, *adjwgt, *htable;
|
||||
|
||||
numflag = (numflag == 0 ? 0 : 1); /* make sure that numflag is 0 or 1 */
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
|
||||
ASSERT(adjwgt != NULL);
|
||||
|
||||
htable = ismalloc(nvtxs, 0, "htable");
|
||||
|
||||
minedge = maxedge = adjncy[0];
|
||||
minewgt = maxewgt = adjwgt[0];
|
||||
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
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) {
|
||||
if (verbose)
|
||||
printf("Vertex %"PRIDX" contains a self-loop "
|
||||
"(i.e., diagonal entry in the matrix)!\n", i+numflag);
|
||||
err++;
|
||||
}
|
||||
else {
|
||||
for (l=xadj[k]; l<xadj[k+1]; l++) {
|
||||
if (adjncy[l] == i) {
|
||||
if (adjwgt[l] != adjwgt[j]) {
|
||||
if (verbose)
|
||||
printf("Edges (u:%"PRIDX" v:%"PRIDX" wgt:%"PRIDX") and "
|
||||
"(v:%"PRIDX" u:%"PRIDX" wgt:%"PRIDX") "
|
||||
"do not have the same weight!\n",
|
||||
i+numflag, k+numflag, adjwgt[j],
|
||||
k+numflag, i+numflag, adjwgt[l]);
|
||||
err++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l == xadj[k+1]) {
|
||||
if (verbose)
|
||||
printf("Missing edge: (%"PRIDX" %"PRIDX")!\n", k+numflag, i+numflag);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
if (htable[k] == 0) {
|
||||
htable[k]++;
|
||||
}
|
||||
else {
|
||||
if (verbose)
|
||||
printf("Edge %"PRIDX" from vertex %"PRIDX" is repeated %"PRIDX" times\n",
|
||||
k+numflag, i+numflag, htable[k]++);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++)
|
||||
htable[adjncy[j]] = 0;
|
||||
}
|
||||
|
||||
|
||||
if (err > 0 && verbose) {
|
||||
printf("A total of %"PRIDX" errors exist in the input file. "
|
||||
"Correct them, and run again!\n", err);
|
||||
}
|
||||
|
||||
gk_free((void **)&htable, LTERM);
|
||||
|
||||
return (err == 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function performs a quick check of the weights of the graph */
|
||||
/*************************************************************************/
|
||||
int CheckInputGraphWeights(idx_t nvtxs, idx_t ncon, idx_t *xadj, idx_t *adjncy,
|
||||
idx_t *vwgt, idx_t *vsize, idx_t *adjwgt)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
if (ncon <= 0) {
|
||||
printf("Input Error: ncon must be >= 1.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vwgt) {
|
||||
for (i=ncon*nvtxs; i>=0; i--) {
|
||||
if (vwgt[i] < 0) {
|
||||
printf("Input Error: negative vertex weight(s).\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vsize) {
|
||||
for (i=nvtxs; i>=0; i--) {
|
||||
if (vsize[i] < 0) {
|
||||
printf("Input Error: negative vertex sizes(s).\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (adjwgt) {
|
||||
for (i=xadj[nvtxs]-1; i>=0; i--) {
|
||||
if (adjwgt[i] < 0) {
|
||||
printf("Input Error: non-positive edge weight(s).\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function creates a graph whose topology is consistent with
|
||||
Metis' requirements that:
|
||||
- There are no self-edges.
|
||||
- It is undirected; i.e., (u,v) and (v,u) should be present and of the
|
||||
same weight.
|
||||
- The adjacency list should not contain multiple edges to the same
|
||||
other vertex.
|
||||
|
||||
Any of the above errors are fixed by performing the following operations:
|
||||
- Self-edges are removed.
|
||||
- The undirected graph is formed by the union of edges.
|
||||
- One of the duplicate edges is selected.
|
||||
|
||||
The routine does not change the provided vertex weights.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
graph_t *FixGraph(graph_t *graph)
|
||||
{
|
||||
idx_t i, j, k, l, nvtxs, nedges;
|
||||
idx_t *xadj, *adjncy, *adjwgt;
|
||||
idx_t *nxadj, *nadjncy, *nadjwgt;
|
||||
graph_t *ngraph;
|
||||
uvw_t *edges;
|
||||
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
ASSERT(adjwgt != NULL);
|
||||
|
||||
ngraph = CreateGraph();
|
||||
|
||||
ngraph->nvtxs = nvtxs;
|
||||
|
||||
/* deal with vertex weights/sizes */
|
||||
ngraph->ncon = graph->ncon;
|
||||
ngraph->vwgt = icopy(nvtxs*graph->ncon, graph->vwgt,
|
||||
imalloc(nvtxs*graph->ncon, "FixGraph: vwgt"));
|
||||
|
||||
ngraph->vsize = ismalloc(nvtxs, 1, "FixGraph: vsize");
|
||||
if (graph->vsize)
|
||||
icopy(nvtxs, graph->vsize, ngraph->vsize);
|
||||
|
||||
/* fix graph by sorting the "superset" of edges */
|
||||
edges = (uvw_t *)gk_malloc(sizeof(uvw_t)*2*xadj[nvtxs], "FixGraph: edges");
|
||||
|
||||
for (nedges=0, i=0; i<nvtxs; i++) {
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
/* keep only the upper-trianglular part of the adjacency matrix */
|
||||
if (i < adjncy[j]) {
|
||||
edges[nedges].u = i;
|
||||
edges[nedges].v = adjncy[j];
|
||||
edges[nedges].w = adjwgt[j];
|
||||
nedges++;
|
||||
}
|
||||
else if (i > adjncy[j]) {
|
||||
edges[nedges].u = adjncy[j];
|
||||
edges[nedges].v = i;
|
||||
edges[nedges].w = adjwgt[j];
|
||||
nedges++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uvwsorti(nedges, edges);
|
||||
|
||||
|
||||
/* keep the unique subset */
|
||||
for (k=0, i=1; i<nedges; i++) {
|
||||
if (edges[k].v != edges[i].v || edges[k].u != edges[i].u) {
|
||||
edges[++k] = edges[i];
|
||||
}
|
||||
}
|
||||
nedges = k+1;
|
||||
|
||||
/* allocate memory for the fixed graph */
|
||||
nxadj = ngraph->xadj = ismalloc(nvtxs+1, 0, "FixGraph: nxadj");
|
||||
nadjncy = ngraph->adjncy = imalloc(2*nedges, "FixGraph: nadjncy");
|
||||
nadjwgt = ngraph->adjwgt = imalloc(2*nedges, "FixGraph: nadjwgt");
|
||||
|
||||
/* create the adjacency list of the fixed graph from the upper-triangular
|
||||
part of the adjacency matrix */
|
||||
for (k=0; k<nedges; k++) {
|
||||
nxadj[edges[k].u]++;
|
||||
nxadj[edges[k].v]++;
|
||||
}
|
||||
MAKECSR(i, nvtxs, nxadj);
|
||||
|
||||
for (k=0; k<nedges; k++) {
|
||||
nadjncy[nxadj[edges[k].u]] = edges[k].v;
|
||||
nadjncy[nxadj[edges[k].v]] = edges[k].u;
|
||||
nadjwgt[nxadj[edges[k].u]] = edges[k].w;
|
||||
nadjwgt[nxadj[edges[k].v]] = edges[k].w;
|
||||
nxadj[edges[k].u]++;
|
||||
nxadj[edges[k].v]++;
|
||||
}
|
||||
SHIFTCSR(i, nvtxs, nxadj);
|
||||
|
||||
gk_free((void **)&edges, LTERM);
|
||||
|
||||
return ngraph;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,229 +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.
|
||||
|
||||
The compressed graph that is generated has its adjwgts set to 1.
|
||||
|
||||
\returns 1 if compression was performed, otherwise it returns 0.
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
graph_t *CompressGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy,
|
||||
idx_t *vwgt, idx_t *cptr, idx_t *cind)
|
||||
{
|
||||
idx_t i, ii, iii, j, jj, k, l, cnvtxs, cnedges;
|
||||
idx_t *cxadj, *cadjncy, *cvwgt, *mark, *map;
|
||||
ikv_t *keys;
|
||||
graph_t *graph=NULL;
|
||||
|
||||
mark = ismalloc(nvtxs, -1, "CompressGraph: mark");
|
||||
map = ismalloc(nvtxs, -1, "CompressGraph: map");
|
||||
keys = ikvmalloc(nvtxs, "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;
|
||||
}
|
||||
|
||||
ikvsorti(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;
|
||||
|
||||
map[ii] = cnvtxs;
|
||||
cind[l++] = ii;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_INFO,
|
||||
printf(" Compression: reduction in # of vertices: %"PRIDX".\n", nvtxs-cnvtxs));
|
||||
|
||||
|
||||
if (cnvtxs < COMPRESSION_FRACTION*nvtxs) {
|
||||
/* Sufficient compression is possible, so go ahead and create the
|
||||
compressed graph */
|
||||
|
||||
graph = CreateGraph();
|
||||
|
||||
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 = imalloc(cnvtxs+1, "CompressGraph: xadj");
|
||||
cvwgt = graph->vwgt = ismalloc(cnvtxs, 0, "CompressGraph: vwgt");
|
||||
cadjncy = graph->adjncy = imalloc(cnedges, "CompressGraph: adjncy");
|
||||
graph->adjwgt = ismalloc(cnedges, 1, "CompressGraph: adjwgt");
|
||||
|
||||
/* Now go and compress the graph */
|
||||
iset(nvtxs, -1, mark);
|
||||
l = cxadj[0] = 0;
|
||||
for (i=0; i<cnvtxs; i++) {
|
||||
mark[i] = i; /* Remove any dioganal entries in the compressed graph */
|
||||
for (j=cptr[i]; j<cptr[i+1]; j++) {
|
||||
ii = cind[j];
|
||||
|
||||
/* accumulate the vertex weights of the consistuent vertices */
|
||||
cvwgt[i] += (vwgt == NULL ? 1 : vwgt[ii]);
|
||||
|
||||
/* generate the combined adjancency list */
|
||||
for (jj=xadj[ii]; jj<xadj[ii+1]; jj++) {
|
||||
k = map[adjncy[jj]];
|
||||
if (mark[k] != i) {
|
||||
mark[k] = i;
|
||||
cadjncy[l++] = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
cxadj[i+1] = l;
|
||||
}
|
||||
|
||||
graph->nvtxs = cnvtxs;
|
||||
graph->nedges = l;
|
||||
graph->ncon = 1;
|
||||
|
||||
SetupGraph_tvwgt(graph);
|
||||
SetupGraph_label(graph);
|
||||
}
|
||||
|
||||
gk_free((void **)&keys, &map, &mark, LTERM);
|
||||
|
||||
return graph;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function prunes all the vertices in a graph with degree greater
|
||||
than factor*average.
|
||||
|
||||
\returns the number of vertices that were prunned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
graph_t *PruneGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy,
|
||||
idx_t *vwgt, idx_t *iperm, real_t factor)
|
||||
{
|
||||
idx_t i, j, k, l, nlarge, pnvtxs, pnedges;
|
||||
idx_t *pxadj, *padjncy, *padjwgt, *pvwgt;
|
||||
idx_t *perm;
|
||||
graph_t *graph=NULL;
|
||||
|
||||
perm = imalloc(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;
|
||||
}
|
||||
}
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_INFO,
|
||||
printf(" Pruned %"PRIDX" of %"PRIDX" vertices.\n", nlarge, nvtxs));
|
||||
|
||||
|
||||
if (nlarge > 0 && nlarge < nvtxs) {
|
||||
/* Prunning is possible, so go ahead and create the prunned graph */
|
||||
graph = CreateGraph();
|
||||
|
||||
/* Allocate memory for the prunned graph*/
|
||||
pxadj = graph->xadj = imalloc(pnvtxs+1, "PruneGraph: xadj");
|
||||
pvwgt = graph->vwgt = imalloc(pnvtxs, "PruneGraph: vwgt");
|
||||
padjncy = graph->adjncy = imalloc(pnedges, "PruneGraph: adjncy");
|
||||
graph->adjwgt = ismalloc(pnedges, 1, "PruneGraph: adjwgt");
|
||||
|
||||
pxadj[0] = pnedges = l = 0;
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (xadj[i+1]-xadj[i] < factor) {
|
||||
pvwgt[l] = (vwgt == NULL ? 1 : vwgt[i]);
|
||||
|
||||
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;
|
||||
|
||||
SetupGraph_tvwgt(graph);
|
||||
SetupGraph_label(graph);
|
||||
}
|
||||
else if (nlarge > 0 && nlarge == nvtxs) {
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_INFO,
|
||||
printf(" Pruning is ignored as it removes all vertices.\n"));
|
||||
nlarge = 0;
|
||||
}
|
||||
|
||||
|
||||
gk_free((void **)&perm, LTERM);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,699 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Functions that deal with eliminating disconnected partitions
|
||||
|
||||
\date Started 7/15/98
|
||||
\author George
|
||||
\author Copyright 1997-2009, Regents of the University of Minnesota
|
||||
\version $Id: contig.c 10513 2011-07-07 22:06:03Z karypis $
|
||||
*/
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function finds the connected components induced by the
|
||||
partitioning vector.
|
||||
|
||||
\param graph is the graph structure
|
||||
\param where is the partitioning vector. If this is NULL, then the
|
||||
entire graph is treated to belong into a single partition.
|
||||
\param cptr is the ptr structure of the CSR representation of the
|
||||
components. The length of this vector must be graph->nvtxs+1.
|
||||
\param cind is the indices structure of the CSR representation of
|
||||
the components. The length of this vector must be graph->nvtxs.
|
||||
|
||||
\returns the number of components that it found.
|
||||
|
||||
\note The cptr and cind parameters can be NULL, in which case only the
|
||||
number of connected components is returned.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t FindPartitionInducedComponents(graph_t *graph, idx_t *where,
|
||||
idx_t *cptr, idx_t *cind)
|
||||
{
|
||||
idx_t i, ii, j, jj, k, me=0, nvtxs, first, last, nleft, ncmps;
|
||||
idx_t *xadj, *adjncy;
|
||||
idx_t *touched, *perm, *todo;
|
||||
idx_t mustfree_ccsr=0, mustfree_where=0;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
|
||||
/* Deal with NULL supplied cptr/cind vectors */
|
||||
if (cptr == NULL) {
|
||||
cptr = imalloc(nvtxs+1, "FindPartitionInducedComponents: cptr");
|
||||
cind = imalloc(nvtxs, "FindPartitionInducedComponents: cind");
|
||||
mustfree_ccsr = 1;
|
||||
}
|
||||
|
||||
/* Deal with NULL supplied where vector */
|
||||
if (where == NULL) {
|
||||
where = ismalloc(nvtxs, 0, "FindPartitionInducedComponents: where");
|
||||
mustfree_where = 1;
|
||||
}
|
||||
|
||||
/* Allocate memory required for the BFS traversal */
|
||||
perm = iincset(nvtxs, 0, imalloc(nvtxs, "FindPartitionInducedComponents: perm"));
|
||||
todo = iincset(nvtxs, 0, imalloc(nvtxs, "FindPartitionInducedComponents: todo"));
|
||||
touched = ismalloc(nvtxs, 0, "FindPartitionInducedComponents: touched");
|
||||
|
||||
|
||||
/* Find the connected componends induced by the partition */
|
||||
ncmps = -1;
|
||||
first = last = 0;
|
||||
nleft = nvtxs;
|
||||
while (nleft > 0) {
|
||||
if (first == last) { /* Find another starting vertex */
|
||||
cptr[++ncmps] = first;
|
||||
ASSERT(touched[todo[0]] == 0);
|
||||
i = todo[0];
|
||||
cind[last++] = i;
|
||||
touched[i] = 1;
|
||||
me = where[i];
|
||||
}
|
||||
|
||||
i = cind[first++];
|
||||
k = perm[i];
|
||||
j = todo[k] = todo[--nleft];
|
||||
perm[j] = k;
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
k = adjncy[j];
|
||||
if (where[k] == me && !touched[k]) {
|
||||
cind[last++] = k;
|
||||
touched[k] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
cptr[++ncmps] = first;
|
||||
|
||||
if (mustfree_ccsr)
|
||||
gk_free((void **)&cptr, &cind, LTERM);
|
||||
if (mustfree_where)
|
||||
gk_free((void **)&where, LTERM);
|
||||
|
||||
gk_free((void **)&perm, &todo, &touched, LTERM);
|
||||
|
||||
return ncmps;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes a permutation of the vertices based on a
|
||||
breadth-first-traversal. It can be used for re-ordering the graph
|
||||
to reduce its bandwidth for better cache locality.
|
||||
|
||||
\param ctrl is the control structure
|
||||
\param graph is the graph structure
|
||||
\param perm is the array that upon completion, perm[i] will store
|
||||
the ID of the vertex that corresponds to the ith vertex in the
|
||||
re-ordered graph.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void ComputeBFSOrdering(ctrl_t *ctrl, graph_t *graph, idx_t *bfsperm)
|
||||
{
|
||||
idx_t i, j, k, nvtxs, first, last;
|
||||
idx_t *xadj, *adjncy, *perm;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
|
||||
/* Allocate memory required for the BFS traversal */
|
||||
perm = iincset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
|
||||
|
||||
iincset(nvtxs, 0, bfsperm); /* this array will also store the vertices
|
||||
still to be processed */
|
||||
|
||||
/* Find the connected componends induced by the partition */
|
||||
first = last = 0;
|
||||
while (first < nvtxs) {
|
||||
if (first == last) { /* Find another starting vertex */
|
||||
k = bfsperm[last];
|
||||
ASSERT(perm[k] != -1);
|
||||
perm[k] = -1; /* mark node as being visited */
|
||||
last++;
|
||||
}
|
||||
|
||||
i = bfsperm[first++];
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
k = adjncy[j];
|
||||
/* if a node has been already been visited, its perm[] will be -1 */
|
||||
if (perm[k] != -1) {
|
||||
/* perm[k] is the location within bfsperm of where k resides;
|
||||
put in that location bfsperm[last] that we are about to
|
||||
overwrite and update perm[bfsperm[last]] to reflect that. */
|
||||
bfsperm[perm[k]] = bfsperm[last];
|
||||
perm[bfsperm[last]] = perm[k];
|
||||
|
||||
bfsperm[last++] = k; /* put node at the end of the "queue" */
|
||||
perm[k] = -1; /* mark node as being visited */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks whether a graph is contiguous or not.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
idx_t IsConnected(graph_t *graph, idx_t report)
|
||||
{
|
||||
idx_t ncmps;
|
||||
|
||||
ncmps = FindPartitionInducedComponents(graph, NULL, NULL, NULL);
|
||||
|
||||
if (ncmps != 1 && report)
|
||||
printf("The graph is not connected. It has %"PRIDX" connected components.\n", ncmps);
|
||||
|
||||
return (ncmps == 1);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks whether or not partition pid is contigous
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t IsConnectedSubdomain(ctrl_t *ctrl, graph_t *graph, idx_t pid, idx_t report)
|
||||
{
|
||||
idx_t i, j, k, nvtxs, first, last, nleft, ncmps, wgt;
|
||||
idx_t *xadj, *adjncy, *where, *touched, *queue;
|
||||
idx_t *cptr;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
where = graph->where;
|
||||
|
||||
touched = ismalloc(nvtxs, 0, "IsConnected: touched");
|
||||
queue = imalloc(nvtxs, "IsConnected: queue");
|
||||
cptr = imalloc(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) {
|
||||
printf("The graph has %"PRIDX" connected components in partition %"PRIDX":\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]];
|
||||
printf("[%5"PRIDX" %5"PRIDX"] ", cptr[i+1]-cptr[i], wgt);
|
||||
/*
|
||||
if (cptr[i+1]-cptr[i] == 1)
|
||||
printf("[%"PRIDX" %"PRIDX"] ", queue[cptr[i]], xadj[queue[cptr[i]]+1]-xadj[queue[cptr[i]]]);
|
||||
*/
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
gk_free((void **)&touched, &queue, &cptr, LTERM);
|
||||
|
||||
return (ncmps == 1 ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function identifies the number of connected components in a graph
|
||||
that result after removing the vertices that belong to the vertex
|
||||
separator (i.e., graph->where[i] == 2).
|
||||
The connected component memberships are returned in the CSR-style
|
||||
pair of arrays cptr, cind.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
idx_t FindSepInducedComponents(ctrl_t *ctrl, graph_t *graph, idx_t *cptr,
|
||||
idx_t *cind)
|
||||
{
|
||||
idx_t i, j, k, nvtxs, first, last, nleft, ncmps, wgt;
|
||||
idx_t *xadj, *adjncy, *where, *touched, *queue;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
where = graph->where;
|
||||
|
||||
touched = ismalloc(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;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function finds all the connected components induced by the
|
||||
partitioning vector in graph->where and tries to push them around to
|
||||
remove some of them. */
|
||||
/*************************************************************************/
|
||||
void EliminateComponents(ctrl_t *ctrl, graph_t *graph)
|
||||
{
|
||||
idx_t i, ii, j, jj, k, me, nparts, nvtxs, ncon, ncmps, other,
|
||||
ncand, target;
|
||||
idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts;
|
||||
idx_t *cptr, *cind, *cpvec, *pcptr, *pcind, *cwhere;
|
||||
idx_t cid, bestcid, *cwgt, *bestcwgt;
|
||||
idx_t ntodo, oldntodo, *todo;
|
||||
rkv_t *cand;
|
||||
real_t *tpwgts;
|
||||
idx_t *vmarker=NULL, *pmarker=NULL, *modind=NULL; /* volume specific work arrays */
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
ncon = graph->ncon;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
vwgt = graph->vwgt;
|
||||
adjwgt = (ctrl->objtype == METIS_OBJTYPE_VOL ? NULL : graph->adjwgt);
|
||||
|
||||
where = graph->where;
|
||||
pwgts = graph->pwgts;
|
||||
|
||||
nparts = ctrl->nparts;
|
||||
tpwgts = ctrl->tpwgts;
|
||||
|
||||
cptr = iwspacemalloc(ctrl, nvtxs+1);
|
||||
cind = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
ncmps = FindPartitionInducedComponents(graph, where, cptr, cind);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO,
|
||||
printf("I found %"PRIDX" components, for this %"PRIDX"-way partition\n",
|
||||
ncmps, nparts));
|
||||
|
||||
/* There are more components than partitions */
|
||||
if (ncmps > nparts) {
|
||||
cwgt = iwspacemalloc(ctrl, ncon);
|
||||
bestcwgt = iwspacemalloc(ctrl, ncon);
|
||||
cpvec = iwspacemalloc(ctrl, nparts);
|
||||
pcptr = iset(nparts+1, 0, iwspacemalloc(ctrl, nparts+1));
|
||||
pcind = iwspacemalloc(ctrl, ncmps);
|
||||
cwhere = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs));
|
||||
todo = iwspacemalloc(ctrl, ncmps);
|
||||
cand = (rkv_t *)wspacemalloc(ctrl, nparts*sizeof(rkv_t));
|
||||
|
||||
if (ctrl->objtype == METIS_OBJTYPE_VOL) {
|
||||
/* Vol-refinement specific working arrays */
|
||||
modind = iwspacemalloc(ctrl, nvtxs);
|
||||
vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
|
||||
pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts));
|
||||
}
|
||||
|
||||
|
||||
/* Get a CSR representation of the components-2-partitions mapping */
|
||||
for (i=0; i<ncmps; i++)
|
||||
pcptr[where[cind[cptr[i]]]]++;
|
||||
MAKECSR(i, nparts, pcptr);
|
||||
for (i=0; i<ncmps; i++)
|
||||
pcind[pcptr[where[cind[cptr[i]]]]++] = i;
|
||||
SHIFTCSR(i, nparts, pcptr);
|
||||
|
||||
/* Assign the heaviest component of each partition to its original partition */
|
||||
for (ntodo=0, i=0; i<nparts; i++) {
|
||||
if (pcptr[i+1]-pcptr[i] == 1)
|
||||
bestcid = pcind[pcptr[i]];
|
||||
else {
|
||||
for (bestcid=-1, j=pcptr[i]; j<pcptr[i+1]; j++) {
|
||||
cid = pcind[j];
|
||||
iset(ncon, 0, cwgt);
|
||||
for (ii=cptr[cid]; ii<cptr[cid+1]; ii++)
|
||||
iaxpy(ncon, 1, vwgt+cind[ii]*ncon, 1, cwgt, 1);
|
||||
if (bestcid == -1 || isum(ncon, bestcwgt, 1) < isum(ncon, cwgt, 1)) {
|
||||
bestcid = cid;
|
||||
icopy(ncon, cwgt, bestcwgt);
|
||||
}
|
||||
}
|
||||
/* Keep track of those that need to be dealt with */
|
||||
for (j=pcptr[i]; j<pcptr[i+1]; j++) {
|
||||
if (pcind[j] != bestcid)
|
||||
todo[ntodo++] = pcind[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (j=cptr[bestcid]; j<cptr[bestcid+1]; j++) {
|
||||
ASSERT(where[cind[j]] == i);
|
||||
cwhere[cind[j]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while (ntodo > 0) {
|
||||
oldntodo = ntodo;
|
||||
for (i=0; i<ntodo; i++) {
|
||||
cid = todo[i];
|
||||
me = where[cind[cptr[cid]]]; /* Get the domain of this component */
|
||||
|
||||
/* Determine the weight of the block to be moved */
|
||||
iset(ncon, 0, cwgt);
|
||||
for (j=cptr[cid]; j<cptr[cid+1]; j++)
|
||||
iaxpy(ncon, 1, vwgt+cind[j]*ncon, 1, cwgt, 1);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO,
|
||||
printf("Trying to move %"PRIDX" [%"PRIDX"] from %"PRIDX"\n",
|
||||
cid, isum(ncon, cwgt, 1), me));
|
||||
|
||||
/* Determine the connectivity */
|
||||
iset(nparts, 0, cpvec);
|
||||
for (j=cptr[cid]; j<cptr[cid+1]; j++) {
|
||||
ii = cind[j];
|
||||
for (jj=xadj[ii]; jj<xadj[ii+1]; jj++)
|
||||
if (cwhere[adjncy[jj]] != -1)
|
||||
cpvec[cwhere[adjncy[jj]]] += (adjwgt ? adjwgt[jj] : 1);
|
||||
}
|
||||
|
||||
/* Put the neighbors into a cand[] array for sorting */
|
||||
for (ncand=0, j=0; j<nparts; j++) {
|
||||
if (cpvec[j] > 0) {
|
||||
cand[ncand].key = cpvec[j];
|
||||
cand[ncand++].val = j;
|
||||
}
|
||||
}
|
||||
if (ncand == 0)
|
||||
continue;
|
||||
|
||||
rkvsortd(ncand, cand);
|
||||
|
||||
/* Limit the moves to only the top candidates, which are defined as
|
||||
those with connectivity at least 50% of the best.
|
||||
This applies only when ncon=1, as for multi-constraint, balancing
|
||||
will be hard. */
|
||||
if (ncon == 1) {
|
||||
for (j=1; j<ncand; j++) {
|
||||
if (cand[j].key < .5*cand[0].key)
|
||||
break;
|
||||
}
|
||||
ncand = j;
|
||||
}
|
||||
|
||||
/* Now among those, select the one with the best balance */
|
||||
target = cand[0].val;
|
||||
for (j=1; j<ncand; j++) {
|
||||
if (BetterBalanceKWay(ncon, cwgt, ctrl->ubfactors,
|
||||
1, pwgts+target*ncon, ctrl->pijbm+target*ncon,
|
||||
1, pwgts+cand[j].val*ncon, ctrl->pijbm+cand[j].val*ncon))
|
||||
target = cand[j].val;
|
||||
}
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO,
|
||||
printf("\tMoving it to %"PRIDX" [%"PRIDX"] [%"PRIDX"]\n", target, cpvec[target], ncand));
|
||||
|
||||
/* Note that as a result of a previous movement, a connected component may
|
||||
now will like to stay to its original partition */
|
||||
if (target != me) {
|
||||
switch (ctrl->objtype) {
|
||||
case METIS_OBJTYPE_CUT:
|
||||
MoveGroupContigForCut(ctrl, graph, target, cid, cptr, cind);
|
||||
break;
|
||||
|
||||
case METIS_OBJTYPE_VOL:
|
||||
MoveGroupContigForVol(ctrl, graph, target, cid, cptr, cind,
|
||||
vmarker, pmarker, modind);
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unknown objtype %d\n", ctrl->objtype);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the cwhere vector */
|
||||
for (j=cptr[cid]; j<cptr[cid+1]; j++)
|
||||
cwhere[cind[j]] = target;
|
||||
|
||||
todo[i] = todo[--ntodo];
|
||||
}
|
||||
if (oldntodo == ntodo) {
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, printf("Stopped at ntodo: %"PRIDX"\n", ntodo));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<nvtxs; i++)
|
||||
ASSERT(where[i] == cwhere[i]);
|
||||
|
||||
}
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function moves a collection of vertices and updates their rinfo
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void MoveGroupContigForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t gid,
|
||||
idx_t *ptr, idx_t *ind)
|
||||
{
|
||||
idx_t i, ii, iii, j, jj, k, l, nvtxs, nbnd, from, me;
|
||||
idx_t *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind;
|
||||
ckrinfo_t *myrinfo;
|
||||
cnbr_t *mynbrs;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
|
||||
where = graph->where;
|
||||
bndptr = graph->bndptr;
|
||||
bndind = graph->bndind;
|
||||
|
||||
nbnd = graph->nbnd;
|
||||
|
||||
for (iii=ptr[gid]; iii<ptr[gid+1]; iii++) {
|
||||
i = ind[iii];
|
||||
from = where[i];
|
||||
|
||||
myrinfo = graph->ckrinfo+i;
|
||||
if (myrinfo->inbr == -1) {
|
||||
myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1);
|
||||
myrinfo->nnbrs = 0;
|
||||
}
|
||||
mynbrs = ctrl->cnbrpool + myrinfo->inbr;
|
||||
|
||||
/* find the location of 'to' in myrinfo or create it if it is not there */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if (mynbrs[k].pid == to)
|
||||
break;
|
||||
}
|
||||
if (k == myrinfo->nnbrs) {
|
||||
mynbrs[k].pid = to;
|
||||
mynbrs[k].ed = 0;
|
||||
myrinfo->nnbrs++;
|
||||
}
|
||||
|
||||
graph->mincut -= mynbrs[k].ed-myrinfo->id;
|
||||
|
||||
/* Update ID/ED and BND related information for the moved vertex */
|
||||
iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1);
|
||||
iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1);
|
||||
UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd,
|
||||
bndptr, bndind, BNDTYPE_REFINE);
|
||||
|
||||
/* Update the degrees of adjacent vertices */
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
ii = adjncy[j];
|
||||
me = where[ii];
|
||||
myrinfo = graph->ckrinfo+ii;
|
||||
|
||||
UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me,
|
||||
from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, BNDTYPE_REFINE);
|
||||
}
|
||||
|
||||
ASSERT(CheckRInfo(ctrl, graph->ckrinfo+i));
|
||||
}
|
||||
|
||||
graph->nbnd = nbnd;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function moves a collection of vertices and updates their rinfo
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void MoveGroupContigForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t gid,
|
||||
idx_t *ptr, idx_t *ind, idx_t *vmarker, idx_t *pmarker,
|
||||
idx_t *modind)
|
||||
{
|
||||
idx_t i, ii, iii, j, jj, k, l, nvtxs, from, me, other, xgain;
|
||||
idx_t *xadj, *vsize, *adjncy, *where;
|
||||
vkrinfo_t *myrinfo, *orinfo;
|
||||
vnbr_t *mynbrs, *onbrs;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
vsize = graph->vsize;
|
||||
adjncy = graph->adjncy;
|
||||
where = graph->where;
|
||||
|
||||
for (iii=ptr[gid]; iii<ptr[gid+1]; iii++) {
|
||||
i = ind[iii];
|
||||
from = where[i];
|
||||
|
||||
myrinfo = graph->vkrinfo+i;
|
||||
if (myrinfo->inbr == -1) {
|
||||
myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1);
|
||||
myrinfo->nnbrs = 0;
|
||||
}
|
||||
mynbrs = ctrl->vnbrpool + myrinfo->inbr;
|
||||
|
||||
xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? vsize[i] : 0);
|
||||
|
||||
/* find the location of 'to' in myrinfo or create it if it is not there */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if (mynbrs[k].pid == to)
|
||||
break;
|
||||
}
|
||||
if (k == myrinfo->nnbrs) {
|
||||
if (myrinfo->nid > 0)
|
||||
xgain -= vsize[i];
|
||||
|
||||
/* determine the volume gain resulting from that move */
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
ii = adjncy[j];
|
||||
other = where[ii];
|
||||
orinfo = graph->vkrinfo+ii;
|
||||
onbrs = ctrl->vnbrpool + orinfo->inbr;
|
||||
ASSERT(other != to)
|
||||
|
||||
if (from == other) {
|
||||
/* Same subdomain vertex: Decrease the gain if 'to' is a new neighbor. */
|
||||
for (l=0; l<orinfo->nnbrs; l++) {
|
||||
if (onbrs[l].pid == to)
|
||||
break;
|
||||
}
|
||||
if (l == orinfo->nnbrs)
|
||||
xgain -= vsize[ii];
|
||||
}
|
||||
else {
|
||||
/* Remote vertex: increase if 'to' is a new subdomain */
|
||||
for (l=0; l<orinfo->nnbrs; l++) {
|
||||
if (onbrs[l].pid == to)
|
||||
break;
|
||||
}
|
||||
if (l == orinfo->nnbrs)
|
||||
xgain -= vsize[ii];
|
||||
|
||||
/* Remote vertex: decrease if i is the only connection to 'from' */
|
||||
for (l=0; l<orinfo->nnbrs; l++) {
|
||||
if (onbrs[l].pid == from && onbrs[l].ned == 1) {
|
||||
xgain += vsize[ii];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
graph->minvol -= xgain;
|
||||
graph->mincut -= -myrinfo->nid;
|
||||
}
|
||||
else {
|
||||
graph->minvol -= (xgain + mynbrs[k].gv);
|
||||
graph->mincut -= mynbrs[k].ned-myrinfo->nid;
|
||||
}
|
||||
|
||||
|
||||
/* Update where and pwgts */
|
||||
where[i] = to;
|
||||
iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1);
|
||||
iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1);
|
||||
|
||||
/* Update the id/ed/gains/bnd of potentially affected nodes */
|
||||
KWayVolUpdate(ctrl, graph, i, from, to, NULL, NULL, NULL, NULL,
|
||||
NULL, BNDTYPE_REFINE, vmarker, pmarker, modind);
|
||||
|
||||
/*CheckKWayVolPartitionParams(ctrl, graph);*/
|
||||
}
|
||||
|
||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
||||
ASSERTP(ComputeVolume(graph, where) == graph->minvol,
|
||||
("%"PRIDX" %"PRIDX"\n", ComputeVolume(graph, where), graph->minvol));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,461 +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 total edgecut
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t ComputeCut(graph_t *graph, idx_t *where)
|
||||
{
|
||||
idx_t 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 total volume
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t ComputeVolume(graph_t *graph, idx_t *where)
|
||||
{
|
||||
idx_t i, j, k, me, nvtxs, nparts, totalv;
|
||||
idx_t *xadj, *adjncy, *vsize, *marker;
|
||||
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
vsize = graph->vsize;
|
||||
|
||||
nparts = where[iargmax(nvtxs, where)]+1;
|
||||
marker = ismalloc(nparts, -1, "ComputeVolume: marker");
|
||||
|
||||
totalv = 0;
|
||||
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
marker[where[i]] = i;
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
k = where[adjncy[j]];
|
||||
if (marker[k] != i) {
|
||||
marker[k] = i;
|
||||
totalv += (vsize ? vsize[i] : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gk_free((void **)&marker, LTERM);
|
||||
|
||||
return totalv;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes the cut given the graph and a where vector
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t ComputeMaxCut(graph_t *graph, idx_t nparts, idx_t *where)
|
||||
{
|
||||
idx_t i, j, maxcut;
|
||||
idx_t *cuts;
|
||||
|
||||
cuts = ismalloc(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[iargmax(nparts, cuts)];
|
||||
|
||||
printf("%zu => %"PRIDX"\n", iargmax(nparts, cuts), maxcut);
|
||||
|
||||
gk_free((void **)&cuts, LTERM);
|
||||
|
||||
return maxcut;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks whether or not the boundary information is correct
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t CheckBnd(graph_t *graph)
|
||||
{
|
||||
idx_t i, j, nvtxs, nbnd;
|
||||
idx_t *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, ("%"PRIDX" %"PRIDX"\n", nbnd, graph->nbnd));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks whether or not the boundary information is correct
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t CheckBnd2(graph_t *graph)
|
||||
{
|
||||
idx_t i, j, nvtxs, nbnd, id, ed;
|
||||
idx_t *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, ("%"PRIDX" %"PRIDX" %"PRIDX"\n", i, id, ed));
|
||||
ASSERT(bndind[bndptr[i]] == i);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERTP(nbnd == graph->nbnd, ("%"PRIDX" %"PRIDX"\n", nbnd, graph->nbnd));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks whether or not the boundary information is correct
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t CheckNodeBnd(graph_t *graph, idx_t onbnd)
|
||||
{
|
||||
idx_t i, j, nvtxs, nbnd;
|
||||
idx_t *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, ("%"PRIDX" %"PRIDX"\n", nbnd, onbnd));
|
||||
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (where[i] != 2) {
|
||||
ASSERTP(bndptr[i] == -1, ("%"PRIDX" %"PRIDX"\n", i, bndptr[i]));
|
||||
}
|
||||
else {
|
||||
ASSERTP(bndptr[i] != -1, ("%"PRIDX" %"PRIDX"\n", i, bndptr[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks whether or not the rinfo of a vertex is consistent
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t CheckRInfo(ctrl_t *ctrl, ckrinfo_t *rinfo)
|
||||
{
|
||||
idx_t i, j;
|
||||
cnbr_t *nbrs;
|
||||
|
||||
nbrs = ctrl->cnbrpool + rinfo->inbr;
|
||||
|
||||
for (i=0; i<rinfo->nnbrs; i++) {
|
||||
for (j=i+1; j<rinfo->nnbrs; j++)
|
||||
ASSERTP(nbrs[i].pid != nbrs[j].pid,
|
||||
("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n",
|
||||
i, j, nbrs[i].pid, nbrs[j].pid));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks the correctness of the NodeFM data structures
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t CheckNodePartitionParams(graph_t *graph)
|
||||
{
|
||||
idx_t i, j, k, l, nvtxs, me, other;
|
||||
idx_t *xadj, *adjncy, *adjwgt, *vwgt, *where;
|
||||
idx_t 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]) {
|
||||
printf("Something wrong with edegrees: %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\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]) {
|
||||
printf("Something wrong with part-weights: %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", pwgts[0], pwgts[1], pwgts[2], graph->pwgts[0], graph->pwgts[1], graph->pwgts[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks if the separator is indeed a separator
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t IsSeparable(graph_t *graph)
|
||||
{
|
||||
idx_t i, j, nvtxs, other;
|
||||
idx_t *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,
|
||||
("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n",
|
||||
i, where[i], adjncy[j], where[adjncy[j]], xadj[i+1]-xadj[i],
|
||||
xadj[adjncy[j]+1]-xadj[adjncy[j]]));
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function recomputes the vrinfo fields and checks them against
|
||||
those in the graph->vrinfo structure */
|
||||
/*************************************************************************/
|
||||
void CheckKWayVolPartitionParams(ctrl_t *ctrl, graph_t *graph)
|
||||
{
|
||||
idx_t i, ii, j, k, kk, l, nvtxs, nbnd, mincut, minvol, me, other, pid;
|
||||
idx_t *xadj, *vsize, *adjncy, *pwgts, *where, *bndind, *bndptr;
|
||||
vkrinfo_t *rinfo, *myrinfo, *orinfo, tmprinfo;
|
||||
vnbr_t *mynbrs, *onbrs, *tmpnbrs;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
vsize = graph->vsize;
|
||||
adjncy = graph->adjncy;
|
||||
where = graph->where;
|
||||
rinfo = graph->vkrinfo;
|
||||
|
||||
tmpnbrs = (vnbr_t *)wspacemalloc(ctrl, ctrl->nparts*sizeof(vnbr_t));
|
||||
|
||||
/*------------------------------------------------------------
|
||||
/ Compute now the iv/ev degrees
|
||||
/------------------------------------------------------------*/
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
me = where[i];
|
||||
|
||||
myrinfo = rinfo+i;
|
||||
mynbrs = ctrl->vnbrpool + myrinfo->inbr;
|
||||
|
||||
for (k=0; k<myrinfo->nnbrs; k++)
|
||||
tmpnbrs[k] = mynbrs[k];
|
||||
|
||||
tmprinfo.nnbrs = myrinfo->nnbrs;
|
||||
tmprinfo.nid = myrinfo->nid;
|
||||
tmprinfo.ned = myrinfo->ned;
|
||||
|
||||
myrinfo = &tmprinfo;
|
||||
mynbrs = tmpnbrs;
|
||||
|
||||
for (k=0; k<myrinfo->nnbrs; k++)
|
||||
mynbrs[k].gv = 0;
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
ii = adjncy[j];
|
||||
other = where[ii];
|
||||
orinfo = rinfo+ii;
|
||||
onbrs = ctrl->vnbrpool + orinfo->inbr;
|
||||
|
||||
if (me == other) {
|
||||
/* Find which domains 'i' is connected and 'ii' is not and update their gain */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
pid = mynbrs[k].pid;
|
||||
for (kk=0; kk<orinfo->nnbrs; kk++) {
|
||||
if (onbrs[kk].pid == pid)
|
||||
break;
|
||||
}
|
||||
if (kk == orinfo->nnbrs)
|
||||
mynbrs[k].gv -= vsize[ii];
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Find the orinfo[me].ed and see if I'm the only connection */
|
||||
for (k=0; k<orinfo->nnbrs; k++) {
|
||||
if (onbrs[k].pid == me)
|
||||
break;
|
||||
}
|
||||
|
||||
if (onbrs[k].ned == 1) { /* I'm the only connection of 'ii' in 'me' */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if (mynbrs[k].pid == other) {
|
||||
mynbrs[k].gv += vsize[ii];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increase the gains for all the common domains between 'i' and 'ii' */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if ((pid = mynbrs[k].pid) == other)
|
||||
continue;
|
||||
for (kk=0; kk<orinfo->nnbrs; kk++) {
|
||||
if (onbrs[kk].pid == pid) {
|
||||
mynbrs[k].gv += vsize[ii];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
/* Find which domains 'i' is connected and 'ii' is not and update their gain */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if ((pid = mynbrs[k].pid) == other)
|
||||
continue;
|
||||
for (kk=0; kk<orinfo->nnbrs; kk++) {
|
||||
if (onbrs[kk].pid == pid)
|
||||
break;
|
||||
}
|
||||
if (kk == orinfo->nnbrs)
|
||||
mynbrs[k].gv -= vsize[ii];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myrinfo = rinfo+i;
|
||||
mynbrs = ctrl->vnbrpool + myrinfo->inbr;
|
||||
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
pid = mynbrs[k].pid;
|
||||
for (kk=0; kk<tmprinfo.nnbrs; kk++) {
|
||||
if (tmpnbrs[kk].pid == pid) {
|
||||
if (tmpnbrs[kk].gv != mynbrs[k].gv)
|
||||
printf("[%8"PRIDX" %8"PRIDX" %8"PRIDX" %+8"PRIDX" %+8"PRIDX"]\n",
|
||||
i, where[i], pid, mynbrs[k].gv, tmpnbrs[kk].gv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,60 +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 13933 2013-03-29 22:20:46Z karypis $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LIBMETIS_DEFS_H_
|
||||
#define _LIBMETIS_DEFS_H_
|
||||
|
||||
#define METISTITLE "METIS 5.0 Copyright 1998-13, Regents of the University of Minnesota\n"
|
||||
#define MAXLINE 1280000
|
||||
|
||||
#define LTERM (void **) 0 /* List terminator for gk_free() */
|
||||
|
||||
#define HTLENGTH ((1<<11)-1)
|
||||
|
||||
#define INIT_MAXNAD 200 /* Initial number of maximum number of
|
||||
adjacent domains. This number will be
|
||||
adjusted as required. */
|
||||
|
||||
/* Types of boundaries */
|
||||
#define BNDTYPE_REFINE 1 /* Used for k-way refinement-purposes */
|
||||
#define BNDTYPE_BALANCE 2 /* Used for k-way balancing purposes */
|
||||
|
||||
/* Mode of optimization */
|
||||
#define OMODE_REFINE 1 /* Optimize the objective function */
|
||||
#define OMODE_BALANCE 2 /* Balance the subdomains */
|
||||
|
||||
/* Types of vertex statues in the priority queue */
|
||||
#define VPQSTATUS_PRESENT 1 /* The vertex is in the queue */
|
||||
#define VPQSTATUS_EXTRACTED 2 /* The vertex has been extracted from the queue */
|
||||
#define VPQSTATUS_NOTPRESENT 3 /* The vertex is not present in the queue and
|
||||
has not been extracted before */
|
||||
|
||||
#define UNMATCHED -1
|
||||
|
||||
#define LARGENIPARTS 7 /* Number of random initial partitions */
|
||||
#define SMALLNIPARTS 5 /* Number of random initial partitions */
|
||||
|
||||
#define COARSEN_FRACTION 0.85 /* Node reduction between succesive coarsening levels */
|
||||
|
||||
#define COMPRESSION_FRACTION 0.85
|
||||
|
||||
#define MMDSWITCH 120
|
||||
|
||||
/* Default ufactors for the various operational modes */
|
||||
#define PMETIS_DEFAULT_UFACTOR 1
|
||||
#define MCPMETIS_DEFAULT_UFACTOR 10
|
||||
#define KMETIS_DEFAULT_UFACTOR 30
|
||||
#define OMETIS_DEFAULT_UFACTOR 200
|
||||
|
||||
#endif
|
||||
|
|
@ -1,543 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Functions for the edge-based FM refinement
|
||||
|
||||
\date Started 7/23/97
|
||||
\author George
|
||||
\author Copyright 1997-2011, Regents of the University of Minnesota
|
||||
\version\verbatim $Id: fm.c 10187 2011-06-13 13:46:57Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* This function performs an edge-based FM refinement
|
||||
**************************************************************************/
|
||||
void FM_2WayRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter)
|
||||
{
|
||||
if (graph->ncon == 1)
|
||||
FM_2WayCutRefine(ctrl, graph, ntpwgts, niter);
|
||||
else
|
||||
FM_Mc2WayCutRefine(ctrl, graph, ntpwgts, niter);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function performs a cut-focused FM refinement */
|
||||
/*************************************************************************/
|
||||
void FM_2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter)
|
||||
{
|
||||
idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, limit, tmp;
|
||||
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts;
|
||||
idx_t *moved, *swaps, *perm;
|
||||
rpq_t *queues[2];
|
||||
idx_t higain, mincut, mindiff, origdiff, initcut, newcut, mincutorder, avgvwgt;
|
||||
idx_t tpwgts[2];
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
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 = iwspacemalloc(ctrl, nvtxs);
|
||||
swaps = iwspacemalloc(ctrl, nvtxs);
|
||||
perm = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
tpwgts[0] = graph->tvwgt[0]*ntpwgts[0];
|
||||
tpwgts[1] = graph->tvwgt[0]-tpwgts[0];
|
||||
|
||||
limit = gk_min(gk_max(0.01*nvtxs, 15), 100);
|
||||
avgvwgt = gk_min((pwgts[0]+pwgts[1])/20, 2*(pwgts[0]+pwgts[1])/nvtxs);
|
||||
|
||||
queues[0] = rpqCreate(nvtxs);
|
||||
queues[1] = rpqCreate(nvtxs);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
|
||||
Print2WayRefineStats(ctrl, graph, ntpwgts, 0, -2));
|
||||
|
||||
origdiff = iabs(tpwgts[0]-pwgts[0]);
|
||||
iset(nvtxs, -1, moved);
|
||||
for (pass=0; pass<niter; pass++) { /* Do a number of passes */
|
||||
rpqReset(queues[0]);
|
||||
rpqReset(queues[1]);
|
||||
|
||||
mincutorder = -1;
|
||||
newcut = mincut = initcut = graph->mincut;
|
||||
mindiff = iabs(tpwgts[0]-pwgts[0]);
|
||||
|
||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
||||
ASSERT(CheckBnd(graph));
|
||||
|
||||
/* Insert boundary nodes in the priority queues */
|
||||
nbnd = graph->nbnd;
|
||||
irandArrayPermute(nbnd, perm, nbnd, 1);
|
||||
for (ii=0; ii<nbnd; ii++) {
|
||||
i = perm[ii];
|
||||
ASSERT(ed[bndind[i]] > 0 || id[bndind[i]] == 0);
|
||||
ASSERT(bndptr[bndind[i]] != -1);
|
||||
rpqInsert(queues[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 = rpqGetTop(queues[from])) == -1)
|
||||
break;
|
||||
ASSERT(bndptr[higain] != -1);
|
||||
|
||||
newcut -= (ed[higain]-id[higain]);
|
||||
INC_DEC(pwgts[to], pwgts[from], vwgt[higain]);
|
||||
|
||||
if ((newcut < mincut && iabs(tpwgts[0]-pwgts[0]) <= origdiff+avgvwgt) ||
|
||||
(newcut == mincut && iabs(tpwgts[0]-pwgts[0]) < mindiff)) {
|
||||
mincut = newcut;
|
||||
mindiff = iabs(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, METIS_DBG_MOVEINFO,
|
||||
printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\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];
|
||||
|
||||
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 */
|
||||
rpqDelete(queues[where[k]], k);
|
||||
}
|
||||
else { /* If it has not been moved, update its position in the queue */
|
||||
if (moved[k] == -1)
|
||||
rpqUpdate(queues[where[k]], k, 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)
|
||||
rpqInsert(queues[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);
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = mincut;
|
||||
graph->nbnd = nbnd;
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
|
||||
Print2WayRefineStats(ctrl, graph, ntpwgts, 0, mincutorder));
|
||||
|
||||
if (mincutorder <= 0 || mincut == initcut)
|
||||
break;
|
||||
}
|
||||
|
||||
rpqDestroy(queues[0]);
|
||||
rpqDestroy(queues[1]);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function performs a cut-focused multi-constraint FM refinement */
|
||||
/*************************************************************************/
|
||||
void FM_Mc2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter)
|
||||
{
|
||||
idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, pass,
|
||||
me, limit, tmp, cnum;
|
||||
idx_t *xadj, *adjncy, *vwgt, *adjwgt, *pwgts, *where, *id, *ed,
|
||||
*bndptr, *bndind;
|
||||
idx_t *moved, *swaps, *perm, *qnum;
|
||||
idx_t higain, mincut, initcut, newcut, mincutorder;
|
||||
real_t *invtvwgt, *ubfactors, *minbalv, *newbalv;
|
||||
real_t origbal, minbal, newbal, rgain, ffactor;
|
||||
rpq_t **queues;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
ncon = graph->ncon;
|
||||
xadj = graph->xadj;
|
||||
vwgt = graph->vwgt;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
invtvwgt = graph->invtvwgt;
|
||||
where = graph->where;
|
||||
id = graph->id;
|
||||
ed = graph->ed;
|
||||
pwgts = graph->pwgts;
|
||||
bndptr = graph->bndptr;
|
||||
bndind = graph->bndind;
|
||||
|
||||
moved = iwspacemalloc(ctrl, nvtxs);
|
||||
swaps = iwspacemalloc(ctrl, nvtxs);
|
||||
perm = iwspacemalloc(ctrl, nvtxs);
|
||||
qnum = iwspacemalloc(ctrl, nvtxs);
|
||||
ubfactors = rwspacemalloc(ctrl, ncon);
|
||||
newbalv = rwspacemalloc(ctrl, ncon);
|
||||
minbalv = rwspacemalloc(ctrl, ncon);
|
||||
|
||||
limit = gk_min(gk_max(0.01*nvtxs, 25), 150);
|
||||
|
||||
|
||||
/* Determine a fudge factor to allow the refinement routines to get out
|
||||
of tight balancing constraints. */
|
||||
ffactor = .5/gk_max(20, nvtxs);
|
||||
|
||||
/* Initialize the queues */
|
||||
queues = (rpq_t **)wspacemalloc(ctrl, 2*ncon*sizeof(rpq_t *));
|
||||
for (i=0; i<2*ncon; i++)
|
||||
queues[i] = rpqCreate(nvtxs);
|
||||
for (i=0; i<nvtxs; i++)
|
||||
qnum[i] = iargmax_nrm(ncon, vwgt+i*ncon, invtvwgt);
|
||||
|
||||
/* Determine the unbalance tolerance for each constraint. The tolerance is
|
||||
equal to the maximum of the original load imbalance and the user-supplied
|
||||
allowed tolerance. The rationale behind this approach is to allow the
|
||||
refinement routine to improve the cut, without having to worry about fixing
|
||||
load imbalance problems. The load imbalance is addressed by the balancing
|
||||
routines. */
|
||||
origbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ctrl->ubfactors, ubfactors);
|
||||
for (i=0; i<ncon; i++)
|
||||
ubfactors[i] = (ubfactors[i] > 0 ? ctrl->ubfactors[i]+ubfactors[i] : ctrl->ubfactors[i]);
|
||||
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
|
||||
Print2WayRefineStats(ctrl, graph, ntpwgts, origbal, -2));
|
||||
|
||||
iset(nvtxs, -1, moved);
|
||||
for (pass=0; pass<niter; pass++) { /* Do a number of passes */
|
||||
for (i=0; i<2*ncon; i++)
|
||||
rpqReset(queues[i]);
|
||||
|
||||
mincutorder = -1;
|
||||
newcut = mincut = initcut = graph->mincut;
|
||||
|
||||
minbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ubfactors, minbalv);
|
||||
|
||||
ASSERT(ComputeCut(graph, where) == graph->mincut);
|
||||
ASSERT(CheckBnd(graph));
|
||||
|
||||
/* Insert boundary nodes in the priority queues */
|
||||
nbnd = graph->nbnd;
|
||||
irandArrayPermute(nbnd, perm, nbnd/5, 1);
|
||||
for (ii=0; ii<nbnd; ii++) {
|
||||
i = bndind[perm[ii]];
|
||||
ASSERT(ed[i] > 0 || id[i] == 0);
|
||||
ASSERT(bndptr[i] != -1);
|
||||
//rgain = 1.0*(ed[i]-id[i])/sqrt(vwgt[i*ncon+qnum[i]]+1);
|
||||
//rgain = (ed[i]-id[i] > 0 ? 1.0*(ed[i]-id[i])/sqrt(vwgt[i*ncon+qnum[i]]+1) : ed[i]-id[i]);
|
||||
rgain = ed[i]-id[i];
|
||||
rpqInsert(queues[2*qnum[i]+where[i]], i, rgain);
|
||||
}
|
||||
|
||||
for (nswaps=0; nswaps<nvtxs; nswaps++) {
|
||||
SelectQueue(graph, ctrl->pijbm, ubfactors, queues, &from, &cnum);
|
||||
|
||||
to = (from+1)%2;
|
||||
|
||||
if (from == -1 || (higain = rpqGetTop(queues[2*cnum+from])) == -1)
|
||||
break;
|
||||
ASSERT(bndptr[higain] != -1);
|
||||
|
||||
newcut -= (ed[higain]-id[higain]);
|
||||
|
||||
iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1);
|
||||
iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1);
|
||||
newbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ubfactors, newbalv);
|
||||
|
||||
if ((newcut < mincut && newbal <= ffactor) ||
|
||||
(newcut == mincut && (newbal < minbal ||
|
||||
(newbal == minbal && BetterBalance2Way(ncon, minbalv, newbalv))))) {
|
||||
mincut = newcut;
|
||||
minbal = newbal;
|
||||
mincutorder = nswaps;
|
||||
rcopy(ncon, newbalv, minbalv);
|
||||
}
|
||||
else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */
|
||||
newcut += (ed[higain]-id[higain]);
|
||||
iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1);
|
||||
iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
where[higain] = to;
|
||||
moved[higain] = nswaps;
|
||||
swaps[nswaps] = higain;
|
||||
|
||||
if (ctrl->dbglvl&METIS_DBG_MOVEINFO) {
|
||||
printf("Moved%6"PRIDX" from %"PRIDX"(%"PRIDX") Gain:%5"PRIDX", "
|
||||
"Cut:%5"PRIDX", NPwgts:", higain, from, cnum, ed[higain]-id[higain], newcut);
|
||||
for (l=0; l<ncon; l++)
|
||||
printf("(%.3"PRREAL" %.3"PRREAL")", pwgts[l]*invtvwgt[l], pwgts[ncon+l]*invtvwgt[l]);
|
||||
printf(" %+.3"PRREAL" LB: %.3"PRREAL"(%+.3"PRREAL")\n",
|
||||
minbal, ComputeLoadImbalance(graph, 2, ctrl->pijbm), newbal);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
* 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];
|
||||
|
||||
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 */
|
||||
rpqDelete(queues[2*qnum[k]+where[k]], k);
|
||||
}
|
||||
else { /* If it has not been moved, update its position in the queue */
|
||||
if (moved[k] == -1) {
|
||||
//rgain = 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1);
|
||||
//rgain = (ed[k]-id[k] > 0 ?
|
||||
// 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1) : ed[k]-id[k]);
|
||||
rgain = ed[k]-id[k];
|
||||
rpqUpdate(queues[2*qnum[k]+where[k]], k, rgain);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ed[k] > 0) { /* It will now become a boundary vertex */
|
||||
BNDInsert(nbnd, bndind, bndptr, k);
|
||||
if (moved[k] == -1) {
|
||||
//rgain = 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1);
|
||||
//rgain = (ed[k]-id[k] > 0 ?
|
||||
// 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1) : ed[k]-id[k]);
|
||||
rgain = ed[k]-id[k];
|
||||
rpqInsert(queues[2*qnum[k]+where[k]], k, rgain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* 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);
|
||||
|
||||
iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1);
|
||||
iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+((to+1)%2)*ncon, 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = mincut;
|
||||
graph->nbnd = nbnd;
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE,
|
||||
Print2WayRefineStats(ctrl, graph, ntpwgts, minbal, mincutorder));
|
||||
|
||||
if (mincutorder <= 0 || mincut == initcut)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i=0; i<2*ncon; i++)
|
||||
rpqDestroy(queues[i]);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function selects the partition number and the queue from which
|
||||
we will move vertices out. */
|
||||
/*************************************************************************/
|
||||
void SelectQueue(graph_t *graph, real_t *pijbm, real_t *ubfactors,
|
||||
rpq_t **queues, idx_t *from, idx_t *cnum)
|
||||
{
|
||||
idx_t ncon, i, part;
|
||||
real_t max, tmp;
|
||||
|
||||
ncon = graph->ncon;
|
||||
|
||||
*from = -1;
|
||||
*cnum = -1;
|
||||
|
||||
/* First determine the side and the queue, irrespective of the presence of nodes.
|
||||
The side & queue is determined based on the most violated balancing constraint. */
|
||||
for (max=0.0, part=0; part<2; part++) {
|
||||
for (i=0; i<ncon; i++) {
|
||||
tmp = graph->pwgts[part*ncon+i]*pijbm[part*ncon+i] - ubfactors[i];
|
||||
/* the '=' in the test bellow is to ensure that under tight constraints
|
||||
the partition that is at the max is selected */
|
||||
if (tmp >= max) {
|
||||
max = tmp;
|
||||
*from = part;
|
||||
*cnum = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (*from != -1) {
|
||||
/* in case the desired queue is empty, select a queue from the same side */
|
||||
if (rpqLength(queues[2*(*cnum)+(*from)]) == 0) {
|
||||
for (i=0; i<ncon; i++) {
|
||||
if (rpqLength(queues[2*i+(*from)]) > 0) {
|
||||
max = graph->pwgts[(*from)*ncon+i]*pijbm[(*from)*ncon+i] - ubfactors[i];
|
||||
*cnum = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i++; i<ncon; i++) {
|
||||
tmp = graph->pwgts[(*from)*ncon+i]*pijbm[(*from)*ncon+i] - ubfactors[i];
|
||||
if (tmp > max && rpqLength(queues[2*i+(*from)]) > 0) {
|
||||
max = tmp;
|
||||
*cnum = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
printf("Selected1 %"PRIDX"(%"PRIDX") -> %"PRIDX" [%5"PRREAL"]\n",
|
||||
*from, *cnum, rpqLength(queues[2*(*cnum)+(*from)]), max);
|
||||
*/
|
||||
}
|
||||
else {
|
||||
/* the partitioning does not violate balancing constraints, in which case select
|
||||
a queue based on cut criteria */
|
||||
for (part=0; part<2; part++) {
|
||||
for (i=0; i<ncon; i++) {
|
||||
if (rpqLength(queues[2*i+part]) > 0 &&
|
||||
(*from == -1 || rpqSeeTopKey(queues[2*i+part]) > max)) {
|
||||
max = rpqSeeTopKey(queues[2*i+part]);
|
||||
*from = part;
|
||||
*cnum = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
printf("Selected2 %"PRIDX"(%"PRIDX") -> %"PRIDX"\n",
|
||||
*from, *cnum, rpqLength(queues[2*(*cnum)+(*from)]), max);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Prints statistics about the refinement */
|
||||
/*************************************************************************/
|
||||
void Print2WayRefineStats(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
|
||||
real_t deltabal, idx_t mincutorder)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (mincutorder == -2) {
|
||||
printf("Parts: ");
|
||||
printf("Nv-Nb[%5"PRIDX" %5"PRIDX"] ICut: %6"PRIDX,
|
||||
graph->nvtxs, graph->nbnd, graph->mincut);
|
||||
printf(" [");
|
||||
for (i=0; i<graph->ncon; i++)
|
||||
printf("(%.3"PRREAL" %.3"PRREAL" T:%.3"PRREAL" %.3"PRREAL")",
|
||||
graph->pwgts[i]*graph->invtvwgt[i],
|
||||
graph->pwgts[graph->ncon+i]*graph->invtvwgt[i],
|
||||
ntpwgts[i], ntpwgts[graph->ncon+i]);
|
||||
printf("] LB: %.3"PRREAL"(%+.3"PRREAL")\n",
|
||||
ComputeLoadImbalance(graph, 2, ctrl->pijbm), deltabal);
|
||||
}
|
||||
else {
|
||||
printf("\tMincut: %6"PRIDX" at %5"PRIDX" NBND %6"PRIDX" NPwgts: [",
|
||||
graph->mincut, mincutorder, graph->nbnd);
|
||||
for (i=0; i<graph->ncon; i++)
|
||||
printf("(%.3"PRREAL" %.3"PRREAL")",
|
||||
graph->pwgts[i]*graph->invtvwgt[i], graph->pwgts[graph->ncon+i]*graph->invtvwgt[i]);
|
||||
printf("] LB: %.3"PRREAL"(%+.3"PRREAL")\n",
|
||||
ComputeLoadImbalance(graph, 2, ctrl->pijbm), deltabal);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,142 +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(idx_t nvtxs, idx_t *xadj, idx_t *adjncy)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
for (i=0; i<=nvtxs; i++)
|
||||
xadj[i]--;
|
||||
|
||||
for (i=0; i<xadj[nvtxs]; i++)
|
||||
adjncy[i]--;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function changes the numbering to start from 1 instead of 0 */
|
||||
/*************************************************************************/
|
||||
void Change2FNumbering(idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vector)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
for (i=0; i<nvtxs; i++)
|
||||
vector[i]++;
|
||||
|
||||
for (i=0; i<xadj[nvtxs]; 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(idx_t nvtxs, idx_t *xadj, idx_t *adjncy)
|
||||
{
|
||||
idx_t 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(idx_t nvtxs, idx_t *xadj, idx_t *adjncy,
|
||||
idx_t *v1, idx_t *v2)
|
||||
{
|
||||
idx_t 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(idx_t n, idx_t *ptr, idx_t *ind)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
for (i=0; i<=n; i++)
|
||||
ptr[i]--;
|
||||
for (i=0; i<ptr[n]; i++)
|
||||
ind[i]--;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function changes the numbering to start from 1 instead of 0 */
|
||||
/*************************************************************************/
|
||||
void ChangeMesh2FNumbering(idx_t n, idx_t *ptr, idx_t *ind, idx_t nvtxs,
|
||||
idx_t *xadj, idx_t *adjncy)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
for (i=0; i<ptr[n]; i++)
|
||||
ind[i]++;
|
||||
for (i=0; i<=n; i++)
|
||||
ptr[i]++;
|
||||
|
||||
for (i=0; i<xadj[nvtxs]; 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(idx_t ne, idx_t nn, idx_t *ptr, idx_t *ind,
|
||||
idx_t *epart, idx_t *npart)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
for (i=0; i<ptr[ne]; i++)
|
||||
ind[i]++;
|
||||
for (i=0; i<=ne; i++)
|
||||
ptr[i]++;
|
||||
|
||||
for (i=0; i<ne; i++)
|
||||
epart[i]++;
|
||||
|
||||
for (i=0; i<nn; i++)
|
||||
npart[i]++;
|
||||
}
|
||||
|
||||
|
|
@ -1,136 +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"
|
||||
|
||||
#define FRENAME(name, dargs, cargs, name1, name2, name3, name4) \
|
||||
int name1 dargs { return name cargs; } \
|
||||
int name2 dargs { return name cargs; } \
|
||||
int name3 dargs { return name cargs; } \
|
||||
int name4 dargs { return name cargs; }
|
||||
|
||||
|
||||
FRENAME(
|
||||
METIS_PartGraphRecursive,
|
||||
(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt,
|
||||
idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts,
|
||||
real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part),
|
||||
(nvtxs, ncon, xadj, adjncy, vwgt,
|
||||
vsize, adjwgt, nparts, tpwgts,
|
||||
ubvec, options, edgecut, part),
|
||||
METIS_PARTGRAPHRECURSIVE,
|
||||
metis_partgraphrecursive,
|
||||
metis_partgraphrecursive_,
|
||||
metis_partgraphrecursive__
|
||||
)
|
||||
|
||||
|
||||
FRENAME(
|
||||
METIS_PartGraphKway,
|
||||
(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt,
|
||||
idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts,
|
||||
real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part),
|
||||
(nvtxs, ncon, xadj, adjncy, vwgt,
|
||||
vsize, adjwgt, nparts, tpwgts,
|
||||
ubvec, options, edgecut, part),
|
||||
METIS_PARTGRAPHKWAY,
|
||||
metis_partgraphkway,
|
||||
metis_partgraphkway_,
|
||||
metis_partgraphkway__
|
||||
)
|
||||
|
||||
FRENAME(
|
||||
METIS_MeshToDual,
|
||||
(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *ncommon, idx_t *numflag,
|
||||
idx_t **r_xadj, idx_t **r_adjncy),
|
||||
(ne, nn, eptr, eind, ncommon, numflag, r_xadj, r_adjncy),
|
||||
METIS_MESHTODUAL,
|
||||
metis_meshtodual,
|
||||
metis_meshtodual_,
|
||||
metis_meshtodual__
|
||||
)
|
||||
|
||||
|
||||
FRENAME(
|
||||
METIS_MeshToNodal,
|
||||
(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *numflag, idx_t **r_xadj,
|
||||
idx_t **r_adjncy),
|
||||
(ne, nn, eptr, eind, numflag, r_xadj, r_adjncy),
|
||||
METIS_MESHTONODAL,
|
||||
metis_meshtonodal,
|
||||
metis_meshtonodal_,
|
||||
metis_meshtonodal__
|
||||
)
|
||||
|
||||
|
||||
FRENAME(
|
||||
METIS_PartMeshNodal,
|
||||
(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize,
|
||||
idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart,
|
||||
idx_t *npart),
|
||||
(ne, nn, eptr, eind, vwgt, vsize, nparts, tpwgts, options, objval, epart, npart),
|
||||
METIS_PARTMESHNODAL,
|
||||
metis_partmeshnodal,
|
||||
metis_partmeshnodal_,
|
||||
metis_partmeshnodal__
|
||||
)
|
||||
|
||||
|
||||
FRENAME(
|
||||
METIS_PartMeshDual,
|
||||
(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize,
|
||||
idx_t *ncommon, idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval,
|
||||
idx_t *epart, idx_t *npart),
|
||||
(ne, nn, eptr, eind, vwgt, vsize, ncommon, nparts, tpwgts, options, objval, epart, npart),
|
||||
METIS_PARTMESHDUAL,
|
||||
metis_partmeshdual,
|
||||
metis_partmeshdual_,
|
||||
metis_partmeshdual__
|
||||
)
|
||||
|
||||
|
||||
FRENAME(
|
||||
METIS_NodeND,
|
||||
(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *perm,
|
||||
idx_t *iperm),
|
||||
(nvtxs, xadj, adjncy, vwgt, options, perm, iperm),
|
||||
METIS_NODEND,
|
||||
metis_nodend,
|
||||
metis_nodend_,
|
||||
metis_nodend__
|
||||
)
|
||||
|
||||
|
||||
FRENAME(
|
||||
METIS_Free,
|
||||
(void *ptr),
|
||||
(ptr),
|
||||
METIS_FREE,
|
||||
metis_free,
|
||||
metis_free_,
|
||||
metis_free__
|
||||
)
|
||||
|
||||
|
||||
FRENAME(
|
||||
METIS_SetDefaultOptions,
|
||||
(idx_t *options),
|
||||
(options),
|
||||
METIS_SETDEFAULTOPTIONS,
|
||||
metis_setdefaultoptions,
|
||||
metis_setdefaultoptions_,
|
||||
metis_setdefaultoptions__
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/*!
|
||||
\file gklib.c
|
||||
\brief Various helper routines generated using GKlib's templates
|
||||
|
||||
\date Started 4/12/2007
|
||||
\author George
|
||||
\author Copyright 1997-2009, Regents of the University of Minnesota
|
||||
\version\verbatim $Id: gklib.c 10395 2011-06-23 23:28:06Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! BLAS routines */
|
||||
/*************************************************************************/
|
||||
GK_MKBLAS(i, idx_t, idx_t)
|
||||
GK_MKBLAS(r, real_t, real_t)
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Memory allocation routines */
|
||||
/*************************************************************************/
|
||||
GK_MKALLOC(i, idx_t)
|
||||
GK_MKALLOC(r, real_t)
|
||||
GK_MKALLOC(ikv, ikv_t)
|
||||
GK_MKALLOC(rkv, rkv_t)
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Priority queues routines */
|
||||
/*************************************************************************/
|
||||
#define key_gt(a, b) ((a) > (b))
|
||||
GK_MKPQUEUE(ipq, ipq_t, ikv_t, idx_t, idx_t, ikvmalloc, IDX_MAX, key_gt)
|
||||
GK_MKPQUEUE(rpq, rpq_t, rkv_t, real_t, idx_t, rkvmalloc, REAL_MAX, key_gt)
|
||||
#undef key_gt
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Random number generation routines */
|
||||
/*************************************************************************/
|
||||
GK_MKRANDOM(i, idx_t, idx_t)
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Utility routines */
|
||||
/*************************************************************************/
|
||||
GK_MKARRAY2CSR(i, idx_t)
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Sorting routines */
|
||||
/*************************************************************************/
|
||||
void isorti(size_t n, idx_t *base)
|
||||
{
|
||||
#define i_lt(a, b) ((*a) < (*b))
|
||||
GK_MKQSORT(idx_t, base, n, i_lt);
|
||||
#undef i_lt
|
||||
}
|
||||
|
||||
void isortd(size_t n, idx_t *base)
|
||||
{
|
||||
#define i_gt(a, b) ((*a) > (*b))
|
||||
GK_MKQSORT(idx_t, base, n, i_gt);
|
||||
#undef i_gt
|
||||
}
|
||||
|
||||
void rsorti(size_t n, real_t *base)
|
||||
{
|
||||
#define r_lt(a, b) ((*a) < (*b))
|
||||
GK_MKQSORT(real_t, base, n, r_lt);
|
||||
#undef r_lt
|
||||
}
|
||||
|
||||
void rsortd(size_t n, real_t *base)
|
||||
{
|
||||
#define r_gt(a, b) ((*a) > (*b))
|
||||
GK_MKQSORT(real_t, base, n, r_gt);
|
||||
#undef r_gt
|
||||
}
|
||||
|
||||
void ikvsorti(size_t n, ikv_t *base)
|
||||
{
|
||||
#define ikey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(ikv_t, base, n, ikey_lt);
|
||||
#undef ikey_lt
|
||||
}
|
||||
|
||||
/* Sorts based both on key and val */
|
||||
void ikvsortii(size_t n, ikv_t *base)
|
||||
{
|
||||
#define ikeyval_lt(a, b) ((a)->key < (b)->key || ((a)->key == (b)->key && (a)->val < (b)->val))
|
||||
GK_MKQSORT(ikv_t, base, n, ikeyval_lt);
|
||||
#undef ikeyval_lt
|
||||
}
|
||||
|
||||
void ikvsortd(size_t n, ikv_t *base)
|
||||
{
|
||||
#define ikey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(ikv_t, base, n, ikey_gt);
|
||||
#undef ikey_gt
|
||||
}
|
||||
|
||||
void rkvsorti(size_t n, rkv_t *base)
|
||||
{
|
||||
#define rkey_lt(a, b) ((a)->key < (b)->key)
|
||||
GK_MKQSORT(rkv_t, base, n, rkey_lt);
|
||||
#undef rkey_lt
|
||||
}
|
||||
|
||||
void rkvsortd(size_t n, rkv_t *base)
|
||||
{
|
||||
#define rkey_gt(a, b) ((a)->key > (b)->key)
|
||||
GK_MKQSORT(rkv_t, base, n, rkey_gt);
|
||||
#undef rkey_gt
|
||||
}
|
||||
|
||||
void uvwsorti(size_t n, uvw_t *base)
|
||||
{
|
||||
#define uvwkey_lt(a, b) ((a)->u < (b)->u || ((a)->u == (b)->u && (a)->v < (b)->v))
|
||||
GK_MKQSORT(uvw_t, base, n, uvwkey_lt);
|
||||
#undef uvwkey_lt
|
||||
}
|
||||
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Data structures and prototypes for GKlib integration
|
||||
|
||||
\date Started 12/23/2008
|
||||
\author George
|
||||
\version\verbatim $Id: gklib_defs.h 10395 2011-06-23 23:28:06Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#ifndef _LIBMETIS_GKLIB_H_
|
||||
#define _LIBMETIS_GKLIB_H_
|
||||
|
||||
#include "gklib_rename.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Stores a weighted edge */
|
||||
/*************************************************************************/
|
||||
typedef struct {
|
||||
idx_t u, v, w; /*!< Edge (u,v) with weight w */
|
||||
} uvw_t;
|
||||
|
||||
/*************************************************************************
|
||||
* Define various data structure using GKlib's templates.
|
||||
**************************************************************************/
|
||||
GK_MKKEYVALUE_T(ikv_t, idx_t, idx_t)
|
||||
GK_MKKEYVALUE_T(rkv_t, real_t, idx_t)
|
||||
GK_MKPQUEUE_T(ipq_t, ikv_t)
|
||||
GK_MKPQUEUE_T(rpq_t, rkv_t)
|
||||
|
||||
|
||||
/* gklib.c */
|
||||
GK_MKBLAS_PROTO(i, idx_t, idx_t)
|
||||
GK_MKBLAS_PROTO(r, real_t, real_t)
|
||||
GK_MKALLOC_PROTO(i, idx_t)
|
||||
GK_MKALLOC_PROTO(r, real_t)
|
||||
GK_MKALLOC_PROTO(ikv, ikv_t)
|
||||
GK_MKALLOC_PROTO(rkv, rkv_t)
|
||||
GK_MKPQUEUE_PROTO(ipq, ipq_t, idx_t, idx_t)
|
||||
GK_MKPQUEUE_PROTO(rpq, rpq_t, real_t, idx_t)
|
||||
GK_MKRANDOM_PROTO(i, idx_t, idx_t)
|
||||
GK_MKARRAY2CSR_PROTO(i, idx_t)
|
||||
void isorti(size_t n, idx_t *base);
|
||||
void isortd(size_t n, idx_t *base);
|
||||
void rsorti(size_t n, real_t *base);
|
||||
void rsortd(size_t n, real_t *base);
|
||||
void ikvsorti(size_t n, ikv_t *base);
|
||||
void ikvsortii(size_t n, ikv_t *base);
|
||||
void ikvsortd(size_t n, ikv_t *base);
|
||||
void rkvsorti(size_t n, rkv_t *base);
|
||||
void rkvsortd(size_t n, rkv_t *base);
|
||||
void uvwsorti(size_t n, uvw_t *base);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
|
||||
* Copyright 1997, Regents of the University of Minnesota
|
||||
*
|
||||
* This file contains header files
|
||||
*
|
||||
* Started 10/2/97
|
||||
* George
|
||||
*
|
||||
* $Id: gklib_rename.h 10395 2011-06-23 23:28:06Z karypis $
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LIBMETIS_GKLIB_RENAME_H_
|
||||
#define _LIBMETIS_GKLIB_RENAME_H_
|
||||
|
||||
/* gklib.c - generated from the .o files using the ./utils/listundescapedsumbols.csh */
|
||||
#define iAllocMatrix libmetis__iAllocMatrix
|
||||
#define iFreeMatrix libmetis__iFreeMatrix
|
||||
#define iSetMatrix libmetis__iSetMatrix
|
||||
#define iargmax libmetis__iargmax
|
||||
#define iargmax_n libmetis__iargmax_n
|
||||
#define iargmin libmetis__iargmin
|
||||
#define iarray2csr libmetis__iarray2csr
|
||||
#define iaxpy libmetis__iaxpy
|
||||
#define icopy libmetis__icopy
|
||||
#define idot libmetis__idot
|
||||
#define iincset libmetis__iincset
|
||||
#define ikvAllocMatrix libmetis__ikvAllocMatrix
|
||||
#define ikvFreeMatrix libmetis__ikvFreeMatrix
|
||||
#define ikvSetMatrix libmetis__ikvSetMatrix
|
||||
#define ikvcopy libmetis__ikvcopy
|
||||
#define ikvmalloc libmetis__ikvmalloc
|
||||
#define ikvrealloc libmetis__ikvrealloc
|
||||
#define ikvset libmetis__ikvset
|
||||
#define ikvsmalloc libmetis__ikvsmalloc
|
||||
#define ikvsortd libmetis__ikvsortd
|
||||
#define ikvsorti libmetis__ikvsorti
|
||||
#define ikvsortii libmetis__ikvsortii
|
||||
#define imalloc libmetis__imalloc
|
||||
#define imax libmetis__imax
|
||||
#define imin libmetis__imin
|
||||
#define inorm2 libmetis__inorm2
|
||||
#define ipqCheckHeap libmetis__ipqCheckHeap
|
||||
#define ipqCreate libmetis__ipqCreate
|
||||
#define ipqDelete libmetis__ipqDelete
|
||||
#define ipqDestroy libmetis__ipqDestroy
|
||||
#define ipqFree libmetis__ipqFree
|
||||
#define ipqGetTop libmetis__ipqGetTop
|
||||
#define ipqInit libmetis__ipqInit
|
||||
#define ipqInsert libmetis__ipqInsert
|
||||
#define ipqLength libmetis__ipqLength
|
||||
#define ipqReset libmetis__ipqReset
|
||||
#define ipqSeeKey libmetis__ipqSeeKey
|
||||
#define ipqSeeTopKey libmetis__ipqSeeTopKey
|
||||
#define ipqSeeTopVal libmetis__ipqSeeTopVal
|
||||
#define ipqUpdate libmetis__ipqUpdate
|
||||
#define isrand libmetis__isrand
|
||||
#define irand libmetis__irand
|
||||
#define irandArrayPermute libmetis__irandArrayPermute
|
||||
#define irandArrayPermuteFine libmetis__irandArrayPermuteFine
|
||||
#define irandInRange libmetis__irandInRange
|
||||
#define irealloc libmetis__irealloc
|
||||
#define iscale libmetis__iscale
|
||||
#define iset libmetis__iset
|
||||
#define ismalloc libmetis__ismalloc
|
||||
#define isortd libmetis__isortd
|
||||
#define isorti libmetis__isorti
|
||||
#define isrand libmetis__isrand
|
||||
#define isum libmetis__isum
|
||||
#define rAllocMatrix libmetis__rAllocMatrix
|
||||
#define rFreeMatrix libmetis__rFreeMatrix
|
||||
#define rSetMatrix libmetis__rSetMatrix
|
||||
#define rargmax libmetis__rargmax
|
||||
#define rargmax_n libmetis__rargmax_n
|
||||
#define rargmin libmetis__rargmin
|
||||
#define raxpy libmetis__raxpy
|
||||
#define rcopy libmetis__rcopy
|
||||
#define rdot libmetis__rdot
|
||||
#define rincset libmetis__rincset
|
||||
#define rkvAllocMatrix libmetis__rkvAllocMatrix
|
||||
#define rkvFreeMatrix libmetis__rkvFreeMatrix
|
||||
#define rkvSetMatrix libmetis__rkvSetMatrix
|
||||
#define rkvcopy libmetis__rkvcopy
|
||||
#define rkvmalloc libmetis__rkvmalloc
|
||||
#define rkvrealloc libmetis__rkvrealloc
|
||||
#define rkvset libmetis__rkvset
|
||||
#define rkvsmalloc libmetis__rkvsmalloc
|
||||
#define rkvsortd libmetis__rkvsortd
|
||||
#define rkvsorti libmetis__rkvsorti
|
||||
#define rmalloc libmetis__rmalloc
|
||||
#define rmax libmetis__rmax
|
||||
#define rmin libmetis__rmin
|
||||
#define rnorm2 libmetis__rnorm2
|
||||
#define rpqCheckHeap libmetis__rpqCheckHeap
|
||||
#define rpqCreate libmetis__rpqCreate
|
||||
#define rpqDelete libmetis__rpqDelete
|
||||
#define rpqDestroy libmetis__rpqDestroy
|
||||
#define rpqFree libmetis__rpqFree
|
||||
#define rpqGetTop libmetis__rpqGetTop
|
||||
#define rpqInit libmetis__rpqInit
|
||||
#define rpqInsert libmetis__rpqInsert
|
||||
#define rpqLength libmetis__rpqLength
|
||||
#define rpqReset libmetis__rpqReset
|
||||
#define rpqSeeKey libmetis__rpqSeeKey
|
||||
#define rpqSeeTopKey libmetis__rpqSeeTopKey
|
||||
#define rpqSeeTopVal libmetis__rpqSeeTopVal
|
||||
#define rpqUpdate libmetis__rpqUpdate
|
||||
#define rrealloc libmetis__rrealloc
|
||||
#define rscale libmetis__rscale
|
||||
#define rset libmetis__rset
|
||||
#define rsmalloc libmetis__rsmalloc
|
||||
#define rsortd libmetis__rsortd
|
||||
#define rsorti libmetis__rsorti
|
||||
#define rsum libmetis__rsum
|
||||
#define uvwsorti libmetis__uvwsorti
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,274 +0,0 @@
|
|||
/**
|
||||
\file
|
||||
\brief Functions that deal with setting up the graphs for METIS.
|
||||
|
||||
\date Started 7/25/1997
|
||||
\author George
|
||||
\author Copyright 1997-2009, Regents of the University of Minnesota
|
||||
\version\verbatim $Id: graph.c 10513 2011-07-07 22:06:03Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function sets up the graph from the user input */
|
||||
/*************************************************************************/
|
||||
graph_t *SetupGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t ncon, idx_t *xadj,
|
||||
idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt)
|
||||
{
|
||||
idx_t i, j, k, sum;
|
||||
real_t *nvwgt;
|
||||
graph_t *graph;
|
||||
|
||||
/* allocate the graph and fill in the fields */
|
||||
graph = CreateGraph();
|
||||
|
||||
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 (vwgt) {
|
||||
graph->vwgt = vwgt;
|
||||
graph->free_vwgt = 0;
|
||||
}
|
||||
else {
|
||||
vwgt = graph->vwgt = ismalloc(ncon*nvtxs, 1, "SetupGraph: vwgt");
|
||||
}
|
||||
|
||||
graph->tvwgt = imalloc(ncon, "SetupGraph: tvwgts");
|
||||
graph->invtvwgt = rmalloc(ncon, "SetupGraph: invtvwgts");
|
||||
for (i=0; i<ncon; i++) {
|
||||
graph->tvwgt[i] = isum(nvtxs, vwgt+i, ncon);
|
||||
graph->invtvwgt[i] = 1.0/(graph->tvwgt[i] > 0 ? graph->tvwgt[i] : 1);
|
||||
}
|
||||
|
||||
|
||||
if (ctrl->objtype == METIS_OBJTYPE_VOL) {
|
||||
/* Setup the vsize */
|
||||
if (vsize) {
|
||||
graph->vsize = vsize;
|
||||
graph->free_vsize = 0;
|
||||
}
|
||||
else {
|
||||
vsize = graph->vsize = ismalloc(nvtxs, 1, "SetupGraph: vsize");
|
||||
}
|
||||
|
||||
/* Allocate memory for edge weights and initialize them to the sum of the vsize */
|
||||
adjwgt = graph->adjwgt = imalloc(graph->nedges, "SetupGraph: adjwgt");
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++)
|
||||
adjwgt[j] = 1+vsize[i]+vsize[adjncy[j]];
|
||||
}
|
||||
}
|
||||
else { /* For edgecut minimization */
|
||||
/* setup the edge weights */
|
||||
if (adjwgt) {
|
||||
graph->adjwgt = adjwgt;
|
||||
graph->free_adjwgt = 0;
|
||||
}
|
||||
else {
|
||||
adjwgt = graph->adjwgt = ismalloc(graph->nedges, 1, "SetupGraph: adjwgt");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* setup various derived info */
|
||||
SetupGraph_tvwgt(graph);
|
||||
|
||||
if (ctrl->optype == METIS_OP_PMETIS || ctrl->optype == METIS_OP_OMETIS)
|
||||
SetupGraph_label(graph);
|
||||
|
||||
ASSERT(CheckGraph(graph, ctrl->numflag, 1));
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Set's up the tvwgt/invtvwgt info */
|
||||
/*************************************************************************/
|
||||
void SetupGraph_tvwgt(graph_t *graph)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
if (graph->tvwgt == NULL)
|
||||
graph->tvwgt = imalloc(graph->ncon, "SetupGraph_tvwgt: tvwgt");
|
||||
if (graph->invtvwgt == NULL)
|
||||
graph->invtvwgt = rmalloc(graph->ncon, "SetupGraph_tvwgt: invtvwgt");
|
||||
|
||||
for (i=0; i<graph->ncon; i++) {
|
||||
graph->tvwgt[i] = isum(graph->nvtxs, graph->vwgt+i, graph->ncon);
|
||||
graph->invtvwgt[i] = 1.0/(graph->tvwgt[i] > 0 ? graph->tvwgt[i] : 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Set's up the label info */
|
||||
/*************************************************************************/
|
||||
void SetupGraph_label(graph_t *graph)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
if (graph->label == NULL)
|
||||
graph->label = imalloc(graph->nvtxs, "SetupGraph_label: label");
|
||||
|
||||
for (i=0; i<graph->nvtxs; i++)
|
||||
graph->label[i] = i;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Setup the various arrays for the splitted graph */
|
||||
/*************************************************************************/
|
||||
graph_t *SetupSplitGraph(graph_t *graph, idx_t snvtxs, idx_t snedges)
|
||||
{
|
||||
graph_t *sgraph;
|
||||
|
||||
sgraph = CreateGraph();
|
||||
|
||||
sgraph->nvtxs = snvtxs;
|
||||
sgraph->nedges = snedges;
|
||||
sgraph->ncon = graph->ncon;
|
||||
|
||||
/* Allocate memory for the splitted graph */
|
||||
sgraph->xadj = imalloc(snvtxs+1, "SetupSplitGraph: xadj");
|
||||
sgraph->vwgt = imalloc(sgraph->ncon*snvtxs, "SetupSplitGraph: vwgt");
|
||||
sgraph->adjncy = imalloc(snedges, "SetupSplitGraph: adjncy");
|
||||
sgraph->adjwgt = imalloc(snedges, "SetupSplitGraph: adjwgt");
|
||||
sgraph->label = imalloc(snvtxs, "SetupSplitGraph: label");
|
||||
sgraph->tvwgt = imalloc(sgraph->ncon, "SetupSplitGraph: tvwgt");
|
||||
sgraph->invtvwgt = rmalloc(sgraph->ncon, "SetupSplitGraph: invtvwgt");
|
||||
|
||||
if (graph->vsize)
|
||||
sgraph->vsize = imalloc(snvtxs, "SetupSplitGraph: vsize");
|
||||
|
||||
return sgraph;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function creates and initializes a graph_t data structure */
|
||||
/*************************************************************************/
|
||||
graph_t *CreateGraph(void)
|
||||
{
|
||||
graph_t *graph;
|
||||
|
||||
graph = (graph_t *)gk_malloc(sizeof(graph_t), "CreateGraph: graph");
|
||||
|
||||
InitGraph(graph);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function initializes a graph_t data structure */
|
||||
/*************************************************************************/
|
||||
void InitGraph(graph_t *graph)
|
||||
{
|
||||
memset((void *)graph, 0, sizeof(graph_t));
|
||||
|
||||
/* graph size constants */
|
||||
graph->nvtxs = -1;
|
||||
graph->nedges = -1;
|
||||
graph->ncon = -1;
|
||||
graph->mincut = -1;
|
||||
graph->minvol = -1;
|
||||
graph->nbnd = -1;
|
||||
|
||||
/* memory for the graph structure */
|
||||
graph->xadj = NULL;
|
||||
graph->vwgt = NULL;
|
||||
graph->vsize = NULL;
|
||||
graph->adjncy = NULL;
|
||||
graph->adjwgt = NULL;
|
||||
graph->label = NULL;
|
||||
graph->cmap = NULL;
|
||||
graph->tvwgt = NULL;
|
||||
graph->invtvwgt = NULL;
|
||||
|
||||
/* by default these are set to true, but the can be explicitly changed afterwards */
|
||||
graph->free_xadj = 1;
|
||||
graph->free_vwgt = 1;
|
||||
graph->free_vsize = 1;
|
||||
graph->free_adjncy = 1;
|
||||
graph->free_adjwgt = 1;
|
||||
|
||||
|
||||
/* memory for the partition/refinement structure */
|
||||
graph->where = NULL;
|
||||
graph->pwgts = NULL;
|
||||
graph->id = NULL;
|
||||
graph->ed = NULL;
|
||||
graph->bndptr = NULL;
|
||||
graph->bndind = NULL;
|
||||
graph->nrinfo = NULL;
|
||||
graph->ckrinfo = NULL;
|
||||
graph->vkrinfo = NULL;
|
||||
|
||||
/* linked-list structure */
|
||||
graph->coarser = NULL;
|
||||
graph->finer = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function frees the refinement/partition memory stored in a graph */
|
||||
/*************************************************************************/
|
||||
void FreeRData(graph_t *graph)
|
||||
{
|
||||
|
||||
/* The following is for the -minconn and -contig to work properly in
|
||||
the vol-refinement routines */
|
||||
if ((void *)graph->ckrinfo == (void *)graph->vkrinfo)
|
||||
graph->ckrinfo = NULL;
|
||||
|
||||
|
||||
/* free partition/refinement structure */
|
||||
gk_free((void **)&graph->where, &graph->pwgts, &graph->id, &graph->ed,
|
||||
&graph->bndptr, &graph->bndind, &graph->nrinfo, &graph->ckrinfo,
|
||||
&graph->vkrinfo, LTERM);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function deallocates any memory stored in a graph */
|
||||
/*************************************************************************/
|
||||
void FreeGraph(graph_t **r_graph)
|
||||
{
|
||||
graph_t *graph;
|
||||
|
||||
graph = *r_graph;
|
||||
|
||||
/* free graph structure */
|
||||
if (graph->free_xadj)
|
||||
gk_free((void **)&graph->xadj, LTERM);
|
||||
if (graph->free_vwgt)
|
||||
gk_free((void **)&graph->vwgt, LTERM);
|
||||
if (graph->free_vsize)
|
||||
gk_free((void **)&graph->vsize, LTERM);
|
||||
if (graph->free_adjncy)
|
||||
gk_free((void **)&graph->adjncy, LTERM);
|
||||
if (graph->free_adjwgt)
|
||||
gk_free((void **)&graph->adjwgt, LTERM);
|
||||
|
||||
/* free partition/refinement structure */
|
||||
FreeRData(graph);
|
||||
|
||||
gk_free((void **)&graph->tvwgt, &graph->invtvwgt, &graph->label,
|
||||
&graph->cmap, &graph, LTERM);
|
||||
|
||||
*r_graph = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,630 +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(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
|
||||
idx_t niparts)
|
||||
{
|
||||
mdbglvl_et dbglvl;
|
||||
|
||||
ASSERT(graph->tvwgt[0] >= 0);
|
||||
|
||||
dbglvl = ctrl->dbglvl;
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE);
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
|
||||
|
||||
switch (ctrl->iptype) {
|
||||
case METIS_IPTYPE_RANDOM:
|
||||
if (graph->ncon == 1)
|
||||
RandomBisection(ctrl, graph, ntpwgts, niparts);
|
||||
else
|
||||
McRandomBisection(ctrl, graph, ntpwgts, niparts);
|
||||
break;
|
||||
|
||||
case METIS_IPTYPE_GROW:
|
||||
if (graph->nedges == 0)
|
||||
if (graph->ncon == 1)
|
||||
RandomBisection(ctrl, graph, ntpwgts, niparts);
|
||||
else
|
||||
McRandomBisection(ctrl, graph, ntpwgts, niparts);
|
||||
else
|
||||
if (graph->ncon == 1)
|
||||
GrowBisection(ctrl, graph, ntpwgts, niparts);
|
||||
else
|
||||
McGrowBisection(ctrl, graph, ntpwgts, niparts);
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unknown initial partition type: %d\n", ctrl->iptype);
|
||||
}
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Cut: %"PRIDX"\n", graph->mincut));
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
|
||||
ctrl->dbglvl = dbglvl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes the initial separator of the coarsest graph */
|
||||
/*************************************************************************/
|
||||
void InitSeparator(ctrl_t *ctrl, graph_t *graph, idx_t niparts)
|
||||
{
|
||||
real_t ntpwgts[2] = {0.5, 0.5};
|
||||
mdbglvl_et dbglvl;
|
||||
|
||||
dbglvl = ctrl->dbglvl;
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE);
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
|
||||
|
||||
/* this is required for the cut-based part of the refinement */
|
||||
Setup2WayBalMultipliers(ctrl, graph, ntpwgts);
|
||||
|
||||
switch (ctrl->iptype) {
|
||||
case METIS_IPTYPE_EDGE:
|
||||
if (graph->nedges == 0)
|
||||
RandomBisection(ctrl, graph, ntpwgts, niparts);
|
||||
else
|
||||
GrowBisection(ctrl, graph, ntpwgts, niparts);
|
||||
|
||||
Compute2WayPartitionParams(ctrl, graph);
|
||||
ConstructSeparator(ctrl, graph);
|
||||
break;
|
||||
|
||||
case METIS_IPTYPE_NODE:
|
||||
GrowBisectionNode(ctrl, graph, ntpwgts, niparts);
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unkown iptype of %"PRIDX"\n", ctrl->iptype);
|
||||
}
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Sep: %"PRIDX"\n", graph->mincut));
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
|
||||
|
||||
ctrl->dbglvl = dbglvl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes a bisection of a graph by randomly assigning
|
||||
the vertices followed by a bisection refinement.
|
||||
The resulting partition is returned in graph->where.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void RandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
|
||||
idx_t niparts)
|
||||
{
|
||||
idx_t i, ii, j, k, nvtxs, pwgts[2], zeromaxpwgt, from, me,
|
||||
bestcut=0, icut, mincut, inbfs;
|
||||
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where;
|
||||
idx_t *perm, *bestwhere;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
vwgt = graph->vwgt;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
|
||||
Allocate2WayPartitionMemory(ctrl, graph);
|
||||
where = graph->where;
|
||||
|
||||
bestwhere = iwspacemalloc(ctrl, nvtxs);
|
||||
perm = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
zeromaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[0];
|
||||
|
||||
for (inbfs=0; inbfs<niparts; inbfs++) {
|
||||
iset(nvtxs, 1, where);
|
||||
|
||||
if (inbfs > 0) {
|
||||
irandArrayPermute(nvtxs, perm, nvtxs/2, 1);
|
||||
pwgts[1] = graph->tvwgt[0];
|
||||
pwgts[0] = 0;
|
||||
|
||||
for (ii=0; ii<nvtxs; ii++) {
|
||||
i = perm[ii];
|
||||
if (pwgts[0]+vwgt[i] < zeromaxpwgt) {
|
||||
where[i] = 0;
|
||||
pwgts[0] += vwgt[i];
|
||||
pwgts[1] -= vwgt[i];
|
||||
if (pwgts[0] > zeromaxpwgt)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do some partition refinement */
|
||||
Compute2WayPartitionParams(ctrl, graph);
|
||||
/* printf("IPART: %3"PRIDX" [%5"PRIDX" %5"PRIDX"] [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); */
|
||||
|
||||
Balance2Way(ctrl, graph, ntpwgts);
|
||||
/* printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */
|
||||
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, 4);
|
||||
/* printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */
|
||||
|
||||
if (inbfs==0 || bestcut > graph->mincut) {
|
||||
bestcut = graph->mincut;
|
||||
icopy(nvtxs, where, bestwhere);
|
||||
if (bestcut == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = bestcut;
|
||||
icopy(nvtxs, bestwhere, where);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function takes a graph and produces a bisection by using a region
|
||||
growing algorithm. The resulting bisection is refined using FM.
|
||||
The resulting partition is returned in graph->where.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void GrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
|
||||
idx_t niparts)
|
||||
{
|
||||
idx_t i, j, k, nvtxs, drain, nleft, first, last,
|
||||
pwgts[2], oneminpwgt, onemaxpwgt,
|
||||
from, me, bestcut=0, icut, mincut, inbfs;
|
||||
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where;
|
||||
idx_t *queue, *touched, *gain, *bestwhere;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
vwgt = graph->vwgt;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
|
||||
Allocate2WayPartitionMemory(ctrl, graph);
|
||||
where = graph->where;
|
||||
|
||||
bestwhere = iwspacemalloc(ctrl, nvtxs);
|
||||
queue = iwspacemalloc(ctrl, nvtxs);
|
||||
touched = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[1];
|
||||
oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*ntpwgts[1];
|
||||
|
||||
for (inbfs=0; inbfs<niparts; inbfs++) {
|
||||
iset(nvtxs, 1, where);
|
||||
|
||||
iset(nvtxs, 0, touched);
|
||||
|
||||
pwgts[1] = graph->tvwgt[0];
|
||||
pwgts[0] = 0;
|
||||
|
||||
|
||||
queue[0] = irandInRange(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 = irandInRange(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] < oneminpwgt) {
|
||||
drain = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
where[i] = 0;
|
||||
INC_DEC(pwgts[0], pwgts[1], vwgt[i]);
|
||||
if (pwgts[1] <= onemaxpwgt)
|
||||
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)
|
||||
where[irandInRange(nvtxs)] = 1;
|
||||
if (pwgts[0] == 0)
|
||||
where[irandInRange(nvtxs)] = 0;
|
||||
|
||||
/*************************************************************
|
||||
* Do some partition refinement
|
||||
**************************************************************/
|
||||
Compute2WayPartitionParams(ctrl, graph);
|
||||
/*
|
||||
printf("IPART: %3"PRIDX" [%5"PRIDX" %5"PRIDX"] [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n",
|
||||
graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut);
|
||||
*/
|
||||
|
||||
Balance2Way(ctrl, graph, ntpwgts);
|
||||
/*
|
||||
printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0],
|
||||
graph->pwgts[1], graph->mincut);
|
||||
*/
|
||||
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
|
||||
/*
|
||||
printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0],
|
||||
graph->pwgts[1], graph->mincut);
|
||||
*/
|
||||
|
||||
if (inbfs == 0 || bestcut > graph->mincut) {
|
||||
bestcut = graph->mincut;
|
||||
icopy(nvtxs, where, bestwhere);
|
||||
if (bestcut == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = bestcut;
|
||||
icopy(nvtxs, bestwhere, where);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function takes a multi-constraint graph and computes a bisection
|
||||
by randomly assigning the vertices and then refining it. The resulting
|
||||
partition is returned in graph->where.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
|
||||
idx_t niparts)
|
||||
{
|
||||
idx_t i, ii, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs, qnum;
|
||||
idx_t *bestwhere, *where, *perm, *counts;
|
||||
idx_t *vwgt;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
ncon = graph->ncon;
|
||||
vwgt = graph->vwgt;
|
||||
|
||||
Allocate2WayPartitionMemory(ctrl, graph);
|
||||
where = graph->where;
|
||||
|
||||
bestwhere = iwspacemalloc(ctrl, nvtxs);
|
||||
perm = iwspacemalloc(ctrl, nvtxs);
|
||||
counts = iwspacemalloc(ctrl, ncon);
|
||||
|
||||
for (inbfs=0; inbfs<2*niparts; inbfs++) {
|
||||
irandArrayPermute(nvtxs, perm, nvtxs/2, 1);
|
||||
iset(ncon, 0, counts);
|
||||
|
||||
/* partition by spliting the queues randomly */
|
||||
for (ii=0; ii<nvtxs; ii++) {
|
||||
i = perm[ii];
|
||||
qnum = iargmax(ncon, vwgt+i*ncon);
|
||||
where[i] = (counts[qnum]++)%2;
|
||||
}
|
||||
|
||||
Compute2WayPartitionParams(ctrl, graph);
|
||||
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
|
||||
Balance2Way(ctrl, graph, ntpwgts);
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
|
||||
Balance2Way(ctrl, graph, ntpwgts);
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
|
||||
|
||||
if (inbfs == 0 || bestcut >= graph->mincut) {
|
||||
bestcut = graph->mincut;
|
||||
icopy(nvtxs, where, bestwhere);
|
||||
if (bestcut == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = bestcut;
|
||||
icopy(nvtxs, bestwhere, where);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function takes a multi-constraint graph and produces a bisection
|
||||
by using a region growing algorithm. The resulting partition is
|
||||
returned in graph->where.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
|
||||
idx_t niparts)
|
||||
{
|
||||
idx_t i, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs;
|
||||
idx_t *bestwhere, *where;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
|
||||
Allocate2WayPartitionMemory(ctrl, graph);
|
||||
where = graph->where;
|
||||
|
||||
bestwhere = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
for (inbfs=0; inbfs<2*niparts; inbfs++) {
|
||||
iset(nvtxs, 1, where);
|
||||
where[irandInRange(nvtxs)] = 0;
|
||||
|
||||
Compute2WayPartitionParams(ctrl, graph);
|
||||
|
||||
Balance2Way(ctrl, graph, ntpwgts);
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
|
||||
Balance2Way(ctrl, graph, ntpwgts);
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
|
||||
|
||||
if (inbfs == 0 || bestcut >= graph->mincut) {
|
||||
bestcut = graph->mincut;
|
||||
icopy(nvtxs, where, bestwhere);
|
||||
if (bestcut == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = bestcut;
|
||||
icopy(nvtxs, bestwhere, where);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* This function takes a graph and produces a tri-section into left, right,
|
||||
and separator using a region growing algorithm. The resulting separator
|
||||
is refined using node FM.
|
||||
The resulting partition is returned in graph->where.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void GrowBisectionNode(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
|
||||
idx_t niparts)
|
||||
{
|
||||
idx_t i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], oneminpwgt,
|
||||
onemaxpwgt, from, me, bestcut=0, icut, mincut, inbfs;
|
||||
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *bndind;
|
||||
idx_t *queue, *touched, *gain, *bestwhere;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
vwgt = graph->vwgt;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
|
||||
bestwhere = iwspacemalloc(ctrl, nvtxs);
|
||||
queue = iwspacemalloc(ctrl, nvtxs);
|
||||
touched = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*0.5;
|
||||
oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*0.5;
|
||||
|
||||
|
||||
/* Allocate refinement memory. Allocate sufficient memory for both edge and node */
|
||||
graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts");
|
||||
graph->where = imalloc(nvtxs, "GrowBisectionNode: where");
|
||||
graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr");
|
||||
graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind");
|
||||
graph->id = imalloc(nvtxs, "GrowBisectionNode: id");
|
||||
graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed");
|
||||
graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo");
|
||||
|
||||
where = graph->where;
|
||||
bndind = graph->bndind;
|
||||
|
||||
for (inbfs=0; inbfs<niparts; inbfs++) {
|
||||
iset(nvtxs, 1, where);
|
||||
iset(nvtxs, 0, touched);
|
||||
|
||||
pwgts[1] = graph->tvwgt[0];
|
||||
pwgts[0] = 0;
|
||||
|
||||
queue[0] = irandInRange(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 = irandInRange(nleft);
|
||||
for (i=0; i<nvtxs; i++) { /* select the kth untouched vertex */
|
||||
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] < oneminpwgt) {
|
||||
drain = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
where[i] = 0;
|
||||
INC_DEC(pwgts[0], pwgts[1], vwgt[i]);
|
||||
if (pwgts[1] <= onemaxpwgt)
|
||||
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, ntpwgts);
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, 4);
|
||||
|
||||
/* Construct and refine the vertex separator */
|
||||
for (i=0; i<graph->nbnd; i++) {
|
||||
j = bndind[i];
|
||||
if (xadj[j+1]-xadj[j] > 0) /* ignore islands */
|
||||
where[j] = 2;
|
||||
}
|
||||
|
||||
Compute2WayNodePartitionParams(ctrl, graph);
|
||||
FM_2WayNodeRefine2Sided(ctrl, graph, 1);
|
||||
FM_2WayNodeRefine1Sided(ctrl, graph, 4);
|
||||
|
||||
/*
|
||||
printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n",
|
||||
inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut);
|
||||
*/
|
||||
|
||||
if (inbfs == 0 || bestcut > graph->mincut) {
|
||||
bestcut = graph->mincut;
|
||||
icopy(nvtxs, where, bestwhere);
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = bestcut;
|
||||
icopy(nvtxs, bestwhere, where);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* This function takes a graph and produces a tri-section into left, right,
|
||||
and separator using a region growing algorithm. The resulting separator
|
||||
is refined using node FM.
|
||||
The resulting partition is returned in graph->where.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,
|
||||
idx_t niparts)
|
||||
{
|
||||
idx_t i, j, k, nvtxs, bestcut=0, mincut, inbfs;
|
||||
idx_t *xadj, *where, *bndind, *bestwhere;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
|
||||
/* Allocate refinement memory. Allocate sufficient memory for both edge and node */
|
||||
graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts");
|
||||
graph->where = imalloc(nvtxs, "GrowBisectionNode: where");
|
||||
graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr");
|
||||
graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind");
|
||||
graph->id = imalloc(nvtxs, "GrowBisectionNode: id");
|
||||
graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed");
|
||||
graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo");
|
||||
|
||||
bestwhere = iwspacemalloc(ctrl, nvtxs);
|
||||
|
||||
where = graph->where;
|
||||
bndind = graph->bndind;
|
||||
|
||||
for (inbfs=0; inbfs<niparts; inbfs++) {
|
||||
iset(nvtxs, 1, where);
|
||||
if (inbfs > 0)
|
||||
where[irandInRange(nvtxs)] = 0;
|
||||
|
||||
Compute2WayPartitionParams(ctrl, graph);
|
||||
General2WayBalance(ctrl, graph, ntpwgts);
|
||||
FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);
|
||||
|
||||
/* Construct and refine the vertex separator */
|
||||
for (i=0; i<graph->nbnd; i++) {
|
||||
j = bndind[i];
|
||||
if (xadj[j+1]-xadj[j] > 0) /* ignore islands */
|
||||
where[j] = 2;
|
||||
}
|
||||
|
||||
Compute2WayNodePartitionParams(ctrl, graph);
|
||||
FM_2WayNodeRefine2Sided(ctrl, graph, 4);
|
||||
|
||||
/*
|
||||
printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n",
|
||||
inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut);
|
||||
*/
|
||||
|
||||
if (inbfs == 0 || bestcut > graph->mincut) {
|
||||
bestcut = graph->mincut;
|
||||
icopy(nvtxs, where, bestwhere);
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = bestcut;
|
||||
icopy(nvtxs, bestwhere, where);
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief The top-level routines for multilevel k-way partitioning that minimizes
|
||||
the edge cut.
|
||||
|
||||
\date Started 7/28/1997
|
||||
\author George
|
||||
\author Copyright 1997-2011, Regents of the University of Minnesota
|
||||
\version\verbatim $Id: kmetis.c 13905 2013-03-25 13:21:20Z karypis $ \endverbatim
|
||||
*/
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function is the entry point for MCKMETIS */
|
||||
/*************************************************************************/
|
||||
int METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy,
|
||||
idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts,
|
||||
real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *objval,
|
||||
idx_t *part)
|
||||
{
|
||||
int sigrval=0, renumber=0;
|
||||
graph_t *graph;
|
||||
ctrl_t *ctrl;
|
||||
|
||||
/* set up malloc cleaning code and signal catchers */
|
||||
if (!gk_malloc_init())
|
||||
return METIS_ERROR_MEMORY;
|
||||
|
||||
gk_sigtrap();
|
||||
|
||||
if ((sigrval = gk_sigcatch()) != 0)
|
||||
goto SIGTHROW;
|
||||
|
||||
|
||||
/* set up the run parameters */
|
||||
ctrl = SetupCtrl(METIS_OP_KMETIS, options, *ncon, *nparts, tpwgts, ubvec);
|
||||
if (!ctrl) {
|
||||
gk_siguntrap();
|
||||
return METIS_ERROR_INPUT;
|
||||
}
|
||||
|
||||
/* if required, change the numbering to 0 */
|
||||
if (ctrl->numflag == 1) {
|
||||
Change2CNumbering(*nvtxs, xadj, adjncy);
|
||||
renumber = 1;
|
||||
}
|
||||
|
||||
/* set up the graph */
|
||||
graph = SetupGraph(ctrl, *nvtxs, *ncon, xadj, adjncy, vwgt, vsize, adjwgt);
|
||||
|
||||
/* set up multipliers for making balance computations easier */
|
||||
SetupKWayBalMultipliers(ctrl, graph);
|
||||
|
||||
/* set various run parameters that depend on the graph */
|
||||
ctrl->CoarsenTo = gk_max((*nvtxs)/(20*gk_log2(*nparts)), 30*(*nparts));
|
||||
ctrl->nIparts = (ctrl->CoarsenTo == 30*(*nparts) ? 4 : 5);
|
||||
|
||||
/* take care contiguity requests for disconnected graphs */
|
||||
if (ctrl->contig && !IsConnected(graph, 0))
|
||||
gk_errexit(SIGERR, "METIS Error: A contiguous partition is requested for a non-contiguous input graph.\n");
|
||||
|
||||
/* allocate workspace memory */
|
||||
AllocateWorkSpace(ctrl, graph);
|
||||
|
||||
/* start the partitioning */
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl));
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr));
|
||||
|
||||
*objval = MlevelKWayPartitioning(ctrl, graph, part);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr));
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl));
|
||||
|
||||
/* clean up */
|
||||
FreeCtrl(&ctrl);
|
||||
|
||||
SIGTHROW:
|
||||
/* if required, change the numbering back to 1 */
|
||||
if (renumber)
|
||||
Change2FNumbering(*nvtxs, xadj, adjncy, part);
|
||||
|
||||
gk_siguntrap();
|
||||
gk_malloc_cleanup(0);
|
||||
|
||||
return metis_rcode(sigrval);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes a k-way partitioning of a graph that minimizes
|
||||
the specified objective function.
|
||||
|
||||
\param ctrl is the control structure
|
||||
\param graph is the graph to be partitioned
|
||||
\param part is the vector that on return will store the partitioning
|
||||
|
||||
\returns the objective value of the partitoning. The partitioning
|
||||
itself is stored in the part vector.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part)
|
||||
{
|
||||
idx_t i, j, objval=0, curobj=0, bestobj=0;
|
||||
real_t curbal=0.0, bestbal=0.0;
|
||||
graph_t *cgraph;
|
||||
int status;
|
||||
|
||||
|
||||
for (i=0; i<ctrl->ncuts; i++) {
|
||||
cgraph = CoarsenGraph(ctrl, graph);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
|
||||
AllocateKWayPartitionMemory(ctrl, cgraph);
|
||||
|
||||
/* Release the work space */
|
||||
FreeWorkSpace(ctrl);
|
||||
|
||||
/* Compute the initial partitioning */
|
||||
InitKWayPartitioning(ctrl, cgraph);
|
||||
|
||||
/* Re-allocate the work space */
|
||||
AllocateWorkSpace(ctrl, graph);
|
||||
AllocateRefinementWorkSpace(ctrl, 2*cgraph->nedges);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_IPART,
|
||||
printf("Initial %"PRIDX"-way partitioning cut: %"PRIDX"\n", ctrl->nparts, objval));
|
||||
|
||||
RefineKWay(ctrl, graph, cgraph);
|
||||
|
||||
switch (ctrl->objtype) {
|
||||
case METIS_OBJTYPE_CUT:
|
||||
curobj = graph->mincut;
|
||||
break;
|
||||
|
||||
case METIS_OBJTYPE_VOL:
|
||||
curobj = graph->minvol;
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype);
|
||||
}
|
||||
|
||||
curbal = ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors);
|
||||
|
||||
if (i == 0
|
||||
|| (curbal <= 0.0005 && bestobj > curobj)
|
||||
|| (bestbal > 0.0005 && curbal < bestbal)) {
|
||||
icopy(graph->nvtxs, graph->where, part);
|
||||
bestobj = curobj;
|
||||
bestbal = curbal;
|
||||
}
|
||||
|
||||
FreeRData(graph);
|
||||
|
||||
if (bestobj == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
FreeGraph(&graph);
|
||||
|
||||
return bestobj;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes the initial k-way partitioning using PMETIS
|
||||
*/
|
||||
/*************************************************************************/
|
||||
void InitKWayPartitioning(ctrl_t *ctrl, graph_t *graph)
|
||||
{
|
||||
idx_t i, ntrials, options[METIS_NOPTIONS], curobj=0, bestobj=0;
|
||||
idx_t *bestwhere=NULL;
|
||||
real_t *ubvec=NULL;
|
||||
int status;
|
||||
|
||||
METIS_SetDefaultOptions(options);
|
||||
options[METIS_OPTION_NITER] = 10;
|
||||
options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT;
|
||||
options[METIS_OPTION_NO2HOP] = ctrl->no2hop;
|
||||
|
||||
|
||||
ubvec = rmalloc(graph->ncon, "InitKWayPartitioning: ubvec");
|
||||
for (i=0; i<graph->ncon; i++)
|
||||
ubvec[i] = (real_t)pow(ctrl->ubfactors[i], 1.0/log(ctrl->nparts));
|
||||
|
||||
|
||||
switch (ctrl->objtype) {
|
||||
case METIS_OBJTYPE_CUT:
|
||||
case METIS_OBJTYPE_VOL:
|
||||
options[METIS_OPTION_NCUTS] = ctrl->nIparts;
|
||||
status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon,
|
||||
graph->xadj, graph->adjncy, graph->vwgt, graph->vsize,
|
||||
graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec,
|
||||
options, &curobj, graph->where);
|
||||
|
||||
if (status != METIS_OK)
|
||||
gk_errexit(SIGERR, "Failed during initial partitioning\n");
|
||||
|
||||
break;
|
||||
|
||||
#ifdef XXX /* This does not seem to help */
|
||||
case METIS_OBJTYPE_VOL:
|
||||
bestwhere = imalloc(graph->nvtxs, "InitKWayPartitioning: bestwhere");
|
||||
options[METIS_OPTION_NCUTS] = 2;
|
||||
|
||||
ntrials = (ctrl->nIparts+1)/2;
|
||||
for (i=0; i<ntrials; i++) {
|
||||
status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon,
|
||||
graph->xadj, graph->adjncy, graph->vwgt, graph->vsize,
|
||||
graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec,
|
||||
options, &curobj, graph->where);
|
||||
if (status != METIS_OK)
|
||||
gk_errexit(SIGERR, "Failed during initial partitioning\n");
|
||||
|
||||
curobj = ComputeVolume(graph, graph->where);
|
||||
|
||||
if (i == 0 || bestobj > curobj) {
|
||||
bestobj = curobj;
|
||||
if (i < ntrials-1)
|
||||
icopy(graph->nvtxs, graph->where, bestwhere);
|
||||
}
|
||||
|
||||
if (bestobj == 0)
|
||||
break;
|
||||
}
|
||||
if (bestobj != curobj)
|
||||
icopy(graph->nvtxs, bestwhere, graph->where);
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype);
|
||||
}
|
||||
|
||||
gk_free((void **)&ubvec, &bestwhere, LTERM);
|
||||
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,672 +0,0 @@
|
|||
/*!
|
||||
\file
|
||||
\brief Driving routines for multilevel k-way refinement
|
||||
|
||||
\date Started 7/28/1997
|
||||
\author George
|
||||
\author Copyright 1997-2009, Regents of the University of Minnesota
|
||||
\version $Id: kwayrefine.c 10737 2011-09-13 13:37:25Z karypis $
|
||||
*/
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function is the entry point of cut-based refinement */
|
||||
/*************************************************************************/
|
||||
void RefineKWay(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph)
|
||||
{
|
||||
idx_t i, nlevels, contig=ctrl->contig;
|
||||
graph_t *ptr;
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr));
|
||||
|
||||
/* Determine how many levels are there */
|
||||
for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++);
|
||||
|
||||
/* Compute the parameters of the coarsest graph */
|
||||
ComputeKWayPartitionParams(ctrl, graph);
|
||||
|
||||
/* Try to minimize the sub-domain connectivity */
|
||||
if (ctrl->minconn)
|
||||
EliminateSubDomainEdges(ctrl, graph);
|
||||
|
||||
/* Deal with contiguity constraints at the beginning */
|
||||
if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) {
|
||||
EliminateComponents(ctrl, graph);
|
||||
|
||||
ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE);
|
||||
Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE);
|
||||
|
||||
ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE);
|
||||
Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE);
|
||||
|
||||
ctrl->contig = 0;
|
||||
}
|
||||
|
||||
/* Refine each successively finer graph */
|
||||
for (i=0; ;i++) {
|
||||
if (ctrl->minconn && i == nlevels/2)
|
||||
EliminateSubDomainEdges(ctrl, graph);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr));
|
||||
|
||||
if (2*i >= nlevels && !IsBalanced(ctrl, graph, .02)) {
|
||||
ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE);
|
||||
Greedy_KWayOptimize(ctrl, graph, 1, 0, OMODE_BALANCE);
|
||||
ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE);
|
||||
}
|
||||
|
||||
Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 5.0, OMODE_REFINE);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr));
|
||||
|
||||
/* Deal with contiguity constraints in the middle */
|
||||
if (contig && i == nlevels/2) {
|
||||
if (FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) {
|
||||
EliminateComponents(ctrl, graph);
|
||||
|
||||
if (!IsBalanced(ctrl, graph, .02)) {
|
||||
ctrl->contig = 1;
|
||||
ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE);
|
||||
Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE);
|
||||
|
||||
ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE);
|
||||
Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE);
|
||||
ctrl->contig = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (graph == orggraph)
|
||||
break;
|
||||
|
||||
graph = graph->finer;
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr));
|
||||
ASSERT(graph->vwgt != NULL);
|
||||
|
||||
ProjectKWayPartition(ctrl, graph);
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr));
|
||||
}
|
||||
|
||||
/* Deal with contiguity requirement at the end */
|
||||
ctrl->contig = contig;
|
||||
if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts)
|
||||
EliminateComponents(ctrl, graph);
|
||||
|
||||
if (!IsBalanced(ctrl, graph, 0.0)) {
|
||||
ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE);
|
||||
Greedy_KWayOptimize(ctrl, graph, 10, 0, OMODE_BALANCE);
|
||||
|
||||
ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE);
|
||||
Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE);
|
||||
}
|
||||
|
||||
if (ctrl->contig)
|
||||
ASSERT(FindPartitionInducedComponents(graph, graph->where, NULL, NULL) == ctrl->nparts);
|
||||
|
||||
IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr));
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function allocates memory for the k-way cut-based refinement */
|
||||
/*************************************************************************/
|
||||
void AllocateKWayPartitionMemory(ctrl_t *ctrl, graph_t *graph)
|
||||
{
|
||||
|
||||
graph->pwgts = imalloc(ctrl->nparts*graph->ncon, "AllocateKWayPartitionMemory: pwgts");
|
||||
graph->where = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: where");
|
||||
graph->bndptr = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: bndptr");
|
||||
graph->bndind = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: bndind");
|
||||
|
||||
switch (ctrl->objtype) {
|
||||
case METIS_OBJTYPE_CUT:
|
||||
graph->ckrinfo = (ckrinfo_t *)gk_malloc(graph->nvtxs*sizeof(ckrinfo_t),
|
||||
"AllocateKWayPartitionMemory: ckrinfo");
|
||||
break;
|
||||
|
||||
case METIS_OBJTYPE_VOL:
|
||||
graph->vkrinfo = (vkrinfo_t *)gk_malloc(graph->nvtxs*sizeof(vkrinfo_t),
|
||||
"AllocateKWayVolPartitionMemory: vkrinfo");
|
||||
|
||||
/* This is to let the cut-based -minconn and -contig large-scale graph
|
||||
changes to go through */
|
||||
graph->ckrinfo = (ckrinfo_t *)graph->vkrinfo;
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes the initial id/ed for cut-based partitioning */
|
||||
/**************************************************************************/
|
||||
void ComputeKWayPartitionParams(ctrl_t *ctrl, graph_t *graph)
|
||||
{
|
||||
idx_t i, j, k, l, nvtxs, ncon, nparts, nbnd, mincut, me, other;
|
||||
idx_t *xadj, *vwgt, *adjncy, *adjwgt, *pwgts, *where, *bndind, *bndptr;
|
||||
|
||||
nparts = ctrl->nparts;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
ncon = graph->ncon;
|
||||
xadj = graph->xadj;
|
||||
vwgt = graph->vwgt;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
|
||||
where = graph->where;
|
||||
pwgts = iset(nparts*ncon, 0, graph->pwgts);
|
||||
bndind = graph->bndind;
|
||||
bndptr = iset(nvtxs, -1, graph->bndptr);
|
||||
|
||||
nbnd = mincut = 0;
|
||||
|
||||
/* Compute pwgts */
|
||||
if (ncon == 1) {
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
ASSERT(where[i] >= 0 && where[i] < nparts);
|
||||
pwgts[where[i]] += vwgt[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
me = where[i];
|
||||
for (j=0; j<ncon; j++)
|
||||
pwgts[me*ncon+j] += vwgt[i*ncon+j];
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the required info for refinement */
|
||||
switch (ctrl->objtype) {
|
||||
case METIS_OBJTYPE_CUT:
|
||||
{
|
||||
ckrinfo_t *myrinfo;
|
||||
cnbr_t *mynbrs;
|
||||
|
||||
memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs);
|
||||
cnbrpoolReset(ctrl);
|
||||
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
me = where[i];
|
||||
myrinfo = graph->ckrinfo+i;
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
if (me == where[adjncy[j]])
|
||||
myrinfo->id += adjwgt[j];
|
||||
else
|
||||
myrinfo->ed += adjwgt[j];
|
||||
}
|
||||
|
||||
/* Time to compute the particular external degrees */
|
||||
if (myrinfo->ed > 0) {
|
||||
mincut += myrinfo->ed;
|
||||
|
||||
myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1);
|
||||
mynbrs = ctrl->cnbrpool + myrinfo->inbr;
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
other = where[adjncy[j]];
|
||||
if (me != other) {
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if (mynbrs[k].pid == other) {
|
||||
mynbrs[k].ed += adjwgt[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == myrinfo->nnbrs) {
|
||||
mynbrs[k].pid = other;
|
||||
mynbrs[k].ed = adjwgt[j];
|
||||
myrinfo->nnbrs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(myrinfo->nnbrs <= xadj[i+1]-xadj[i]);
|
||||
|
||||
/* Only ed-id>=0 nodes are considered to be in the boundary */
|
||||
if (myrinfo->ed-myrinfo->id >= 0)
|
||||
BNDInsert(nbnd, bndind, bndptr, i);
|
||||
}
|
||||
else {
|
||||
myrinfo->inbr = -1;
|
||||
}
|
||||
}
|
||||
|
||||
graph->mincut = mincut/2;
|
||||
graph->nbnd = nbnd;
|
||||
|
||||
}
|
||||
ASSERT(CheckBnd2(graph));
|
||||
break;
|
||||
|
||||
case METIS_OBJTYPE_VOL:
|
||||
{
|
||||
vkrinfo_t *myrinfo;
|
||||
vnbr_t *mynbrs;
|
||||
|
||||
memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs);
|
||||
vnbrpoolReset(ctrl);
|
||||
|
||||
/* Compute now the id/ed degrees */
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
me = where[i];
|
||||
myrinfo = graph->vkrinfo+i;
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
if (me == where[adjncy[j]])
|
||||
myrinfo->nid++;
|
||||
else
|
||||
myrinfo->ned++;
|
||||
}
|
||||
|
||||
/* Time to compute the particular external degrees */
|
||||
if (myrinfo->ned > 0) {
|
||||
mincut += myrinfo->ned;
|
||||
|
||||
myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1);
|
||||
mynbrs = ctrl->vnbrpool + myrinfo->inbr;
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
other = where[adjncy[j]];
|
||||
if (me != other) {
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if (mynbrs[k].pid == other) {
|
||||
mynbrs[k].ned++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == myrinfo->nnbrs) {
|
||||
mynbrs[k].gv = 0;
|
||||
mynbrs[k].pid = other;
|
||||
mynbrs[k].ned = 1;
|
||||
myrinfo->nnbrs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT(myrinfo->nnbrs <= xadj[i+1]-xadj[i]);
|
||||
}
|
||||
else {
|
||||
myrinfo->inbr = -1;
|
||||
}
|
||||
}
|
||||
graph->mincut = mincut/2;
|
||||
|
||||
ComputeKWayVolGains(ctrl, graph);
|
||||
}
|
||||
ASSERT(graph->minvol == ComputeVolume(graph, graph->where));
|
||||
break;
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function projects a partition, and at the same time computes the
|
||||
parameters for refinement. */
|
||||
/*************************************************************************/
|
||||
void ProjectKWayPartition(ctrl_t *ctrl, graph_t *graph)
|
||||
{
|
||||
idx_t i, j, k, nvtxs, nbnd, nparts, me, other, istart, iend, tid, ted;
|
||||
idx_t *xadj, *adjncy, *adjwgt;
|
||||
idx_t *cmap, *where, *bndptr, *bndind, *cwhere, *htable;
|
||||
graph_t *cgraph;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nparts = ctrl->nparts;
|
||||
|
||||
cgraph = graph->coarser;
|
||||
cwhere = cgraph->where;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
cmap = graph->cmap;
|
||||
xadj = graph->xadj;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
|
||||
AllocateKWayPartitionMemory(ctrl, graph);
|
||||
|
||||
where = graph->where;
|
||||
bndind = graph->bndind;
|
||||
bndptr = iset(nvtxs, -1, graph->bndptr);
|
||||
|
||||
htable = iset(nparts, -1, iwspacemalloc(ctrl, nparts));
|
||||
|
||||
/* Compute the required info for refinement */
|
||||
switch (ctrl->objtype) {
|
||||
case METIS_OBJTYPE_CUT:
|
||||
ASSERT(CheckBnd2(cgraph));
|
||||
{
|
||||
ckrinfo_t *myrinfo;
|
||||
cnbr_t *mynbrs;
|
||||
|
||||
/* 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] = cgraph->ckrinfo[k].ed; /* For optimization */
|
||||
}
|
||||
|
||||
memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs);
|
||||
cnbrpoolReset(ctrl);
|
||||
|
||||
for (nbnd=0, i=0; i<nvtxs; i++) {
|
||||
istart = xadj[i];
|
||||
iend = xadj[i+1];
|
||||
|
||||
myrinfo = graph->ckrinfo+i;
|
||||
|
||||
if (cmap[i] == 0) { /* Interior node. Note that cmap[i] = crinfo[cmap[i]].ed */
|
||||
for (tid=0, j=istart; j<iend; j++)
|
||||
tid += adjwgt[j];
|
||||
|
||||
myrinfo->id = tid;
|
||||
myrinfo->inbr = -1;
|
||||
}
|
||||
else { /* Potentially an interface node */
|
||||
myrinfo->inbr = cnbrpoolGetNext(ctrl, iend-istart+1);
|
||||
mynbrs = ctrl->cnbrpool + myrinfo->inbr;
|
||||
|
||||
me = where[i];
|
||||
for (tid=0, ted=0, j=istart; j<iend; j++) {
|
||||
other = where[adjncy[j]];
|
||||
if (me == other) {
|
||||
tid += adjwgt[j];
|
||||
}
|
||||
else {
|
||||
ted += adjwgt[j];
|
||||
if ((k = htable[other]) == -1) {
|
||||
htable[other] = myrinfo->nnbrs;
|
||||
mynbrs[myrinfo->nnbrs].pid = other;
|
||||
mynbrs[myrinfo->nnbrs++].ed = adjwgt[j];
|
||||
}
|
||||
else {
|
||||
mynbrs[k].ed += adjwgt[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
myrinfo->id = tid;
|
||||
myrinfo->ed = ted;
|
||||
|
||||
/* Remove space for edegrees if it was interior */
|
||||
if (ted == 0) {
|
||||
ctrl->nbrpoolcpos -= iend-istart+1;
|
||||
myrinfo->inbr = -1;
|
||||
}
|
||||
else {
|
||||
if (ted-tid >= 0)
|
||||
BNDInsert(nbnd, bndind, bndptr, i);
|
||||
|
||||
for (j=0; j<myrinfo->nnbrs; j++)
|
||||
htable[mynbrs[j].pid] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graph->nbnd = nbnd;
|
||||
|
||||
}
|
||||
ASSERT(CheckBnd2(graph));
|
||||
break;
|
||||
|
||||
case METIS_OBJTYPE_VOL:
|
||||
{
|
||||
vkrinfo_t *myrinfo;
|
||||
vnbr_t *mynbrs;
|
||||
|
||||
ASSERT(cgraph->minvol == ComputeVolume(cgraph, cgraph->where));
|
||||
|
||||
/* 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] = cgraph->vkrinfo[k].ned; /* For optimization */
|
||||
}
|
||||
|
||||
memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs);
|
||||
vnbrpoolReset(ctrl);
|
||||
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
istart = xadj[i];
|
||||
iend = xadj[i+1];
|
||||
myrinfo = graph->vkrinfo+i;
|
||||
|
||||
if (cmap[i] == 0) { /* Note that cmap[i] = crinfo[cmap[i]].ed */
|
||||
myrinfo->nid = iend-istart;
|
||||
myrinfo->inbr = -1;
|
||||
}
|
||||
else { /* Potentially an interface node */
|
||||
myrinfo->inbr = vnbrpoolGetNext(ctrl, iend-istart+1);
|
||||
mynbrs = ctrl->vnbrpool + myrinfo->inbr;
|
||||
|
||||
me = where[i];
|
||||
for (tid=0, ted=0, j=istart; j<iend; j++) {
|
||||
other = where[adjncy[j]];
|
||||
if (me == other) {
|
||||
tid++;
|
||||
}
|
||||
else {
|
||||
ted++;
|
||||
if ((k = htable[other]) == -1) {
|
||||
htable[other] = myrinfo->nnbrs;
|
||||
mynbrs[myrinfo->nnbrs].gv = 0;
|
||||
mynbrs[myrinfo->nnbrs].pid = other;
|
||||
mynbrs[myrinfo->nnbrs++].ned = 1;
|
||||
}
|
||||
else {
|
||||
mynbrs[k].ned++;
|
||||
}
|
||||
}
|
||||
}
|
||||
myrinfo->nid = tid;
|
||||
myrinfo->ned = ted;
|
||||
|
||||
/* Remove space for edegrees if it was interior */
|
||||
if (ted == 0) {
|
||||
ctrl->nbrpoolcpos -= iend-istart+1;
|
||||
myrinfo->inbr = -1;
|
||||
}
|
||||
else {
|
||||
for (j=0; j<myrinfo->nnbrs; j++)
|
||||
htable[mynbrs[j].pid] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ComputeKWayVolGains(ctrl, graph);
|
||||
|
||||
ASSERT(graph->minvol == ComputeVolume(graph, graph->where));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype);
|
||||
}
|
||||
|
||||
graph->mincut = cgraph->mincut;
|
||||
icopy(nparts*graph->ncon, cgraph->pwgts, graph->pwgts);
|
||||
|
||||
FreeGraph(&graph->coarser);
|
||||
graph->coarser = NULL;
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes the boundary definition for balancing. */
|
||||
/*************************************************************************/
|
||||
void ComputeKWayBoundary(ctrl_t *ctrl, graph_t *graph, idx_t bndtype)
|
||||
{
|
||||
idx_t i, nvtxs, nbnd;
|
||||
idx_t *bndind, *bndptr;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
bndind = graph->bndind;
|
||||
bndptr = iset(nvtxs, -1, graph->bndptr);
|
||||
|
||||
nbnd = 0;
|
||||
|
||||
switch (ctrl->objtype) {
|
||||
case METIS_OBJTYPE_CUT:
|
||||
/* Compute the boundary */
|
||||
if (bndtype == BNDTYPE_REFINE) {
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (graph->ckrinfo[i].ed-graph->ckrinfo[i].id >= 0)
|
||||
BNDInsert(nbnd, bndind, bndptr, i);
|
||||
}
|
||||
}
|
||||
else { /* BNDTYPE_BALANCE */
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (graph->ckrinfo[i].ed > 0)
|
||||
BNDInsert(nbnd, bndind, bndptr, i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case METIS_OBJTYPE_VOL:
|
||||
/* Compute the boundary */
|
||||
if (bndtype == BNDTYPE_REFINE) {
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (graph->vkrinfo[i].gv >= 0)
|
||||
BNDInsert(nbnd, bndind, bndptr, i);
|
||||
}
|
||||
}
|
||||
else { /* BNDTYPE_BALANCE */
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
if (graph->vkrinfo[i].ned > 0)
|
||||
BNDInsert(nbnd, bndind, bndptr, i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype);
|
||||
}
|
||||
|
||||
graph->nbnd = nbnd;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function computes the initial gains in the communication volume */
|
||||
/*************************************************************************/
|
||||
void ComputeKWayVolGains(ctrl_t *ctrl, graph_t *graph)
|
||||
{
|
||||
idx_t i, ii, j, k, l, nvtxs, nparts, me, other, pid;
|
||||
idx_t *xadj, *vsize, *adjncy, *adjwgt, *where,
|
||||
*bndind, *bndptr, *ophtable;
|
||||
vkrinfo_t *myrinfo, *orinfo;
|
||||
vnbr_t *mynbrs, *onbrs;
|
||||
|
||||
WCOREPUSH;
|
||||
|
||||
nparts = ctrl->nparts;
|
||||
|
||||
nvtxs = graph->nvtxs;
|
||||
xadj = graph->xadj;
|
||||
vsize = graph->vsize;
|
||||
adjncy = graph->adjncy;
|
||||
adjwgt = graph->adjwgt;
|
||||
|
||||
where = graph->where;
|
||||
bndind = graph->bndind;
|
||||
bndptr = iset(nvtxs, -1, graph->bndptr);
|
||||
|
||||
ophtable = iset(nparts, -1, iwspacemalloc(ctrl, nparts));
|
||||
|
||||
/* Compute the volume gains */
|
||||
graph->minvol = graph->nbnd = 0;
|
||||
for (i=0; i<nvtxs; i++) {
|
||||
myrinfo = graph->vkrinfo+i;
|
||||
myrinfo->gv = IDX_MIN;
|
||||
|
||||
if (myrinfo->nnbrs > 0) {
|
||||
me = where[i];
|
||||
mynbrs = ctrl->vnbrpool + myrinfo->inbr;
|
||||
|
||||
graph->minvol += myrinfo->nnbrs*vsize[i];
|
||||
|
||||
for (j=xadj[i]; j<xadj[i+1]; j++) {
|
||||
ii = adjncy[j];
|
||||
other = where[ii];
|
||||
orinfo = graph->vkrinfo+ii;
|
||||
onbrs = ctrl->vnbrpool + orinfo->inbr;
|
||||
|
||||
for (k=0; k<orinfo->nnbrs; k++)
|
||||
ophtable[onbrs[k].pid] = k;
|
||||
ophtable[other] = 1; /* this is to simplify coding */
|
||||
|
||||
if (me == other) {
|
||||
/* Find which domains 'i' is connected to but 'ii' is not
|
||||
and update their gain */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if (ophtable[mynbrs[k].pid] == -1)
|
||||
mynbrs[k].gv -= vsize[ii];
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(ophtable[me] != -1);
|
||||
|
||||
if (onbrs[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<myrinfo->nnbrs; k++) {
|
||||
if (ophtable[mynbrs[k].pid] != -1)
|
||||
mynbrs[k].gv += vsize[ii];
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Find which domains 'i' is connected to and 'ii' is not
|
||||
and update their gain */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if (ophtable[mynbrs[k].pid] == -1)
|
||||
mynbrs[k].gv -= vsize[ii];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the marker vector */
|
||||
for (k=0; k<orinfo->nnbrs; k++)
|
||||
ophtable[onbrs[k].pid] = -1;
|
||||
ophtable[other] = -1;
|
||||
}
|
||||
|
||||
/* Compute the max vgain */
|
||||
for (k=0; k<myrinfo->nnbrs; k++) {
|
||||
if (mynbrs[k].gv > myrinfo->gv)
|
||||
myrinfo->gv = mynbrs[k].gv;
|
||||
}
|
||||
|
||||
/* Add the extra gain due to id == 0 */
|
||||
if (myrinfo->ned > 0 && myrinfo->nid == 0)
|
||||
myrinfo->gv += vsize[i];
|
||||
}
|
||||
|
||||
if (myrinfo->gv >= 0)
|
||||
BNDInsert(graph->nbnd, bndind, bndptr, i);
|
||||
}
|
||||
|
||||
WCOREPOP;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks if the partition weights are within the balance
|
||||
contraints */
|
||||
/*************************************************************************/
|
||||
int IsBalanced(ctrl_t *ctrl, graph_t *graph, real_t ffactor)
|
||||
{
|
||||
return
|
||||
(ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors)
|
||||
<= ffactor);
|
||||
}
|
||||
|
||||
|
|
@ -1,258 +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 10060 2011-06-02 18:56:30Z karypis $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LIBMETIS_MACROS_H_
|
||||
#define _LIBMETIS_MACROS_H_
|
||||
|
||||
/*************************************************************************
|
||||
* 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 icopy(n, a, b) (idx_t *)memcpy((void *)(b), (void *)(a), sizeof(idx_t)*(n))
|
||||
|
||||
#define HASHFCT(key, size) ((key)%(size))
|
||||
#define SWAP gk_SWAP
|
||||
|
||||
/* gets the appropriate option value */
|
||||
#define GETOPTION(options, idx, defval) \
|
||||
((options) == NULL || (options)[idx] == -1 ? defval : (options)[idx])
|
||||
|
||||
/* converts a user provided ufactor into a real ubfactor */
|
||||
#define I2RUBFACTOR(ufactor) (1.0+0.001*(ufactor))
|
||||
|
||||
/* set/reset the current workspace core */
|
||||
#define WCOREPUSH wspacepush(ctrl)
|
||||
#define WCOREPOP wspacepop(ctrl)
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* These macros insert and remove nodes from a Direct Access list
|
||||
**************************************************************************/
|
||||
#define ListInsert(n, lind, lptr, i) \
|
||||
do { \
|
||||
ASSERT(lptr[i] == -1); \
|
||||
lind[n] = i; \
|
||||
lptr[i] = (n)++;\
|
||||
} while(0)
|
||||
|
||||
#define ListDelete(n, lind, lptr, i) \
|
||||
do { \
|
||||
ASSERT(lptr[i] != -1); \
|
||||
lind[lptr[i]] = lind[--(n)]; \
|
||||
lptr[lind[n]] = lptr[i]; \
|
||||
lptr[i] = -1; \
|
||||
} while(0)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* These macros insert and remove nodes from the boundary list
|
||||
**************************************************************************/
|
||||
#define BNDInsert(nbnd, bndind, bndptr, vtx) \
|
||||
ListInsert(nbnd, bndind, bndptr, vtx)
|
||||
|
||||
#define BNDDelete(nbnd, bndind, bndptr, vtx) \
|
||||
ListDelete(nbnd, bndind, bndptr, vtx)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* These macros deal with id/ed updating during k-way refinement
|
||||
**************************************************************************/
|
||||
#define UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, \
|
||||
nbnd, bndptr, bndind, bndtype) \
|
||||
do { \
|
||||
where[i] = to; \
|
||||
myrinfo->ed += myrinfo->id-mynbrs[k].ed; \
|
||||
SWAP(myrinfo->id, mynbrs[k].ed, j); \
|
||||
if (mynbrs[k].ed == 0) \
|
||||
mynbrs[k] = mynbrs[--myrinfo->nnbrs]; \
|
||||
else \
|
||||
mynbrs[k].pid = from; \
|
||||
\
|
||||
/* Update the boundary information. Both deletion and addition is \
|
||||
allowed as this routine can be used for moving arbitrary nodes. */ \
|
||||
if (bndtype == BNDTYPE_REFINE) { \
|
||||
if (bndptr[i] != -1 && myrinfo->ed - myrinfo->id < 0) \
|
||||
BNDDelete(nbnd, bndind, bndptr, i); \
|
||||
if (bndptr[i] == -1 && myrinfo->ed - myrinfo->id >= 0) \
|
||||
BNDInsert(nbnd, bndind, bndptr, i); \
|
||||
} \
|
||||
else { \
|
||||
if (bndptr[i] != -1 && myrinfo->ed <= 0) \
|
||||
BNDDelete(nbnd, bndind, bndptr, i); \
|
||||
if (bndptr[i] == -1 && myrinfo->ed > 0) \
|
||||
BNDInsert(nbnd, bndind, bndptr, i); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define UpdateAdjacentVertexInfoAndBND(ctrl, vid, adjlen, me, from, to, \
|
||||
myrinfo, ewgt, nbnd, bndptr, bndind, bndtype) \
|
||||
do { \
|
||||
idx_t k; \
|
||||
cnbr_t *mynbrs; \
|
||||
\
|
||||
if (myrinfo->inbr == -1) { \
|
||||
myrinfo->inbr = cnbrpoolGetNext(ctrl, adjlen+1); \
|
||||
myrinfo->nnbrs = 0; \
|
||||
} \
|
||||
ASSERT(CheckRInfo(ctrl, myrinfo)); \
|
||||
\
|
||||
mynbrs = ctrl->cnbrpool + myrinfo->inbr; \
|
||||
\
|
||||
/* Update global ID/ED and boundary */ \
|
||||
if (me == from) { \
|
||||
INC_DEC(myrinfo->ed, myrinfo->id, (ewgt)); \
|
||||
if (bndtype == BNDTYPE_REFINE) { \
|
||||
if (myrinfo->ed-myrinfo->id >= 0 && bndptr[(vid)] == -1) \
|
||||
BNDInsert(nbnd, bndind, bndptr, (vid)); \
|
||||
} \
|
||||
else { \
|
||||
if (myrinfo->ed > 0 && bndptr[(vid)] == -1) \
|
||||
BNDInsert(nbnd, bndind, bndptr, (vid)); \
|
||||
} \
|
||||
} \
|
||||
else if (me == to) { \
|
||||
INC_DEC(myrinfo->id, myrinfo->ed, (ewgt)); \
|
||||
if (bndtype == BNDTYPE_REFINE) { \
|
||||
if (myrinfo->ed-myrinfo->id < 0 && bndptr[(vid)] != -1) \
|
||||
BNDDelete(nbnd, bndind, bndptr, (vid)); \
|
||||
} \
|
||||
else { \
|
||||
if (myrinfo->ed <= 0 && bndptr[(vid)] != -1) \
|
||||
BNDDelete(nbnd, bndind, bndptr, (vid)); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* Remove contribution from the .ed of 'from' */ \
|
||||
if (me != from) { \
|
||||
for (k=0; k<myrinfo->nnbrs; k++) { \
|
||||
if (mynbrs[k].pid == from) { \
|
||||
if (mynbrs[k].ed == (ewgt)) \
|
||||
mynbrs[k] = mynbrs[--myrinfo->nnbrs]; \
|
||||
else \
|
||||
mynbrs[k].ed -= (ewgt); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* Add contribution to the .ed of 'to' */ \
|
||||
if (me != to) { \
|
||||
for (k=0; k<myrinfo->nnbrs; k++) { \
|
||||
if (mynbrs[k].pid == to) { \
|
||||
mynbrs[k].ed += (ewgt); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (k == myrinfo->nnbrs) { \
|
||||
mynbrs[k].pid = to; \
|
||||
mynbrs[k].ed = (ewgt); \
|
||||
myrinfo->nnbrs++; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
ASSERT(CheckRInfo(ctrl, myrinfo));\
|
||||
} while(0)
|
||||
|
||||
|
||||
#define UpdateQueueInfo(queue, vstatus, vid, me, from, to, myrinfo, oldnnbrs, \
|
||||
nupd, updptr, updind, bndtype) \
|
||||
do { \
|
||||
real_t rgain; \
|
||||
\
|
||||
if (me == to || me == from || oldnnbrs != myrinfo->nnbrs) { \
|
||||
rgain = (myrinfo->nnbrs > 0 ? \
|
||||
1.0*myrinfo->ed/sqrt(myrinfo->nnbrs) : 0.0) - myrinfo->id; \
|
||||
\
|
||||
if (bndtype == BNDTYPE_REFINE) { \
|
||||
if (vstatus[(vid)] == VPQSTATUS_PRESENT) { \
|
||||
if (myrinfo->ed-myrinfo->id >= 0) \
|
||||
rpqUpdate(queue, (vid), rgain); \
|
||||
else { \
|
||||
rpqDelete(queue, (vid)); \
|
||||
vstatus[(vid)] = VPQSTATUS_NOTPRESENT; \
|
||||
ListDelete(nupd, updind, updptr, (vid)); \
|
||||
} \
|
||||
} \
|
||||
else if (vstatus[(vid)] == VPQSTATUS_NOTPRESENT && myrinfo->ed-myrinfo->id >= 0) { \
|
||||
rpqInsert(queue, (vid), rgain); \
|
||||
vstatus[(vid)] = VPQSTATUS_PRESENT; \
|
||||
ListInsert(nupd, updind, updptr, (vid)); \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
if (vstatus[(vid)] == VPQSTATUS_PRESENT) { \
|
||||
if (myrinfo->ed > 0) \
|
||||
rpqUpdate(queue, (vid), rgain); \
|
||||
else { \
|
||||
rpqDelete(queue, (vid)); \
|
||||
vstatus[(vid)] = VPQSTATUS_NOTPRESENT; \
|
||||
ListDelete(nupd, updind, updptr, (vid)); \
|
||||
} \
|
||||
} \
|
||||
else if (vstatus[(vid)] == VPQSTATUS_NOTPRESENT && myrinfo->ed > 0) { \
|
||||
rpqInsert(queue, (vid), rgain); \
|
||||
vstatus[(vid)] = VPQSTATUS_PRESENT; \
|
||||
ListInsert(nupd, updind, updptr, (vid)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This macro determines the set of subdomains that a vertex can move to
|
||||
without increasins the maxndoms. */
|
||||
/*************************************************************************/
|
||||
#define SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, vtmp) \
|
||||
do { \
|
||||
idx_t j, k, l, nadd, to; \
|
||||
for (j=0; j<myrinfo->nnbrs; j++) { \
|
||||
safetos[to = mynbrs[j].pid] = 0; \
|
||||
\
|
||||
/* uncompress the connectivity info for the 'to' subdomain */ \
|
||||
for (k=0; k<nads[to]; k++) \
|
||||
vtmp[adids[to][k]] = 1; \
|
||||
\
|
||||
for (nadd=0, k=0; k<myrinfo->nnbrs; k++) { \
|
||||
if (k == j) \
|
||||
continue; \
|
||||
\
|
||||
l = mynbrs[k].pid; \
|
||||
if (vtmp[l] == 0) { \
|
||||
if (nads[l] > maxndoms-1) { \
|
||||
nadd = maxndoms; \
|
||||
break; \
|
||||
} \
|
||||
nadd++; \
|
||||
} \
|
||||
} \
|
||||
if (nads[to]+nadd <= maxndoms) \
|
||||
safetos[to] = 1; \
|
||||
if (nadd == 0) \
|
||||
safetos[to] = 2; \
|
||||
\
|
||||
/* cleanup the connectivity info due to the 'to' subdomain */ \
|
||||
for (k=0; k<nads[to]; k++) \
|
||||
vtmp[adids[to][k]] = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,330 +0,0 @@
|
|||
/*
|
||||
* mutil.c
|
||||
*
|
||||
* This file contains various utility functions for the MOC portion of the
|
||||
* code
|
||||
*
|
||||
* Started 2/15/98
|
||||
* George
|
||||
*
|
||||
* $Id: mcutil.c 13901 2013-03-24 16:17:03Z karypis $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function compares two vectors x & y and returns true
|
||||
if \forall i, x[i] <= y[i].
|
||||
*/
|
||||
/**************************************************************************/
|
||||
int rvecle(idx_t n, real_t *x, real_t *y)
|
||||
{
|
||||
for (n--; n>=0; n--) {
|
||||
if (x[n] > y[n])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function compares two vectors x & y and returns true
|
||||
if \forall i, x[i] >= y[i].
|
||||
*/
|
||||
/**************************************************************************/
|
||||
int rvecge(idx_t n, real_t *x, real_t *y)
|
||||
{
|
||||
for (n--; n>=0; n--) {
|
||||
if (x[n] < y[n])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function compares vectors x1+x2 against y and returns true
|
||||
if \forall i, x1[i]+x2[i] <= y[i].
|
||||
*/
|
||||
/**************************************************************************/
|
||||
int rvecsumle(idx_t n, real_t *x1, real_t *x2, real_t *y)
|
||||
{
|
||||
for (n--; n>=0; n--) {
|
||||
if (x1[n]+x2[n] > y[n])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function returns max_i(x[i]-y[i]) */
|
||||
/**************************************************************************/
|
||||
real_t rvecmaxdiff(idx_t n, real_t *x, real_t *y)
|
||||
{
|
||||
real_t max;
|
||||
|
||||
max = x[0]-y[0];
|
||||
|
||||
for (n--; n>0; n--) {
|
||||
if (max < x[n]-y[n])
|
||||
max = x[n]-y[n];
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function returns true if \forall i, x[i] <= z[i]. */
|
||||
/**************************************************************************/
|
||||
int ivecle(idx_t n, idx_t *x, idx_t *z)
|
||||
{
|
||||
for (n--; n>=0; n--) {
|
||||
if (x[n] > z[n])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function returns true if \forall i, x[i] >= z[i]. */
|
||||
/**************************************************************************/
|
||||
int ivecge(idx_t n, idx_t *x, idx_t *z)
|
||||
{
|
||||
for (n--; n>=0; n--) {
|
||||
if (x[n] < z[n])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function returns true if \forall i, a*x[i]+y[i] <= z[i]. */
|
||||
/**************************************************************************/
|
||||
int ivecaxpylez(idx_t n, idx_t a, idx_t *x, idx_t *y, idx_t *z)
|
||||
{
|
||||
for (n--; n>=0; n--) {
|
||||
if (a*x[n]+y[n] > z[n])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function returns true if \forall i, a*x[i]+y[i] >= z[i]. */
|
||||
/**************************************************************************/
|
||||
int ivecaxpygez(idx_t n, idx_t a, idx_t *x, idx_t *y, idx_t *z)
|
||||
{
|
||||
for (n--; n>=0; n--) {
|
||||
if (a*x[n]+y[n] < z[n])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function checks if v+u2 provides a better balance in the weight
|
||||
vector that v+u1 */
|
||||
/*************************************************************************/
|
||||
int BetterVBalance(idx_t ncon, real_t *invtvwgt, idx_t *v_vwgt, idx_t *u1_vwgt,
|
||||
idx_t *u2_vwgt)
|
||||
{
|
||||
idx_t i;
|
||||
real_t sum1=0.0, sum2=0.0, diff1=0.0, diff2=0.0;
|
||||
|
||||
for (i=0; i<ncon; i++) {
|
||||
sum1 += (v_vwgt[i]+u1_vwgt[i])*invtvwgt[i];
|
||||
sum2 += (v_vwgt[i]+u2_vwgt[i])*invtvwgt[i];
|
||||
}
|
||||
sum1 = sum1/ncon;
|
||||
sum2 = sum2/ncon;
|
||||
|
||||
for (i=0; i<ncon; i++) {
|
||||
diff1 += rabs(sum1 - (v_vwgt[i]+u1_vwgt[i])*invtvwgt[i]);
|
||||
diff2 += rabs(sum2 - (v_vwgt[i]+u2_vwgt[i])*invtvwgt[i]);
|
||||
}
|
||||
|
||||
return (diff1 - diff2 >= 0);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function takes two ubfactor-centered load imbalance vectors x & y,
|
||||
and returns true if y is better balanced than x. */
|
||||
/*************************************************************************/
|
||||
int BetterBalance2Way(idx_t n, real_t *x, real_t *y)
|
||||
{
|
||||
real_t nrm1=0.0, nrm2=0.0;
|
||||
|
||||
for (--n; n>=0; n--) {
|
||||
if (x[n] > 0) nrm1 += x[n]*x[n];
|
||||
if (y[n] > 0) nrm2 += y[n]*y[n];
|
||||
}
|
||||
return nrm2 < nrm1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Given a vertex and two weights, this function returns 1, if the second
|
||||
partition will be more balanced than the first after the weighted
|
||||
additional of that vertex.
|
||||
The balance determination takes into account the ideal target weights
|
||||
of the two partitions.
|
||||
*/
|
||||
/*************************************************************************/
|
||||
int BetterBalanceKWay(idx_t ncon, idx_t *vwgt, real_t *ubvec,
|
||||
idx_t a1, idx_t *pt1, real_t *bm1,
|
||||
idx_t a2, idx_t *pt2, real_t *bm2)
|
||||
{
|
||||
idx_t i;
|
||||
real_t tmp, nrm1=0.0, nrm2=0.0, max1=0.0, max2=0.0;
|
||||
|
||||
for (i=0; i<ncon; i++) {
|
||||
tmp = bm1[i]*(pt1[i]+a1*vwgt[i]) - ubvec[i];
|
||||
//printf("BB: %d %+.4f ", (int)i, (float)tmp);
|
||||
nrm1 += tmp*tmp;
|
||||
max1 = (tmp > max1 ? tmp : max1);
|
||||
|
||||
tmp = bm2[i]*(pt2[i]+a2*vwgt[i]) - ubvec[i];
|
||||
//printf("%+.4f ", (float)tmp);
|
||||
nrm2 += tmp*tmp;
|
||||
max2 = (tmp > max2 ? tmp : max2);
|
||||
|
||||
//printf("%4d %4d %4d %4d %4d %4d %4d %.2f\n",
|
||||
// (int)vwgt[i],
|
||||
// (int)a1, (int)pt1[i], (int)tpt1[i],
|
||||
// (int)a2, (int)pt2[i], (int)tpt2[i], ubvec[i]);
|
||||
}
|
||||
//printf(" %.3f %.3f %.3f %.3f\n", (float)max1, (float)nrm1, (float)max2, (float)nrm2);
|
||||
|
||||
if (max2 < max1)
|
||||
return 1;
|
||||
|
||||
if (max2 == max1 && nrm2 < nrm1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Computes the maximum load imbalance of a partitioning solution over
|
||||
all the constraints. */
|
||||
/**************************************************************************/
|
||||
real_t ComputeLoadImbalance(graph_t *graph, idx_t nparts, real_t *pijbm)
|
||||
{
|
||||
idx_t i, j, ncon, *pwgts;
|
||||
real_t max, cur;
|
||||
|
||||
ncon = graph->ncon;
|
||||
pwgts = graph->pwgts;
|
||||
|
||||
max = 1.0;
|
||||
for (i=0; i<ncon; i++) {
|
||||
for (j=0; j<nparts; j++) {
|
||||
cur = pwgts[j*ncon+i]*pijbm[j*ncon+i];
|
||||
if (cur > max)
|
||||
max = cur;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Computes the maximum load imbalance difference of a partitioning
|
||||
solution over all the constraints.
|
||||
The difference is defined with respect to the allowed maximum
|
||||
unbalance for the respective constraint.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
real_t ComputeLoadImbalanceDiff(graph_t *graph, idx_t nparts, real_t *pijbm,
|
||||
real_t *ubvec)
|
||||
{
|
||||
idx_t i, j, ncon, *pwgts;
|
||||
real_t max, cur;
|
||||
|
||||
ncon = graph->ncon;
|
||||
pwgts = graph->pwgts;
|
||||
|
||||
max = -1.0;
|
||||
for (i=0; i<ncon; i++) {
|
||||
for (j=0; j<nparts; j++) {
|
||||
cur = pwgts[j*ncon+i]*pijbm[j*ncon+i] - ubvec[i];
|
||||
if (cur > max)
|
||||
max = cur;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Computes the difference between load imbalance of each constraint across
|
||||
the partitions minus the desired upper bound on the load imabalnce.
|
||||
It also returns the maximum load imbalance across the partitions &
|
||||
constraints. */
|
||||
/**************************************************************************/
|
||||
real_t ComputeLoadImbalanceDiffVec(graph_t *graph, idx_t nparts, real_t *pijbm,
|
||||
real_t *ubfactors, real_t *diffvec)
|
||||
{
|
||||
idx_t i, j, ncon, *pwgts;
|
||||
real_t cur, max;
|
||||
|
||||
ncon = graph->ncon;
|
||||
pwgts = graph->pwgts;
|
||||
|
||||
for (max=-1.0, i=0; i<ncon; i++) {
|
||||
diffvec[i] = pwgts[i]*pijbm[i] - ubfactors[i];
|
||||
for (j=1; j<nparts; j++) {
|
||||
cur = pwgts[j*ncon+i]*pijbm[j*ncon+i] - ubfactors[i];
|
||||
if (cur > diffvec[i])
|
||||
diffvec[i] = cur;
|
||||
}
|
||||
if (max < diffvec[i])
|
||||
max = diffvec[i];
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! Computes the load imbalance of each constraint across the partitions. */
|
||||
/**************************************************************************/
|
||||
void ComputeLoadImbalanceVec(graph_t *graph, idx_t nparts, real_t *pijbm,
|
||||
real_t *lbvec)
|
||||
{
|
||||
idx_t i, j, ncon, *pwgts;
|
||||
real_t cur;
|
||||
|
||||
ncon = graph->ncon;
|
||||
pwgts = graph->pwgts;
|
||||
|
||||
for (i=0; i<ncon; i++) {
|
||||
lbvec[i] = pwgts[i]*pijbm[i];
|
||||
for (j=1; j<nparts; j++) {
|
||||
cur = pwgts[j*ncon+i]*pijbm[j*ncon+i];
|
||||
if (cur > lbvec[i])
|
||||
lbvec[i] = cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,412 +0,0 @@
|
|||
/*
|
||||
* Copyright 1997, Regents of the University of Minnesota
|
||||
*
|
||||
* mesh.c
|
||||
*
|
||||
* This file contains routines for converting 3D and 4D finite element
|
||||
* meshes into dual or nodal graphs
|
||||
*
|
||||
* Started 8/18/97
|
||||
* George
|
||||
*
|
||||
* $Id: mesh.c 13804 2013-03-04 23:49:08Z karypis $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "metislib.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! This function creates a graph corresponding to the dual of a finite element
|
||||
mesh.
|
||||
|
||||
\param ne is the number of elements in the mesh.
|
||||
\param nn is the number of nodes in the mesh.
|
||||
\param eptr is an array of size ne+1 used to mark the start and end
|
||||
locations in the nind array.
|
||||
\param eind is an array that stores for each element the set of node IDs
|
||||
(indices) that it is made off. The length of this array is equal
|
||||
to the total number of nodes over all the mesh elements.
|
||||
\param ncommon is the minimum number of nodes that two elements must share
|
||||
in order to be connected via an edge in the dual graph.
|
||||
\param numflag is either 0 or 1 indicating if the numbering of the nodes
|
||||
starts from 0 or 1, respectively. The same numbering is used for the
|
||||
returned graph as well.
|
||||
\param r_xadj indicates where the adjacency list of each vertex is stored
|
||||
in r_adjncy. The memory for this array is allocated by this routine.
|
||||
It can be freed by calling METIS_free().
|
||||
\param r_adjncy stores the adjacency list of each vertex in the generated
|
||||
dual graph. The memory for this array is allocated by this routine.
|
||||
It can be freed by calling METIS_free().
|
||||
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
int METIS_MeshToDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind,
|
||||
idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy)
|
||||
{
|
||||
int sigrval=0, renumber=0;
|
||||
|
||||
/* set up malloc cleaning code and signal catchers */
|
||||
if (!gk_malloc_init())
|
||||
return METIS_ERROR_MEMORY;
|
||||
|
||||
gk_sigtrap();
|
||||
|
||||
if ((sigrval = gk_sigcatch()) != 0)
|
||||
goto SIGTHROW;
|
||||
|
||||
|
||||
/* renumber the mesh */
|
||||
if (*numflag == 1) {
|
||||
ChangeMesh2CNumbering(*ne, eptr, eind);
|
||||
renumber = 1;
|
||||
}
|
||||
|
||||
/* create dual graph */
|
||||
*r_xadj = *r_adjncy = NULL;
|
||||
CreateGraphDual(*ne, *nn, eptr, eind, *ncommon, r_xadj, r_adjncy);
|
||||
|
||||
|
||||
SIGTHROW:
|
||||
if (renumber)
|
||||
ChangeMesh2FNumbering(*ne, eptr, eind, *ne, *r_xadj, *r_adjncy);
|
||||
|
||||
gk_siguntrap();
|
||||
gk_malloc_cleanup(0);
|
||||
|
||||
if (sigrval != 0) {
|
||||
if (*r_xadj != NULL)
|
||||
free(*r_xadj);
|
||||
if (*r_adjncy != NULL)
|
||||
free(*r_adjncy);
|
||||
*r_xadj = *r_adjncy = NULL;
|
||||
}
|
||||
|
||||
return metis_rcode(sigrval);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! This function creates a graph corresponding to (almost) the nodal of a
|
||||
finite element mesh. In the nodal graph, each node is connected to the
|
||||
nodes corresponding to the union of nodes present in all the elements
|
||||
in which that node belongs.
|
||||
|
||||
\param ne is the number of elements in the mesh.
|
||||
\param nn is the number of nodes in the mesh.
|
||||
\param eptr is an array of size ne+1 used to mark the start and end
|
||||
locations in the nind array.
|
||||
\param eind is an array that stores for each element the set of node IDs
|
||||
(indices) that it is made off. The length of this array is equal
|
||||
to the total number of nodes over all the mesh elements.
|
||||
\param numflag is either 0 or 1 indicating if the numbering of the nodes
|
||||
starts from 0 or 1, respectively. The same numbering is used for the
|
||||
returned graph as well.
|
||||
\param r_xadj indicates where the adjacency list of each vertex is stored
|
||||
in r_adjncy. The memory for this array is allocated by this routine.
|
||||
It can be freed by calling METIS_free().
|
||||
\param r_adjncy stores the adjacency list of each vertex in the generated
|
||||
dual graph. The memory for this array is allocated by this routine.
|
||||
It can be freed by calling METIS_free().
|
||||
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
int METIS_MeshToNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind,
|
||||
idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy)
|
||||
{
|
||||
int sigrval=0, renumber=0;
|
||||
|
||||
/* set up malloc cleaning code and signal catchers */
|
||||
if (!gk_malloc_init())
|
||||
return METIS_ERROR_MEMORY;
|
||||
|
||||
gk_sigtrap();
|
||||
|
||||
if ((sigrval = gk_sigcatch()) != 0)
|
||||
goto SIGTHROW;
|
||||
|
||||
|
||||
/* renumber the mesh */
|
||||
if (*numflag == 1) {
|
||||
ChangeMesh2CNumbering(*ne, eptr, eind);
|
||||
renumber = 1;
|
||||
}
|
||||
|
||||
/* create nodal graph */
|
||||
*r_xadj = *r_adjncy = NULL;
|
||||
CreateGraphNodal(*ne, *nn, eptr, eind, r_xadj, r_adjncy);
|
||||
|
||||
|
||||
SIGTHROW:
|
||||
if (renumber)
|
||||
ChangeMesh2FNumbering(*ne, eptr, eind, *nn, *r_xadj, *r_adjncy);
|
||||
|
||||
gk_siguntrap();
|
||||
gk_malloc_cleanup(0);
|
||||
|
||||
if (sigrval != 0) {
|
||||
if (*r_xadj != NULL)
|
||||
free(*r_xadj);
|
||||
if (*r_adjncy != NULL)
|
||||
free(*r_adjncy);
|
||||
*r_xadj = *r_adjncy = NULL;
|
||||
}
|
||||
|
||||
return metis_rcode(sigrval);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! This function creates the dual of a finite element mesh */
|
||||
/*****************************************************************************/
|
||||
void CreateGraphDual(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t ncommon,
|
||||
idx_t **r_xadj, idx_t **r_adjncy)
|
||||
{
|
||||
idx_t i, j, nnbrs;
|
||||
idx_t *nptr, *nind;
|
||||
idx_t *xadj, *adjncy;
|
||||
idx_t *marker, *nbrs;
|
||||
|
||||
if (ncommon < 1) {
|
||||
printf(" Increased ncommon to 1, as it was initially %"PRIDX"\n", ncommon);
|
||||
ncommon = 1;
|
||||
}
|
||||
|
||||
/* construct the node-element list first */
|
||||
nptr = ismalloc(nn+1, 0, "CreateGraphDual: nptr");
|
||||
nind = imalloc(eptr[ne], "CreateGraphDual: nind");
|
||||
|
||||
for (i=0; i<ne; i++) {
|
||||
for (j=eptr[i]; j<eptr[i+1]; j++)
|
||||
nptr[eind[j]]++;
|
||||
}
|
||||
MAKECSR(i, nn, nptr);
|
||||
|
||||
for (i=0; i<ne; i++) {
|
||||
for (j=eptr[i]; j<eptr[i+1]; j++)
|
||||
nind[nptr[eind[j]]++] = i;
|
||||
}
|
||||
SHIFTCSR(i, nn, nptr);
|
||||
|
||||
|
||||
/* Allocate memory for xadj, since you know its size.
|
||||
These are done using standard malloc as they are returned
|
||||
to the calling function */
|
||||
if ((xadj = (idx_t *)malloc((ne+1)*sizeof(idx_t))) == NULL)
|
||||
gk_errexit(SIGMEM, "***Failed to allocate memory for xadj.\n");
|
||||
*r_xadj = xadj;
|
||||
iset(ne+1, 0, xadj);
|
||||
|
||||
/* allocate memory for working arrays used by FindCommonElements */
|
||||
marker = ismalloc(ne, 0, "CreateGraphDual: marker");
|
||||
nbrs = imalloc(ne, "CreateGraphDual: nbrs");
|
||||
|
||||
for (i=0; i<ne; i++) {
|
||||
xadj[i] = FindCommonElements(i, eptr[i+1]-eptr[i], eind+eptr[i], nptr,
|
||||
nind, eptr, ncommon, marker, nbrs);
|
||||
}
|
||||
MAKECSR(i, ne, xadj);
|
||||
|
||||
/* Allocate memory for adjncy, since you now know its size.
|
||||
These are done using standard malloc as they are returned
|
||||
to the calling function */
|
||||
if ((adjncy = (idx_t *)malloc(xadj[ne]*sizeof(idx_t))) == NULL) {
|
||||
free(xadj);
|
||||
*r_xadj = NULL;
|
||||
gk_errexit(SIGMEM, "***Failed to allocate memory for adjncy.\n");
|
||||
}
|
||||
*r_adjncy = adjncy;
|
||||
|
||||
for (i=0; i<ne; i++) {
|
||||
nnbrs = FindCommonElements(i, eptr[i+1]-eptr[i], eind+eptr[i], nptr,
|
||||
nind, eptr, ncommon, marker, nbrs);
|
||||
for (j=0; j<nnbrs; j++)
|
||||
adjncy[xadj[i]++] = nbrs[j];
|
||||
}
|
||||
SHIFTCSR(i, ne, xadj);
|
||||
|
||||
gk_free((void **)&nptr, &nind, &marker, &nbrs, LTERM);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! This function finds all elements that share at least ncommon nodes with
|
||||
the ``query'' element.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
idx_t FindCommonElements(idx_t qid, idx_t elen, idx_t *eind, idx_t *nptr,
|
||||
idx_t *nind, idx_t *eptr, idx_t ncommon, idx_t *marker, idx_t *nbrs)
|
||||
{
|
||||
idx_t i, ii, j, jj, k, l, overlap;
|
||||
|
||||
/* find all elements that share at least one node with qid */
|
||||
for (k=0, i=0; i<elen; i++) {
|
||||
j = eind[i];
|
||||
for (ii=nptr[j]; ii<nptr[j+1]; ii++) {
|
||||
jj = nind[ii];
|
||||
|
||||
if (marker[jj] == 0)
|
||||
nbrs[k++] = jj;
|
||||
marker[jj]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* put qid into the neighbor list (in case it is not there) so that it
|
||||
will be removed in the next step */
|
||||
if (marker[qid] == 0)
|
||||
nbrs[k++] = qid;
|
||||
marker[qid] = 0;
|
||||
|
||||
/* compact the list to contain only those with at least ncommon nodes */
|
||||
for (j=0, i=0; i<k; i++) {
|
||||
overlap = marker[l = nbrs[i]];
|
||||
if (overlap >= ncommon ||
|
||||
overlap >= elen-1 ||
|
||||
overlap >= eptr[l+1]-eptr[l]-1)
|
||||
nbrs[j++] = l;
|
||||
marker[l] = 0;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! This function creates the (almost) nodal of a finite element mesh */
|
||||
/*****************************************************************************/
|
||||
void CreateGraphNodal(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind,
|
||||
idx_t **r_xadj, idx_t **r_adjncy)
|
||||
{
|
||||
idx_t i, j, nnbrs;
|
||||
idx_t *nptr, *nind;
|
||||
idx_t *xadj, *adjncy;
|
||||
idx_t *marker, *nbrs;
|
||||
|
||||
|
||||
/* construct the node-element list first */
|
||||
nptr = ismalloc(nn+1, 0, "CreateGraphNodal: nptr");
|
||||
nind = imalloc(eptr[ne], "CreateGraphNodal: nind");
|
||||
|
||||
for (i=0; i<ne; i++) {
|
||||
for (j=eptr[i]; j<eptr[i+1]; j++)
|
||||
nptr[eind[j]]++;
|
||||
}
|
||||
MAKECSR(i, nn, nptr);
|
||||
|
||||
for (i=0; i<ne; i++) {
|
||||
for (j=eptr[i]; j<eptr[i+1]; j++)
|
||||
nind[nptr[eind[j]]++] = i;
|
||||
}
|
||||
SHIFTCSR(i, nn, nptr);
|
||||
|
||||
|
||||
/* Allocate memory for xadj, since you know its size.
|
||||
These are done using standard malloc as they are returned
|
||||
to the calling function */
|
||||
if ((xadj = (idx_t *)malloc((nn+1)*sizeof(idx_t))) == NULL)
|
||||
gk_errexit(SIGMEM, "***Failed to allocate memory for xadj.\n");
|
||||
*r_xadj = xadj;
|
||||
iset(nn+1, 0, xadj);
|
||||
|
||||
/* allocate memory for working arrays used by FindCommonElements */
|
||||
marker = ismalloc(nn, 0, "CreateGraphNodal: marker");
|
||||
nbrs = imalloc(nn, "CreateGraphNodal: nbrs");
|
||||
|
||||
for (i=0; i<nn; i++) {
|
||||
xadj[i] = FindCommonNodes(i, nptr[i+1]-nptr[i], nind+nptr[i], eptr,
|
||||
eind, marker, nbrs);
|
||||
}
|
||||
MAKECSR(i, nn, xadj);
|
||||
|
||||
/* Allocate memory for adjncy, since you now know its size.
|
||||
These are done using standard malloc as they are returned
|
||||
to the calling function */
|
||||
if ((adjncy = (idx_t *)malloc(xadj[nn]*sizeof(idx_t))) == NULL) {
|
||||
free(xadj);
|
||||
*r_xadj = NULL;
|
||||
gk_errexit(SIGMEM, "***Failed to allocate memory for adjncy.\n");
|
||||
}
|
||||
*r_adjncy = adjncy;
|
||||
|
||||
for (i=0; i<nn; i++) {
|
||||
nnbrs = FindCommonNodes(i, nptr[i+1]-nptr[i], nind+nptr[i], eptr,
|
||||
eind, marker, nbrs);
|
||||
for (j=0; j<nnbrs; j++)
|
||||
adjncy[xadj[i]++] = nbrs[j];
|
||||
}
|
||||
SHIFTCSR(i, nn, xadj);
|
||||
|
||||
gk_free((void **)&nptr, &nind, &marker, &nbrs, LTERM);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! This function finds the union of nodes that are in the same elements with
|
||||
the ``query'' node.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
idx_t FindCommonNodes(idx_t qid, idx_t nelmnts, idx_t *elmntids, idx_t *eptr,
|
||||
idx_t *eind, idx_t *marker, idx_t *nbrs)
|
||||
{
|
||||
idx_t i, ii, j, jj, k;
|
||||
|
||||
/* find all nodes that share at least one element with qid */
|
||||
marker[qid] = 1; /* this is to prevent self-loops */
|
||||
for (k=0, i=0; i<nelmnts; i++) {
|
||||
j = elmntids[i];
|
||||
for (ii=eptr[j]; ii<eptr[j+1]; ii++) {
|
||||
jj = eind[ii];
|
||||
if (marker[jj] == 0) {
|
||||
nbrs[k++] = jj;
|
||||
marker[jj] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the marker */
|
||||
marker[qid] = 0;
|
||||
for (i=0; i<k; i++) {
|
||||
marker[nbrs[i]] = 0;
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function creates and initializes a mesh_t structure */
|
||||
/*************************************************************************/
|
||||
mesh_t *CreateMesh(void)
|
||||
{
|
||||
mesh_t *mesh;
|
||||
|
||||
mesh = (mesh_t *)gk_malloc(sizeof(mesh_t), "CreateMesh: mesh");
|
||||
|
||||
InitMesh(mesh);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function initializes a mesh_t data structure */
|
||||
/*************************************************************************/
|
||||
void InitMesh(mesh_t *mesh)
|
||||
{
|
||||
memset((void *)mesh, 0, sizeof(mesh_t));
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*! This function deallocates any memory stored in a mesh */
|
||||
/*************************************************************************/
|
||||
void FreeMesh(mesh_t **r_mesh)
|
||||
{
|
||||
mesh_t *mesh = *r_mesh;
|
||||
|
||||
gk_free((void **)&mesh->eptr, &mesh->eind, &mesh->ewgt, &mesh, LTERM);
|
||||
|
||||
*r_mesh = NULL;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue