diff --git a/scotch_6.0.3/INSTALL.txt b/scotch_6.0.3/INSTALL.txt new file mode 100644 index 00000000..87fa6774 --- /dev/null +++ b/scotch_6.0.3/INSTALL.txt @@ -0,0 +1,561 @@ +Scotch 6.0 installation instructions +==================================== + + +1) Mandatory tools +================== + +In order for you to compile Scotch and/or PT-Scotch, you must have GNU +Make installed on your system, as well as an implementation of the MPI +message-passing library in the case of PT-Scotch. Lex and Yacc are +optional. There is a possibility to install Scotch without having Lex +or Yacc, but it may require the tuning of sample Flex and Bison (i.e., +the GNU equivalents of Lex and Yacc) outputs created on a Linux +system, which may need some tricky work to compile on other systems, +because of different C library implementations. + +To check if GNU Make is installed and is found first, please type: + +%prompt% make --version + +It should read: +% GNU Make x.xx +% Copyright (C) 20xx Free Software Foundation, Inc. +etc, etc. + + +Alternatively, if GNU Make is installed but its directory does +not appear first in the PATH variable that is searched for +executables, you can try to locate it using the which command: + +%prompt% which make + +If several occurences of make are found, one might be GNU Make, +so try to figure out which of them. + +To see if lex and yacc are present, type +%prompt% which lex +%prompt% which yacc (or "bison", the GNU flavor of yacc) + +If some of these are missing, please: +- check your path variable (just in case they are located in + some unusual place, such as /usr/local/bin, /opt/bin, + /opt/local/bin/, /opt/gnu/bin, etc). Tools such as "which", + "locate" or "find" may help you find them; +- ask your system administrator (highly recommended); +- install a copy of GNU Make of your own (less recommended, + please ask your system administrator first). GNU Make is + available from the FSF website, at: + http://www.gnu.org/software/make/ and + http://ftp.gnu.org/pub/gnu/make/ . + A GNU version of lex and yacc is also available from the + very same FSF website, at: + http://www.gnu.org/software/flex/ + http://ftp.gnu.org/non-gnu/flex/ + http://www.gnu.org/software/bison/ + http://ftp.gnu.org/pub/gnu/bison/ ; +- use the "last resort" files placed in a directory judiciously + called "last_resort", located in subdirectory "src/libscotch". + These files are: + . parser_ll.c + . parser_ly.h + . parser_yy.c . + They should be copied in the directory where object files are + created, and "touch"ed so that their modification date is more + recent than those of the corresponding "parser_ll.l" and + "parser_yy.y" files. Then cross your fingers and hope it + compiles properly on your system. Else, you will have to dig in + their code to have them compile properly... + The Makefile of the libScotch library has been designed so as + to copy the last_resort/* files automatically when the lex or + yacc tools are not found. + In this case, depending on your platform, you may also have to set + the "-DSCOTCH_RENAME_PARSER" flag in order for all symbols to be + properly redefined (see Section 2.2). + + +2) Configuration +================ + +2.1) Creating the "Makefile.inc" file +------------------------------------- + +Go to the "src/" directory. + +Look in the "Make.inc/" subdirectory for a configuration +file which matches your system configuration. If there +is none, build a proper one in the "Make.inc/" subdirectory, +basing on the structure of existing ones. + +In particular, the Makefile.inc file contains three variables +which specify which C compiler to use. Their semantic is as +follows: the compiler command in variable CCS is used to compile +the sequential (hence the "S" in "CCS") Scotch distribution. The +compiler command in CCP is used to compile the parallel ("P") +PT-Scotch distribution. The compiler command in CCD is used to compile +the version of the "dummysizes" ("D") executable used for compiling +PT-Scotch, as explained below. + +Create a symbolic link from the configuration file to the +current "src/" working directory, renaming it as "Makefile.inc": + +%prompt% ln -s Make.inc/Makefile.inc.xxxx_xxx_xxx Makefile.inc + +If symbolic links are not available on your system, make a +plain copy of the file to a file named "Makefile.inc" in the +current "src/" working directory: + +%prompt% cp Make.inc/Makefile.inc.xxxx_xxx_xxx Makefile.inc + +Some additional scripts, designed to ease the installation of Scotch +on specific platforms, are also present in subdirectories of the +Make.inc directory. This is for instance the case for the mingw32 +platform. + + +2.2) Parser symbol conflicts +---------------------------- + +Since Scotch uses a parser to analyze its strategy strings, it may +happen that the symbols of this parser conflict with those of +another parser used in a third-party library. All "Makefile.inc.*" +platform configuration files which base on flex / bison are already +tailored so as to prevent such conflicts. If you use other parsing +tools, you may have to provide other options. Another solution is to +use the pre-processed parser files of the "src/libscotch/last_resort" +subdirectory (corresponding operation instructions are given in +Section 1). + + +2.3) Integer size issues +------------------------ + +By default, all integers used in Scotch and PT-Scotch are of the "int" +C type, corresponding to the "INTEGER" type in Fortran. To coerce the +size of the Scotch integer type to 32 or 64 bits, add the "-DINTSIZE32" +or "-DINTSIZE64" flags, respectively, to the C compiler flags in the +Makefile.inc configuration file. If you do so, make sure to use +integer types of equivalent size to declare variables passed to Scotch +routines from caller C and Fortran procedures. Also, when running on +32_64-bit architectures (that is, integer types are 32-bit wide, +while address types are 64-bit wide), some integer array indices +returned by the Fortran interface have to be of a size equivalent to +those of memory addresses, that is, 64 bits. The size of these +variables is determined by the "-DIDXSIZE32" and "-DIDXSIZE64" flags, +respectively. When none of them is provided, the size of the indices +is assumed to be equivalent to that of the Scotch integer type. + +For instance, on a 32-bit architecture, you can use 64-bit integers in +Scotch by just setting the "-DINTSIZE64" flag, because addresses will +remain on 32 bits. On a 32_64 architecture, you can use either 32-bit +or 64-bit integers in Scotch, by setting the "-DINTSIZE32" or +"-DINTSIZE64" flags accordingly, but in all cases you must set the +"-DIDXSIZE64" flag in order for some of the routines of the Fortran +interface to operate properly, because the array indices returned by +these routines have to be stored as 64-bit quantities. + +Of course, on 64-bit architectures, another possibility is to tune +your C and Fortran compilers to make them interpret all "int" and +"INTEGER" types as 64 bit values. This solution is the simplest one, +as there is no need to use any of the aforementioned flags, nor to +hard-code type lengths in user's code. Yet, it prevents mixing 32 and +64-bit features, and may create problems when linking PT-Scotch if a +corresponding MPI library is not available. + +Be careful not to mismatch the 32-bit and 64-bit versions of the +"scotch.h" and "ptscotch.h" include files that are generated at +compile time. When several versions of Scotch are simultaneously +present on a system, Make sure to place the corresponding include and +library files in separate directories. Most Scotch data structures +will have different sizes, depending on integer or pointer +sizes. Consequently, compiling a 64-bit executable with the 32-bit +version of "scotch.h" may lead to unpredictable behavior because of +memory overflow. + + +2.4) Compression libraries +-------------------------- + +The binaries of the Scotch distribution can handle compressed +graphs in input or output. Three compressed graph formats are +currently supported: bzip2, gzip and lzma. In order for them to be +actually activated, the proper libraries must be available on your +system. On a Linux platform, they are called "zlib" for the gzip +format, "libbz2" for the bzip2 format, and "liblzma" for the lzma +format. Note that it is the "development" version (also called +"devel", for short, within package names) of each of these libraries +which is required for the compilation to succeed. +According to the libraries installed on your system, you may set +flags "-DCOMMON_FILE_COMPRESS_BZ2", "-DCOMMON_FILE_COMPRESS_GZ" and/or +"-DCOMMON_FILE_COMPRESS_LZMA" in the CFLAGS variable of your +Makefile.inc configuration file, to have these formats and their +respective extensions ".bz2", ".gz" and ".lzma", recognized and +handled by Scotch. + +Compression and decompression are handled either by extra threads +or by fork'ed child processes if threads are not available. On +systems which do not provide a functional fork() system call, +compressed files cannot be handled when the "-DCOMMON_PTHREAD" flag +is not set (see below). + + +2.5) Multi-threading +-------------------- + +Scotch can also take advantage of Posix threads when they are +available. They are used in several places: + +- to compress and uncompress file data. This can be done either + by launching a service thread, or else by creating a separate + process by means of a Posix fork() system call. This choice is + controlled by the "-DCOMMON_PTHREAD" flag: if it is set, threads + will be used, else fork() calls will be performed. For systems + which do not support the fork() system call, such as the MinGW32 + platform, one can set the "-DCOMMON_STUB_FORK" flag, which creates + a stub fork() routine which always returns an error. Therefore, + without both fork() and threads, one must set the + "-DCOMMON_STUB_FORK" flag without setting "-DCOMMON_PTHREAD", so + that compilation will successfully complete; however, in this case, + compressed graphs shall not be handled in practice. + +- to create distributed graphs in parallel. Since this task involves + concurrent MPI communications, the MPI library must support the + MPI_THREAD_MULTIPLE level. The use of threads within Scotch itself + is controlled by the "-DSCOTCH_PTHREAD" flag, which is completely + independent from the "-DCOMMON_PTHREAD" flag. Any of them can be set + without setting the other. + + Note that if you compile Scotch with the "-DSCOTCH_PTHREAD" flag, + you will have to initialize your communication subsystem by using + the MPI_Init_thread() MPI call, not MPI_Init(), and the provided + thread support level value returned by the routine must be + checked carefully. + If you have doubts on the stability of your MPI implementation, it + is better not to set "-DSCOTCH_PTHREAD". For instance, on Linux + platforms, concurrency problems have been experienced with MPICH2 + versions prior to 1.0.7 using TCP; consequently, if the MPI + implementation on your platform is based on an older MPICH2 version, + do not set the "-DSCOTCH_PTHREAD" flag. + + Note that since the Scotch and PT-Scotch libraries are distinct, you + can still compile Scotch with threads enabled, and compile PT-Scotch + with threads disabled. However, since PT-Scotch calls Scotch + routines when operating on a single process, threaded routines will + be used on each process, without interfering with MPI. + +- to run in a multi-threaded way several key algorithms of the Scotch + (no longer really) sequential library, such as graph coarsening and + k-way diffusion. More algorithms will be re-coded in a threaded way + in future versions. + +To date, thread management is performed in a very rudimentary way. +The available number of threads can only be set at compile-time, and +the assignment of threads to cores is performed in increasing order, +starting from 0, which may not always prove to be the most efficient +mapping in terms of memory affinity. We plan to add a mechanism for +dynamic thread allocation in the near future, based upon the hwloc +library. + +The compilation flags used to manage threads are the following: + +"-DCOMMON_PTHREAD" enables threads for algorithms not related to +graph management, partitioning and/or ordering, e.g. compressed +file handling. + +"-DCOMMON_PTHREAD_BARRIER" creates a replacement for missing +pthread_barrier_t implementations, which unfortunately happens on some +systems. + +"-DSCOTCH_PTHREAD" is necessary to enable multi-threaded algorithms +in Scotch and/or PT-Scotch. + +"-DSCOTCH_PTHREAD_AFFINITY_LINUX" enables Linux extensions for +handling thread affinity. As said above, this may not prove +efficient in all cases. More options will be provided in the +near future. + +"-DSCOTCH_PTHREAD_NUMBER=x" sets the overall number of threads to be +used by multi-threaded algorithms. This number may not necessary be a +power of two. Since some algorithms have had to be reformulated to +accomodate for multi-threading, some algorithms will most probably be +much more efficient than sequential processing only for a number of +threads strictly greater than 2. Setting "-DSCOTCH_PTHREAD_NUMBER=1" +allows one to run sequential algorithms instead of multi-threaded +ones, while benefitting from multi-threading for file compression and +distributed graph handling. + +When compiling under mingw32 on Windows systems, it is possible to +benefit from multi-threading by including the "semaphore.h" and +"pthread.h" files, included in the "src/misc" subdirectory, at compile +time. These files have been kindly provided by Samuel Thibault, under +a BSD 2-Clause License. These files will not work for Cygwin. This is +not a problem, as Cygwin provides its own implementation of Posix +threads. + + +2.6) Monitoring memory allocation +--------------------------------- + +Some memory allocation information can be aggregated if PT-Scotch is +compiled with the -DCOMMON_MEMORY_TRACE flag. When this flag is set, +the "-va" option will make dgmap, dgord and dgpart output the minimum, +maximum and average peak amount of memory used over all processes. + +Several API routines will also be made available to report the current +and maximum amount of memory used by Scotch within the process they +are called: SCOTCH_memCur() and SCOTCH_memMax(), respectively. + +A rudimentary memory checking mechanism is available for platforms +that do not have efficient memory checking and debugging tools such as +Valgrind or gdb. It can be activated through the +"-DCOMMON_MEMORY_CHECK=x" flag. This is almost only for internal +debugging purposes. The value of the "-DCOMMON_MEMORY_CHECK" is 1 if +memory checking should be enabled by default, and 0 else. This +mechanism is absolutely NOT thread-safe at the time being. + + +2.7) Randomness +--------------- + +Many algorithms in Scotch and PT-Scotch are based on the random +selection of vertices (e.g. seed vertices for graph growing +algorithms, vertices to be mated for coarsening algorithms, +etc.). This selection is performed by using integer pseudo-random +generators to produce seemingly uncorrelated vertex indices. + +The advantage of pseudo-randomness over pure randomness is that the +same pseudo-random seed will always yield the same sequence of +pseudo-random numbers. Consequently, while using a different random +seed for each run is likely to explore better the solution space, +using a fixed random seed eases the debugging of programs, because +algorithms behave identically across multiple runs (save for +asynchronousness issues, see next section). By default, Scotch is +compiled with the "-DCOMMON_RANDOM_FIXED_SEED" flag set, so that +multiple executions of the same sequential programs will always yield +the same results. + +Prior to version 6.0, Scotch relied on the operating system +pseudo-random generator. While this posed no problem for most +sequential programs, parallel runs of PT-Scotch were not reproducible +on some systems, because the MPI implementation also used this +pseudo-random generator for its own purposes. In order to avoid this +problem, Scotch now uses its own pseudo-random generator. Users that +want to go on using the operating system pseudo-random generator +(e.g. for regression testing with respect to version 5.x) can still do +so, by compiling with the "-DCOMMON_RANDOM_SYSTEM" flag set. In this +case, the "-DCOMMON_RANDOM_RAND" flag allows one to use the srand() +routine instead of the default srandom() routine. + + +2.8) Deterministic behavior +--------------------------- + +When Scotch is compiled with the "-DCOMMON_RANDOM_FIXED_SEED" +flag set, multiple executions of the same sequential programs +will always yield the same results. Yet, non-deterministic +multi-threaded and/or parallel algorithms may still introduce +some variability in the produced results, due to operating system +artifacts. + +To ease the tracking down of bugs, it is possible to coerce Scotch to +exhibit a deterministic behavior by setting the +"-DSCOTCH_DETERMINISTIC" flag. This option makes sure that two +consecutive runs of Scotch on the same graph and same number of +processes and/or threads will always yield the same result. However, +it does not mean that two executions of Scotch on different numbers of +processes and/or threads will always yield the same result. Indeed, +changing the number of processes impacts graph data distribution and +consequently the order in which vertices are processed. Consequently, +coarsening algorithms are likely to produce different coarse graphs, +leading to different partitions. + +This option is likely to have adverse impact on performance, since all +non-deterministic multi-threaded algorithms will be disabled. In the +case of Scotch, the multi-threaded matching algorithm for coarsening +will be replaced by its sequential counterpart, whatever the available +number of threads is. In the case of PT-Scotch, point-to-point +messages will be received in a fixed order rather than being processed +on a first-come, first-serve basis. + +Setting this flag automatically results in setting the +"-DCOMMON_RANDOM_FIXED_SEED" flag. Users are also strongly advised to +compile without setting the "-DCOMMON_RANDOM_SYSTEM" flag, in order to +avoid any interference with third-party libraries that might use the +operating system pseudo-random generator. + + +2.9) Point-to-point or collective communications +------------------------------------------------ + +Since distributed graph vertices can have any initial distribution +across processes, communication rounds are likely to involve all of +the processes in an almost all-to-all scheme. In order to speed-up +running time, most of these communications are performed by means of +asynchronous sends and receives, which allows computations to overlap +with communications. However, for large numbers of processes, this can +lead to the saturation of the communication network of the target +parallel machine. To avoid this, communication consuming routines also +have a collective communication based version. The use of this version +is enabled by default, as it greatly improves scalability for large +numbers of processes. To disable it, set the "-DSCOTCH_PTOP" flag at +compile time. + + +2.10) MeTiS compatibility library +--------------------------------- + +In order to ease the adoption of Scotch/PT-Scotch by people who +already developed code based on the MeTiS/ParMeTiS interface, a MeTiS +V3 compatibility library is included in the Scotch package. It +provides stubs for the graph partitioning and ordering routines of +MeTiS/ParMeTiS, but not for the service routines that are comprised +in this package. Consequently, for people willing to use both +libraries, that is, experiment with the graph partitioning features of +Scotch while using the service routines of the genuine MeTiS package, +special measures have to be taken. + +A first solution can be to coerce the linker to pick partitioning +routines from the libscotch, and service routines from the +libmetis. This can be done by placing the library names in this +order as arguments to the linker command. Yet, some linkers may still +report an error, as some symbols are multiply defined. + +Alternately, the names of the compatibility routines can be changed so +as to avoid conflicts. When the "-DSCOTCH_METIS_PREFIX" flag is set at +compile time, all Scotch versions of the MeTiS routines are prefixed +with "SCOTCH_". Of course, this will require an equivalent change in +the user's application code. + +An advantage of the Scotch/PT-Scotch stubs over the genuine +MeTiS/ParMeTiS V3 routines is that they can be available in a 64-bit +version. In this case, all int's that were passed to MeTiS/ParMeTiS +routines must be replaced by 64-bit integer values (even the option +configuration values). However, in this case, one will not be able to +link against the service routines of the genuine MeTiS/ParMeTiS V3 +library, as the latter is only available as a 32-bit implementation. + + +3) Compilation +============== + +Once you have performed the configuration of the "Makefile.inc" file, +compile the Scotch distribution by typing "make scotch", or just +"make", in the current "src/" working directory. To compile the +PT-Scotch distribution, type "make ptscotch" in the same "src/" +directory. This can be done in any order. Typing "make scotch +ptscotch" to compile both is equivalent to typing "make ptscotch" +alone, since PT-Scotch requires Scotch. + +The most common problem you may encounter when trying to compile +PT-Scotch on a new platform relates to the "dummysizes" and +"ptdummysizes" executables. The purpose of these programs is to +determine, on the target platform, the sizes of the opaque data +structures of Scotch and PT-Scotch, respectively. They have to be +compiled and run before any library function can be compiled. The +sequential case poses no specific problems, as "dummysizes" is always +compiled with the same command as the one used to compile the +sequential Scotch package (hence, "CCD=$(CCS)" when executing "make +scotch"). In the parallel case, "ptdummysizes" has to take into +account the sizes of some MPI data structures, such as MPI_Comm, and +the most common way to have access to this information is to use some +flavor of MPI-aware compilers such as "mpicc" which automatically +refer to "mpi.h". Therefore, "CCD=mpicc" will work for most systems +and MPI implementations. Yet, on some platforms, programs compiled for +parallel execution cannot be run interactively. Moreover, +"ptdummysizes" itself does not contain any MPI calls, as it just wants +to know the sizes of the data structures, and the communication +susbystem of the platform may not want to run it. In any of these +cases, compilation will break. It is possible to solve this problem by +specifying, in the CCD variable of "Makefile.inc", how to compile +"ptdummysizes" sequentially but with knowledge of the location of the +"mpi.h" include file, for instance with the following line: "CCD = +my_sequential_cc -I/path/to/my/mpi/implementation/include/dir/". + +If no error occurs, all of the relevant header, library and executable +files will be created and copied to the "../include/", "../lib/" and +"../bin/" directories, relatively to your current "src/" working +directory. Headers, libraries and binaries of Scotch and PT-Scotch can +coexist in these directories without any interference. + +Then, typing "make install" will perform a GNU-like installation, with +header, library, binary and man files copied to the "include", "lib", +"bin" and "man" subdirectories of the path specified in the "prefix" +variable, which is set by default to "/usr/local". For instance, +typing "make prefix=/home/myself/usr/ install" will install the +Scotch/PT-Scotch files in a subtree of directory "/home/myself/usr/". + + +4) Checking +=========== + +A set of test programs is available in the "src/check" directory. They +serve as non-regression checks for both sequential and parallel +features of Scotch and PT-Scotch. They can be launched by typing "make +check" and/or "make ptcheck" in the "src/" directory. + +In the case of "ptcheck", programs will be run in debug mode; user +action is required (by typing ENTER whenever necessary) for launching +the parallel programs. + +One might look at these programs for examples of how to use the Scotch +and PT-Scotch libraries. However, some of these programs test internal +features, and interact with the library through non-standard and +non-documented procedures. It is therefore recommended NOT to imitate +these calling practices and rather to follow the guidelines provided in +the Scotch and PT-Scotch user manuals. + + +5) Use +====== + +Users willing to use the features of the sequential (but possibly +threaded) libScotch library have to include "scotch.h" and to link +against the "libscotch" library, plus an error handling package such +as "libscotcherr" or "libscotcherrexit". + +Users willing to use the features of the distributed-memory parallel +libPTScotch library have to include "ptscotch.h" (which itself +includes "scotch.h") and to link against both the "libptscotch" and +"libscotch" libraries (in this order whenever order is significant), +plus an error handling package such as "libptscotcherr" or +"libptscotcherrexit". + +In the case of complex programs, which may run as sequential programs +but may also call parallel routines, it is necessary to link only once +against a Scotch error handling routine, and this routine cannot call +MPI routines. Hence, the "libscotcherr" or "libscotcherrexit" +libraries must be used. This will not impact the behavior of the +parallel routines, but process numbers will not be displayed in case +of an error. + + +6) Documentation and use +======================== + +The Scotch and PT-Scotch user's manuals are available in the "doc/" +directory. They describe how to use the libscotch and libptscotch +libraries, as well as the standalone programs of the Scotch and +PT-Scotch distributions. + + +7) Note to packagers +==================== + +Since version 6.0, the Scotch and PT-Scotch packages can be made +independent. The libScotch will not be tied by any dependency against +any MPI package, while the libPTScotch has to depend on the one with +which it has been compiled, in addition to the libScotch package that +it uses. + +In versions 5.x, the libPTScotch also contained a modified copy of the +libScotch. It is no longer the case, which will result in lower disk +footprint. + +Regarding the use of threads, since Scotch is at the time being not +dynamically configurable, one has to decide whether to compile it with +threads enabled or not and, additionally, with which number of threads +it will run. Based on the current processor market, I recommend to +compile with -DSCOTCH_PTHREAD_NUMBER=2 (and, of course, +-DSCOTCH_PTHREAD_AFFINITY_LINUX whenever possible). The penalty for +single-thread CPUs will not be too high, while hyper-threaded and +many-core CPUs will benefit from the extra thread. diff --git a/scotch_6.0.3/LICENCE_fr.txt b/scotch_6.0.3/LICENCE_fr.txt new file mode 100644 index 00000000..963dd9ae --- /dev/null +++ b/scotch_6.0.3/LICENCE_fr.txt @@ -0,0 +1,7 @@ +Cette copie de la distribution logicielle Scotch 6.0 est distribuée +selon les termes de la licence de logiciel libre CeCILL-C. + +Une copie du texte de cette licence se trouve dans le sous-répertoire +"doc", dans le fichier appelé "CeCILL-C_V1-fr.txt". Veuillez en lire +attentivement les clauses. Vous ne pourrez utiliser cette copie de la +distribution logicielle Scotch 6.0 que si vous les acceptez. diff --git a/scotch_6.0.3/LICENSE_en.txt b/scotch_6.0.3/LICENSE_en.txt new file mode 100644 index 00000000..024da081 --- /dev/null +++ b/scotch_6.0.3/LICENSE_en.txt @@ -0,0 +1,6 @@ +This copy of the Scotch 6.0 distribution is licensed to you under the +terms of the CeCILL-C free/libre software license. + +A copy of this license is available in subdirectory "doc", in file +named "CeCILL-C_V1-en.txt". Please read its terms carefully. Only if +you accept them can you use this copy of the Scotch 6.0 distribution. diff --git a/scotch_6.0.3/LISEZ-MOI.txt b/scotch_6.0.3/LISEZ-MOI.txt new file mode 100644 index 00000000..d1a601d6 --- /dev/null +++ b/scotch_6.0.3/LISEZ-MOI.txt @@ -0,0 +1,8 @@ +Les clauses selon lesquelles cette copie de la distribution logicielle +Scotch 6.0 est mise à votre disposition sont définies dans le fichier +"LICENCE_fr.txt", situé dans le même répertoire que le présent +fichier. + +Si vous les acceptez, veuillez vous référer au fichier "INSTALL.txt", +également situé dans ce répertoire, pour consulter les instructions +d'installation. diff --git a/scotch_6.0.3/README.txt b/scotch_6.0.3/README.txt new file mode 100644 index 00000000..953e5a23 --- /dev/null +++ b/scotch_6.0.3/README.txt @@ -0,0 +1,6 @@ +The terms under which this copy of the Scotch 6.0 distribution +is provided to you are described in file "LICENSE_en.txt", located +in the same directory as this file. + +If you accept them, please refer to file "INSTALL.txt", also +located in this directory, for the installation instructions. diff --git a/scotch_6.0.3/doc/CeCILL-C_V1-en.txt b/scotch_6.0.3/doc/CeCILL-C_V1-en.txt new file mode 100644 index 00000000..3d2a8191 --- /dev/null +++ b/scotch_6.0.3/doc/CeCILL-C_V1-en.txt @@ -0,0 +1,517 @@ + +CeCILL-C FREE SOFTWARE LICENSE AGREEMENT + + + Notice + +This Agreement is a Free Software license agreement that is the result +of discussions between its authors in order to ensure compliance with +the two main principles guiding its drafting: + + * firstly, compliance with the principles governing the distribution + of Free Software: access to source code, broad rights granted to + users, + * secondly, the election of a governing law, French law, with which + it is conformant, both as regards the law of torts and + intellectual property law, and the protection that it offers to + both authors and holders of the economic rights over software. + +The authors of the CeCILL-C (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) +license are: + +Commissariat à l'Energie Atomique - CEA, a public scientific, technical +and industrial research establishment, having its principal place of +business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. + +Centre National de la Recherche Scientifique - CNRS, a public scientific +and technological establishment, having its principal place of business +at 3 rue Michel-Ange, 75794 Paris cedex 16, France. + +Institut National de Recherche en Informatique et en Automatique - +INRIA, a public scientific and technological establishment, having its +principal place of business at Domaine de Voluceau, Rocquencourt, BP +105, 78153 Le Chesnay cedex, France. + + + Preamble + +The purpose of this Free Software license agreement is to grant users +the right to modify and re-use the software governed by this license. + +The exercising of this right is conditional upon the obligation to make +available to the community the modifications made to the source code of +the software so as to contribute to its evolution. + +In consideration of access to the source code and the rights to copy, +modify and redistribute granted by the license, users are provided only +with a limited warranty and the software's author, the holder of the +economic rights, and the successive licensors only have limited liability. + +In this respect, the risks associated with loading, using, modifying +and/or developing or reproducing the software by the user are brought to +the user's attention, given its Free Software status, which may make it +complicated to use, with the result that its use is reserved for +developers and experienced professionals having in-depth computer +knowledge. Users are therefore encouraged to load and test the +suitability of the software as regards their requirements in conditions +enabling the security of their systems and/or data to be ensured and, +more generally, to use and operate it in the same conditions of +security. This Agreement may be freely reproduced and published, +provided it is not altered, and that no provisions are either added or +removed herefrom. + +This Agreement may apply to any or all software for which the holder of +the economic rights decides to submit the use thereof to its provisions. + + + Article 1 - DEFINITIONS + +For the purpose of this Agreement, when the following expressions +commence with a capital letter, they shall have the following meaning: + +Agreement: means this license agreement, and its possible subsequent +versions and annexes. + +Software: means the software in its Object Code and/or Source Code form +and, where applicable, its documentation, "as is" when the Licensee +accepts the Agreement. + +Initial Software: means the Software in its Source Code and possibly its +Object Code form and, where applicable, its documentation, "as is" when +it is first distributed under the terms and conditions of the Agreement. + +Modified Software: means the Software modified by at least one +Integrated Contribution. + +Source Code: means all the Software's instructions and program lines to +which access is required so as to modify the Software. + +Object Code: means the binary files originating from the compilation of +the Source Code. + +Holder: means the holder(s) of the economic rights over the Initial +Software. + +Licensee: means the Software user(s) having accepted the Agreement. + +Contributor: means a Licensee having made at least one Integrated +Contribution. + +Licensor: means the Holder, or any other individual or legal entity, who +distributes the Software under the Agreement. + +Integrated Contribution: means any or all modifications, corrections, +translations, adaptations and/or new functions integrated into the +Source Code by any or all Contributors. + +Related Module: means a set of sources files including their +documentation that, without modification to the Source Code, enables +supplementary functions or services in addition to those offered by the +Software. + +Derivative Software: means any combination of the Software, modified or +not, and of a Related Module. + +Parties: mean both the Licensee and the Licensor. + +These expressions may be used both in singular and plural form. + + + Article 2 - PURPOSE + +The purpose of the Agreement is the grant by the Licensor to the +Licensee of a non-exclusive, transferable and worldwide license for the +Software as set forth in Article 5 hereinafter for the whole term of the +protection granted by the rights over said Software. + + + Article 3 - ACCEPTANCE + +3.1 The Licensee shall be deemed as having accepted the terms and +conditions of this Agreement upon the occurrence of the first of the +following events: + + * (i) loading the Software by any or all means, notably, by + downloading from a remote server, or by loading from a physical + medium; + * (ii) the first time the Licensee exercises any of the rights + granted hereunder. + +3.2 One copy of the Agreement, containing a notice relating to the +characteristics of the Software, to the limited warranty, and to the +fact that its use is restricted to experienced users has been provided +to the Licensee prior to its acceptance as set forth in Article 3.1 +hereinabove, and the Licensee hereby acknowledges that it has read and +understood it. + + + Article 4 - EFFECTIVE DATE AND TERM + + + 4.1 EFFECTIVE DATE + +The Agreement shall become effective on the date when it is accepted by +the Licensee as set forth in Article 3.1. + + + 4.2 TERM + +The Agreement shall remain in force for the entire legal term of +protection of the economic rights over the Software. + + + Article 5 - SCOPE OF RIGHTS GRANTED + +The Licensor hereby grants to the Licensee, who accepts, the following +rights over the Software for any or all use, and for the term of the +Agreement, on the basis of the terms and conditions set forth hereinafter. + +Besides, if the Licensor owns or comes to own one or more patents +protecting all or part of the functions of the Software or of its +components, the Licensor undertakes not to enforce the rights granted by +these patents against successive Licensees using, exploiting or +modifying the Software. If these patents are transferred, the Licensor +undertakes to have the transferees subscribe to the obligations set +forth in this paragraph. + + + 5.1 RIGHT OF USE + +The Licensee is authorized to use the Software, without any limitation +as to its fields of application, with it being hereinafter specified +that this comprises: + + 1. permanent or temporary reproduction of all or part of the Software + by any or all means and in any or all form. + + 2. loading, displaying, running, or storing the Software on any or + all medium. + + 3. entitlement to observe, study or test its operation so as to + determine the ideas and principles behind any or all constituent + elements of said Software. This shall apply when the Licensee + carries out any or all loading, displaying, running, transmission + or storage operation as regards the Software, that it is entitled + to carry out hereunder. + + + 5.2 RIGHT OF MODIFICATION + +The right of modification includes the right to translate, adapt, +arrange, or make any or all modifications to the Software, and the right +to reproduce the resulting software. It includes, in particular, the +right to create a Derivative Software. + +The Licensee is authorized to make any or all modification to the +Software provided that it includes an explicit notice that it is the +author of said modification and indicates the date of the creation thereof. + + + 5.3 RIGHT OF DISTRIBUTION + +In particular, the right of distribution includes the right to publish, +transmit and communicate the Software to the general public on any or +all medium, and by any or all means, and the right to market, either in +consideration of a fee, or free of charge, one or more copies of the +Software by any means. + +The Licensee is further authorized to distribute copies of the modified +or unmodified Software to third parties according to the terms and +conditions set forth hereinafter. + + + 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION + +The Licensee is authorized to distribute true copies of the Software in +Source Code or Object Code form, provided that said distribution +complies with all the provisions of the Agreement and is accompanied by: + + 1. a copy of the Agreement, + + 2. a notice relating to the limitation of both the Licensor's + warranty and liability as set forth in Articles 8 and 9, + +and that, in the event that only the Object Code of the Software is +redistributed, the Licensee allows effective access to the full Source +Code of the Software at a minimum during the entire period of its +distribution of the Software, it being understood that the additional +cost of acquiring the Source Code shall not exceed the cost of +transferring the data. + + + 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE + +When the Licensee makes an Integrated Contribution to the Software, the +terms and conditions for the distribution of the resulting Modified +Software become subject to all the provisions of this Agreement. + +The Licensee is authorized to distribute the Modified Software, in +source code or object code form, provided that said distribution +complies with all the provisions of the Agreement and is accompanied by: + + 1. a copy of the Agreement, + + 2. a notice relating to the limitation of both the Licensor's + warranty and liability as set forth in Articles 8 and 9, + +and that, in the event that only the object code of the Modified +Software is redistributed, the Licensee allows effective access to the +full source code of the Modified Software at a minimum during the entire +period of its distribution of the Modified Software, it being understood +that the additional cost of acquiring the source code shall not exceed +the cost of transferring the data. + + + 5.3.3 DISTRIBUTION OF DERIVATIVE SOFTWARE + +When the Licensee creates Derivative Software, this Derivative Software +may be distributed under a license agreement other than this Agreement, +subject to compliance with the requirement to include a notice +concerning the rights over the Software as defined in Article 6.4. +In the event the creation of the Derivative Software required modification +of the Source Code, the Licensee undertakes that: + + 1. the resulting Modified Software will be governed by this Agreement, + 2. the Integrated Contributions in the resulting Modified Software + will be clearly identified and documented, + 3. the Licensee will allow effective access to the source code of the + Modified Software, at a minimum during the entire period of + distribution of the Derivative Software, such that such + modifications may be carried over in a subsequent version of the + Software; it being understood that the additional cost of + purchasing the source code of the Modified Software shall not + exceed the cost of transferring the data. + + + 5.3.4 COMPATIBILITY WITH THE CeCILL LICENSE + +When a Modified Software contains an Integrated Contribution subject to +the CeCILL license agreement, or when a Derivative Software contains a +Related Module subject to the CeCILL license agreement, the provisions +set forth in the third item of Article 6.4 are optional. + + + Article 6 - INTELLECTUAL PROPERTY + + + 6.1 OVER THE INITIAL SOFTWARE + +The Holder owns the economic rights over the Initial Software. Any or +all use of the Initial Software is subject to compliance with the terms +and conditions under which the Holder has elected to distribute its work +and no one shall be entitled to modify the terms and conditions for the +distribution of said Initial Software. + +The Holder undertakes that the Initial Software will remain ruled at +least by this Agreement, for the duration set forth in Article 4.2. + + + 6.2 OVER THE INTEGRATED CONTRIBUTIONS + +The Licensee who develops an Integrated Contribution is the owner of the +intellectual property rights over this Contribution as defined by +applicable law. + + + 6.3 OVER THE RELATED MODULES + +The Licensee who develops a Related Module is the owner of the +intellectual property rights over this Related Module as defined by +applicable law and is free to choose the type of agreement that shall +govern its distribution under the conditions defined in Article 5.3.3. + + + 6.4 NOTICE OF RIGHTS + +The Licensee expressly undertakes: + + 1. not to remove, or modify, in any manner, the intellectual property + notices attached to the Software; + + 2. to reproduce said notices, in an identical manner, in the copies + of the Software modified or not; + + 3. to ensure that use of the Software, its intellectual property + notices and the fact that it is governed by the Agreement is + indicated in a text that is easily accessible, specifically from + the interface of any Derivative Software. + +The Licensee undertakes not to directly or indirectly infringe the +intellectual property rights of the Holder and/or Contributors on the +Software and to take, where applicable, vis-à-vis its staff, any and all +measures required to ensure respect of said intellectual property rights +of the Holder and/or Contributors. + + + Article 7 - RELATED SERVICES + +7.1 Under no circumstances shall the Agreement oblige the Licensor to +provide technical assistance or maintenance services for the Software. + +However, the Licensor is entitled to offer this type of services. The +terms and conditions of such technical assistance, and/or such +maintenance, shall be set forth in a separate instrument. Only the +Licensor offering said maintenance and/or technical assistance services +shall incur liability therefor. + +7.2 Similarly, any Licensor is entitled to offer to its licensees, under +its sole responsibility, a warranty, that shall only be binding upon +itself, for the redistribution of the Software and/or the Modified +Software, under terms and conditions that it is free to decide. Said +warranty, and the financial terms and conditions of its application, +shall be subject of a separate instrument executed between the Licensor +and the Licensee. + + + Article 8 - LIABILITY + +8.1 Subject to the provisions of Article 8.2, the Licensee shall be +entitled to claim compensation for any direct loss it may have suffered +from the Software as a result of a fault on the part of the relevant +Licensor, subject to providing evidence thereof. + +8.2 The Licensor's liability is limited to the commitments made under +this Agreement and shall not be incurred as a result of in particular: +(i) loss due the Licensee's total or partial failure to fulfill its +obligations, (ii) direct or consequential loss that is suffered by the +Licensee due to the use or performance of the Software, and (iii) more +generally, any consequential loss. In particular the Parties expressly +agree that any or all pecuniary or business loss (i.e. loss of data, +loss of profits, operating loss, loss of customers or orders, +opportunity cost, any disturbance to business activities) or any or all +legal proceedings instituted against the Licensee by a third party, +shall constitute consequential loss and shall not provide entitlement to +any or all compensation from the Licensor. + + + Article 9 - WARRANTY + +9.1 The Licensee acknowledges that the scientific and technical +state-of-the-art when the Software was distributed did not enable all +possible uses to be tested and verified, nor for the presence of +possible defects to be detected. In this respect, the Licensee's +attention has been drawn to the risks associated with loading, using, +modifying and/or developing and reproducing the Software which are +reserved for experienced users. + +The Licensee shall be responsible for verifying, by any or all means, +the suitability of the product for its requirements, its good working +order, and for ensuring that it shall not cause damage to either persons +or properties. + +9.2 The Licensor hereby represents, in good faith, that it is entitled +to grant all the rights over the Software (including in particular the +rights set forth in Article 5). + +9.3 The Licensee acknowledges that the Software is supplied "as is" by +the Licensor without any other express or tacit warranty, other than +that provided for in Article 9.2 and, in particular, without any warranty +as to its commercial value, its secured, safe, innovative or relevant +nature. + +Specifically, the Licensor does not warrant that the Software is free +from any error, that it will operate without interruption, that it will +be compatible with the Licensee's own equipment and software +configuration, nor that it will meet the Licensee's requirements. + +9.4 The Licensor does not either expressly or tacitly warrant that the +Software does not infringe any third party intellectual property right +relating to a patent, software or any other property right. Therefore, +the Licensor disclaims any and all liability towards the Licensee +arising out of any or all proceedings for infringement that may be +instituted in respect of the use, modification and redistribution of the +Software. Nevertheless, should such proceedings be instituted against +the Licensee, the Licensor shall provide it with technical and legal +assistance for its defense. Such technical and legal assistance shall be +decided on a case-by-case basis between the relevant Licensor and the +Licensee pursuant to a memorandum of understanding. The Licensor +disclaims any and all liability as regards the Licensee's use of the +name of the Software. No warranty is given as regards the existence of +prior rights over the name of the Software or as regards the existence +of a trademark. + + + Article 10 - TERMINATION + +10.1 In the event of a breach by the Licensee of its obligations +hereunder, the Licensor may automatically terminate this Agreement +thirty (30) days after notice has been sent to the Licensee and has +remained ineffective. + +10.2 A Licensee whose Agreement is terminated shall no longer be +authorized to use, modify or distribute the Software. However, any +licenses that it may have granted prior to termination of the Agreement +shall remain valid subject to their having been granted in compliance +with the terms and conditions hereof. + + + Article 11 - MISCELLANEOUS + + + 11.1 EXCUSABLE EVENTS + +Neither Party shall be liable for any or all delay, or failure to +perform the Agreement, that may be attributable to an event of force +majeure, an act of God or an outside cause, such as defective +functioning or interruptions of the electricity or telecommunications +networks, network paralysis following a virus attack, intervention by +government authorities, natural disasters, water damage, earthquakes, +fire, explosions, strikes and labor unrest, war, etc. + +11.2 Any failure by either Party, on one or more occasions, to invoke +one or more of the provisions hereof, shall under no circumstances be +interpreted as being a waiver by the interested Party of its right to +invoke said provision(s) subsequently. + +11.3 The Agreement cancels and replaces any or all previous agreements, +whether written or oral, between the Parties and having the same +purpose, and constitutes the entirety of the agreement between said +Parties concerning said purpose. No supplement or modification to the +terms and conditions hereof shall be effective as between the Parties +unless it is made in writing and signed by their duly authorized +representatives. + +11.4 In the event that one or more of the provisions hereof were to +conflict with a current or future applicable act or legislative text, +said act or legislative text shall prevail, and the Parties shall make +the necessary amendments so as to comply with said act or legislative +text. All other provisions shall remain effective. Similarly, invalidity +of a provision of the Agreement, for any reason whatsoever, shall not +cause the Agreement as a whole to be invalid. + + + 11.5 LANGUAGE + +The Agreement is drafted in both French and English and both versions +are deemed authentic. + + + Article 12 - NEW VERSIONS OF THE AGREEMENT + +12.1 Any person is authorized to duplicate and distribute copies of this +Agreement. + +12.2 So as to ensure coherence, the wording of this Agreement is +protected and may only be modified by the authors of the License, who +reserve the right to periodically publish updates or new versions of the +Agreement, each with a separate number. These subsequent versions may +address new issues encountered by Free Software. + +12.3 Any Software distributed under a given version of the Agreement may +only be subsequently distributed under the same version of the Agreement +or a subsequent version. + + + Article 13 - GOVERNING LAW AND JURISDICTION + +13.1 The Agreement is governed by French law. The Parties agree to +endeavor to seek an amicable solution to any disagreements or disputes +that may arise during the performance of the Agreement. + +13.2 Failing an amicable solution within two (2) months as from their +occurrence, and unless emergency proceedings are necessary, the +disagreements or disputes shall be referred to the Paris Courts having +jurisdiction, by the more diligent Party. + + +Version 1.0 dated 2006-09-05. diff --git a/scotch_6.0.3/doc/CeCILL-C_V1-fr.txt b/scotch_6.0.3/doc/CeCILL-C_V1-fr.txt new file mode 100644 index 00000000..4fa44ba7 --- /dev/null +++ b/scotch_6.0.3/doc/CeCILL-C_V1-fr.txt @@ -0,0 +1,521 @@ + +CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-C + + + Avertissement + +Ce contrat est une licence de logiciel libre issue d'une concertation +entre ses auteurs afin que le respect de deux grands principes préside à +sa rédaction: + + * d'une part, le respect des principes de diffusion des logiciels + libres: accès au code source, droits étendus conférés aux + utilisateurs, + * d'autre part, la désignation d'un droit applicable, le droit + français, auquel elle est conforme, tant au regard du droit de la + responsabilité civile que du droit de la propriété intellectuelle + et de la protection qu'il offre aux auteurs et titulaires des + droits patrimoniaux sur un logiciel. + +Les auteurs de la licence CeCILL-C (pour Ce[a] C[nrs] I[nria] L[ogiciel] +L[ibre]) sont: + +Commissariat à l'Energie Atomique - CEA, établissement public de +recherche à caractère scientifique, technique et industriel, dont le +siège est situé 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris. + +Centre National de la Recherche Scientifique - CNRS, établissement +public à caractère scientifique et technologique, dont le siège est +situé 3 rue Michel-Ange, 75794 Paris cedex 16. + +Institut National de Recherche en Informatique et en Automatique - +INRIA, établissement public à caractère scientifique et technologique, +dont le siège est situé Domaine de Voluceau, Rocquencourt, BP 105, 78153 +Le Chesnay cedex. + + + Préambule + +Ce contrat est une licence de logiciel libre dont l'objectif est de +conférer aux utilisateurs la liberté de modifier et de réutiliser le +logiciel régi par cette licence. + +L'exercice de cette liberté est assorti d'une obligation de remettre à +la disposition de la communauté les modifications apportées au code +source du logiciel afin de contribuer à son évolution. + +L'accessibilité au code source et les droits de copie, de modification +et de redistribution qui découlent de ce contrat ont pour contrepartie +de n'offrir aux utilisateurs qu'une garantie limitée et de ne faire +peser sur l'auteur du logiciel, le titulaire des droits patrimoniaux et +les concédants successifs qu'une responsabilité restreinte. + +A cet égard l'attention de l'utilisateur est attirée sur les risques +associés au chargement, à l'utilisation, à la modification et/ou au +développement et à la reproduction du logiciel par l'utilisateur étant +donné sa spécificité de logiciel libre, qui peut le rendre complexe à +manipuler et qui le réserve donc à des développeurs ou des +professionnels avertis possédant des connaissances informatiques +approfondies. Les utilisateurs sont donc invités à charger et tester +l'adéquation du logiciel à leurs besoins dans des conditions permettant +d'assurer la sécurité de leurs systèmes et/ou de leurs données et, plus +généralement, à l'utiliser et l'exploiter dans les mêmes conditions de +sécurité. Ce contrat peut être reproduit et diffusé librement, sous +réserve de le conserver en l'état, sans ajout ni suppression de clauses. + +Ce contrat est susceptible de s'appliquer à tout logiciel dont le +titulaire des droits patrimoniaux décide de soumettre l'exploitation aux +dispositions qu'il contient. + + + Article 1 - DEFINITIONS + +Dans ce contrat, les termes suivants, lorsqu'ils seront écrits avec une +lettre capitale, auront la signification suivante: + +Contrat: désigne le présent contrat de licence, ses éventuelles versions +postérieures et annexes. + +Logiciel: désigne le logiciel sous sa forme de Code Objet et/ou de Code +Source et le cas échéant sa documentation, dans leur état au moment de +l'acceptation du Contrat par le Licencié. + +Logiciel Initial: désigne le Logiciel sous sa forme de Code Source et +éventuellement de Code Objet et le cas échéant sa documentation, dans +leur état au moment de leur première diffusion sous les termes du Contrat. + +Logiciel Modifié: désigne le Logiciel modifié par au moins une +Contribution Intégrée. + +Code Source: désigne l'ensemble des instructions et des lignes de +programme du Logiciel et auquel l'accès est nécessaire en vue de +modifier le Logiciel. + +Code Objet: désigne les fichiers binaires issus de la compilation du +Code Source. + +Titulaire: désigne le ou les détenteurs des droits patrimoniaux d'auteur +sur le Logiciel Initial. + +Licencié: désigne le ou les utilisateurs du Logiciel ayant accepté le +Contrat. + +Contributeur: désigne le Licencié auteur d'au moins une Contribution +Intégrée. + +Concédant: désigne le Titulaire ou toute personne physique ou morale +distribuant le Logiciel sous le Contrat. + +Contribution Intégrée: désigne l'ensemble des modifications, +corrections, traductions, adaptations et/ou nouvelles fonctionnalités +intégrées dans le Code Source par tout Contributeur. + +Module Lié: désigne un ensemble de fichiers sources y compris leur +documentation qui, sans modification du Code Source, permet de réaliser +des fonctionnalités ou services supplémentaires à ceux fournis par le +Logiciel. + +Logiciel Dérivé: désigne toute combinaison du Logiciel, modifié ou non, +et d'un Module Lié. + +Parties: désigne collectivement le Licencié et le Concédant. + +Ces termes s'entendent au singulier comme au pluriel. + + + Article 2 - OBJET + +Le Contrat a pour objet la concession par le Concédant au Licencié d'une +licence non exclusive, cessible et mondiale du Logiciel telle que +définie ci-après à l'article 5 pour toute la durée de protection des droits +portant sur ce Logiciel. + + + Article 3 - ACCEPTATION + +3.1 L'acceptation par le Licencié des termes du Contrat est réputée +acquise du fait du premier des faits suivants: + + * (i) le chargement du Logiciel par tout moyen notamment par + téléchargement à partir d'un serveur distant ou par chargement à + partir d'un support physique; + * (ii) le premier exercice par le Licencié de l'un quelconque des + droits concédés par le Contrat. + +3.2 Un exemplaire du Contrat, contenant notamment un avertissement +relatif aux spécificités du Logiciel, à la restriction de garantie et à +la limitation à un usage par des utilisateurs expérimentés a été mis à +disposition du Licencié préalablement à son acceptation telle que +définie à l'article 3.1 ci dessus et le Licencié reconnaît en avoir pris +connaissance. + + + Article 4 - ENTREE EN VIGUEUR ET DUREE + + + 4.1 ENTREE EN VIGUEUR + +Le Contrat entre en vigueur à la date de son acceptation par le Licencié +telle que définie en 3.1. + + + 4.2 DUREE + +Le Contrat produira ses effets pendant toute la durée légale de +protection des droits patrimoniaux portant sur le Logiciel. + + + Article 5 - ETENDUE DES DROITS CONCEDES + +Le Concédant concède au Licencié, qui accepte, les droits suivants sur +le Logiciel pour toutes destinations et pour la durée du Contrat dans +les conditions ci-après détaillées. + +Par ailleurs, si le Concédant détient ou venait à détenir un ou +plusieurs brevets d'invention protégeant tout ou partie des +fonctionnalités du Logiciel ou de ses composants, il s'engage à ne pas +opposer les éventuels droits conférés par ces brevets aux Licenciés +successifs qui utiliseraient, exploiteraient ou modifieraient le +Logiciel. En cas de cession de ces brevets, le Concédant s'engage à +faire reprendre les obligations du présent alinéa aux cessionnaires. + + + 5.1 DROIT D'UTILISATION + +Le Licencié est autorisé à utiliser le Logiciel, sans restriction quant +aux domaines d'application, étant ci-après précisé que cela comporte: + + 1. la reproduction permanente ou provisoire du Logiciel en tout ou + partie par tout moyen et sous toute forme. + + 2. le chargement, l'affichage, l'exécution, ou le stockage du + Logiciel sur tout support. + + 3. la possibilité d'en observer, d'en étudier, ou d'en tester le + fonctionnement afin de déterminer les idées et principes qui sont + à la base de n'importe quel élément de ce Logiciel; et ceci, + lorsque le Licencié effectue toute opération de chargement, + d'affichage, d'exécution, de transmission ou de stockage du + Logiciel qu'il est en droit d'effectuer en vertu du Contrat. + + + 5.2 DROIT DE MODIFICATION + +Le droit de modification comporte le droit de traduire, d'adapter, +d'arranger ou d'apporter toute autre modification au Logiciel et le +droit de reproduire le logiciel en résultant. Il comprend en particulier +le droit de créer un Logiciel Dérivé. + +Le Licencié est autorisé à apporter toute modification au Logiciel sous +réserve de mentionner, de façon explicite, son nom en tant qu'auteur de +cette modification et la date de création de celle-ci. + + + 5.3 DROIT DE DISTRIBUTION + +Le droit de distribution comporte notamment le droit de diffuser, de +transmettre et de communiquer le Logiciel au public sur tout support et +par tout moyen ainsi que le droit de mettre sur le marché à titre +onéreux ou gratuit, un ou des exemplaires du Logiciel par tout procédé. + +Le Licencié est autorisé à distribuer des copies du Logiciel, modifié ou +non, à des tiers dans les conditions ci-après détaillées. + + + 5.3.1 DISTRIBUTION DU LOGICIEL SANS MODIFICATION + +Le Licencié est autorisé à distribuer des copies conformes du Logiciel, +sous forme de Code Source ou de Code Objet, à condition que cette +distribution respecte les dispositions du Contrat dans leur totalité et +soit accompagnée: + + 1. d'un exemplaire du Contrat, + + 2. d'un avertissement relatif à la restriction de garantie et de + responsabilité du Concédant telle que prévue aux articles 8 + et 9, + +et que, dans le cas où seul le Code Objet du Logiciel est redistribué, +le Licencié permette un accès effectif au Code Source complet du +Logiciel pendant au moins toute la durée de sa distribution du Logiciel, +étant entendu que le coût additionnel d'acquisition du Code Source ne +devra pas excéder le simple coût de transfert des données. + + + 5.3.2 DISTRIBUTION DU LOGICIEL MODIFIE + +Lorsque le Licencié apporte une Contribution Intégrée au Logiciel, les +conditions de distribution du Logiciel Modifié en résultant sont alors +soumises à l'intégralité des dispositions du Contrat. + +Le Licencié est autorisé à distribuer le Logiciel Modifié sous forme de +code source ou de code objet, à condition que cette distribution +respecte les dispositions du Contrat dans leur totalité et soit +accompagnée: + + 1. d'un exemplaire du Contrat, + + 2. d'un avertissement relatif à la restriction de garantie et de + responsabilité du Concédant telle que prévue aux articles 8 + et 9, + +et que, dans le cas où seul le code objet du Logiciel Modifié est +redistribué, le Licencié permette un accès effectif à son code source +complet pendant au moins toute la durée de sa distribution du Logiciel +Modifié, étant entendu que le coût additionnel d'acquisition du code +source ne devra pas excéder le simple coût de transfert des données. + + + 5.3.3 DISTRIBUTION DU LOGICIEL DERIVE + +Lorsque le Licencié crée un Logiciel Dérivé, ce Logiciel Dérivé peut +être distribué sous un contrat de licence autre que le présent Contrat à +condition de respecter les obligations de mention des droits sur le +Logiciel telles que définies à l'article 6.4. Dans le cas où la création du +Logiciel Dérivé a nécessité une modification du Code Source le licencié +s'engage à ce que: + + 1. le Logiciel Modifié correspondant à cette modification soit régi + par le présent Contrat, + 2. les Contributions Intégrées dont le Logiciel Modifié résulte + soient clairement identifiées et documentées, + 3. le Licencié permette un accès effectif au code source du Logiciel + Modifié, pendant au moins toute la durée de la distribution du + Logiciel Dérivé, de telle sorte que ces modifications puissent + être reprises dans une version ultérieure du Logiciel, étant + entendu que le coût additionnel d'acquisition du code source du + Logiciel Modifié ne devra pas excéder le simple coût du transfert + des données. + + + 5.3.4 COMPATIBILITE AVEC LA LICENCE CeCILL + +Lorsqu'un Logiciel Modifié contient une Contribution Intégrée soumise au +contrat de licence CeCILL, ou lorsqu'un Logiciel Dérivé contient un +Module Lié soumis au contrat de licence CeCILL, les stipulations prévues +au troisième item de l'article 6.4 sont facultatives. + + + Article 6 - PROPRIETE INTELLECTUELLE + + + 6.1 SUR LE LOGICIEL INITIAL + +Le Titulaire est détenteur des droits patrimoniaux sur le Logiciel +Initial. Toute utilisation du Logiciel Initial est soumise au respect +des conditions dans lesquelles le Titulaire a choisi de diffuser son +oeuvre et nul autre n'a la faculté de modifier les conditions de +diffusion de ce Logiciel Initial. + +Le Titulaire s'engage à ce que le Logiciel Initial reste au moins régi +par le Contrat et ce, pour la durée visée à l'article 4.2. + + + 6.2 SUR LES CONTRIBUTIONS INTEGREES + +Le Licencié qui a développé une Contribution Intégrée est titulaire sur +celle-ci des droits de propriété intellectuelle dans les conditions +définies par la législation applicable. + + + 6.3 SUR LES MODULES LIES + +Le Licencié qui a développé un Module Lié est titulaire sur celui-ci des +droits de propriété intellectuelle dans les conditions définies par la +législation applicable et reste libre du choix du contrat régissant sa +diffusion dans les conditions définies à l'article 5.3.3. + + + 6.4 MENTIONS DES DROITS + +Le Licencié s'engage expressément: + + 1. à ne pas supprimer ou modifier de quelque manière que ce soit les + mentions de propriété intellectuelle apposées sur le Logiciel; + + 2. à reproduire à l'identique lesdites mentions de propriété + intellectuelle sur les copies du Logiciel modifié ou non; + + 3. à faire en sorte que l'utilisation du Logiciel, ses mentions de + propriété intellectuelle et le fait qu'il est régi par le Contrat + soient indiqués dans un texte facilement accessible notamment + depuis l'interface de tout Logiciel Dérivé. + +Le Licencié s'engage à ne pas porter atteinte, directement ou +indirectement, aux droits de propriété intellectuelle du Titulaire et/ou +des Contributeurs sur le Logiciel et à prendre, le cas échéant, à +l'égard de son personnel toutes les mesures nécessaires pour assurer le +respect des dits droits de propriété intellectuelle du Titulaire et/ou +des Contributeurs. + + + Article 7 - SERVICES ASSOCIES + +7.1 Le Contrat n'oblige en aucun cas le Concédant à la réalisation de +prestations d'assistance technique ou de maintenance du Logiciel. + +Cependant le Concédant reste libre de proposer ce type de services. Les +termes et conditions d'une telle assistance technique et/ou d'une telle +maintenance seront alors déterminés dans un acte séparé. Ces actes de +maintenance et/ou assistance technique n'engageront que la seule +responsabilité du Concédant qui les propose. + +7.2 De même, tout Concédant est libre de proposer, sous sa seule +responsabilité, à ses licenciés une garantie, qui n'engagera que lui, +lors de la redistribution du Logiciel et/ou du Logiciel Modifié et ce, +dans les conditions qu'il souhaite. Cette garantie et les modalités +financières de son application feront l'objet d'un acte séparé entre le +Concédant et le Licencié. + + + Article 8 - RESPONSABILITE + +8.1 Sous réserve des dispositions de l'article 8.2, le Licencié a la +faculté, sous réserve de prouver la faute du Concédant concerné, de +solliciter la réparation du préjudice direct qu'il subirait du fait du +Logiciel et dont il apportera la preuve. + +8.2 La responsabilité du Concédant est limitée aux engagements pris en +application du Contrat et ne saurait être engagée en raison notamment: +(i) des dommages dus à l'inexécution, totale ou partielle, de ses +obligations par le Licencié, (ii) des dommages directs ou indirects +découlant de l'utilisation ou des performances du Logiciel subis par le +Licencié et (iii) plus généralement d'un quelconque dommage indirect. En +particulier, les Parties conviennent expressément que tout préjudice +financier ou commercial (par exemple perte de données, perte de +bénéfices, perte d'exploitation, perte de clientèle ou de commandes, +manque à gagner, trouble commercial quelconque) ou toute action dirigée +contre le Licencié par un tiers, constitue un dommage indirect et +n'ouvre pas droit à réparation par le Concédant. + + + Article 9 - GARANTIE + +9.1 Le Licencié reconnaît que l'état actuel des connaissances +scientifiques et techniques au moment de la mise en circulation du +Logiciel ne permet pas d'en tester et d'en vérifier toutes les +utilisations ni de détecter l'existence d'éventuels défauts. L'attention +du Licencié a été attirée sur ce point sur les risques associés au +chargement, à l'utilisation, la modification et/ou au développement et à +la reproduction du Logiciel qui sont réservés à des utilisateurs avertis. + +Il relève de la responsabilité du Licencié de contrôler, par tous +moyens, l'adéquation du produit à ses besoins, son bon fonctionnement et +de s'assurer qu'il ne causera pas de dommages aux personnes et aux biens. + +9.2 Le Concédant déclare de bonne foi être en droit de concéder +l'ensemble des droits attachés au Logiciel (comprenant notamment les +droits visés à l'article 5). + +9.3 Le Licencié reconnaît que le Logiciel est fourni "en l'état" par le +Concédant sans autre garantie, expresse ou tacite, que celle prévue à +l'article 9.2 et notamment sans aucune garantie sur sa valeur commerciale, +son caractère sécurisé, innovant ou pertinent. + +En particulier, le Concédant ne garantit pas que le Logiciel est exempt +d'erreur, qu'il fonctionnera sans interruption, qu'il sera compatible +avec l'équipement du Licencié et sa configuration logicielle ni qu'il +remplira les besoins du Licencié. + +9.4 Le Concédant ne garantit pas, de manière expresse ou tacite, que le +Logiciel ne porte pas atteinte à un quelconque droit de propriété +intellectuelle d'un tiers portant sur un brevet, un logiciel ou sur tout +autre droit de propriété. Ainsi, le Concédant exclut toute garantie au +profit du Licencié contre les actions en contrefaçon qui pourraient être +diligentées au titre de l'utilisation, de la modification, et de la +redistribution du Logiciel. Néanmoins, si de telles actions sont +exercées contre le Licencié, le Concédant lui apportera son aide +technique et juridique pour sa défense. Cette aide technique et +juridique est déterminée au cas par cas entre le Concédant concerné et +le Licencié dans le cadre d'un protocole d'accord. Le Concédant dégage +toute responsabilité quant à l'utilisation de la dénomination du +Logiciel par le Licencié. Aucune garantie n'est apportée quant à +l'existence de droits antérieurs sur le nom du Logiciel et sur +l'existence d'une marque. + + + Article 10 - RESILIATION + +10.1 En cas de manquement par le Licencié aux obligations mises à sa +charge par le Contrat, le Concédant pourra résilier de plein droit le +Contrat trente (30) jours après notification adressée au Licencié et +restée sans effet. + +10.2 Le Licencié dont le Contrat est résilié n'est plus autorisé à +utiliser, modifier ou distribuer le Logiciel. Cependant, toutes les +licences qu'il aura concédées antérieurement à la résiliation du Contrat +resteront valides sous réserve qu'elles aient été effectuées en +conformité avec le Contrat. + + + Article 11 - DISPOSITIONS DIVERSES + + + 11.1 CAUSE EXTERIEURE + +Aucune des Parties ne sera responsable d'un retard ou d'une défaillance +d'exécution du Contrat qui serait dû à un cas de force majeure, un cas +fortuit ou une cause extérieure, telle que, notamment, le mauvais +fonctionnement ou les interruptions du réseau électrique ou de +télécommunication, la paralysie du réseau liée à une attaque +informatique, l'intervention des autorités gouvernementales, les +catastrophes naturelles, les dégâts des eaux, les tremblements de terre, +le feu, les explosions, les grèves et les conflits sociaux, l'état de +guerre... + +11.2 Le fait, par l'une ou l'autre des Parties, d'omettre en une ou +plusieurs occasions de se prévaloir d'une ou plusieurs dispositions du +Contrat, ne pourra en aucun cas impliquer renonciation par la Partie +intéressée à s'en prévaloir ultérieurement. + +11.3 Le Contrat annule et remplace toute convention antérieure, écrite +ou orale, entre les Parties sur le même objet et constitue l'accord +entier entre les Parties sur cet objet. Aucune addition ou modification +aux termes du Contrat n'aura d'effet à l'égard des Parties à moins +d'être faite par écrit et signée par leurs représentants dûment habilités. + +11.4 Dans l'hypothèse où une ou plusieurs des dispositions du Contrat +s'avèrerait contraire à une loi ou à un texte applicable, existants ou +futurs, cette loi ou ce texte prévaudrait, et les Parties feraient les +amendements nécessaires pour se conformer à cette loi ou à ce texte. +Toutes les autres dispositions resteront en vigueur. De même, la +nullité, pour quelque raison que ce soit, d'une des dispositions du +Contrat ne saurait entraîner la nullité de l'ensemble du Contrat. + + + 11.5 LANGUE + +Le Contrat est rédigé en langue française et en langue anglaise, ces +deux versions faisant également foi. + + + Article 12 - NOUVELLES VERSIONS DU CONTRAT + +12.1 Toute personne est autorisée à copier et distribuer des copies de +ce Contrat. + +12.2 Afin d'en préserver la cohérence, le texte du Contrat est protégé +et ne peut être modifié que par les auteurs de la licence, lesquels se +réservent le droit de publier périodiquement des mises à jour ou de +nouvelles versions du Contrat, qui posséderont chacune un numéro +distinct. Ces versions ultérieures seront susceptibles de prendre en +compte de nouvelles problématiques rencontrées par les logiciels libres. + +12.3 Tout Logiciel diffusé sous une version donnée du Contrat ne pourra +faire l'objet d'une diffusion ultérieure que sous la même version du +Contrat ou une version postérieure. + + + Article 13 - LOI APPLICABLE ET COMPETENCE TERRITORIALE + +13.1 Le Contrat est régi par la loi française. Les Parties conviennent +de tenter de régler à l'amiable les différends ou litiges qui +viendraient à se produire par suite ou à l'occasion du Contrat. + +13.2 A défaut d'accord amiable dans un délai de deux (2) mois à compter +de leur survenance et sauf situation relevant d'une procédure d'urgence, +les différends ou litiges seront portés par la Partie la plus diligente +devant les Tribunaux compétents de Paris. + + +Version 1.0 du 2006-09-05. diff --git a/scotch_6.0.3/doc/ptscotch_user6.0.pdf b/scotch_6.0.3/doc/ptscotch_user6.0.pdf new file mode 100644 index 00000000..e4712800 Binary files /dev/null and b/scotch_6.0.3/doc/ptscotch_user6.0.pdf differ diff --git a/scotch_6.0.3/doc/ptscotch_user6.0.ps.gz b/scotch_6.0.3/doc/ptscotch_user6.0.ps.gz new file mode 100644 index 00000000..24405981 Binary files /dev/null and b/scotch_6.0.3/doc/ptscotch_user6.0.ps.gz differ diff --git a/scotch_6.0.3/doc/scotch_example.f b/scotch_6.0.3/doc/scotch_example.f new file mode 100644 index 00000000..7c9fb3bd --- /dev/null +++ b/scotch_6.0.3/doc/scotch_example.f @@ -0,0 +1,121 @@ +************************************************************ +** ** +** NAME : scotch_example.f ** +** ** +** AUTHOR : Francois PELLEGRINI ** +** ** +** FUNCTION : FORTRAN testbed for the LibSCOTCH ** +** library routines. ** +** ** +** DATES : # Version 3.4 : from : 04 feb 2000 ** +** to 07 feb 2000 ** +** # Version 4.0 : from : 13 mar 2005 ** +** to 13 mar 2005 ** +** ** +*234567***************************************************** + + PROGRAM SCOTCH_TEST + IMPLICIT NONE + INCLUDE "scotchf.h" + DOUBLEPRECISION SCOTCHGRAPH (SCOTCH_GRAPHDIM) + INTEGER VERTNBR + DATA VERTNBR / 3 / + INTEGER EDGENBR + DATA EDGENBR / 4 / + INTEGER VERTTAB (4) + DATA VERTTAB / 1, 2, 4, 5 / + INTEGER EDGETAB (4) + DATA EDGETAB / 2, 1, 3, 2 / + INTEGER INDXTAB (1) + INTEGER IDXVERTNBR + INTEGER IDXVERTTABIDX, IDXVENDTABIDX + INTEGER IDXVELOTABIDX, IDXVLBLTABIDX + INTEGER IDXEDGENBR + INTEGER IDXEDGETABIDX, IDXEDLOTABIDX + INTEGER IDXBASEVAL, IDXFLAGVAL + INTEGER IERR + + PRINT *, 'Starting' + + CALL SCOTCHFGRAPHINIT (SCOTCHGRAPH (1), IERR) + IF (IERR .NE. 0) THEN + PRINT *, 'ERROR : MAIN : Cannot initialize graph' + STOP + ENDIF + + CALL SCOTCHFGRAPHBUILD (SCOTCHGRAPH (1), 1, VERTNBR, + * VERTTAB (1), VERTTAB (2), + * VERTTAB (1), VERTTAB (1), + * EDGENBR, + * EDGETAB (1), EDGETAB (1), IERR) + IF (IERR .NE. 0) THEN + PRINT *, 'ERROR : MAIN : Cannot build graph' + STOP + ENDIF + + CALL SCOTCHFGRAPHCHECK (SCOTCHGRAPH (1), IERR) + IF (IERR .NE. 0) THEN + PRINT *, 'ERROR : MAIN : Invalid check' + STOP + ENDIF + + PRINT *, 'Outputing original graph' + + CALL SCOTCHFGRAPHSAVE (SCOTCHGRAPH (1), 1, IERR) + IF (IERR .NE. 0) THEN + PRINT *, 'ERROR : MAIN : Invalid graph output' + STOP + ENDIF + + CALL SCOTCHFGRAPHDATA (SCOTCHGRAPH (1), INDXTAB (1), + * IDXBASEVAL, IDXVERTNBR, + * IDXVERTTABIDX, IDXVENDTABIDX, + * IDXVELOTABIDX, IDXVLBLTABIDX, + * IDXEDGENBR, + * IDXEDGETABIDX, IDXEDLOTABIDX, + * IDXFLAGVAL, IERR); + IF (IERR .NE. 0) THEN + PRINT *, 'ERROR : MAIN : Cannot get graph data' + STOP + ENDIF + + PRINT *, 'Number of vertices : ', IDXVERTNBR + PRINT *, 'Index of verttab : ', IDXVERTTABIDX + PRINT *, 'Index of vendtab : ', IDXVENDTABIDX + PRINT *, 'Index of velotab : ', IDXVELOTABIDX + PRINT *, 'Index of vlbltab : ', IDXVLBLTABIDX + PRINT *, 'Number of edges : ', IDXEDGENBR + PRINT *, 'Index of edgetab : ', IDXEDGETABIDX + PRINT *, 'Index of edlotab : ', IDXEDLOTABIDX + + PRINT *, 'Updating vertex and edge arrays' + INDXTAB (IDXVERTTABIDX + 1) = 3 + INDXTAB (IDXEDGETABIDX) = 2 + INDXTAB (IDXEDGETABIDX + 1) = 3 + INDXTAB (IDXEDGETABIDX + 2) = 1 + INDXTAB (IDXEDGETABIDX + 3) = 1 + + PRINT *, 'Outputting updated graph' + + CALL SCOTCHFGRAPHCHECK (SCOTCHGRAPH (1), IERR) + IF (IERR .NE. 0) THEN + PRINT *, 'ERROR : MAIN : Invalid check' + STOP + ENDIF + + CALL SCOTCHFGRAPHSAVE (SCOTCHGRAPH (1), 1, IERR) + IF (IERR .NE. 0) THEN + PRINT *, 'ERROR : MAIN : Invalid graph output' + STOP + ENDIF + + CALL SCOTCHFGRAPHEXIT (SCOTCHGRAPH (1), IERR) + IF (IERR .NE. 0) THEN + PRINT *, 'ERROR : MAIN : Cannot destroy graph' + STOP + ENDIF + + PRINT *, 'Test complete' + + RETURN + END diff --git a/scotch_6.0.3/doc/scotch_user6.0.pdf b/scotch_6.0.3/doc/scotch_user6.0.pdf new file mode 100644 index 00000000..c5d92cef Binary files /dev/null and b/scotch_6.0.3/doc/scotch_user6.0.pdf differ diff --git a/scotch_6.0.3/doc/scotch_user6.0.ps.gz b/scotch_6.0.3/doc/scotch_user6.0.ps.gz new file mode 100644 index 00000000..0dd54f3f Binary files /dev/null and b/scotch_6.0.3/doc/scotch_user6.0.ps.gz differ diff --git a/scotch_6.0.3/grf/3elt.grf.gz b/scotch_6.0.3/grf/3elt.grf.gz new file mode 100644 index 00000000..41ad935f Binary files /dev/null and b/scotch_6.0.3/grf/3elt.grf.gz differ diff --git a/scotch_6.0.3/grf/3elt.xyz.gz b/scotch_6.0.3/grf/3elt.xyz.gz new file mode 100644 index 00000000..f4081c5b Binary files /dev/null and b/scotch_6.0.3/grf/3elt.xyz.gz differ diff --git a/scotch_6.0.3/grf/4elt.grf.gz b/scotch_6.0.3/grf/4elt.grf.gz new file mode 100644 index 00000000..f63da9a6 Binary files /dev/null and b/scotch_6.0.3/grf/4elt.grf.gz differ diff --git a/scotch_6.0.3/grf/4elt.xyz.gz b/scotch_6.0.3/grf/4elt.xyz.gz new file mode 100644 index 00000000..989ef131 Binary files /dev/null and b/scotch_6.0.3/grf/4elt.xyz.gz differ diff --git a/scotch_6.0.3/grf/4elt2.grf.gz b/scotch_6.0.3/grf/4elt2.grf.gz new file mode 100644 index 00000000..251b35f6 Binary files /dev/null and b/scotch_6.0.3/grf/4elt2.grf.gz differ diff --git a/scotch_6.0.3/grf/4elt2.xyz.gz b/scotch_6.0.3/grf/4elt2.xyz.gz new file mode 100644 index 00000000..21fcc598 Binary files /dev/null and b/scotch_6.0.3/grf/4elt2.xyz.gz differ diff --git a/scotch_6.0.3/grf/bump.grf.gz b/scotch_6.0.3/grf/bump.grf.gz new file mode 100644 index 00000000..76c06fc6 Binary files /dev/null and b/scotch_6.0.3/grf/bump.grf.gz differ diff --git a/scotch_6.0.3/grf/bump.xyz.gz b/scotch_6.0.3/grf/bump.xyz.gz new file mode 100644 index 00000000..f3e1f038 Binary files /dev/null and b/scotch_6.0.3/grf/bump.xyz.gz differ diff --git a/scotch_6.0.3/man/man1/amk_ccc.1 b/scotch_6.0.3/man/man1/amk_ccc.1 new file mode 100644 index 00000000..aba79209 --- /dev/null +++ b/scotch_6.0.3/man/man1/amk_ccc.1 @@ -0,0 +1,107 @@ +." Text automatically generated by txt2man +.TH amk_ccc 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBamk_ccc, amk_fft2, amk_hy, amk_m2, amk_p2 \fP- create target architectures +\fB +.SH SYNOPSIS +.nf +.fam C +\fBamk_ccc\fP [\fIoptions\fP] \fIdim\fP [\fItfile\fP] +.PP +\fBamk_fft2\fP [\fIoptions\fP] \fIdim\fP [\fItfile\fP] +.PP +\fBamk_hy\fP [\fIoptions\fP] \fIdim\fP [\fItfile\fP] +.PP +\fBamk_m2\fP [\fIoptions\fP] \fIdimX\fP [\fIdimY\fP] [\fItfile\fP] +.PP +\fBamk_p2\fP [\fIoptions\fP] [\fIwght0\fP] [\fIwght1\fP] [\fItfile\fP] +.fam T +.fi +.SH DESCRIPTION +The amk_* programs create target architecture files for some common, +regular topologies. +.PP +\fBamk_ccc\fP creates a decomposition-defined cube-connected-cycle +topology of dimension \fIdim\fP. The decomposition is performed first by +bisection along the dimensions of the hypercube, then along the +remaining cycle graphs. +.PP +\fBamk_fft2\fP creates a decomposition-defined fast-Fourier-transform +topology of dimension \fIdim\fP. The decomposition is performed by +recursive bisection of the vertices, by descending dimension +(that is, bit number in the labeling of the vertices). +.PP +\fBamk_hy\fP creates a decomposition-defined hypercube topology of +dimension \fIdim\fP. The decomposition is performed by +recursive bisection of the vertices, by descending dimension +(that is, bit number in the labeling of the vertices). Save for +experimentation purposes, this program is deprecated, as the +algorithmically-defined 'hcub' target architecture is a more +convenient and efficient way to represent hypercube architectures. +.PP +\fBamk_m2\fP creates a decomposition-defined 2D regular grid topology of +dimensions \fIdimX\fP and \fIdimY\fP. The decomposition is performed by +recursive splitting along the dimensions, either by cutting the +longest one, or by one-way dissection, depending on the '\fB-m\fP' option +flag. Save for experimentation purposes, this program is deprecated, +as the algorithmically-defined 'mesh2D' and 'mesh3D' target +architectures are a more convenient and efficient way to represent +2D and 3D grid architectures. +.PP +\fBamk_p2\fP creates a weighted path graph topology comprising only two +vertices of weights \fIwght0\fP and \fIwght1\fP. This is just a helper program, +which builds a 'wcmplt' algorithmically-defined complete graph with +two vertices. It may be used to compute weighted bisections of a +graph. +.SH OPTIONS +.TP +.B +\fB-m\fP\fImeth\fP +For \fBamk_m2\fP only. Perform either recursive dissection or +one-way dissection, according to the given method flag: +.RS +.TP +.B +n +perform nested dissection (default). +.TP +.B +o +perform one-way dissection (cut across Y, then X). +.RE +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Create a cube-connected-cycle target architecture of dimension 4, +and save it to file 'ccc4.tgt'. +.PP +.nf +.fam C + $ amk_ccc 4 ccc4.tgt + +.fam T +.fi +Run gmap to compute a bisection, into two parts of respective weights +3 and 5, of graph 'brol.grf' and save the resulting mapping to +file 'brol.map'. The dash '-' standard file name is used so that the +target architecture description is read from the standard input, +through the pipe. +.PP +.nf +.fam C + $ amk_p2 3 5 | gmap brol.grf - brol.map + +.fam T +.fi +.SH SEE ALSO +\fBgmk_msh\fP(1), \fBgtst\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgout\fP(1), \fBamk_grf\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/amk_fft2.1 b/scotch_6.0.3/man/man1/amk_fft2.1 new file mode 100644 index 00000000..05ba3448 --- /dev/null +++ b/scotch_6.0.3/man/man1/amk_fft2.1 @@ -0,0 +1 @@ +.so man1/amk_ccc.1 diff --git a/scotch_6.0.3/man/man1/amk_hy.1 b/scotch_6.0.3/man/man1/amk_hy.1 new file mode 100644 index 00000000..05ba3448 --- /dev/null +++ b/scotch_6.0.3/man/man1/amk_hy.1 @@ -0,0 +1 @@ +.so man1/amk_ccc.1 diff --git a/scotch_6.0.3/man/man1/amk_m2.1 b/scotch_6.0.3/man/man1/amk_m2.1 new file mode 100644 index 00000000..05ba3448 --- /dev/null +++ b/scotch_6.0.3/man/man1/amk_m2.1 @@ -0,0 +1 @@ +.so man1/amk_ccc.1 diff --git a/scotch_6.0.3/man/man1/amk_p2.1 b/scotch_6.0.3/man/man1/amk_p2.1 new file mode 100644 index 00000000..05ba3448 --- /dev/null +++ b/scotch_6.0.3/man/man1/amk_p2.1 @@ -0,0 +1 @@ +.so man1/amk_ccc.1 diff --git a/scotch_6.0.3/man/man1/atst.1 b/scotch_6.0.3/man/man1/atst.1 new file mode 100644 index 00000000..9e7e5487 --- /dev/null +++ b/scotch_6.0.3/man/man1/atst.1 @@ -0,0 +1,56 @@ +." Text automatically generated by txt2man +.TH atst 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBatst \fP- test the consistency of target architectures +\fB +.SH SYNOPSIS +.nf +.fam C +\fBatst\fP [\fIoptions\fP] [\fIafile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBatst\fP program checks the consistency of a Scotch +decomposition-defined target architecture and, in case of success, +outputs some statistics regarding the number of target vertices and +the length of paths linking them. Target architectures define the +topology of the target graphs used by static mapping programs +\fBgmap\fP(1) and \fBdgmap\fP(1). +.PP +The resulting statistics are stored in file \fIlfile\fP. When file names +are not specified, data is read from standard input and written to +standard output. Standard streams can also be explicitly represented +by a dash '-'. +.PP +When the proper libraries have been included at compile time, \fBatst\fP +can directly handle compressed files, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.tgt.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Test the consistency of architecture arch.tgt: +.PP +.nf +.fam C + $ atst arch.tgt + +.fam T +.fi +.SH SEE ALSO +\fBamk_grf\fP(1), \fBamk_ccc\fP(1), \fBamk_fft2\fP(1), \fBamk_hy\fP(1), \fBamk_m2\fP(1), +\fBamk_p2\fP(1), \fBgmap\fP(1), \fBdgmap\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/dgmap.1 b/scotch_6.0.3/man/man1/dgmap.1 new file mode 100644 index 00000000..e9a41779 --- /dev/null +++ b/scotch_6.0.3/man/man1/dgmap.1 @@ -0,0 +1,141 @@ +." Text automatically generated by txt2man +.TH dgmap 1 "August 03, 2010" "" "PT-Scotch user's manual" +.SH NAME +\fBdgmap, dgpart \fP- compute static mappings and partitions in parallel +\fB +.SH SYNOPSIS +.nf +.fam C +\fBdgmap\fP [\fIoptions\fP] [\fIgfile\fP] [\fItfile\fP] [\fImfile\fP] [\fIlfile\fP] +.PP +\fBdgpart\fP [\fIoptions\fP] [\fInparts\fP] [\fIgfile\fP] [\fImfile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBdgmap\fP program computes, in a parallel way, a static mapping of a +source graph onto a target graph. +.PP +The \fBdgpart\fP program is a shortcut of \fBdgmap\fP for computing partitions +of a source graph. +.PP +Source graph file \fIgfile\fP is either a centralized graph file, or a set +of files representing fragments of a distributed graph. For \fBdgmap\fP, +the target architecture file \fItfile\fP describes either algorithmically-coded +topologies such as meshes and hypercubes, or decomposition-defined +architectures created by means of the \fBamk_grf\fP(1) program. See +\fBgmap\fP(1) for a description of target architectures. The resulting +mapping is stored in file \fImfile\fP. Eventual logging information (such +as the one produced by option \fB-v\fP) is sent to file \fIlfile\fP. When file +names are not specified, data is read from standard input and +written to standard output. Standard streams can also be explicitely +represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, \fBdgmap\fP +and \fBdgpart\fP can directly handle compressed graphs, both as input and +output. A stream is treated as compressed whenever its name is +postfixed with a compressed file extension, such as +in 'brol.grf.bz2' or '-.gz'. The compression formats which can be +supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), +and the lzma format ('.lzma', on input only). +.PP +\fBdgmap\fP and \fBdgpart\fP base on implementations of the MPI interface to +spread work across the processing elements. They are therefore not +likely to be run directly, but instead through some launcher command +such as \fBmpirun\fP. +.SH OPTIONS +.TP +.B +\fB-c\fPopt +Choose default mapping strategy according to one or +several \fIoptions\fP among: +.RS +.TP +.B +b +enforce load balance as much as possible. +.TP +.B +q +privilege quality over speed (default). +.TP +.B +s +privilege speed over quality. +.TP +.B +t +enforce safety. +.TP +.B +x +enforce scalability. +.RE +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-m\fP\fIstrat\fP +Use parallel mapping strategy \fIstrat\fP (see +PT-Scotch user's manual for more information). +.TP +.B +\fB-r\fP\fIpnum\fP +Set root process for centralized files (default is 0). +.TP +.B +\fB-V\fP +Display program version and copyright. +.TP +.B +\fB-v\fP\fIverb\fP +Set verbose mode to \fIverb\fP. It is a set of one of more +characters which can be: +.RS +.TP +.B +m +mapping information. +.TP +.B +s +strategy information. +.TP +.B +t +timing information. +.SH NOTE +At the time being (version 5.1.0), \fBdgmap\fP cannot compute full static +mappings as \fBgmap\fP(1) does, but only partitions (that is, mappings +onto unweighted or weighted complete graphs). Target architectures +other than the 'cmplt' and 'wcmplt' ones will lead to an error +message. +.SH EXAMPLES +Run \fBdgpart\fP on 5 processing elements to compute a partition into 7 +parts of graph brol.grf and save the resulting ordering to file brol.map. +.PP +.nf +.fam C + $ mpirun -np 5 dgpart 7 brol.grf brol.map + +.fam T +.fi +Run \fBdgpart\fP on 5 processing elements to partition into 7 parts the +distributed graph stored on graph fragment files brol5-0.dgr to +brol5-4.dgr, and save the resulting mapping to file brol.map (see +\fBdgscat\fP(1) for an explanation of the '%p' and '%r' sequences in names +of distributed graph fragments). +.PP +.nf +.fam C + $ mpirun -np 5 dgpart 7 brol%p-%r.dgr brol.map + +.fam T +.fi +.SH SEE ALSO +\fBdgtst\fP(1), \fBdgscat\fP(1), \fBamk_grf\fP(1), \fBacpl\fP(1), \fBgmap\fP(1), \fBgmtst\fP(1). +.PP +PT-Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/dgord.1 b/scotch_6.0.3/man/man1/dgord.1 new file mode 100644 index 00000000..a18bfe8d --- /dev/null +++ b/scotch_6.0.3/man/man1/dgord.1 @@ -0,0 +1,138 @@ +." Text automatically generated by txt2man +.TH dgord 1 "August 03, 2010" "" "PT-Scotch user's manual" +.SH NAME +\fBdgord \fP- compute sparse matrix orderings of graphs in parallel +\fB +.SH SYNOPSIS +.nf +.fam C +\fBdgord\fP [\fIoptions\fP] [\fIgfile\fP] [\fIofile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBdgord\fP program computes, in a parallel way, an ordering of a +Scotch source graph representing the pattern of some symmetric +sparse matrix. +.PP +Source graph file \fIgfile\fP is either a centralized graph file, or a set +of files representing fragments of a distributed graph. The resulting +ordering is stored in file \fIofile\fP. Eventual logging information (such +as the one produced by option \fB-v\fP) is sent to file \fIlfile\fP. When file +names are not specified, data is read from standard input and +written to standard output. Standard streams can also be explicitely +represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, \fBdgord\fP +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.PP +\fBdgord\fP bases on implementations of the MPI interface to spread work +across the processing elements. It is therefore not likely to be run +directly, but instead through some launcher command such as \fBmpirun\fP. +.SH OPTIONS +.TP +.B +\fB-c\fPopt +Choose default ordering strategy according to one or +several \fIoptions\fP among: +.RS +.TP +.B +b +enforce load balance as much as possible. +.TP +.B +q +privilege quality over speed (default). +.TP +.B +s +privilege speed over quality. +.TP +.B +t +enforce safety. +.TP +.B +x +enforce scalability. +.RE +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-m\fP\fImfile\fP +Save column block mapping data to file \fImfile\fP. Mapping +data specifies, for each vertex, the index of the column +block to which this vertex belongs. +.TP +.B +\fB-o\fP\fIstrat\fP +Use parallel graph ordering strategy \fIstrat\fP (see +PT-Scotch user's manual for more information). +.TP +.B +\fB-r\fP\fIpnum\fP +Set root process for centralized files (default is 0). +.TP +.B +\fB-t\fP\fItfile\fP +Save partitioning tree data to file \fItfile\fP. Partitioning +tree data specifies, for each vertex, the index of the +first vertex of the parent block of the block to which +the vertex belongs. Altogether with the mapping data +provided in file \fImfile\fP, it allows one to rebuild the +separator tree of the nested dissection process. +.TP +.B +\fB-V\fP +Display program version and copyright. +.TP +.B +\fB-v\fP\fIverb\fP +Set verbose mode to \fIverb\fP. It is a set of one of more +characters which can be: +.RS +.TP +.B +s +strategy information. +.TP +.B +t +timing information. +.SH EXAMPLES +Run \fBdgord\fP on 5 processing elements to reorder matrix graph brol.grf +and save the resulting ordering to file brol.ord, using the default +sequential graph ordering strategy: +.PP +.nf +.fam C + $ mpirun -np 5 dgord brol.grf brol.ord + +.fam T +.fi +Run \fBdgord\fP on 5 processing elements to reorder the distributed matrix +stored on graph fragment files brol5-0.dgr to brol5-4.dgr, and save +the resulting ordering to file brol.ord (see \fBdgscat\fP(1) for an +explanation of the '%p' and '%r' sequences in names of distributed +graph fragments). +.PP +.nf +.fam C + $ mpirun -np 5 dgord brol%p-%r.dgr brol.ord + +.fam T +.fi +.SH SEE ALSO +\fBdgtst\fP(1), \fBdgscat\fP(1), \fBgmk_hy\fP(1), \fBgord\fP(1). +.PP +PT-Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/dgpart.1 b/scotch_6.0.3/man/man1/dgpart.1 new file mode 100644 index 00000000..05001ace --- /dev/null +++ b/scotch_6.0.3/man/man1/dgpart.1 @@ -0,0 +1 @@ +.so man1/dgmap.1 diff --git a/scotch_6.0.3/man/man1/dgscat.1 b/scotch_6.0.3/man/man1/dgscat.1 new file mode 100644 index 00000000..cf86c312 --- /dev/null +++ b/scotch_6.0.3/man/man1/dgscat.1 @@ -0,0 +1,117 @@ +." Text automatically generated by txt2man +.TH dgscat 1 "August 03, 2010" "" "PT-Scotch user's manual" +.SH NAME +\fBdgscat \fP- build distributed source graph file fragments from a centralized source graph file +\fB +.SH SYNOPSIS +.nf +.fam C +\fBdgscat\fP [\fIoptions\fP] [\fIigfile\fP] [\fIogfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBdgscat\fP program reads a centralized source graph \fIigfile\fP and +writes it back on the form of a set of files \fIogfile\fP representing +fragments of a distributed source graph. +.PP +When file names are not specified, data is read from standard input +and written to standard output. Standard streams can also be +explicitly represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, dgord +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.PP +dgord bases on implementations of the MPI interface to spread work +across the processing elements. It is therefore not likely to be run +directly, but instead through some launcher command such as \fBmpirun\fP. +.SH DISTRIBUTED FILE NAMES +In order to tell whether programs should read from, or write to, a +single file located on only one processor, or to multiple instances +of the same file on all of the processors, or else to distinct files +on each of the processors, a special grammar has been designed, +which is based on the '%' escape character. Four such escape +sequences are defined, which are interpreted independently on every +processor, prior to file opening. By default, when a filename is +provided, it is assumed that the file is to be opened on only one of +the processors, called the root processor, which is usually process +0 of the communicator within which the program is run. The index +of the root processor can be changed by means of the \fB-r\fP +option. Using any of the first three escape sequences below will +instruct programs to open in parallel a file of name equal to the +interpreted filename, on every processor on which they are run. +.TP +.B +%p +Replaced by the number of processes in the global communicator in +which the program is run. Leads to parallel opening. +.TP +.B +%r +Replaced on each process running the program by the rank of this +process in the global communicator. Leads to parallel opening. +.TP +.B +%- +Discarded, but leads to parallel opening. This sequence is mainly +used to instruct programs to open on every processor a file of +identical name. The opened files can be, according whether the +given path leads to a shared directory or to directories that +are local to each processor, either to the opening of multiple +instances of the same file, or to the opening of distinct files +which may each have a different content, respectively (but in +this latter case it is much recommended to identify files by +means of the '%r' sequence). +.TP +.B +%% +Replaced by a single '%' character. File names using this escape +sequence are not considered for parallel opening, unless one or +several of the three other escape sequences are also present. +.RE +.PP +For instance, filename 'brol' will lead to the opening of file 'brol' +on the root processor only, filename '%\fB-brol\fP' (or even 'br%\fB-ol\fP') will +lead to the parallel opening of files called 'brol' on every +processor, and filename 'brol%p-%r' will lead to the opening of files +'brol2-0' and 'brol2-1', respectively, on each of the two processors +on which the program were to run. +.SH OPTIONS +.TP +.B +\fB-c\fP +Check the consistency of the input source graph after +loading it into memory. +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-r\fP\fIpnum\fP +Set root process for centralized files (default is 0). +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Run \fBdgscat\fP on 5 processing elements to scatter centralized graph +file brol.grf into 5 gzipped file fragments brol5-0.dgr.gz to +brol5-4.dgr.gz. +.PP +.nf +.fam C + $ mpirun -np 5 dgscat brol.grf brol%p-%r.dgr.gz + +.fam T +.fi +.SH SEE ALSO +\fBdgtst\fP(1), \fBdgord\fP(1), \fBgmk_hy\fP(1). +.PP +PT-Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/dgtst.1 b/scotch_6.0.3/man/man1/dgtst.1 new file mode 100644 index 00000000..7089e41b --- /dev/null +++ b/scotch_6.0.3/man/man1/dgtst.1 @@ -0,0 +1,78 @@ +." Text automatically generated by txt2man +.TH dgtst 1 "August 03, 2010" "" "PT-Scotch user's manual" +.SH NAME +\fBdgtst \fP- test the consistency of source graphs in parallel +\fB +.SH SYNOPSIS +.nf +.fam C +\fBdgtst\fP [\fIoptions\fP] [\fIgfile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBdgtst\fP program checks, in a parallel way, the consistency of a +Scotch source graph and, in case of success, outputs some statistics +regarding edge weights, vertex weights, and vertex degrees. +.PP +It produces the very same results as the \fBgtst\fP(1) program of the +Scotch sequential distribution, but unlike this latter it can handle +distributed graphs. +.PP +Source graph file \fIgfile\fP is either a centralized graph file, or a set +of files representing fragments of a distributed graph. The +resulting statistics are stored in file \fIlfile\fP. When file names are +not specified, data is read from standard input and written to +standard output. Standard streams can also be explicitly +represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, \fBdgtst\fP +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.PP +\fBdgtst\fP bases on implementations of the MPI interface to spread work +across the processing elements. It is therefore not likely to be run +directly, but instead through some launcher command such as \fBmpirun\fP. +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-r\fP\fIpnum\fP +Set root process for centralized files (default is 0). +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Run \fBdgtst\fP on 5 processing elements to test the consistency of graph brol.grf +.PP +.nf +.fam C + $ mpirun -np 5 dgtst brol.grf + +.fam T +.fi +Run dgord on 5 processing elements to test the consistency of a +distributed graph stored on graph fragment files brol5-0.dgr to +brol5-4.dgr, and save the resulting ordering to file brol.ord (see +\fBdgscat\fP(1) for an explanation of the '%p' and '%r' sequences in names +of distributed graph fragments). +.PP +.nf +.fam C + $ mpirun -np 5 dgtst brol%p-%r.dgr brol.ord + +.fam T +.fi +.SH SEE ALSO +\fBdgscat\fP(1), \fBgtst\fP(1), \fBdgord\fP(1). +.PP +PT-Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gcv.1 b/scotch_6.0.3/man/man1/gcv.1 new file mode 100644 index 00000000..d8b161b1 --- /dev/null +++ b/scotch_6.0.3/man/man1/gcv.1 @@ -0,0 +1,106 @@ +." Text automatically generated by txt2man +.TH gcv 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgcv \fP- graph file converter +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgcv\fP [\fIoptions\fP] [\fIigfile\fP] [\fIogfile\fP] [\fIoxfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBgcv\fP program converts Scotch graph files from and to other +external file formats. +.PP +File \fIigfile\fP is converted into graph file \fIogfile\fP, with optional +geometry data being put in geometry file \fIoxfile\fP, if it is +available. +.PP +When file names are not specified, data is read from standard input +and written to standard output. Standard streams can also be +explicitly represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, dgtst +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-i\fP\fIifmt\fP +Set format of input graph file, which can be: +.RS +.TP +.B +b\fInum\fP +Boeing-Harwell format. This is a matrix format. +Only square matrices are supported. Square matrices +with unsymmetric pattern are symmetrized. In +case the file contains several matrices, the \fInum\fP +parameter allow the user to provide the index of +the matrix to convert, starting from 0. When the \fInum\fP +parameter is not set, it is assumed to be 0. +.TP +.B +c +Chaco format. This is an adjacency graph +format, also used by MeTiS. +.TP +.B +m +Matrix Market format. This is a matrix format +describing individual edges. Matrix pattern is +symmetrized, such that rectangular matrices are +eventually squared. +.TP +.B +s +Scotch graph format. This is an adjacency graph format. +.RE +.TP +.B +\fB-o\fP\fIofmt\fP +Set format of output graph file, which can be: +.RS +.TP +.B +c +Chaco format. +.TP +.B +m +Matrix Market symmetric pattern format. +.TP +.B +s +Scotch format. This is the default. +.RE +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Convert a Matrix Market graph into a Scotch graph. Matrix Market +files do not comprise geometry data, so no geometry file is needed +on output: +.PP +.nf +.fam C + $ gcv -im brol.mm brol.grf + +.fam T +.fi +.SH SEE ALSO +\fBgtst\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgout\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gmap.1 b/scotch_6.0.3/man/man1/gmap.1 new file mode 100644 index 00000000..c0796dc7 --- /dev/null +++ b/scotch_6.0.3/man/man1/gmap.1 @@ -0,0 +1,180 @@ +." Text automatically generated by txt2man +.TH gmap 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgmap, gpart \fP- compute static mappings and partitions sequentially +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgmap\fP [\fIoptions\fP] [\fIgfile\fP] [\fItfile\fP] [\fImfile\fP] [\fIlfile\fP] +.PP +\fBgpart\fP [\fIoptions\fP] [\fInparts\fP] [\fIgfile\fP] [\fImfile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBgmap\fP program computes, in a sequential way, a static mapping of a +source graph onto a target graph. +.PP +The \fBgpart\fP program is a shortcut of \fBgmap\fP for computing unweighted +partitions of a source graph. +.PP +Source graph file \fIgfile\fP can only be a centralized graph file. For \fBgmap\fP, +the target architecture file \fItfile\fP describes either algorithmically-coded +topologies such as meshes and hypercubes, or decomposition-defined +architectures created by means of the \fBamk_grf\fP(1) program. The resulting +mapping is stored in file \fImfile\fP. Eventual logging information (such +as the one produced by option \fB-v\fP) is sent to file \fIlfile\fP. When file +names are not specified, data is read from standard input and +written to standard output. Standard streams can also be explicitely +represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, \fBgmap\fP +and \fBgpart\fP can directly handle compressed graphs, both as input and +output. A stream is treated as compressed whenever its name is +postfixed with a compressed file extension, such as +in 'brol.grf.bz2' or '-.gz'. The compression formats which can be +supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), +and the lzma format ('.lzma', on input only). +.SH OPTIONS +.TP +.B +\fB-c\fPopt +Choose default mapping strategy according to one or +several \fIoptions\fP among: +.RS +.TP +.B +b +enforce load balance as much as possible. +.TP +.B +q +privilege quality over speed (default). +.TP +.B +s +privilege speed over quality. +.TP +.B +t +enforce safety. +.RE +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-m\fPstrat +Use sequential mapping strategy strat (see +Scotch user's manual for more information). +.TP +.B +\fB-V\fP +Display program version and copyright. +.TP +.B +\fB-v\fPverb +Set verbose mode to verb. It is a set of one of more +characters which can be: +.RS +.TP +.B +m +mapping information. +.TP +.B +s +strategy information. +.TP +.B +t +timing information. +.SH TARGET ARCHITECTURES +Target architectures represent graphs onto which source graphs are +mapped. In order to speed-up the obtainment of target architecture +topological properties during the computation of mappings, some +classical topologies are algorithmically coded into the mapper +itself. These topologies are consequently simply defined by their +code name, followed by their dimensional parameters: +.TP +.B +cmplt \fIdim\fP +unweighted complete graph of size \fIdim\fP. +.TP +.B +cmpltw \fIdim\fP \fIw0\fP \fIw1\fP \.\.\. \fIwdim-1\fP +weighted complete graph of size +size and of respective loads +\fIw0\fP, \fIw1\fP, \.\.\., \fIwdim-1\fP. +.TP +.B +hcub \fIdim\fP +hypercube of dimension \fIdim\fP. +.TP +.B +leaf \fIhgt\fP \fIn0\fP \fIw0\fP \.\.\. \fInhgt-1\fP \fIwhgt-1\fP +tree-leaf graph of height \fIhgt\fP +with (\fIn0\fP times \fIn1\fP times \.\.\. \fInhgt-1\fP) +vertices, with inter-cluster link +weights of \fIw0\fP, \fIw1\fP, \.\.\. \fIwhgt-1\fP. +.TP +.B +mesh2D \fIdimX\fP \fIdimY\fP +2D mesh of \fIdimX\fP times \fIdimY\fP nodes. +.TP +.B +mesh3D \fIdimX\fP \fIdimY\fP \fIdimZ\fP +23 mesh of \fIdimX\fP times \fIdimY\fP times \fIdimZ\fP nodes. +.TP +.B +torus2D \fIdimX\fP \fIdimY\fP +2D torus of \fIdimX\fP times \fIdimY\fP nodes. +.TP +.B +torus3D \fIdimX\fP \fIdimY\fP \fIdimZ\fP +3D torus of \fIdimX\fP times \fIdimY\fP times \fIdimZ\fP nodes. +.PP +Other target topologies can be created from their source graph +description by using the \fBamk_grf\fP(1) command. In this case, the +target description will begin with the code name \fBdeco\fP. +.SH MAPPINGS +Mappings are represented by as many lines as there are vertices in +the source graph. Each of these lines is made of two figures: the +number of the vertex (or its label if source graph vertices are +labeled) and the index of the target vertex to which it has been +assigned. Target vertex indices range from 0 to the number of +vertices in the target architecture (that is, the number of parts) +minus one. +.PP +This block of lines is always preceded by the number of such +lines. In most cases, since full mappings are requested, the number +of lines is equal to the number of vertices in the source graph. +.SH EXAMPLES +Run \fBgpart\fP to compute a partition into 7 parts of graph 'brol.grf' and +save the resulting ordering to file 'brol.map'. +.PP +.nf +.fam C + $ gpart 7 brol.grf brol.map + +.fam T +.fi +Run \fBgmap\fP to compute a partition, into 3 parts of respective weights +1, 2 and 4, of graph 'brol.grf' and save the resulting mapping to +file 'brol.map'. The dash '-' standard file name is used so that the +target architecture description is read from the standard input, +through the pipe, as provided by the 'echo' shell command. +.PP +.nf +.fam C + $ echo "cmpltw 3 1 2 4" | gmap brol.grf - brol.map + +.fam T +.fi +.SH SEE ALSO +\fBamk_grf\fP(1), \fBacpl\fP(1), \fBgmtst\fP(1), \fBdgmap\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gmk_hy.1 b/scotch_6.0.3/man/man1/gmk_hy.1 new file mode 100644 index 00000000..7fd6658c --- /dev/null +++ b/scotch_6.0.3/man/man1/gmk_hy.1 @@ -0,0 +1,74 @@ +." Text automatically generated by txt2man +.TH gmk_hy 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgmk_hy, gmk_m2, gmk_m3, gmk_ub2 \fP- create source graphs +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgmk_hy\fP [\fIoptions\fP] \fIdim\fP [\fIofile\fP] +.PP +\fBgmk_m2\fP [\fIoptions\fP] [\fB-g\fP\fIcfile\fP] \fIdimX\fP \fIdimY\fP [\fIofile\fP] +.PP +\fBgmk_m3\fP [\fIoptions\fP] [\fB-g\fP\fIcfile\fP] \fIdimX\fP \fIdimY\fP \fIdimZ\fP [\fIofile\fP] +.PP +\fBgmk_ub2\fP [\fIoptions\fP] \fIdim\fP +.fam T +.fi +.SH DESCRIPTION +The \fBgmk_\fP* programs create source graph files for some common, +regular topologies. +.PP +\fBgmk_hy\fP creates a hypercube of dimension \fIdim\fP. +.PP +\fBgmk_m2\fP creates a 2D regular grid of dimensions \fIdimX\fP and \fIdimY\fP. +.PP +\fBgmk_m3\fP creates a 3D regular grid of dimensions \fIdimX\fP, \fIdimY\fP and \fIdimZ\fP. +.PP +\fBgmk_ub2\fP creates an unoriented de Bruijn graph of dimension \fIdim\fP. +.SH OPTIONS +.TP +.B +\fB-b\fP base +For \fBgmk_m2\fP and \fBgmk_m3\fP only. Output graphs with base +value set to base. Default value is 0. +.TP +.B +\fB-e\fP +For \fBgmk_m2\fP only. Build a 8-neighbor grid rather than a +4-neighbor grid. +.TP +.B +\fB-g\fP\fIcfile\fP +For \fBgmk_m2\fP and \fBgmk_m3\fP only. Output graph vertex +coordinates (that is, geometry data to be used by +\fBgout\fP(1)) in file \fIcfile\fP. +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-t\fP +For \fBgmk_m2\fP and \fBgmk_m3\fP only. Create torus graphs, that +is, graphs such that there exist loop edges between +vertices of rank 0 and (\fIdim\fP-1) in every dimension. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Create a 5x7 grid along with its geometry: +.PP +.nf +.fam C + $ gmk_m2 5 7 -g/tmp/m5x7.xyz /tmp/m5x7.grf + +.fam T +.fi +.SH SEE ALSO +\fBgmk_msh\fP(1), \fBgtst\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgout\fP(1), \fBamk_grf\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gmk_m2.1 b/scotch_6.0.3/man/man1/gmk_m2.1 new file mode 100644 index 00000000..46d5f00e --- /dev/null +++ b/scotch_6.0.3/man/man1/gmk_m2.1 @@ -0,0 +1 @@ +.so man1/gmk_hy.1 diff --git a/scotch_6.0.3/man/man1/gmk_m3.1 b/scotch_6.0.3/man/man1/gmk_m3.1 new file mode 100644 index 00000000..46d5f00e --- /dev/null +++ b/scotch_6.0.3/man/man1/gmk_m3.1 @@ -0,0 +1 @@ +.so man1/gmk_hy.1 diff --git a/scotch_6.0.3/man/man1/gmk_msh.1 b/scotch_6.0.3/man/man1/gmk_msh.1 new file mode 100644 index 00000000..89ce8ca1 --- /dev/null +++ b/scotch_6.0.3/man/man1/gmk_msh.1 @@ -0,0 +1,41 @@ +." Text automatically generated by txt2man +.TH gmk_msh 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgmk_msh \fP- create source graph from source mesh +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgmk_msh\fP [\fIoptions\fP] [\fImfile\fP] [\fIgfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBgmk_msh\fP program creates a source graph from a source mesh. +The vertices of the graph are the nodes of the mesh, and all mesh +elements are turned into cliques, that is, there exists an edge +between two vertices in the graph if there exists at least an +element in the mesh which comprises the two associated nodes. +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Create a source graph brol.grf from a source mesh brol.msh: +.PP +.nf +.fam C + $ gmk_msh brol.msh brol.grf + +.fam T +.fi +.SH SEE ALSO +dgmap (1), \fBdgord\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgtst\fP(1), \fBmmk_m2\fP(1), \fBmord\fP(1), \fBmcv\fP(1), \fBmtst\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gmk_ub2.1 b/scotch_6.0.3/man/man1/gmk_ub2.1 new file mode 100644 index 00000000..46d5f00e --- /dev/null +++ b/scotch_6.0.3/man/man1/gmk_ub2.1 @@ -0,0 +1 @@ +.so man1/gmk_hy.1 diff --git a/scotch_6.0.3/man/man1/gmtst.1 b/scotch_6.0.3/man/man1/gmtst.1 new file mode 100644 index 00000000..dcce7a2e --- /dev/null +++ b/scotch_6.0.3/man/man1/gmtst.1 @@ -0,0 +1,72 @@ +." Text automatically generated by txt2man +.TH gmtst 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgmtst \fP- compute statistics on mappings +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgmtst\fP [\fIoptions\fP] [\fIgfile\fP] [\fItfile\fP] [\fImfile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBgmtst\fP program computes, in a sequential way, statistics on a +static mapping, such as load imbalance ratio, edge dilation +distribution, etc. It yields the same results as the ones produced +by the \fB-vm\fP option of the \fBgmap\fP(1) program. +.PP +Source graph file \fIgfile\fP can only be a centralized graph file. File +\fItfile\fP represents the target architecture onto which \fIgfile\fP was +mapped. If mapping file \fImfile\fP was produced by \fBgpart\fP(1), the target +architecture file to provide \fBgmtst\fP should describe a complete graph +with the same number of vertices as the requested number of parts, +for instance by means of the '\fBcmplt\fP \fInum\fP' algorithmically-described +architecture. The resulting statistics are stored in file +\fIlfile\fP. When file names are not specified, data is read from standard +input and written to standard output. Standard streams can also be +explicitly represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, gtst +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLES +Display statistics on mapping brol.map of graph brol.grf onto target +architecture brol.tgt: +.PP +.nf +.fam C + $ gmtst brol.grf brol.tgt brol.map + +.fam T +.fi +Display statistics on partitioning brol.map of graph brol.grf into +\fInum\fP parts. Note the use of the complete graph +algorithmically-described architecture and of the shell pipe command +to provide the complete target architecture description on the +standard input of the \fBgmtst\fP command: +.PP +.nf +.fam C + $ echo "cmplt num" | gmtst brol.grf - brol.map + +.fam T +.fi +.SH SEE ALSO +\fBgmap\fP(1), \fBgout\fP(1), \fBgtst\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gord.1 b/scotch_6.0.3/man/man1/gord.1 new file mode 100644 index 00000000..b8cba699 --- /dev/null +++ b/scotch_6.0.3/man/man1/gord.1 @@ -0,0 +1,112 @@ +." Text automatically generated by txt2man +.TH gord 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgord \fP- compute sparse matrix orderings of graphs +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgord\fP [\fIoptions\fP] [\fIgfile\fP] [\fIofile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBgord\fP program computes, in a sequential way, an ordering of a +Scotch source graph representing the pattern of some symmetric +sparse matrix. +.PP +Source graph file \fIgfile\fP can only be a centralized graph file. The +resulting ordering is stored in file \fIofile\fP. Eventual logging +information (such as the one produced by option \fB-v\fP) is sent to file +\fIlfile\fP. When file names are not specified, data is read from standard +input and written to standard output. Standard streams can also be +explicitely represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, \fBgord\fP +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.SH OPTIONS +.TP +.B +\fB-c\fPopt +Choose default ordering strategy according to one or +several \fIoptions\fP among: +.RS +.TP +.B +b +enforce load balance as much as possible. +.TP +.B +q +privilege quality over speed (default). +.TP +.B +s +privilege speed over quality. +.TP +.B +t +enforce safety. +.RE +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-m\fP\fImfile\fP +Save column block mapping data to file \fImfile\fP. Mapping +data specifies, for each vertex, the index of the column +block to which this vertex belongs. +.TP +.B +\fB-o\fP\fIstrat\fP +Use sequential graph ordering strategy \fIstrat\fP (see +Scotch user's manual for more information). +.TP +.B +\fB-t\fP\fItfile\fP +Save partitioning tree data to file \fItfile\fP. Partitioning +tree data specifies, for each vertex, the index of the +first vertex of the parent block of the block to which +the vertex belongs. Altogether with the mapping data +provided in file \fImfile\fP, it allows one to rebuild the +separator tree of the nested dissection process. +.TP +.B +\fB-V\fP +Display program version and copyright. +.TP +.B +\fB-v\fP\fIverb\fP +Set verbose mode to \fIverb\fP. It is a set of one of more +characters which can be: +.RS +.TP +.B +s +strategy information. +.TP +.B +t +timing information. +.SH EXAMPLE +Reorder matrix graph brol.grf and save the resulting ordering to +file brol.ord using the default sequential graph ordering strategy: +.PP +.nf +.fam C + $ gord brol.grf brol.ord + +.fam T +.fi +.SH SEE ALSO +\fBdgord\fP(1), \fBgmk_hy\fP(1), \fBgtst\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gotst.1 b/scotch_6.0.3/man/man1/gotst.1 new file mode 100644 index 00000000..f3e01ad6 --- /dev/null +++ b/scotch_6.0.3/man/man1/gotst.1 @@ -0,0 +1,60 @@ +." Text automatically generated by txt2man +.TH gotst 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgomtst \fP- compute statistics on sparse matrix orderings +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgotst\fP [\fIoptions\fP] [\fIgfile\fP] [\fIofile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBgotst\fP program computes, in a sequential way, statistics on a +sparse matrix ordering, such as fill-in, operation count, and +separator tree parameters: minimum, maximum, average height and +variance of its leaves. +.PP +Source graph file \fIgfile\fP can only be a centralized graph file. File +\fIofile\fP represents the ordering of the symmetric sparse matrix the +pattern of which is represented by \fIgfile\fP. The resulting statistics +are stored in file \fIlfile\fP. When file names are not specified, data is +read from standard input and written to standard output. Standard +streams can also be explicitly represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, gtst +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.PP +Since \fBgotst\fP performs sequentially the symbolic factorization of +matrix \fIgfile\fP in order to compute fill-in and operation count +numbers, this program can take a long time or even run out of memory, +when applied to very large graphs. +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Display statistics on ordering brol.ord of graph brol.grf: +.PP +.nf +.fam C + $ gotst brol.grf brol.ord + +.fam T +.fi +.SH SEE ALSO +\fBgord\fP(1), \fBgtst\fP(1), \fBdgord\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gout.1 b/scotch_6.0.3/man/man1/gout.1 new file mode 100644 index 00000000..cf535079 --- /dev/null +++ b/scotch_6.0.3/man/man1/gout.1 @@ -0,0 +1,268 @@ +." Text automatically generated by txt2man +.TH gout 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgout \fP- output graphics from matrices and graphs +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgout\fP [\fIoptions\fP] [\fIgfile\fP] [\fIxfile\fP] [\fImfile\fP] [\fIvfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBgout\fP program creates graphics files of various types, +representing the Scotch graph and mapping data which is passed to it. +.PP +Source graph file \fIgfile\fP can only be a centralized graph file. File +\fIxfile\fP stores its associated geometry, whenever necessary. File +\fImfile\fP represents label information attached to each of the graph +vertices, for instance the index of the part to which each vertex +belongs in the case of a mapping file. File \fIvfile\fP is the output +graphics file, the type of which may differ according to the input +parameters. When file names are not specified, data is read from +standard input and written to standard output. Standard streams can +also be explicitly represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, gtst +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-g\fP\fIgeop\fP +Geometry parameters, which can be an arbitrary +combination of any of the following code letters: +.RS +.TP +.B +n +Do not read geometry data, when it is not +available or not required, such as when using +the \fB-om\fP option. +.TP +.B +p +Permute Y and Z geometry dimensions. +.TP +.B +r +Rotate geometry by 90 degrees in the (X,Y) plane. +.RE +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-mn\fP +Do not read mapping data, when it is not available or +not required. +.TP +.B +\fB-o\fP\fIoutp\fP +Select the output file type and allows to provide +additional parameters between braces and separated +by commas: +.RS +.TP +.B +i +OpenInventor 3D mesh file, to be viewed by means of +programs such as \fBivview\fP. Additional parameters for +this output file type are: +.RS +.TP +.B +c +Color output. +.TP +.B +g +Gray level output. +.TP +.B +r +Remove cut edges. +.TP +.B +v +View cut edges. +.RE +.TP +.B +m +PostScript matrix pattern file. Additional parameters +for this output file type are: +.RS +.TP +.B +e +EPSF-type output. +.TP +.B +f +Full-page output. +.RE +.TP +.B +p +PostScript 2D mesh file. This output module was +intended for 2D meshes; as a fallback, the Z +coordinate is projected according to isometric +perspective rules, but drawings of full 3D objects +are most likely to be unreadable. Additional parameters +for this output file type are: +.RS +.TP +.B +c +Color output. +.TP +.B +g +Gray level output. +.TP +.B +e +EPSF-type output. +.TP +.B +f +Full-page output. +.TP +.B +s +Short clipping (disks excluded). +.TP +.B +l +Large clipping (disks included). +.TP +.B +a +Avoid displaying disks. +.TP +.B +d +Display disks. +.TP +.B +r +Remove cut edges. +.TP +.B +v +View cut edges. +.TP +.B +X=\fIrat\fP +Maximum x clipping ratio (in [0.0;1.0]). +.TP +.B +x=\fIrat\fP +Minimum x clipping ratio. +.TP +.B +Y=\fIrat\fP +Maximum y clipping ratio. +.TP +.B +y=\fIrat\fP +Minimum y clipping ratio. +.RE +.TP +.B +t +Tulip 3D mesh file. Additional parameters +for this output file type are: +.RS +.TP +.B +b +Black and white output. +.TP +.B +c +Color output. +.TP +.B +a +Avoid displaying disks. +.TP +.B +d +Display disks. +.TP +.B +r +Remove cut edges. +.TP +.B +v +View cut edges. +.RE +.RE +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLES +Build an OpenInventor file of the mapping of graph brol.grf +contained in file brol.map. Vertices with no mapping information +attached to them will be rendered in white, while distinct colors +will be used to represent the different parts. Cut edges will be +removed: +.PP +.nf +.fam C + $ gout '-oi{r}' brol.grf brol.xyz brol.map brol.iv + $ ivview brol.iv + +.fam T +.fi +Build an OpenInventor file of graph brol.grf without any vertex +information associated to it. Mapping data are not required and +will not be read, but a file name has to be provided, hence the +'-': +.PP +.nf +.fam C + $ gout -oi -mn brol.grf brol.xyz - brol.iv + +.fam T +.fi +Output the pattern of matrix brol.grf on the form of a PostScript +flat drawing. Geometry and mapping data are not required and will +not be read, but file names have to be provided, hence the +two '-'s: +.PP +.nf +.fam C + $ gout -om -gn -mn brol.grf - - brol.ps + +.fam T +.fi +Output a PostScript 2D drawing of a rectangular portion graph +brol.grf, with disks representing mapping data: +.PP +.nf +.fam C + $ gout '-op{c,e,d,x=0.3,X=0.6,y=0.2,Y=0.5}' brol.grf brol.xyz brol.map brol.ps + + +.fam T +.fi +.SH SEE ALSO +\fBgmap\fP(1), \fBgout\fP(1), \fBgtst\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/gpart.1 b/scotch_6.0.3/man/man1/gpart.1 new file mode 100644 index 00000000..ca006864 --- /dev/null +++ b/scotch_6.0.3/man/man1/gpart.1 @@ -0,0 +1 @@ +.so man1/gmap.1 diff --git a/scotch_6.0.3/man/man1/gtst.1 b/scotch_6.0.3/man/man1/gtst.1 new file mode 100644 index 00000000..8ba655a1 --- /dev/null +++ b/scotch_6.0.3/man/man1/gtst.1 @@ -0,0 +1,57 @@ +." Text automatically generated by txt2man +.TH gtst 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBgtst \fP- test the consistency of source graphs +\fB +.SH SYNOPSIS +.nf +.fam C +\fBgtst\fP [\fIoptions\fP] [\fIgfile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBgtst\fP program checks, in a sequential way, the consistency of a +Scotch source graph and, in case of success, outputs some statistics +regarding edge weights, vertex weights, and vertex degrees. +.PP +It produces the very same results as the \fBdgtst\fP(1) program of the +PT-Scotch parallel distribution, but unlike this latter it cannot +handle distributed graphs. +.PP +Source graph file \fIgfile\fP can only be a centralized graph file. The +resulting statistics are stored in file \fIlfile\fP. When file names are +not specified, data is read from standard input and written to +standard output. Standard streams can also be explicitly +represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, \fBgtst\fP +can directly handle compressed graphs, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Test the consistency of graph brol.grf: +.PP +.nf +.fam C + $ gtst brol.grf + +.fam T +.fi +.SH SEE ALSO +\fBdgtst\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgout\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/mmk_m2.1 b/scotch_6.0.3/man/man1/mmk_m2.1 new file mode 100644 index 00000000..b9491ae5 --- /dev/null +++ b/scotch_6.0.3/man/man1/mmk_m2.1 @@ -0,0 +1,55 @@ +." Text automatically generated by txt2man +.TH mmk_m2 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBmmk_m2, mmk_m3 \fP- create source meshes +\fB +.SH SYNOPSIS +.nf +.fam C +\fBmmk_m2\fP [\fIoptions\fP] [\fB-g\fP\fIcfile\fP] \fIdimX\fP \fIdimY\fP [\fIofile\fP] +.PP +\fBmmk_m3\fP [\fIoptions\fP] [\fB-g\fP\fIcfile\fP] \fIdimX\fP \fIdimY\fP \fIdimZ\fP [\fIofile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBmmk_\fP* programs create source mesh files for some common, +regular topologies. +.PP +\fBmmk_m2\fP creates a 2D regular mesh of \fIdimX\fP times \fIdimY\fP elements and +(\fIdimX\fP+1) times (\fIdimY\fP+1) nodes, such that element (i,j) is +connected to nodes (i,j), (i,j+1), (i+1,j) and (i+1,j+1). +.PP +\fBmmk_m3\fP creates a 3D regular mesh of \fIdimX\fP times \fIdimY\fP times \fIdimZ\fP +elements and (\fIdimX\fP+1) times (\fIdimY\fP+1) times (\fIdimZ\fP+1) nodes, +such that element (i,j,k) is connected to nodes (i,j,k), (i,j,k+1), +(i,j+1,k), (i,j+1,k+1), (i+1,j,k), (i+1,j,k+1), (i+1,j+1,k) and +(i+1,j+1,k+1). +.SH OPTIONS +.TP +.B +\fB-g\fP\fIcfile\fP +Output graph vertex coordinates (that is, geometry data to be used by +\fBgout\fP(1)) in file \fIcfile\fP. +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Create a mesh of 5x7 elements, along with its geometry: +.PP +.nf +.fam C + $ mmk_m2 5 7 -g/tmp/m5x7.xyz /tmp/m5x7.msh + +.fam T +.fi +.SH SEE ALSO +\fBmord\fP(1), \fBmtst\fP(1), \fBgmk_msh\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/mmk_m3.1 b/scotch_6.0.3/man/man1/mmk_m3.1 new file mode 100644 index 00000000..5ec3b0be --- /dev/null +++ b/scotch_6.0.3/man/man1/mmk_m3.1 @@ -0,0 +1 @@ +.so man1/mmk_m2.1 diff --git a/scotch_6.0.3/man/man1/mord.1 b/scotch_6.0.3/man/man1/mord.1 new file mode 100644 index 00000000..54a9552d --- /dev/null +++ b/scotch_6.0.3/man/man1/mord.1 @@ -0,0 +1,115 @@ +." Text automatically generated by txt2man +.TH mord 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBmord \fP- compute sparse matrix orderings of meshes +\fB +.SH SYNOPSIS +.nf +.fam C +\fBmord\fP [\fIoptions\fP] [\fImfile\fP] [\fIofile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBmord\fP program computes, in a sequential way, an ordering of a +Scotch source mesh representing the pattern of some symmetric sparse +matrix. Only nodes of the mesh are effectively ordered. Elements +provide connectivity information, such that every node is considered +to be linked to all of the nodes which share at least an element +with it. +.PP +Source mesh file \fImfile\fP can only be a centralized mesh file. The +resulting ordering is stored in file \fIofile\fP. Eventual logging +information (such as the one produced by option \fB-v\fP) is sent to file +\fIlfile\fP. When file names are not specified, data is read from standard +input and written to standard output. Standard streams can also be +explicitely represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, gord +can directly handle compressed meshes, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.msh.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.SH OPTIONS +.TP +.B +\fB-c\fPopt +Choose default ordering strategy according to one or +several \fIoptions\fP among: +.RS +.TP +.B +b +enforce load balance as much as possible. +.TP +.B +q +privilege quality over speed (default). +.TP +.B +s +privilege speed over quality. +.TP +.B +t +enforce safety. +.RE +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-m\fP\fImfile\fP +Save column block mapping data to file \fImfile\fP. Mapping data +specifies, for each node vertex, the index of the column +block to which this node vertex belongs. +.TP +.B +\fB-o\fP\fIstrat\fP +Use sequential mesh ordering strategy \fIstrat\fP (see +Scotch user's manual for more information). +.TP +.B +\fB-t\fP\fItfile\fP +Save partitioning tree data to file \fItfile\fP. Partitioning +tree data specifies, for each node vertex, the index of the +first node vertex of the parent block of the block to which +the node vertex belongs. Altogether with the mapping data +provided in file \fImfile\fP, it allows one to rebuild the +separator tree of the nested dissection process. +.TP +.B +\fB-V\fP +Display program version and copyright. +.TP +.B +\fB-v\fP\fIverb\fP +Set verbose mode to \fIverb\fP. It is a set of one of more +characters which can be: +.RS +.TP +.B +s +strategy information. +.TP +.B +t +timing information. +.SH EXAMPLE +Reorder matrix mesh brol.msh and save the resulting ordering to +file brol.ord using the default sequential mesh ordering strategy: +.PP +.nf +.fam C + $ mord brol.msh brol.ord + +.fam T +.fi +.SH SEE ALSO +\fBgmk_msh\fP(1), \fBgotst\fP(1), \fBmtst\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/man/man1/mtst.1 b/scotch_6.0.3/man/man1/mtst.1 new file mode 100644 index 00000000..d1d18eb2 --- /dev/null +++ b/scotch_6.0.3/man/man1/mtst.1 @@ -0,0 +1,54 @@ +." Text automatically generated by txt2man +.TH mtst 1 "August 03, 2010" "" "Scotch user's manual" +.SH NAME +\fBmtst \fP- test the consistency of source meshes +\fB +.SH SYNOPSIS +.nf +.fam C +\fBmtst\fP [\fIoptions\fP] [\fImfile\fP] [\fIlfile\fP] +.fam T +.fi +.SH DESCRIPTION +The \fBmtst\fP program checks, in a sequential way, the consistency of a +Scotch source mesh and, in case of success, outputs some statistics +regarding edge weights, node and element vertex weights, and node +and element vertex degrees. +.PP +Source mesh file \fImfile\fP can only be a centralized mesh file. The +resulting statistics are stored in file \fIlfile\fP. When file names are +not specified, data is read from standard input and written to +standard output. Standard streams can also be explicitly +represented by a dash '-'. +.PP +When the proper libraries have been included at compile time, \fBmtst\fP +can directly handle compressed meshes, both as input and output. A +stream is treated as compressed whenever its name is postfixed with +a compressed file extension, such as in 'brol.msh.bz2' or '-.gz'. The +compression formats which can be supported are the bzip2 format +('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on +input only). +.SH OPTIONS +.TP +.B +\fB-h\fP +Display some help. +.TP +.B +\fB-V\fP +Display program version and copyright. +.SH EXAMPLE +Test the consistency of mesh brol.msh: +.PP +.nf +.fam C + $ mtst brol.msh + +.fam T +.fi +.SH SEE ALSO +\fBmord\fP(1), \fBgrf_msh\fP(1). +.PP +Scotch user's manual. +.SH AUTHOR +Francois Pellegrini diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.alpha_dec_osf1 b/scotch_6.0.3/src/Make.inc/Makefile.inc.alpha_dec_osf1 new file mode 100644 index 00000000..7462c408 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.alpha_dec_osf1 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = ruv +CAT = cat +CCS = cc +CCP = mpicc +CCD = mpicc +CFLAGS = -v -O3 -omp -ansi_alias -ansi_args -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -lm +CP = cp +LEX = lex +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = yacc diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin10 b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin10 new file mode 100644 index 00000000..c6dc72e3 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin10 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -O3 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_PTHREAD_BARRIER -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_TIMING_OLD -DSCOTCH_PTHREAD -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -lz -lm -lpthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin10.icc b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin10.icc new file mode 100644 index 00000000..94989b05 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin10.icc @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = icc +CCP = mpicc +CCD = icc +CFLAGS = -O3 -restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_PTHREAD_BARRIER -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_TIMING_OLD -DSCOTCH_PTHREAD -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -lz -lm +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin8 b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin8 new file mode 100644 index 00000000..62208f10 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_mac_darwin8 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = mpicc +CFLAGS = -O3 -Drestrict=__restrict -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_TIMING_OLD -DSCOTCH_PTHREAD -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -lm +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_freebsd b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_freebsd new file mode 100644 index 00000000..db2164a1 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_freebsd @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = cc +CCP = mpicc +CCD = mpicc +CFLAGS += -std=c99 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER +CLIBFLAGS = +LDFLAGS += -lz -lm -lpthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2 b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2 new file mode 100644 index 00000000..51d166c9 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_PTHREAD -Drestrict=__restrict +CLIBFLAGS = +LDFLAGS = -lz -lm -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.c99 b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.c99 new file mode 100644 index 00000000..58c70cfb --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.c99 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -std=c99 -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD +CLIBFLAGS = +LDFLAGS = -lz -lm -pthread +CP = cp +LEX = flex -Pscotchyy -D_XOPEN_SOURCE=600 -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.debug b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.debug new file mode 100644 index 00000000..5eaf50c8 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.debug @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -g -O0 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DSCOTCH_DEBUG_ALL -DSCOTCH_DETERMINISTIC -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -g -lz -lm -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.nothreads b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.nothreads new file mode 100644 index 00000000..e04adb96 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.nothreads @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -O3 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -lz -lm -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.prof b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.prof new file mode 100644 index 00000000..8a6da26b --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.prof @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -pg -O3 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -lz -lm -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.shlib b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.shlib new file mode 100644 index 00000000..a4b47cd9 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.shlib @@ -0,0 +1,21 @@ +EXE = +LIB = .so +OBJ = .o + +MAKE = make +AR = gcc +ARFLAGS = -shared -o +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_PTHREAD -Drestrict=__restrict +CLIBFLAGS = -shared -fPIC +LDFLAGS = -lz -lm -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = echo +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.shlib.debug b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.shlib.debug new file mode 100644 index 00000000..a3cac066 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux2.shlib.debug @@ -0,0 +1,21 @@ +EXE = +LIB = .so +OBJ = .o + +MAKE = make +AR = gcc +ARFLAGS = -shared -o +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -g -O0 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DSCOTCH_DEBUG_ALL -DSCOTCH_DETERMINISTIC -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME +CLIBFLAGS = -shared -fPIC +LDFLAGS = -g -lz -lm -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = echo +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux3 b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux3 new file mode 100644 index 00000000..31f6b5fb --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_linux3 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -O3 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD +CLIBFLAGS = +LDFLAGS = -lz -lpthread -lm -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_mingw32 b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_mingw32 new file mode 100644 index 00000000..1ac2ba50 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_pc_mingw32 @@ -0,0 +1,69 @@ +# This make include file is intended for building under MinGW32. As is, +# it relies on : +# - pthread-win32 (http://sourceware.org/pthreads-win32/), +# - zlib (http://www.zlib.net/) +# - mpich2 (http://www.mcs.anl.gov/research/projects/mpich2/). +# It must be adapted to reflect your environment, in particular +# installation root directories, include path and library name. +# Since all files are linked with the MPI libraries, this file is +# for compiling PT-Scotch only. To compile Scotch, remove the +# -DSCOTCH_PTSCOTCH flag, as well as all references to MPI in the +# CFLAGS and CLIBFLAGS = +LDFLAGS variables. + +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = gcc +CCD = gcc + +#--- Compiler/loader flags +CFLAGS_CPL = -O0 -g3 +CFLAGS_INC = +CFLAGS_DEF = -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_STUB_FORK -DSCOTCH_PTSCOTCH -DSCOTCH_RENAME -D'pipe(pfds)=_pipe(pfds,1024,0x8000)' +CLIBFLAGS = +LDFLAGS = + +PGMFILES=$(PROGRAMFILES) + +#--- MPI +MPI_ROOTDIR = $(PGMFILES)/MPICH2 +CFLAGS_INC += -I$(MPI_ROOTDIR)/include +#--- Comment/Uncomment for threaded MPI +CLIBFLAGS = +LDFLAGS += -L$(MPI_ROOTDIR)/lib -lm -lmpi +#CLIBFLAGS = +LDFLAGS += -L$(MPI_ROOTDIR)/lib -lm -lmpich2mt + +#--- Pthread : Uncomment for pthread support +#PTHREAD_ROOTDIR = $(PGMFILES)/pthread-win32 +#CFLAGS_INC += -I$(PTHREAD_ROOTDIR)/include +#CLIBFLAGS = +LDFLAGS += -L$(PTHREAD_ROOTDIR)/lib -lpthreadGC2 + +#--- zlib: Uncomment for compressed files +#ZLIB_ROOTDIR = $(PGMFILES)/zlib-1.2.3 +#CFLAGS_INC += -I$(ZLIB_ROOTDIR)/include +#CLIBFLAGS = +LDFLAGS += -L$(ZLIB_ROOTDIR)/lib -lzdll + +#--- COMMON_PTHREAD: Uncomment for compressed files +#CFLAGS_DEF += -DCOMMON_PTHREAD -DCOMMON_FILE_COMPRESS_GZ + +#--- SCOTCH_PTHREAD: Uncomment for threaded MPI +#CFLAGS_DEF += -DSCOTCH_PTHREAD + +CFLAGS = $(CFLAGS_CPL) $(CFLAGS_INC) $(CFLAGS_DEF) +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = cp +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_sun_solaris5 b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_sun_solaris5 new file mode 100644 index 00000000..92ef9bc0 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.i686_sun_solaris5 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = cc +CCP = mpicc +CCD = mpicc +CFLAGS = -m64 -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -Du_int32_t=uint32_t -Du_int64_t=uint64_t +CLIBFLAGS = +LDFLAGS = -lz -lm -lrt +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = yacc diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.mips_sgi_irix6 b/scotch_6.0.3/src/Make.inc/Makefile.inc.mips_sgi_irix6 new file mode 100644 index 00000000..496ea525 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.mips_sgi_irix6 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = ruv +CAT = cat +CCS = xlc +CCP = mpicc +CCD = mpicc +CFLAGS = -n32 -xansi -fullwarn -O2 -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -lm +CP = cp +LEX = lex +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = yacc diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.pa11_hp_ux10 b/scotch_6.0.3/src/Make.inc/Makefile.inc.pa11_hp_ux10 new file mode 100644 index 00000000..1b044003 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.pa11_hp_ux10 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = ruv +CAT = cat +CCS = cc +CCP = mpicc +CCD = mpicc +CFLAGS = -Aa -z +DA1.1 +w1 +O4 +Onoinitcheck +Onolimit -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME +CLIBFLAGS = +LDFLAGS = -lm +CP = cp +LEX = lex +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = yacc diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.power3_ibm_aix5 b/scotch_6.0.3/src/Make.inc/Makefile.inc.power3_ibm_aix5 new file mode 100644 index 00000000..b90996cb --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.power3_ibm_aix5 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = -X64 -ruv +CAT = cat +CCS = xlc_r +CCP = mpcc_r +CCD = xlc_r -I/usr/lpp/ppe.poe/include +CFLAGS = -ma -q64 -qarch=auto -O3 -qstrict -qtune=pwr3 -qlanglvl=extc99 -s -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -D_ALL_SOURCE +CLIBFLAGS = +LDFLAGS = -bmaxdata:0x80000000 -lpthread -lm +CP = cp +LEX = lex +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = yacc diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.power6_ibm_aix5 b/scotch_6.0.3/src/Make.inc/Makefile.inc.power6_ibm_aix5 new file mode 100644 index 00000000..72e6fdf4 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.power6_ibm_aix5 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = -X64 -ruv +CAT = cat +CCS = xlc_r +CCP = mpcc_r +CCD = xlc_r -I/usr/lpp/ppe.poe/include +CFLAGS = -ma -q64 -qarch=auto -O3 -qstrict -qtune=pwr6 -qlanglvl=extc99 -s -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -D_ALL_SOURCE +CLIBFLAGS = +LDFLAGS = -lpthread -lm +CP = cp +LEX = lex +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = yacc diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.ppc450_ibm_bgp b/scotch_6.0.3/src/Make.inc/Makefile.inc.ppc450_ibm_bgp new file mode 100644 index 00000000..e8f097c6 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.ppc450_ibm_bgp @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = /bgsys/drivers/ppcfloor/comm/bin/mpixlc_r +CCP = /bgsys/drivers/ppcfloor/comm/bin/mpixlc_r +CCD = xlc_r -I/bgsys/drivers/ppcfloor/comm/include +CFLAGS = -O3 -qstrict -qlanglvl=extc99 -qarch=450d -qtune=450 -s -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_DETERMINISTIC -D_ALL_SOURCE +CLIBFLAGS = +LDFLAGS = -lpthread -lm +CP = cp +LEX = lex +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = yacc diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.ppca2_ibm_bgq b/scotch_6.0.3/src/Make.inc/Makefile.inc.ppca2_ibm_bgq new file mode 100644 index 00000000..0b9259ec --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.ppca2_ibm_bgq @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = /bgsys/drivers/ppcfloor/comm/xl/bin/mpixlc_r +CCP = /bgsys/drivers/ppcfloor/comm/xl/bin/mpixlc_r +CCD = xlc_r -I/bgsys/drivers/ppcfloor/comm/xl/include +CFLAGS = -O3 -qstrict -qlanglvl=extc99 -s -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_DETERMINISTIC -D_ALL_SOURCE +CLIBFLAGS = +LDFLAGS = -lpthread -lm +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_cray-xt4_linux2 b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_cray-xt4_linux2 new file mode 100644 index 00000000..e26ccf77 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_cray-xt4_linux2 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = cc +CCP = cc +CCD = cc +CFLAGS = -O3 -c99 -fast -fastsse -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -DIDXSIZE64 +CLIBFLAGS = +LDFLAGS = -lm -lrt +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_freebsd b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_freebsd new file mode 100644 index 00000000..19024bc9 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_freebsd @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = gmake +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = cc +CCP = mpicc +CCD = cc +CFLAGS += -std -fPIC -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD -Drestrict=__restrict -DIDXSIZE64 +CLIBFLAGS = +LDFLAGS += -lz -lm -lthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2 b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2 new file mode 100644 index 00000000..5c37ac56 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2 @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_PTHREAD -Drestrict=__restrict -DIDXSIZE64 +CLIBFLAGS = +LDFLAGS = -lz -lm -lrt -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.icc b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.icc new file mode 100644 index 00000000..d57b7d11 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.icc @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = icc +CCP = mpicc +CCD = icc +CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_PTHREAD -restrict -DIDXSIZE64 +CLIBFLAGS = +LDFLAGS = -lz -lm -lrt -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.icc.debug b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.icc.debug new file mode 100644 index 00000000..2632b48b --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.icc.debug @@ -0,0 +1,21 @@ +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = icc +CCP = mpicc +CCD = icc +CFLAGS = -g -O0 -fp-model strict -traceback -check-uninit -fp-stack-check -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_DEBUG_ALL -DSCOTCH_DETERMINISTIC -DSCOTCH_RENAME -restrict -DIDXSIZE64 +CLIBFLAGS = +LDFLAGS = -g -lz -lm -lrt -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.shlib b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.shlib new file mode 100644 index 00000000..40cab0f6 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/Makefile.inc.x86-64_pc_linux2.shlib @@ -0,0 +1,21 @@ +EXE = +LIB = .so +OBJ = .o + +MAKE = make +AR = gcc +ARFLAGS = -shared -o +CAT = cat +CCS = gcc +CCP = mpicc +CCD = gcc +CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_PTHREAD -Drestrict=__restrict -DIDXSIZE64 +CLIBFLAGS = -shared -fPIC +LDFLAGS = -lz -lm -lrt -pthread +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = ln +MKDIR = mkdir +MV = mv +RANLIB = echo +YACC = bison -pscotchyy -y -b y diff --git a/scotch_6.0.3/src/Make.inc/mingw32/README.txt b/scotch_6.0.3/src/Make.inc/mingw32/README.txt new file mode 100644 index 00000000..dcaced41 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/mingw32/README.txt @@ -0,0 +1,13 @@ +These three script files can be used to create a Windows DLL from the +PT-Scotch library on a MinGW32 system. They are intended to be called +directly from the src/Make.inc/mingw32 directory and produce results +in the lib directory. + +The first two ones must be called from a Unix-like shell window. +The last one must be called from a MSDOS-like command window. + +These scripts are intended only as examples. They must be adapted to +reflect your environment, in particular library path and library name. + +They have been provided by Yves Secretan (yves.secretan@ete.inrs.ca) +and are licensed under the CeCILL-C libre/free license. diff --git a/scotch_6.0.3/src/Make.inc/mingw32/gendll_0.sh b/scotch_6.0.3/src/Make.inc/mingw32/gendll_0.sh new file mode 100755 index 00000000..28b495e6 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/mingw32/gendll_0.sh @@ -0,0 +1,20 @@ +#! /bin/sh +# (C) 2008 Yves Secretan (yves.secretan@ete.inrs.ca) +# This software is governed by the CeCILL-C license under French law +# and abiding by the rules of distribution of free software. You can +# use, modify and/or redistribute the software under the terms of the +# CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +# URL: "http://www.cecill.info". +# +# To be executed in a MSYS window. +# +# This file will link the PT-Scotch DLL. It must be adapted to reflect +# your environment, in particular library path and library name. + +export OBJS="../../libscotch/lib*.o" +export LDFLAGS="--shared -Wl,--allow-multiple-definition" +export PGMFILES="/l" +export LDPATH="-L../../../lib -L$PGMFILES/MPICH2/lib -L$PGMFILES/pthread-win32/lib" +export LDLIBS="-lptscotch -lptscotcherr -lmpi -lpthreadGC2" + +gcc --output ../../../lib/libptscotch.dll $LDFLAGS $LDPATH $OBJS $LDLIBS diff --git a/scotch_6.0.3/src/Make.inc/mingw32/gendll_1.sh b/scotch_6.0.3/src/Make.inc/mingw32/gendll_1.sh new file mode 100755 index 00000000..4a4ebf90 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/mingw32/gendll_1.sh @@ -0,0 +1,16 @@ +#! /bin/sh +# (C) 2008 Yves Secretan (yves.secretan@ete.inrs.ca) +# This software is governed by the CeCILL-C license under French law +# and abiding by the rules of distribution of free software. You can +# use, modify and/or redistribute the software under the terms of the +# CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +# URL: "http://www.cecill.info". +# +# To be executed in a MSYS window. +# +# This file creates the Exports definition file from the PT-Scotch DLL. +# It must be adapted to reflect your environment, in particular library +# path and library name. + +echo EXPORTS > ../../../lib/libptscotch.def +nm ../../../lib/libptscotch.a | grep ' T _SCOTCH_' | sed 's/.* T _//' >> ../../../lib/libptscotch.def diff --git a/scotch_6.0.3/src/Make.inc/mingw32/gendll_2.bat b/scotch_6.0.3/src/Make.inc/mingw32/gendll_2.bat new file mode 100755 index 00000000..93156490 --- /dev/null +++ b/scotch_6.0.3/src/Make.inc/mingw32/gendll_2.bat @@ -0,0 +1,14 @@ +REM (C) 2008 Yves Secretan (yves.secretan@ete.inrs.ca) +REM This software is governed by the CeCILL-C license under French law +REM and abiding by the rules of distribution of free software. You can +REM use, modify and/or redistribute the software under the terms of the +REM CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +REM URL: "http://www.cecill.info". +REM +REM To be executed in a DOS window. +REM +REM This file will create the PT-Scotch DLL. It must be adapted to reflect +REM your environment, in particular library path and library name. +REM +set VC_PATH="C:\Program Files\Microsoft Visual Studio .NET\VC7\BIN" +%VC_PATH%\vcvars32.bat && %VC_PATH%\lib.exe /def:..\..\..\lib\libptscotch.def /out:..\..\..\lib\libptscotch.dll diff --git a/scotch_6.0.3/src/Makefile b/scotch_6.0.3/src/Makefile new file mode 100644 index 00000000..6c84c946 --- /dev/null +++ b/scotch_6.0.3/src/Makefile @@ -0,0 +1,134 @@ +## Copyright 2004,2007,2008,2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +## +## This file is part of the Scotch software package for static mapping, +## graph partitioning and sparse matrix ordering. +## +## This software is governed by the CeCILL-C license under French law +## and abiding by the rules of distribution of free software. You can +## use, modify and/or redistribute the software under the terms of the +## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +## URL: "http://www.cecill.info". +## +## As a counterpart to the access to the source code and rights to copy, +## modify and redistribute granted by the license, users are provided +## only with a limited warranty and the software's author, the holder of +## the economic rights, and the successive licensors have only limited +## liability. +## +## In this respect, the user's attention is drawn to the risks associated +## with loading, using, modifying and/or developing or reproducing the +## software by the user in light of its specific status of free software, +## that may mean that it is complicated to manipulate, and that also +## therefore means that it is reserved for developers and experienced +## professionals having in-depth computer knowledge. Users are therefore +## encouraged to load and test the software's suitability as regards +## their requirements in conditions enabling the security of their +## systems and/or data to be ensured and, more generally, to use and +## operate it in the same conditions as regards security. +## +## The fact that you are presently reading this means that you have had +## knowledge of the CeCILL-C license and that you accept its terms. +## + +VERSION = 6 +RELEASE = 0 +PATCHLEVEL = 3 + +.PHONY : clean default install ptscotch realclean required scotch + +default : scotch + +required : Makefile.inc ../bin ../include ../lib + +Makefile.inc : + @echo "#####################################################################" + @echo "BEFORE COMPILING Scotch OR PT-Scotch, YOU SHOULD HAVE AN APPROPRIATE" + @echo "Makefile.inc FILE IN THIS DIRECTORY. PLEASE LOOK INTO DIRECTORY" + @echo " ./Make.inc FOR AN EXISTING Makefile.inc FILE THAT FITS YOUR NEED, OR" + @echo "USE THEM AS MODELS IN CASE YOU NEED TO BUILD A NEW ONE FOR YOUR" + @echo "PARTICULAR PLATFORM." + @echo "#####################################################################" + @echo "Then, type \"make scotch\" (default) for the sequential library" + @echo "and software, or \"make ptscotch\" for the parallel library and" + @echo "software." + @exit 1 + +include Makefile.inc + +prefix ?= /usr/local +bindir ?= $(prefix)/bin +includedir ?= $(prefix)/include +libdir ?= $(prefix)/lib +datarootdir ?= $(prefix)/share +mandir ?= $(datarootdir)/man + +../bin : + -$(MKDIR) ../bin + +../include : + -$(MKDIR) ../include + +../lib : + -$(MKDIR) ../lib + +$(bindir) : + -$(MKDIR) $(bindir) + +$(datarootdir) : + -$(MKDIR) $(datarootdir) + +$(includedir) : + -$(MKDIR) $(includedir) + +$(libdir) : + -$(MKDIR) $(libdir) + +$(mandir) : $(datarootdir) + -$(MKDIR) $(mandir) + +$(mandir)/man1 : $(mandir) + -$(MKDIR) $(mandir)/man1 + +scotch : required + (cd libscotch ; $(MAKE) VERSION=$(VERSION) RELEASE=$(RELEASE) PATCHLEVEL=$(PATCHLEVEL) scotch && $(MAKE) install) + (cd scotch ; $(MAKE) VERSION=$(VERSION) RELEASE=$(RELEASE) PATCHLEVEL=$(PATCHLEVEL) scotch && $(MAKE) install) + (cd libscotchmetis ; $(MAKE) scotch && $(MAKE) install) + +ptscotch : required + (cd libscotch ; $(MAKE) VERSION=$(VERSION) RELEASE=$(RELEASE) PATCHLEVEL=$(PATCHLEVEL) ptscotch && $(MAKE) ptinstall) + (cd scotch ; $(MAKE) VERSION=$(VERSION) RELEASE=$(RELEASE) PATCHLEVEL=$(PATCHLEVEL) ptscotch && $(MAKE) ptinstall) + (cd libscotchmetis ; $(MAKE) ptscotch && $(MAKE) ptinstall) + +check : scotch + (cd check ; $(MAKE) check) + +ptcheck : ptscotch + (cd check ; $(MAKE) ptcheck) + +esmumps : scotch + (cd esmumps ; $(MAKE) scotch && $(MAKE) install) + +ptesmumps : ptscotch + (cd esmumps ; $(MAKE) ptscotch && $(MAKE) ptinstall) + +install : required $(bindir) $(includedir) $(libdir) $(mandir)/man1 + -$(CP) -f ../bin/[agm]*$(EXE) $(bindir) + -$(CP) -f ../bin/d[agm]*$(EXE) $(bindir) + -$(CP) -f ../include/*scotch*.h $(includedir) + -$(CP) -f ../lib/*scotch*$(LIB) $(libdir) + -$(CP) -Rf ../man/* $(mandir) + +clean : required + (cd libscotch ; $(MAKE) clean) + (cd scotch ; $(MAKE) clean) + (cd libscotchmetis ; $(MAKE) clean) + (cd check ; $(MAKE) clean) + (cd esmumps ; $(MAKE) clean) + +realclean : required + (cd libscotch ; $(MAKE) realclean) + (cd scotch ; $(MAKE) realclean) + (cd libscotchmetis ; $(MAKE) realclean) + (cd check ; $(MAKE) realclean) + (cd esmumps ; $(MAKE) realclean) + -$(RM) ../bin/* ../include/* ../lib/* diff --git a/scotch_6.0.3/src/Makefile.inc b/scotch_6.0.3/src/Makefile.inc new file mode 120000 index 00000000..6821a949 --- /dev/null +++ b/scotch_6.0.3/src/Makefile.inc @@ -0,0 +1 @@ +../../etc/wmakeFiles/scotch/Makefile.inc.i686_pc_linux2.shlib-OpenFOAM-64Int32 \ No newline at end of file diff --git a/scotch_6.0.3/src/check/Makefile b/scotch_6.0.3/src/check/Makefile new file mode 100644 index 00000000..f36cf0ab --- /dev/null +++ b/scotch_6.0.3/src/check/Makefile @@ -0,0 +1,220 @@ +## Copyright 2011,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +## +## This file is part of the Scotch software package for static mapping, +## graph partitioning and sparse matrix ordering. +## +## This software is governed by the CeCILL-C license under French law +## and abiding by the rules of distribution of free software. You can +## use, modify and/or redistribute the software under the terms of the +## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +## URL: "http://www.cecill.info". +## +## As a counterpart to the access to the source code and rights to copy, +## modify and redistribute granted by the license, users are provided +## only with a limited warranty and the software's author, the holder of +## the economic rights, and the successive licensors have only limited +## liability. +## +## In this respect, the user's attention is drawn to the risks associated +## with loading, using, modifying and/or developing or reproducing the +## software by the user in light of its specific status of free software, +## that may mean that it is complicated to manipulate, and that also +## therefore means that it is reserved for developers and experienced +## professionals having in-depth computer knowledge. Users are therefore +## encouraged to load and test the software's suitability as regards +## their requirements in conditions enabling the security of their +## systems and/or data to be ensured and, more generally, to use and +## operate it in the same conditions as regards security. +## +## The fact that you are presently reading this means that you have had +## knowledge of the CeCILL-C license and that you accept its terms. +## + +SCOTCHINCLUDEDIR = ../../include +SCOTCHLIBDIR = ../../lib +SCOTCHBINDIR = ../../bin + +LIBPTSCOTCH = -lptscotch -lscotch -lptscotcherrexit +LIBSCOTCH = -lscotch -lscotcherrexit + +DEPPTSCOTCH = $(SCOTCHLIBDIR)/libptscotch$(LIB) +DEPSCOTCH = $(SCOTCHLIBDIR)/libscotch$(LIB) + +EXECP = mpirun -n 4 + +## +## General inference rules. +## + +include ../Makefile.inc + +%$(OBJ) : %.c + $(CC) $(CFLAGS) $(CLIBFLAGS) -I$(SCOTCHINCLUDEDIR) -c $(<) -o $(@) + +%$(EXE) : %.c + $(CC) $(CFLAGS) -I$(SCOTCHINCLUDEDIR) -L$(SCOTCHLIBDIR) $(<) -o $(@) $(SCOTCHLIBS) $(LDFLAGS) + +## +## Project rules. +## + +.PHONY : check ptcheck clean realclean + +check : realclean + $(MAKE) CC="$(CCS)" CCD="$(CCS)" SCOTCHLIBS="$(LIBSCOTCH)" $(CHECKSCOTCH) + +ptcheck : realclean + $(MAKE) CFLAGS="$(CFLAGS) -DSCOTCH_PTSCOTCH" CC="$(CCP)" SCOTCHLIBS="$(LIBPTSCOTCH)" $(CHECKPTSCOTCH) + +clean : + -$(RM) *~ *$(OBJ) + +realclean : clean + -$(RM) \ + test_common_thread \ + test_scotch_graph_color \ + test_scotch_graph_map \ + test_scotch_graph_order \ + test_scotch_graph_part_ovl \ + test_scotch_dgraph_band \ + test_scotch_dgraph_check \ + test_scotch_dgraph_coarsen \ + test_scotch_dgraph_grow \ + test_scotch_dgraph_redist \ + test_strat_par \ + test_strat_seq + +## +## Test cases dependencies. +## + +CHECKSCOTCH = check_common_thread \ + check_strat_seq \ + check_graph_color \ + check_graph_map \ + check_graph_order \ + check_graph_part_ovl \ + check_prog_gpart_remap + +CHECKPTSCOTCH = check_strat_par \ + check_scotch_dgraph_check \ + check_scotch_dgraph_band \ + check_scotch_dgraph_coarsen \ + check_scotch_dgraph_grow \ + check_scotch_dgraph_redist \ + +## +## Todo list. +## + +check_dgraph_fold_comm : test_dgraph_fold_comm + $(EXECS) ./test_dgraph_fold_comm data/dgraph_fold_comm_1.txt + +test_dgraph_fold_comm : test_dgraph_fold_comm.c + +## + +check_scotch_dgraph_redist : test_scotch_dgraph_redist + $(EXECP) ./test_scotch_dgraph_redist data/bump.grf + +test_scotch_dgraph_redist : test_scotch_dgraph_redist.c + +## + +check_prog_gpart_remap : + $(EXECS) $(SCOTCHBINDIR)/gpart 32 data/bump_imbal_32.grf /dev/null -rodata/bump_old.map -vmt + +## + +check_common_thread : test_common_thread + $(EXECS) ./test_common_thread + +test_common_thread : test_common_thread.c \ + $(SCOTCHLIBDIR)/libscotch$(LIB) + +## + +check_graph_color : test_scotch_graph_color + $(EXECS) ./test_scotch_graph_color data/bump.grf + +test_graph_color : test_scotch_graph_color.c \ + $(SCOTCHLIBDIR)/libscotch$(LIB) + +## + +check_graph_map : test_scotch_graph_map + $(EXECS) ./test_scotch_graph_map data/m4x4.grf + $(EXECS) ./test_scotch_graph_map data/m4x4_b1.grf + $(EXECS) ./test_scotch_graph_map data/m16x16.grf + $(EXECS) ./test_scotch_graph_map data/m16x16_b1.grf + +test_graph_map : test_scotch_graph_map.c \ + $(SCOTCHLIBDIR)/libscotch$(LIB) + +## + +check_graph_order : test_scotch_graph_order + $(EXECS) ./test_scotch_graph_order data/bump.grf + $(EXECS) ./test_scotch_graph_order data/bump_b1.grf + +test_graph_order : test_scotch_graph_order.c \ + $(SCOTCHLIBDIR)/libscotch$(LIB) + +## + +check_graph_part_ovl : test_scotch_graph_part_ovl + $(EXECS) ./test_scotch_graph_part_ovl 4 data/m16x16.grf /dev/null + $(EXECS) ./test_scotch_graph_part_ovl 4 data/m16x16_b1.grf /dev/null + +test_graph_part_ovl : test_scotch_graph_part_ovl.c \ + $(SCOTCHLIBDIR)/libscotch$(LIB) + +## + +check_strat_seq : test_strat_seq + $(EXECS) ./test_strat_seq + +test_strat_seq : test_strat_seq.c \ + $(SCOTCHLIBDIR)/libscotch$(LIB) + +## + +check_strat_par : test_strat_par + $(EXECS) ./test_strat_par + +test_strat_par : test_strat_par.c \ + $(SCOTCHLIBDIR)/libptscotch$(LIB) + +## + +check_scotch_dgraph_band : test_scotch_dgraph_band + $(EXECP) ./test_scotch_dgraph_band data/bump_b1.grf + +test_scotch_dgraph_band : test_scotch_dgraph_band.c \ + $(SCOTCHLIBDIR)/libptscotch$(LIB) + +## + +check_scotch_dgraph_coarsen : test_scotch_dgraph_coarsen + $(EXECP) ./test_scotch_dgraph_coarsen data/bump.grf + $(EXECP) ./test_scotch_dgraph_coarsen data/bump_b1.grf + +test_scotch_dgraph_coarsen : test_scotch_dgraph_coarsen.c \ + $(SCOTCHLIBDIR)/libptscotch$(LIB) + +## + +check_scotch_dgraph_check : test_scotch_dgraph_check + $(EXECP) ./test_scotch_dgraph_check data/bump.grf + $(EXECP) ./test_scotch_dgraph_check data/bump_b1.grf + +test_scotch_dgraph_check : test_scotch_dgraph_check.c \ + $(SCOTCHLIBDIR)/libptscotch$(LIB) + +## + +check_scotch_dgraph_grow : test_scotch_dgraph_grow + $(EXECP) ./test_scotch_dgraph_grow data/bump.grf + +test_scotch_dgraph_grow : test_scotch_dgraph_grow.c \ + $(SCOTCHLIBDIR)/libptscotch$(LIB) diff --git a/scotch_6.0.3/src/check/data/bump.grf b/scotch_6.0.3/src/check/data/bump.grf new file mode 100644 index 00000000..1e7d58c9 --- /dev/null +++ b/scotch_6.0.3/src/check/data/bump.grf @@ -0,0 +1,9803 @@ +0 +9800 57978 +0 000 +3 413 407 6 +4 9771 43 9772 44 +4 76 1474 1475 77 +3 1242 147 148 +3 693 206 207 +3 521 348 349 +4 7 412 413 0 +4 6 412 8 647 +4 9 3238 647 7 +4 3235 3238 8 10 +4 11 3233 3235 9 +4 3234 3233 10 12 +4 3684 3234 11 13 +4 14 418 3684 12 +4 15 417 418 13 +4 14 417 16 3088 +4 17 3086 3088 15 +4 16 3086 3087 18 +4 3087 17 3095 19 +4 3095 18 3096 20 +4 21 414 3096 19 +4 20 414 1171 22 +4 1171 21 1172 23 +4 1172 22 1173 24 +4 1173 23 1526 25 +4 1526 24 26 9781 +4 27 3852 9781 25 +4 28 2179 3852 26 +4 27 2179 2180 29 +4 2180 28 30 2503 +4 31 2505 2503 29 +4 2508 2505 30 32 +4 3330 2508 33 31 +4 3330 32 3331 34 +4 35 2248 3331 33 +4 34 2248 2249 36 +4 2249 35 2250 37 +4 38 416 2250 36 +4 39 415 416 37 +4 38 415 2194 40 +4 2194 39 2195 41 +4 2195 40 2196 42 +3 2196 41 43 +4 42 2196 9771 1 +4 9769 9772 1 45 +4 46 9768 9769 44 +4 47 427 9768 45 +4 48 426 427 46 +4 47 426 49 411 +4 50 410 411 48 +4 49 410 51 421 +4 50 421 422 52 +4 422 51 4650 53 +4 4650 52 4651 54 +4 4657 4651 53 55 +4 5380 4657 54 56 +4 57 430 5380 55 +4 56 430 429 58 +4 59 408 429 57 +4 58 408 2218 60 +4 2218 59 2219 61 +4 2219 60 2220 62 +4 2220 61 2221 63 +4 2221 62 2222 64 +4 6701 2222 63 65 +4 6701 64 6703 66 +4 6703 65 3505 67 +4 68 3452 3505 66 +4 69 3451 3452 67 +4 3441 3451 68 70 +4 71 2491 3441 69 +4 70 2491 2492 72 +4 73 409 2492 71 +4 72 409 74 428 +4 73 428 75 1603 +4 74 1603 1604 76 +4 2 1474 1604 75 +4 1475 2 1476 78 +4 1476 77 1477 79 +4 1477 78 1478 80 +4 1478 79 1479 81 +4 1479 80 1480 82 +4 1480 81 1481 83 +4 1481 82 1482 84 +4 1482 83 1483 85 +4 86 1160 1483 84 +4 85 1160 1161 87 +4 1161 86 1162 88 +4 1162 87 1163 89 +4 1163 88 1186 90 +4 1186 89 1185 91 +4 1185 90 1187 92 +4 1187 91 1188 93 +4 1188 92 1189 94 +4 1189 93 1190 95 +4 1190 94 1191 96 +4 1191 95 1192 97 +4 1192 96 1193 98 +4 1193 97 1194 99 +4 1194 98 1195 100 +4 1195 99 1196 101 +4 1196 100 1197 102 +4 1197 101 1198 103 +4 1198 102 1199 104 +4 1199 103 1200 105 +4 1200 104 1201 106 +4 1201 105 1202 107 +4 1202 106 1203 108 +4 1203 107 1204 109 +4 1204 108 1205 110 +4 1205 109 1206 111 +4 1206 110 1207 112 +4 1207 111 1208 113 +4 1208 112 1209 114 +4 1209 113 1210 115 +4 1210 114 1211 116 +4 1211 115 1212 117 +4 1212 116 1213 118 +4 1213 117 1214 119 +4 1214 118 1215 120 +4 1215 119 1216 121 +4 1216 120 1217 122 +4 1217 121 1218 123 +4 1218 122 1219 124 +4 1219 123 1220 125 +4 1220 124 1221 126 +4 1221 125 1222 127 +4 1222 126 1223 128 +4 1223 127 1224 129 +4 1224 128 1225 130 +4 1225 129 1226 131 +4 1226 130 1227 132 +4 1227 131 1228 133 +4 1228 132 1229 134 +4 1229 133 1230 135 +4 1230 134 1231 136 +4 1231 135 1232 137 +4 1232 136 1233 138 +4 1233 137 1234 139 +4 1234 138 1235 140 +4 1235 139 1236 141 +4 1236 140 1237 142 +4 1237 141 1238 143 +4 1238 142 1239 144 +4 1239 143 1240 145 +4 1240 144 1241 146 +4 1241 145 1242 147 +3 1242 146 3 +4 1242 3 1243 149 +4 1243 148 1244 150 +4 1244 149 1245 151 +4 1245 150 1246 152 +4 1246 151 1247 153 +4 1247 152 1248 154 +4 155 923 1248 153 +4 154 923 924 156 +4 924 155 925 157 +4 925 156 926 158 +4 926 157 927 159 +4 927 158 928 160 +4 928 159 929 161 +4 929 160 930 162 +4 930 161 931 163 +4 164 651 931 162 +4 163 651 652 165 +4 652 164 653 166 +4 653 165 654 167 +4 654 166 655 168 +4 655 167 656 169 +4 656 168 657 170 +4 657 169 658 171 +4 658 170 659 172 +4 659 171 660 173 +4 660 172 661 174 +4 661 173 662 175 +4 662 174 663 176 +4 663 175 664 177 +4 664 176 665 178 +4 665 177 666 179 +4 666 178 667 180 +4 667 179 668 181 +4 668 180 669 182 +4 669 181 670 183 +4 670 182 671 184 +4 671 183 672 185 +4 672 184 673 186 +4 673 185 674 187 +4 674 186 675 188 +4 675 187 676 189 +4 676 188 677 190 +4 677 189 678 191 +4 678 190 679 192 +4 679 191 680 193 +4 680 192 681 194 +4 681 193 682 195 +4 682 194 683 196 +4 683 195 684 197 +4 684 196 685 198 +4 685 197 686 199 +4 686 198 687 200 +4 687 199 688 201 +4 688 200 689 202 +4 689 201 690 203 +4 690 202 691 204 +4 691 203 692 205 +3 692 204 206 +4 692 205 693 4 +3 693 4 208 +4 693 207 694 209 +4 694 208 695 210 +4 695 209 696 211 +4 696 210 697 212 +4 697 211 698 213 +4 698 212 699 214 +4 699 213 700 215 +4 700 214 701 216 +4 701 215 702 217 +4 702 216 703 218 +4 703 217 704 219 +4 704 218 705 220 +4 705 219 706 221 +4 706 220 707 222 +4 707 221 708 223 +4 708 222 709 224 +4 709 223 710 225 +4 710 224 711 226 +4 711 225 712 227 +4 712 226 713 228 +4 713 227 714 229 +4 714 228 715 230 +4 715 229 716 231 +4 716 230 717 232 +4 717 231 718 233 +4 718 232 719 234 +4 719 233 720 235 +4 720 234 721 236 +4 721 235 722 237 +4 722 236 723 238 +4 723 237 724 239 +4 724 238 725 240 +4 725 239 726 241 +4 726 240 727 242 +4 727 241 728 243 +4 728 242 729 244 +4 729 243 730 245 +4 730 244 731 246 +4 731 245 732 247 +4 732 246 733 248 +4 733 247 734 249 +4 734 248 735 250 +4 735 249 736 251 +4 736 250 737 252 +4 737 251 738 253 +4 738 252 739 254 +4 739 253 740 255 +4 740 254 741 256 +4 741 255 742 257 +4 258 431 742 256 +4 257 431 432 259 +4 432 258 433 260 +4 433 259 434 261 +4 434 260 435 262 +4 435 261 436 263 +4 436 262 437 264 +4 437 263 438 265 +4 438 264 439 266 +4 439 265 440 267 +4 440 266 441 268 +4 441 267 442 269 +4 442 268 443 270 +4 443 269 444 271 +4 444 270 445 272 +4 445 271 446 273 +4 446 272 447 274 +4 447 273 448 275 +4 448 274 449 276 +4 449 275 450 277 +4 450 276 451 278 +4 451 277 452 279 +4 452 278 453 280 +4 453 279 454 281 +4 454 280 455 282 +4 455 281 456 283 +4 456 282 457 284 +4 457 283 458 285 +4 458 284 459 286 +4 459 285 460 287 +4 460 286 461 288 +4 461 287 462 289 +4 462 288 463 290 +4 463 289 464 291 +4 464 290 465 292 +4 465 291 466 293 +4 466 292 467 294 +4 467 293 468 295 +4 468 294 469 296 +4 469 295 470 297 +4 470 296 471 298 +4 471 297 472 299 +4 472 298 473 300 +4 473 299 474 301 +4 474 300 475 302 +4 475 301 476 303 +4 476 302 477 304 +4 477 303 478 305 +4 478 304 479 306 +4 479 305 480 307 +4 480 306 481 308 +4 481 307 482 309 +4 482 308 483 310 +4 483 309 484 311 +4 484 310 485 312 +4 485 311 486 313 +4 486 312 487 314 +4 487 313 488 315 +4 488 314 489 316 +4 489 315 490 317 +4 490 316 491 318 +4 491 317 492 319 +4 492 318 493 320 +4 493 319 494 321 +4 494 320 495 322 +4 495 321 496 323 +4 496 322 497 324 +4 497 323 498 325 +4 498 324 499 326 +4 499 325 500 327 +4 500 326 501 328 +4 501 327 502 329 +4 502 328 503 330 +4 503 329 504 331 +4 504 330 505 332 +4 505 331 506 333 +4 506 332 507 334 +4 507 333 508 335 +4 508 334 509 336 +4 509 335 510 337 +4 510 336 511 338 +4 511 337 512 339 +4 512 338 513 340 +4 513 339 514 341 +4 514 340 515 342 +4 515 341 516 343 +4 516 342 517 344 +4 517 343 518 345 +4 518 344 519 346 +4 519 345 520 347 +4 520 346 521 348 +3 521 347 5 +4 521 5 522 350 +4 522 349 523 351 +4 523 350 524 352 +4 524 351 525 353 +4 525 352 526 354 +4 526 353 527 355 +4 527 354 528 356 +4 528 355 529 357 +4 529 356 530 358 +4 530 357 531 359 +4 531 358 532 360 +4 532 359 533 361 +4 533 360 534 362 +4 534 361 535 363 +4 535 362 536 364 +4 536 363 537 365 +4 537 364 538 366 +4 538 365 539 367 +4 539 366 540 368 +4 540 367 541 369 +4 541 368 542 370 +4 542 369 543 371 +4 543 370 544 372 +4 544 371 545 373 +4 545 372 546 374 +4 546 373 547 375 +4 550 547 374 376 +4 550 375 551 377 +4 551 376 552 378 +4 552 377 553 379 +4 556 553 378 380 +4 566 556 379 381 +4 566 380 567 382 +4 567 381 568 383 +4 568 382 569 384 +4 569 383 570 385 +4 425 570 386 384 +4 387 423 425 385 +4 386 423 424 388 +4 579 424 389 387 +4 584 579 388 390 +4 584 389 585 391 +4 585 390 586 392 +4 586 391 420 393 +4 394 419 420 392 +4 393 419 594 395 +4 396 596 594 394 +4 622 596 395 397 +4 622 396 623 398 +4 623 397 624 399 +4 398 624 626 400 +4 626 399 628 401 +4 630 628 402 400 +4 630 401 631 403 +4 402 631 2097 404 +4 405 649 2097 403 +4 648 649 404 406 +4 648 405 413 407 +3 413 406 0 +6 58 59 429 2218 2545 2841 +6 72 73 2492 2493 1606 428 +6 49 50 411 4521 4515 421 +6 49 410 48 426 4514 4515 +6 6 7 413 647 646 648 +6 6 412 648 406 407 0 +6 20 21 1171 3882 3128 3096 +6 38 39 416 2194 2252 9704 +6 38 415 37 2250 2251 2252 +6 14 15 418 3088 3098 3099 +6 14 417 13 3099 3100 3684 +6 393 394 420 593 588 594 +6 393 419 586 392 587 588 +6 50 51 422 5237 4521 410 +6 421 51 52 4650 9684 5237 +6 386 387 424 425 577 575 +6 423 387 577 578 579 388 +6 386 423 572 570 385 575 +6 47 48 427 411 4514 5612 +6 47 426 46 5612 7500 9768 +6 73 74 1603 1605 1606 409 +6 58 408 430 57 2841 9690 +6 56 57 429 9689 5380 9690 +6 257 258 432 742 743 744 +6 431 258 259 433 744 745 +6 432 259 260 434 745 746 +6 433 260 261 435 746 747 +6 434 261 262 436 747 748 +6 435 262 263 437 748 749 +6 436 263 264 438 749 750 +6 437 264 265 439 750 751 +6 438 265 266 440 751 752 +6 439 266 267 441 752 753 +6 440 267 268 442 753 754 +6 441 268 269 443 754 755 +6 442 269 270 444 755 756 +6 443 270 271 445 756 757 +6 444 271 272 446 757 758 +6 445 272 273 447 758 759 +6 446 273 274 448 759 760 +6 447 274 275 449 760 761 +6 448 275 276 450 761 762 +6 449 276 277 451 762 763 +6 450 277 278 452 763 764 +6 451 278 279 453 764 765 +6 452 279 280 454 765 766 +6 453 280 281 455 766 767 +6 454 281 282 456 767 768 +6 455 282 283 457 768 769 +6 456 283 284 458 769 770 +6 457 284 285 459 770 771 +6 458 285 286 460 771 772 +6 459 286 287 461 772 773 +6 460 287 288 462 773 774 +6 461 288 289 463 774 775 +6 462 289 290 464 775 776 +6 463 290 291 465 776 777 +6 464 291 292 466 777 778 +6 465 292 293 467 778 779 +6 466 293 294 468 779 780 +6 467 294 295 469 780 781 +6 468 295 296 470 781 782 +6 469 296 297 471 782 783 +6 470 297 298 472 783 784 +6 471 298 299 473 784 785 +6 472 299 300 474 785 786 +6 473 300 301 475 786 787 +6 474 301 302 476 787 788 +6 475 302 303 477 788 789 +6 476 303 304 478 789 790 +6 477 304 305 479 790 791 +6 478 305 306 480 791 792 +6 479 306 307 481 792 793 +6 480 307 308 482 793 794 +6 481 308 309 483 794 795 +6 482 309 310 484 795 796 +6 483 310 311 485 796 797 +6 484 311 312 486 797 798 +6 485 312 313 487 798 799 +6 486 313 314 488 799 800 +6 487 314 315 489 800 801 +6 488 315 316 490 801 802 +6 489 316 317 491 802 803 +6 490 317 318 492 803 804 +6 491 318 319 493 804 805 +6 492 319 320 494 805 806 +6 493 320 321 495 806 807 +6 494 321 322 496 807 808 +6 495 322 323 497 808 809 +6 496 323 324 498 809 810 +6 497 324 325 499 810 811 +6 498 325 326 500 811 812 +6 499 326 327 501 812 813 +6 500 327 328 502 813 814 +6 501 328 329 503 814 815 +6 502 329 330 504 815 816 +6 503 330 331 505 816 817 +6 504 331 332 506 817 818 +6 505 332 333 507 818 819 +6 506 333 334 508 819 820 +6 507 334 335 509 820 821 +6 508 335 336 510 821 822 +6 509 336 337 511 822 823 +6 510 337 338 512 823 824 +6 511 338 339 513 824 825 +6 512 339 340 514 825 826 +6 513 340 341 515 826 827 +6 514 341 342 516 827 828 +6 515 342 343 517 828 829 +6 516 343 344 518 829 830 +6 517 344 345 519 830 831 +6 518 345 346 520 831 832 +6 519 346 347 521 832 833 +7 520 347 348 5 349 522 833 +6 521 349 350 523 833 834 +5 522 350 351 524 834 +6 523 351 352 525 834 835 +6 524 352 353 526 835 836 +6 525 353 354 527 836 837 +6 526 354 355 528 837 838 +6 527 355 356 529 838 839 +6 528 356 357 530 839 840 +6 529 357 358 531 840 841 +6 530 358 359 532 841 842 +6 531 359 360 533 842 843 +6 532 360 361 534 843 844 +6 533 361 362 535 844 845 +6 534 362 363 536 845 846 +6 535 363 364 537 846 847 +6 536 364 365 538 847 848 +6 537 365 366 539 848 849 +6 538 366 367 540 849 850 +6 539 367 368 541 853 850 +6 540 368 369 542 855 853 +6 541 369 370 543 855 856 +6 542 370 371 544 856 857 +6 543 371 372 545 857 858 +6 544 372 373 546 858 859 +6 545 373 374 547 548 859 +6 546 374 548 549 550 375 +6 546 547 549 859 860 861 +6 548 547 550 861 862 863 +6 549 547 375 376 551 863 +6 550 376 377 552 863 864 +6 551 377 378 553 554 864 +6 552 378 554 555 556 379 +6 552 553 555 557 864 865 +6 554 553 556 557 558 565 +6 555 553 379 565 566 380 +6 554 555 558 559 865 866 +6 557 555 559 560 561 565 +6 557 558 560 866 867 868 +6 559 558 561 562 922 868 +6 560 558 562 563 564 565 +6 560 561 563 921 920 922 +6 562 561 564 9743 921 9744 +6 563 561 565 566 9744 567 +6 564 561 558 555 556 566 +6 565 556 380 381 567 564 +6 566 381 382 568 9744 564 +6 567 382 383 569 9744 9739 +6 568 383 384 570 571 9739 +6 569 384 571 572 425 385 +6 569 570 572 573 9739 9740 +6 571 570 425 573 574 575 +6 571 572 574 9740 9741 916 +6 573 572 575 576 916 915 +6 574 572 425 576 577 423 +6 574 575 577 915 2474 1515 +6 576 575 423 424 578 1515 +6 577 424 579 580 581 1515 +6 578 424 388 580 584 389 +6 578 579 581 582 583 584 +6 578 580 582 1515 1516 1517 +6 581 580 583 1517 1508 1506 +6 582 580 584 585 589 1506 +6 583 580 579 389 390 585 +6 584 390 391 586 589 583 +6 585 391 392 420 587 589 +6 586 420 588 589 590 591 +6 587 420 591 592 593 419 +6 586 587 590 585 583 1506 +6 589 587 591 1506 1507 1514 +6 590 587 588 592 599 1514 +6 591 588 593 597 598 599 +6 592 588 419 594 595 597 +6 593 419 394 595 596 395 +6 593 594 596 597 621 606 +6 595 594 621 622 396 395 +6 593 595 592 598 605 606 +6 592 597 599 600 604 605 +6 592 598 600 601 1514 591 +6 599 598 601 602 603 604 +6 599 600 602 1513 1514 1539 +6 601 600 603 1539 1540 1583 +6 602 600 604 1602 1583 608 +6 603 600 598 605 607 608 +6 604 598 597 606 607 614 +6 605 597 621 620 595 614 +6 604 605 608 609 610 614 +6 604 607 609 1602 603 1600 +6 608 607 610 611 1599 1600 +6 609 607 611 612 613 614 +6 609 610 612 6557 1598 1599 +6 611 610 613 615 3764 6557 +6 612 610 614 615 616 620 +6 613 610 620 606 605 607 +6 612 613 616 617 3760 3764 +6 615 613 617 618 619 620 +6 615 616 618 3760 3761 625 +6 617 616 619 623 624 625 +6 618 616 620 621 623 622 +6 619 616 613 614 621 606 +6 619 620 606 595 596 622 +6 621 596 396 397 623 619 +6 622 397 398 624 618 619 +6 623 398 618 625 626 399 +6 618 624 626 627 3761 617 +6 625 624 627 628 399 400 +6 625 626 628 629 3761 3762 +6 627 626 629 630 401 400 +6 627 628 630 635 3762 632 +6 629 628 401 402 631 632 +6 630 402 632 633 403 2097 +6 630 631 633 634 635 629 +6 632 631 634 2097 650 641 +6 632 633 635 636 637 641 +6 632 634 636 3217 3762 629 +6 635 634 637 638 3217 3218 +6 636 634 638 639 640 641 +6 636 637 639 3218 3219 3220 +6 638 637 640 3220 3239 3240 +6 639 637 641 642 643 3239 +6 640 637 642 633 650 634 +6 640 641 643 644 645 650 +6 640 642 644 3237 3236 3239 +6 643 642 645 646 647 3237 +6 644 642 646 648 649 650 +5 644 645 647 412 648 +7 644 646 412 8 3238 3237 7 +7 412 646 645 649 405 406 413 +6 648 645 650 405 404 2097 +6 649 645 633 2097 641 642 +6 163 164 652 931 932 933 +6 651 164 165 653 933 934 +6 652 165 166 654 934 935 +6 653 166 167 655 935 936 +6 654 167 168 656 936 937 +6 655 168 169 657 937 938 +6 656 169 170 658 938 939 +6 657 170 171 659 939 940 +6 658 171 172 660 940 941 +6 659 172 173 661 941 942 +6 660 173 174 662 942 943 +6 661 174 175 663 943 944 +6 662 175 176 664 944 945 +6 663 176 177 665 945 946 +6 664 177 178 666 946 947 +6 665 178 179 667 947 948 +6 666 179 180 668 948 949 +6 667 180 181 669 949 950 +6 668 181 182 670 950 951 +6 669 182 183 671 951 952 +6 670 183 184 672 952 953 +6 671 184 185 673 953 954 +6 672 185 186 674 954 955 +6 673 186 187 675 955 956 +6 674 187 188 676 956 957 +6 675 188 189 677 957 958 +6 676 189 190 678 958 959 +6 677 190 191 679 959 960 +6 678 191 192 680 960 961 +6 679 192 193 681 961 962 +6 680 193 194 682 962 963 +6 681 194 195 683 963 964 +6 682 195 196 684 964 965 +6 683 196 197 685 965 966 +6 684 197 198 686 966 967 +6 685 198 199 687 967 968 +6 686 199 200 688 968 969 +6 687 200 201 689 969 970 +6 688 201 202 690 970 971 +6 689 202 203 691 971 972 +6 690 203 204 692 972 973 +7 691 204 205 206 693 973 694 +6 692 206 4 207 208 694 +7 693 208 209 695 973 692 974 +6 694 209 210 696 974 975 +6 695 210 211 697 975 976 +6 696 211 212 698 976 977 +6 697 212 213 699 977 978 +6 698 213 214 700 978 979 +6 699 214 215 701 979 980 +6 700 215 216 702 980 981 +6 701 216 217 703 981 982 +6 702 217 218 704 982 983 +6 703 218 219 705 983 984 +6 704 219 220 706 984 985 +6 705 220 221 707 985 986 +6 706 221 222 708 986 987 +6 707 222 223 709 987 988 +6 708 223 224 710 988 989 +6 709 224 225 711 989 990 +6 710 225 226 712 990 991 +6 711 226 227 713 991 992 +6 712 227 228 714 992 993 +6 713 228 229 715 993 994 +6 714 229 230 716 994 995 +6 715 230 231 717 995 996 +6 716 231 232 718 996 997 +6 717 232 233 719 997 998 +6 718 233 234 720 998 999 +6 719 234 235 721 999 1000 +6 720 235 236 722 1000 1001 +6 721 236 237 723 1001 1002 +6 722 237 238 724 1002 1003 +6 723 238 239 725 1003 1004 +6 724 239 240 726 1004 1005 +6 725 240 241 727 1005 1006 +6 726 241 242 728 1006 1007 +6 727 242 243 729 1007 1008 +6 728 243 244 730 1008 1009 +6 729 244 245 731 1009 1010 +6 730 245 246 732 1010 1011 +6 731 246 247 733 1011 1012 +6 732 247 248 734 1012 1013 +6 733 248 249 735 1016 1013 +6 734 249 250 736 1016 1017 +6 735 250 251 737 1017 1018 +6 736 251 252 738 1018 1019 +6 737 252 253 739 1019 1020 +6 738 253 254 740 1020 1021 +6 739 254 255 741 1021 1022 +6 740 255 256 742 1022 1023 +6 741 256 257 431 743 1023 +6 742 431 744 1023 1024 1025 +6 743 431 432 745 1025 1026 +6 744 432 433 746 1026 1027 +6 745 433 434 747 1027 1028 +6 746 434 435 748 1028 1029 +6 747 435 436 749 1029 1030 +6 748 436 437 750 1030 1031 +6 749 437 438 751 1031 1032 +6 750 438 439 752 1032 1033 +6 751 439 440 753 1033 1034 +6 752 440 441 754 1034 1035 +6 753 441 442 755 1035 1036 +6 754 442 443 756 1036 1037 +6 755 443 444 757 1037 1038 +6 756 444 445 758 1038 1039 +6 757 445 446 759 1039 1040 +6 758 446 447 760 1040 1041 +6 759 447 448 761 1041 1042 +6 760 448 449 762 1042 1043 +6 761 449 450 763 1043 1044 +6 762 450 451 764 1044 1045 +6 763 451 452 765 1045 1046 +6 764 452 453 766 1046 1047 +6 765 453 454 767 1047 1048 +6 766 454 455 768 1048 1049 +6 767 455 456 769 1049 1050 +6 768 456 457 770 1050 1051 +6 769 457 458 771 1051 1052 +6 770 458 459 772 1052 1053 +6 771 459 460 773 1053 1054 +6 772 460 461 774 1054 1055 +6 773 461 462 775 1055 1056 +6 774 462 463 776 1056 1057 +6 775 463 464 777 1057 1058 +6 776 464 465 778 1058 1059 +6 777 465 466 779 1059 1060 +6 778 466 467 780 1060 1061 +6 779 467 468 781 1061 1062 +6 780 468 469 782 1062 1063 +6 781 469 470 783 1063 1064 +6 782 470 471 784 1064 1065 +6 783 471 472 785 1065 1066 +6 784 472 473 786 1066 1067 +6 785 473 474 787 1067 1068 +6 786 474 475 788 1068 1069 +6 787 475 476 789 1069 1070 +6 788 476 477 790 1070 1071 +6 789 477 478 791 1071 1072 +6 790 478 479 792 1072 1073 +6 791 479 480 793 1073 1074 +6 792 480 481 794 1074 1075 +6 793 481 482 795 1075 1076 +6 794 482 483 796 1076 1077 +6 795 483 484 797 1077 1078 +6 796 484 485 798 1078 1079 +6 797 485 486 799 1079 1080 +6 798 486 487 800 1080 1081 +6 799 487 488 801 1081 1082 +6 800 488 489 802 1082 1083 +6 801 489 490 803 1083 1084 +6 802 490 491 804 1084 1085 +6 803 491 492 805 1085 1086 +6 804 492 493 806 1086 1087 +6 805 493 494 807 1087 1088 +6 806 494 495 808 1088 1089 +6 807 495 496 809 1089 1090 +6 808 496 497 810 1090 1091 +6 809 497 498 811 1091 1092 +6 810 498 499 812 1092 1093 +6 811 499 500 813 1093 1094 +6 812 500 501 814 1094 1095 +6 813 501 502 815 1095 1096 +6 814 502 503 816 1096 1097 +6 815 503 504 817 1097 1098 +6 816 504 505 818 1098 1099 +6 817 505 506 819 1099 1100 +6 818 506 507 820 1100 1101 +6 819 507 508 821 1101 1102 +6 820 508 509 822 1102 1103 +6 821 509 510 823 1103 1104 +6 822 510 511 824 1104 1105 +6 823 511 512 825 1105 1106 +6 824 512 513 826 1106 1107 +6 825 513 514 827 1107 1108 +6 826 514 515 828 1108 1109 +6 827 515 516 829 1109 1110 +6 828 516 517 830 1110 1111 +6 829 517 518 831 1111 1112 +6 830 518 519 832 1112 1113 +6 831 519 520 833 1113 1114 +6 832 520 521 522 834 1114 +6 833 522 523 524 835 1114 +7 834 524 525 836 1114 1115 1116 +6 835 525 526 837 1116 1117 +6 836 526 527 838 1117 1118 +6 837 527 528 839 1118 1119 +6 838 528 529 840 1119 1120 +6 839 529 530 841 1120 1121 +6 840 530 531 842 1121 1122 +6 841 531 532 843 1122 1123 +6 842 532 533 844 1123 1124 +6 843 533 534 845 1124 1125 +6 844 534 535 846 1125 1126 +6 845 535 536 847 1126 1127 +6 846 536 537 848 1127 1128 +6 847 537 538 849 1128 1129 +6 848 538 539 850 851 1129 +6 849 539 851 852 853 540 +6 849 850 852 1129 1130 1131 +6 851 850 853 854 1131 1132 +6 852 850 854 855 541 540 +6 852 853 855 1132 1133 1134 +6 854 853 541 542 856 1134 +6 855 542 543 857 1134 1135 +6 856 543 544 858 1135 1136 +6 857 544 545 859 1136 1137 +6 858 545 546 548 860 1137 +6 859 548 861 1137 1138 1139 +6 860 548 549 862 1139 1140 +6 861 549 863 1140 1141 1142 +6 862 549 550 551 864 1142 +6 863 551 552 554 865 1142 +6 864 554 557 866 1142 1143 +6 865 557 559 867 1143 1144 +6 866 559 868 869 1144 1145 +6 867 559 869 870 922 560 +6 867 868 870 871 1145 1146 +6 869 868 871 872 873 922 +6 869 870 872 1146 1147 1148 +6 871 870 873 874 1151 1148 +6 872 870 874 875 922 920 +6 872 873 875 876 1170 1151 +6 874 873 876 877 919 920 +6 874 875 877 878 879 1170 +6 876 875 878 918 882 919 +6 876 877 879 880 881 882 +6 876 878 880 884 886 1170 +6 879 878 881 884 885 891 +6 880 878 882 883 891 892 +6 881 878 883 917 918 877 +6 881 882 912 892 913 917 +6 879 880 885 886 887 888 +6 884 880 888 889 890 891 +6 879 884 887 1964 1169 1170 +6 886 884 888 1965 1964 2075 +6 887 884 885 889 2075 2076 +6 888 885 890 2076 2077 2081 +6 889 885 891 893 894 2081 +6 890 885 880 881 892 893 +6 891 881 893 896 912 883 +6 891 892 890 894 895 896 +6 890 893 895 897 898 2081 +6 894 893 896 897 909 910 +6 895 893 892 910 911 912 +6 894 895 898 899 900 909 +6 894 897 899 901 2081 2080 +6 898 897 900 901 902 906 +6 899 897 906 907 908 909 +6 898 899 902 903 2080 2082 +6 901 899 903 904 905 906 +6 901 902 904 2082 2083 2084 +6 903 902 905 2084 2085 1565 +6 904 902 906 1563 1564 1565 +6 905 902 899 900 907 1563 +6 906 900 908 1543 1563 1536 +6 907 900 909 1522 1523 1536 +6 908 900 897 895 910 1522 +6 909 895 896 911 1520 1522 +6 910 896 912 1521 1520 914 +6 911 896 892 883 913 914 +6 912 883 914 915 916 917 +6 912 913 915 2474 1521 911 +6 914 913 916 574 576 2474 +6 915 913 917 9741 573 574 +6 916 913 883 882 918 9741 +6 917 882 877 919 9742 9741 +6 918 877 875 920 921 9742 +6 919 875 921 562 922 873 +6 919 920 562 9743 9742 563 +6 562 920 873 870 868 560 +6 154 155 924 1248 1249 1250 +6 923 155 156 925 1250 1251 +6 924 156 157 926 1251 1252 +6 925 157 158 927 1252 1253 +6 926 158 159 928 1253 1254 +6 927 159 160 929 1254 1255 +6 928 160 161 930 1255 1256 +6 929 161 162 931 1256 1257 +6 930 162 163 651 932 1257 +6 931 651 933 1257 1258 1259 +6 932 651 652 934 1259 1260 +6 933 652 653 935 1260 1261 +6 934 653 654 936 1261 1262 +6 935 654 655 937 1262 1263 +6 936 655 656 938 1263 1264 +6 937 656 657 939 1264 1265 +6 938 657 658 940 1265 1266 +6 939 658 659 941 1266 1267 +6 940 659 660 942 1267 1268 +6 941 660 661 943 1268 1269 +6 942 661 662 944 1269 1270 +6 943 662 663 945 1270 1271 +6 944 663 664 946 1271 1272 +6 945 664 665 947 1272 1273 +6 946 665 666 948 1273 1274 +6 947 666 667 949 1274 1275 +6 948 667 668 950 1275 1276 +6 949 668 669 951 1276 1277 +6 950 669 670 952 1277 1278 +6 951 670 671 953 1278 1279 +6 952 671 672 954 1279 1280 +6 953 672 673 955 1280 1281 +6 954 673 674 956 1281 1282 +6 955 674 675 957 1282 1283 +6 956 675 676 958 1283 1284 +6 957 676 677 959 1284 1285 +6 958 677 678 960 1285 1286 +6 959 678 679 961 1286 1287 +6 960 679 680 962 1287 1288 +6 961 680 681 963 1288 1289 +6 962 681 682 964 1289 1290 +6 963 682 683 965 1290 1291 +6 964 683 684 966 1291 1292 +6 965 684 685 967 1292 1293 +6 966 685 686 968 1293 1294 +6 967 686 687 969 1294 1295 +6 968 687 688 970 1295 1296 +6 969 688 689 971 1296 1297 +6 970 689 690 972 1297 1298 +6 971 690 691 973 1298 1299 +6 972 691 692 694 974 1299 +5 973 694 695 975 1299 +6 974 695 696 976 1299 1300 +6 975 696 697 977 1300 1301 +6 976 697 698 978 1301 1302 +6 977 698 699 979 1302 1303 +6 978 699 700 980 1303 1304 +6 979 700 701 981 1304 1305 +6 980 701 702 982 1305 1306 +6 981 702 703 983 1306 1307 +6 982 703 704 984 1307 1308 +6 983 704 705 985 1308 1309 +6 984 705 706 986 1309 1310 +6 985 706 707 987 1310 1311 +6 986 707 708 988 1311 1312 +6 987 708 709 989 1312 1313 +6 988 709 710 990 1313 1314 +6 989 710 711 991 1314 1315 +6 990 711 712 992 1315 1316 +6 991 712 713 993 1316 1317 +6 992 713 714 994 1317 1318 +6 993 714 715 995 1318 1319 +6 994 715 716 996 1319 1320 +6 995 716 717 997 1320 1321 +6 996 717 718 998 1321 1322 +6 997 718 719 999 1322 1323 +6 998 719 720 1000 1323 1324 +6 999 720 721 1001 1324 1325 +6 1000 721 722 1002 1325 1326 +6 1001 722 723 1003 1326 1327 +6 1002 723 724 1004 1327 1328 +6 1003 724 725 1005 1328 1329 +6 1004 725 726 1006 1329 1330 +6 1005 726 727 1007 1330 1331 +6 1006 727 728 1008 1331 1332 +6 1007 728 729 1009 1332 1333 +6 1008 729 730 1010 1333 1334 +6 1009 730 731 1011 1334 1335 +6 1010 731 732 1012 1335 1336 +6 1011 732 733 1013 1014 1336 +6 1012 733 1014 1015 1016 734 +6 1012 1013 1015 1336 1337 1338 +6 1014 1013 1016 1338 1339 1340 +6 1015 1013 734 735 1017 1340 +6 1016 735 736 1018 1340 1341 +6 1017 736 737 1019 1341 1342 +6 1018 737 738 1020 1342 1343 +6 1019 738 739 1021 1343 1344 +6 1020 739 740 1022 1344 1345 +6 1021 740 741 1023 1345 1346 +6 1022 741 742 743 1024 1346 +6 1023 743 1025 1346 1347 1348 +6 1024 743 744 1026 1348 1349 +6 1025 744 745 1027 1349 1350 +6 1026 745 746 1028 1350 1351 +6 1027 746 747 1029 1351 1352 +6 1028 747 748 1030 1352 1353 +6 1029 748 749 1031 1353 1354 +6 1030 749 750 1032 1354 1355 +6 1031 750 751 1033 1355 1356 +6 1032 751 752 1034 1356 1357 +6 1033 752 753 1035 1357 1358 +6 1034 753 754 1036 1358 1359 +6 1035 754 755 1037 1359 1360 +6 1036 755 756 1038 1360 1361 +6 1037 756 757 1039 1361 1362 +6 1038 757 758 1040 1362 1363 +6 1039 758 759 1041 1363 1364 +6 1040 759 760 1042 1364 1365 +6 1041 760 761 1043 1365 1366 +6 1042 761 762 1044 1366 1367 +6 1043 762 763 1045 1367 1368 +6 1044 763 764 1046 1368 1369 +6 1045 764 765 1047 1369 1370 +6 1046 765 766 1048 1370 1371 +6 1047 766 767 1049 1371 1372 +6 1048 767 768 1050 1372 1373 +6 1049 768 769 1051 1373 1374 +6 1050 769 770 1052 1374 1375 +6 1051 770 771 1053 1375 1376 +6 1052 771 772 1054 1376 1377 +6 1053 772 773 1055 1377 1378 +6 1054 773 774 1056 1378 1379 +6 1055 774 775 1057 1379 1380 +6 1056 775 776 1058 1380 1381 +6 1057 776 777 1059 1381 1382 +6 1058 777 778 1060 1382 1383 +6 1059 778 779 1061 1383 1384 +6 1060 779 780 1062 1384 1385 +6 1061 780 781 1063 1385 1386 +6 1062 781 782 1064 1386 1387 +6 1063 782 783 1065 1387 1388 +6 1064 783 784 1066 1388 1389 +6 1065 784 785 1067 1389 1390 +6 1066 785 786 1068 1390 1391 +6 1067 786 787 1069 1391 1392 +6 1068 787 788 1070 1392 1393 +6 1069 788 789 1071 1393 1394 +6 1070 789 790 1072 1394 1395 +6 1071 790 791 1073 1395 1396 +6 1072 791 792 1074 1396 1397 +6 1073 792 793 1075 1397 1398 +6 1074 793 794 1076 1398 1399 +6 1075 794 795 1077 1399 1400 +6 1076 795 796 1078 1400 1401 +6 1077 796 797 1079 1401 1402 +6 1078 797 798 1080 1402 1403 +6 1079 798 799 1081 1403 1404 +6 1080 799 800 1082 1404 1405 +6 1081 800 801 1083 1405 1406 +6 1082 801 802 1084 1406 1407 +6 1083 802 803 1085 1407 1408 +6 1084 803 804 1086 1408 1409 +6 1085 804 805 1087 1409 1410 +6 1086 805 806 1088 1410 1411 +6 1087 806 807 1089 1411 1412 +6 1088 807 808 1090 1412 1413 +6 1089 808 809 1091 1413 1414 +6 1090 809 810 1092 1414 1415 +6 1091 810 811 1093 1415 1416 +6 1092 811 812 1094 1416 1417 +6 1093 812 813 1095 1417 1418 +6 1094 813 814 1096 1418 1419 +6 1095 814 815 1097 1419 1420 +6 1096 815 816 1098 1420 1421 +6 1097 816 817 1099 1421 1422 +6 1098 817 818 1100 1422 1423 +6 1099 818 819 1101 1423 1424 +6 1100 819 820 1102 1424 1425 +6 1101 820 821 1103 1425 1426 +6 1102 821 822 1104 1426 1427 +6 1103 822 823 1105 1427 1428 +6 1104 823 824 1106 1428 1429 +6 1105 824 825 1107 1429 1430 +6 1106 825 826 1108 1430 1431 +6 1107 826 827 1109 1431 1432 +6 1108 827 828 1110 1432 1433 +6 1109 828 829 1111 1433 1434 +6 1110 829 830 1112 1434 1435 +6 1111 830 831 1113 1435 1436 +6 1112 831 832 1114 1436 1115 +6 1113 832 833 834 835 1115 +6 1114 835 1116 1436 1113 1437 +5 1115 835 836 1117 1437 +6 1116 836 837 1118 1437 1438 +6 1117 837 838 1119 1438 1439 +6 1118 838 839 1120 1439 1440 +6 1119 839 840 1121 1440 1441 +6 1120 840 841 1122 1441 1442 +6 1121 841 842 1123 1442 1443 +6 1122 842 843 1124 1443 1444 +6 1123 843 844 1125 1444 1445 +6 1124 844 845 1126 1445 1446 +6 1125 845 846 1127 1446 1447 +6 1126 846 847 1128 1447 1448 +6 1127 847 848 1129 1448 1449 +6 1128 848 849 851 1130 1449 +6 1129 851 1131 1449 1450 1451 +6 1130 851 852 1132 1451 1452 +6 1131 852 854 1133 1452 1453 +6 1132 854 1134 1456 1453 1152 +6 1133 854 855 856 1135 1152 +6 1134 856 857 1136 1152 1153 +6 1135 857 858 1137 1153 1154 +6 1136 858 859 860 1138 1154 +6 1137 860 1139 1154 1155 1156 +6 1138 860 861 1140 1156 1157 +6 1139 861 862 1141 1157 1158 +6 1140 862 1142 1158 1159 1143 +6 1141 862 863 864 865 1143 +6 1142 865 866 1144 1159 1141 +6 1143 866 867 1145 1498 1159 +6 1144 867 869 1146 1498 1499 +6 1145 869 871 1147 1164 1499 +6 1146 871 1148 1149 1164 1165 +6 1147 871 1149 1150 1151 872 +6 1147 1148 1150 1165 1166 1167 +6 1149 1148 1151 1167 1168 1169 +6 1150 1148 872 1169 1170 874 +6 1134 1135 1153 1473 1456 1133 +6 1152 1135 1136 1154 1473 1490 +6 1153 1136 1137 1138 1155 1490 +6 1154 1138 1156 1490 1491 1492 +6 1155 1138 1139 1157 1492 1493 +6 1156 1139 1140 1158 1493 1494 +6 1157 1140 1141 1159 1497 1494 +6 1158 1141 1143 1144 1498 1497 +6 85 86 1161 1483 1484 1488 +6 1160 86 87 1162 1174 1488 +6 1161 87 88 1163 1174 1175 +6 1162 88 89 1175 1177 1186 +6 1146 1147 1165 1499 1527 1528 +6 1164 1147 1149 1166 1528 1533 +6 1165 1149 1167 1535 1533 1541 +6 1166 1149 1150 1168 1541 1962 +6 1167 1150 1169 1962 1963 1964 +6 1168 1150 1151 1170 886 1964 +6 1169 1151 874 886 879 876 +6 414 21 22 1172 3337 3882 +6 1171 22 23 1173 1524 3337 +6 1172 23 24 1524 1525 1526 +6 1161 1162 1175 1176 1488 1489 +6 1174 1162 1176 1163 1177 1178 +6 1174 1175 1489 1642 1643 1178 +6 1175 1163 1178 1179 1186 1183 +6 1175 1177 1179 1180 1643 1176 +6 1178 1177 1180 1181 1182 1183 +6 1178 1179 1181 1643 1644 1645 +6 1180 1179 1182 1645 1646 1647 +6 1181 1179 1183 1184 3097 1647 +6 1182 1179 1184 1185 1186 1177 +6 1182 1183 1185 3097 2241 1187 +6 1184 1183 1186 90 91 1187 +6 1185 1183 1177 1163 89 90 +6 1185 91 92 1188 2241 1184 +6 1187 92 93 1189 2241 1659 +6 1188 93 94 1190 1660 1659 +6 1189 94 95 1191 1662 1660 +6 1190 95 96 1192 1670 1662 +6 1191 96 97 1193 1670 1671 +6 1192 97 98 1194 1671 1672 +6 1193 98 99 1195 1672 1673 +6 1194 99 100 1196 1673 1674 +6 1195 100 101 1197 1674 1675 +6 1196 101 102 1198 1500 1675 +6 1197 102 103 1199 1457 1500 +6 1198 103 104 1200 1457 1458 +6 1199 104 105 1201 1458 1459 +6 1200 105 106 1202 1459 1460 +6 1201 106 107 1203 1460 1685 +6 1202 107 108 1204 1687 1685 +6 1203 108 109 1205 1687 1688 +6 1204 109 110 1206 1688 1689 +6 1205 110 111 1207 1689 1690 +6 1206 111 112 1208 1693 1690 +6 1207 112 113 1209 1693 1694 +6 1208 113 114 1210 1694 1695 +6 1209 114 115 1211 1556 1695 +6 1210 115 116 1212 1546 1556 +6 1211 116 117 1213 1546 1547 +6 1212 117 118 1214 1547 1548 +6 1213 118 119 1215 1548 1549 +6 1214 119 120 1216 1549 1550 +6 1215 120 121 1217 1553 1550 +6 1216 121 122 1218 1555 1553 +6 1217 122 123 1219 1716 1555 +6 1218 123 124 1220 1716 1717 +6 1219 124 125 1221 1717 1718 +6 1220 125 126 1222 1718 1719 +6 1221 126 127 1223 1719 1720 +6 1222 127 128 1224 1720 1721 +6 1223 128 129 1225 1721 1722 +6 1224 129 130 1226 1722 1723 +6 1225 130 131 1227 1726 1723 +6 1226 131 132 1228 1726 1727 +6 1227 132 133 1229 1727 1728 +6 1228 133 134 1230 1728 1729 +6 1229 134 135 1231 1729 1730 +6 1230 135 136 1232 1733 1730 +6 1231 136 137 1233 1733 1734 +6 1232 137 138 1234 1734 1735 +6 1233 138 139 1235 1735 1736 +6 1234 139 140 1236 1736 1737 +6 1235 140 141 1237 1737 1738 +6 1236 141 142 1238 1738 1739 +6 1237 142 143 1239 1739 1740 +6 1238 143 144 1240 1740 1741 +6 1239 144 145 1241 1741 1742 +6 1240 145 146 1242 1742 1743 +7 1241 146 147 3 148 1243 1743 +5 1242 148 149 1244 1743 +6 1243 149 150 1245 1743 1744 +6 1244 150 151 1246 1744 1745 +6 1245 151 152 1247 1745 1746 +6 1246 152 153 1248 1746 1747 +6 1247 153 154 923 1249 1747 +6 1248 923 1250 1747 1748 1749 +6 1249 923 924 1251 1749 1750 +6 1250 924 925 1252 1750 1751 +6 1251 925 926 1253 1751 1752 +6 1252 926 927 1254 1752 1753 +6 1253 927 928 1255 1753 1754 +6 1254 928 929 1256 1754 1755 +6 1255 929 930 1257 1755 1756 +6 1256 930 931 932 1258 1756 +6 1257 932 1259 1756 1757 1758 +6 1258 932 933 1260 1758 1759 +6 1259 933 934 1261 1759 1760 +6 1260 934 935 1262 1760 1761 +6 1261 935 936 1263 1761 1762 +6 1262 936 937 1264 1762 1763 +6 1263 937 938 1265 1763 1764 +6 1264 938 939 1266 1764 1765 +6 1265 939 940 1267 1765 1766 +6 1266 940 941 1268 1766 1767 +6 1267 941 942 1269 1767 1768 +6 1268 942 943 1270 1768 1769 +6 1269 943 944 1271 1769 1770 +6 1270 944 945 1272 1770 1771 +6 1271 945 946 1273 1771 1772 +6 1272 946 947 1274 1772 1773 +6 1273 947 948 1275 1773 1774 +6 1274 948 949 1276 1774 1775 +6 1275 949 950 1277 1775 1776 +6 1276 950 951 1278 1776 1777 +6 1277 951 952 1279 1777 1778 +6 1278 952 953 1280 1778 1779 +6 1279 953 954 1281 1779 1780 +6 1280 954 955 1282 1780 1781 +6 1281 955 956 1283 1781 1782 +6 1282 956 957 1284 1782 1783 +6 1283 957 958 1285 1783 1784 +6 1284 958 959 1286 1784 1785 +6 1285 959 960 1287 1785 1786 +6 1286 960 961 1288 1786 1787 +6 1287 961 962 1289 1787 1788 +6 1288 962 963 1290 1788 1789 +6 1289 963 964 1291 1789 1790 +6 1290 964 965 1292 1790 1791 +6 1291 965 966 1293 1791 1792 +6 1292 966 967 1294 1792 1793 +6 1293 967 968 1295 1793 1794 +6 1294 968 969 1296 1794 1795 +6 1295 969 970 1297 1795 1796 +6 1296 970 971 1298 1796 1797 +6 1297 971 972 1299 1797 1300 +6 1298 972 973 974 975 1300 +7 1299 975 976 1301 1797 1298 2100 +6 1300 976 977 1302 2100 2101 +6 1301 977 978 1303 2101 2102 +6 1302 978 979 1304 2102 2103 +6 1303 979 980 1305 2103 2104 +6 1304 980 981 1306 2104 2105 +6 1305 981 982 1307 2105 2106 +6 1306 982 983 1308 1798 2106 +6 1307 983 984 1309 1798 1799 +6 1308 984 985 1310 1799 1800 +6 1309 985 986 1311 1800 1801 +6 1310 986 987 1312 1801 1802 +6 1311 987 988 1313 1802 1803 +6 1312 988 989 1314 1803 1804 +6 1313 989 990 1315 1804 1805 +6 1314 990 991 1316 1805 1806 +6 1315 991 992 1317 1806 1807 +6 1316 992 993 1318 1807 1808 +6 1317 993 994 1319 1808 1809 +6 1318 994 995 1320 1809 1810 +6 1319 995 996 1321 1810 1811 +6 1320 996 997 1322 1811 1812 +6 1321 997 998 1323 1812 1813 +6 1322 998 999 1324 1813 1814 +6 1323 999 1000 1325 1814 1815 +6 1324 1000 1001 1326 1815 1816 +6 1325 1001 1002 1327 1816 1817 +6 1326 1002 1003 1328 1817 1818 +6 1327 1003 1004 1329 1818 1819 +6 1328 1004 1005 1330 1819 1820 +6 1329 1005 1006 1331 1820 1821 +6 1330 1006 1007 1332 1821 1822 +6 1331 1007 1008 1333 1822 1823 +6 1332 1008 1009 1334 1823 1824 +6 1333 1009 1010 1335 1824 1825 +6 1334 1010 1011 1336 1825 1826 +6 1335 1011 1012 1014 1337 1826 +6 1336 1014 1338 1826 1827 1828 +6 1337 1014 1015 1339 1828 1829 +6 1338 1015 1340 1829 1830 1831 +6 1339 1015 1016 1017 1341 1831 +6 1340 1017 1018 1342 1831 1832 +6 1341 1018 1019 1343 1832 1833 +6 1342 1019 1020 1344 1833 1834 +6 1343 1020 1021 1345 1834 1835 +6 1344 1021 1022 1346 1835 1836 +6 1345 1022 1023 1024 1347 1836 +6 1346 1024 1348 1836 1837 1838 +6 1347 1024 1025 1349 1838 1839 +6 1348 1025 1026 1350 1839 1840 +6 1349 1026 1027 1351 1840 1841 +6 1350 1027 1028 1352 1841 1842 +6 1351 1028 1029 1353 1842 1843 +6 1352 1029 1030 1354 1843 1844 +6 1353 1030 1031 1355 1844 1845 +6 1354 1031 1032 1356 1845 1846 +6 1355 1032 1033 1357 1846 1847 +6 1356 1033 1034 1358 1847 1848 +6 1357 1034 1035 1359 1848 1849 +6 1358 1035 1036 1360 1849 1850 +6 1359 1036 1037 1361 1850 1851 +6 1360 1037 1038 1362 1851 1852 +6 1361 1038 1039 1363 1852 1853 +6 1362 1039 1040 1364 1853 1854 +6 1363 1040 1041 1365 1854 1855 +6 1364 1041 1042 1366 1855 1856 +6 1365 1042 1043 1367 1856 1857 +6 1366 1043 1044 1368 1857 1858 +6 1367 1044 1045 1369 1858 1859 +6 1368 1045 1046 1370 1859 1860 +6 1369 1046 1047 1371 1860 1861 +6 1370 1047 1048 1372 1861 1862 +6 1371 1048 1049 1373 1862 1863 +6 1372 1049 1050 1374 1863 1864 +6 1373 1050 1051 1375 1864 1865 +6 1374 1051 1052 1376 1865 1866 +6 1375 1052 1053 1377 1866 1867 +6 1376 1053 1054 1378 1867 1868 +6 1377 1054 1055 1379 1868 1869 +6 1378 1055 1056 1380 1869 1870 +6 1379 1056 1057 1381 1870 1871 +6 1380 1057 1058 1382 1871 1872 +6 1381 1058 1059 1383 1872 1873 +6 1382 1059 1060 1384 1873 1874 +6 1383 1060 1061 1385 1874 1875 +6 1384 1061 1062 1386 1875 1876 +6 1385 1062 1063 1387 1876 1877 +6 1386 1063 1064 1388 1877 1878 +6 1387 1064 1065 1389 1878 1879 +6 1388 1065 1066 1390 1879 1880 +6 1389 1066 1067 1391 1880 1881 +6 1390 1067 1068 1392 1881 1882 +6 1391 1068 1069 1393 1882 1883 +6 1392 1069 1070 1394 1883 1884 +6 1393 1070 1071 1395 1884 1885 +6 1394 1071 1072 1396 1885 1886 +6 1395 1072 1073 1397 1886 1887 +6 1396 1073 1074 1398 1887 1888 +6 1397 1074 1075 1399 1888 1889 +6 1398 1075 1076 1400 1889 1890 +6 1399 1076 1077 1401 1890 1891 +6 1400 1077 1078 1402 1891 1892 +6 1401 1078 1079 1403 1892 1893 +6 1402 1079 1080 1404 1893 1894 +6 1403 1080 1081 1405 1894 1895 +6 1404 1081 1082 1406 1895 1896 +6 1405 1082 1083 1407 1896 1897 +6 1406 1083 1084 1408 1897 1898 +6 1407 1084 1085 1409 1898 1899 +6 1408 1085 1086 1410 1899 1900 +6 1409 1086 1087 1411 1900 1901 +6 1410 1087 1088 1412 1901 1902 +6 1411 1088 1089 1413 1902 1903 +6 1412 1089 1090 1414 1903 1904 +6 1413 1090 1091 1415 1904 1905 +6 1414 1091 1092 1416 1905 1906 +6 1415 1092 1093 1417 1906 1907 +6 1416 1093 1094 1418 1907 1908 +6 1417 1094 1095 1419 1908 1909 +6 1418 1095 1096 1420 1909 1910 +6 1419 1096 1097 1421 1910 1911 +6 1420 1097 1098 1422 1911 1912 +6 1421 1098 1099 1423 1912 1913 +6 1422 1099 1100 1424 1913 1914 +6 1423 1100 1101 1425 1914 1915 +6 1424 1101 1102 1426 1915 1916 +6 1425 1102 1103 1427 1916 1917 +6 1426 1103 1104 1428 1917 1918 +6 1427 1104 1105 1429 1918 1919 +6 1428 1105 1106 1430 1919 1920 +6 1429 1106 1107 1431 1920 1921 +6 1430 1107 1108 1432 1921 1922 +6 1431 1108 1109 1433 1922 1923 +6 1432 1109 1110 1434 1923 1924 +6 1433 1110 1111 1435 1924 1925 +6 1434 1111 1112 1436 1925 1926 +6 1435 1112 1113 1115 1437 1926 +6 1436 1115 1116 1117 1438 1926 +6 1437 1117 1118 1439 1926 1927 +6 1438 1118 1119 1440 1927 1928 +6 1439 1119 1120 1441 1928 1929 +6 1440 1120 1121 1442 1929 1930 +6 1441 1121 1122 1443 1930 1931 +6 1442 1122 1123 1444 1931 1932 +6 1443 1123 1124 1445 1461 1932 +6 1444 1124 1125 1446 1461 1462 +6 1445 1125 1126 1447 1462 1463 +6 1446 1126 1127 1448 1463 1464 +6 1447 1127 1128 1449 1464 1465 +6 1448 1128 1129 1130 1450 1465 +6 1449 1130 1451 1465 1466 1467 +6 1450 1130 1131 1452 1467 1468 +6 1451 1131 1132 1453 1454 1468 +6 1452 1132 1454 1455 1456 1133 +6 1452 1453 1455 1468 1469 1470 +6 1454 1453 1456 1470 1471 1472 +6 1455 1453 1133 1472 1473 1152 +6 1198 1199 1458 1500 1501 1679 +6 1457 1199 1200 1459 1679 1680 +6 1458 1200 1201 1460 1680 1681 +6 1459 1201 1202 1681 1684 1685 +6 1444 1445 1462 1932 1933 1934 +6 1461 1445 1446 1463 1934 1935 +6 1462 1446 1447 1464 1935 1936 +6 1463 1447 1448 1465 1936 1937 +6 1464 1448 1449 1450 1466 1937 +6 1465 1450 1467 1937 1938 1939 +6 1466 1450 1451 1468 1939 1940 +6 1467 1451 1452 1454 1469 1940 +6 1468 1454 1470 1940 1941 1942 +6 1469 1454 1455 1471 1942 1943 +6 1470 1455 1472 1943 1944 1945 +6 1471 1455 1456 1473 1945 1946 +6 1472 1456 1152 1153 1490 1946 +7 76 2 1475 1608 1604 1609 1618 +6 1474 2 77 1476 1620 1618 +6 1475 77 78 1477 1620 1621 +6 1476 78 79 1478 1621 1622 +6 1477 79 80 1479 1630 1622 +6 1478 80 81 1480 1630 1631 +6 1479 81 82 1481 1631 1632 +6 1480 82 83 1482 1635 1632 +6 1481 83 84 1483 1485 1635 +6 1482 84 85 1160 1484 1485 +6 1483 1160 1485 1486 1487 1488 +6 1483 1484 1486 1502 1635 1482 +6 1485 1484 1487 1502 1503 1504 +6 1486 1484 1488 1504 1505 1489 +6 1487 1484 1160 1161 1174 1489 +6 1488 1174 1176 1505 1487 1642 +6 1473 1153 1154 1155 1491 1946 +6 1490 1155 1492 1946 1947 1948 +6 1491 1155 1156 1493 1948 1949 +6 1492 1156 1157 1494 1495 1949 +6 1493 1157 1495 1496 1497 1158 +6 1493 1494 1496 1951 1949 1952 +6 1495 1494 1497 1952 1530 1529 +6 1496 1494 1158 1159 1498 1529 +6 1144 1145 1499 1159 1497 1529 +6 1498 1145 1146 1164 1527 1529 +6 1197 1198 1457 1501 1675 1676 +6 1500 1457 1676 1677 1678 1679 +6 1485 1486 1503 1637 1634 1635 +6 1502 1486 1504 1637 1638 1639 +6 1503 1486 1487 1505 1639 1640 +6 1504 1487 1489 1640 1641 1642 +6 583 589 590 1507 1508 582 +6 1506 590 1508 1509 1513 1514 +6 1506 1507 1509 1510 1517 582 +6 1508 1507 1510 1511 1512 1513 +6 1508 1509 1511 1517 1518 1519 +6 1510 1509 1512 1523 1519 1537 +6 1511 1509 1513 1537 1538 1539 +6 1512 1509 1507 1514 601 1539 +6 1513 1507 601 599 591 590 +6 577 578 581 1516 2474 576 +6 1515 581 1517 1518 1521 2474 +6 1516 581 582 1508 1510 1518 +6 1517 1510 1519 1520 1521 1516 +6 1518 1510 1520 1522 1523 1511 +6 1518 1519 1521 911 910 1522 +6 1518 1520 911 1516 2474 914 +6 910 1520 1519 1523 908 909 +6 1522 1519 1511 908 1536 1537 +6 1172 1173 1525 3337 3338 4250 +6 1524 1173 1526 3130 2205 4250 +6 1525 1173 24 25 3130 9781 +6 1499 1164 1528 1529 1530 1531 +6 1527 1164 1165 1531 1532 1533 +6 1497 1498 1499 1527 1530 1496 +6 1529 1527 1531 1952 1496 1953 +6 1530 1527 1528 1532 1953 1954 +6 1531 1528 1533 1534 1954 1955 +6 1532 1528 1534 1535 1166 1165 +6 1532 1533 1535 1955 1956 1957 +6 1534 1533 1166 1541 1960 1957 +6 908 1523 1537 1542 1543 907 +6 1536 1523 1511 1512 1538 1542 +6 1537 1512 1539 1540 1545 1542 +6 1538 1512 1513 601 602 1540 +6 1539 602 1538 1582 1545 1583 +6 1535 1166 1167 1960 1961 1962 +6 1536 1537 1543 1544 1545 1538 +6 1536 1542 1544 1562 1563 907 +6 1543 1542 1545 1562 1580 1577 +6 1544 1542 1538 1582 1580 1540 +6 1211 1212 1547 1556 1557 1558 +6 1546 1212 1213 1548 1561 1558 +6 1547 1213 1214 1549 1710 1561 +6 1548 1214 1215 1550 1551 1710 +6 1549 1215 1551 1552 1553 1216 +6 1549 1550 1552 1710 1711 1712 +6 1551 1550 1553 1554 1712 1713 +6 1552 1550 1554 1555 1217 1216 +6 1552 1553 1555 1713 1714 1715 +6 1554 1553 1217 1715 1716 1218 +6 1210 1211 1546 1557 1695 1696 +6 1556 1546 1558 1559 1696 1697 +6 1557 1546 1559 1560 1561 1547 +6 1557 1558 1560 1697 1698 1699 +6 1559 1558 1561 1699 1700 1709 +6 1560 1558 1547 1709 1710 1548 +6 1543 1544 1563 1564 1576 1577 +6 1543 1562 1564 905 907 906 +6 1563 1562 905 1565 1566 1576 +6 905 1564 1566 1567 2085 904 +6 1565 1564 1567 1568 1569 1576 +6 1565 1566 1568 2085 3766 3767 +6 1567 1566 1569 1570 1571 3767 +6 1568 1566 1570 1574 1575 1576 +6 1568 1569 1571 1572 1573 1574 +7 1568 1570 1572 3769 3767 6317 6319 +5 1571 1570 1573 6319 6320 +7 1572 1570 1574 6320 6361 6360 2475 +6 1573 1570 1569 1575 1578 2475 +6 1574 1569 1576 1577 1578 1579 +6 1575 1569 1566 1564 1562 1577 +6 1576 1562 1575 1579 1580 1544 +6 1574 1575 1579 1586 1587 2475 +6 1578 1575 1577 1580 1581 1586 +6 1579 1577 1544 1581 1582 1545 +6 1579 1580 1582 1584 1585 1586 +6 1581 1580 1545 1540 1583 1584 +6 1582 1540 1584 1602 603 602 +6 1582 1583 1581 1585 1601 1602 +6 1581 1584 1586 1591 1588 1601 +6 1581 1585 1579 1578 1587 1588 +6 1578 1586 1588 1589 2475 2476 +6 1587 1586 1589 1590 1591 1585 +6 1587 1588 1590 6354 6353 2476 +6 1589 1588 1591 1592 1594 6354 +6 1590 1588 1585 1592 1593 1601 +6 1590 1591 1593 1594 1595 1596 +6 1592 1591 1599 1596 1600 1601 +6 1590 1592 1595 6358 6356 6354 +6 1594 1592 1596 1597 3970 6358 +6 1595 1592 1597 1598 1599 1593 +6 1595 1596 1598 3970 3969 6556 +6 1597 1596 1599 6556 6557 611 +6 1598 1596 1593 1600 611 609 +6 1599 1593 1601 1602 608 609 +6 1600 1593 1591 1585 1584 1602 +6 1600 1601 1584 1583 603 608 +6 74 75 1604 428 1605 1608 +5 1603 75 76 1608 1474 +6 428 1603 1606 1607 1608 3519 +6 428 1605 1607 2493 409 3516 +6 1606 1605 3518 3516 1613 3519 +7 1605 1603 1604 1474 1609 1610 3519 +5 1608 1474 1610 1611 1618 +6 1608 1609 1611 1612 1613 3519 +6 1610 1609 1612 1616 1617 1618 +6 1610 1611 1613 1614 1615 1616 +7 1610 1612 1614 3518 1607 3519 3523 +6 1613 1612 1615 3523 3524 3528 +6 1614 1612 1616 3093 3544 3528 +6 1615 1612 1611 1617 3093 3094 +6 1616 1611 1618 1619 3094 1624 +7 1617 1611 1619 1620 1475 1609 1474 +6 1617 1618 1620 1621 1623 1624 +5 1619 1618 1475 1476 1621 +6 1620 1476 1477 1622 1623 1619 +6 1621 1477 1623 1629 1630 1478 +6 1621 1622 1619 1624 1625 1629 +7 1619 1623 1625 1626 1617 3094 4367 +6 1624 1623 1626 1627 1628 1629 +5 1624 1625 1627 4376 4367 +7 1626 1625 1628 4377 4376 2862 7215 +6 1627 1625 1629 2861 1633 2862 +6 1628 1625 1623 1622 1630 2861 +6 1629 1622 1478 1479 1631 2861 +6 1630 1479 1480 1632 1633 2861 +6 1631 1480 1633 1634 1635 1481 +7 1631 1632 1634 1636 2861 1628 2862 +6 1633 1632 1635 1636 1637 1502 +6 1634 1632 1481 1502 1485 1482 +5 1633 1634 1637 2862 2863 +7 1636 1634 1502 1503 1638 2863 2864 +5 1637 1503 1639 2864 2865 +6 1638 1503 1504 1640 2865 2866 +6 1639 1504 1505 1641 2866 2867 +6 1640 1505 1642 2479 2490 2867 +6 1641 1505 1489 1176 1643 2479 +6 1642 1176 1178 1180 1644 2479 +6 1643 1180 1645 2479 2480 2481 +6 1644 1180 1181 1646 2481 1650 +6 1645 1181 1647 1648 1649 1650 +6 1646 1181 1648 1655 3097 1182 +6 1646 1647 1649 1653 1654 1655 +6 1646 1648 1650 1651 1652 1653 +6 1646 1649 1651 2481 1645 2495 +6 1650 1649 1652 2495 2496 2497 +6 1651 1649 1653 2497 2498 2499 +6 1652 1649 1648 1654 2499 2500 +6 1653 1648 1655 1656 2500 2501 +6 1654 1648 1647 1656 1657 3097 +6 1654 1655 1657 1658 2501 2812 +6 1656 1655 1658 1659 2241 3097 +6 1656 1657 1659 1660 1661 2812 +6 1658 1657 1660 1189 1188 2241 +6 1658 1659 1661 1662 1190 1189 +6 1658 1660 1662 1663 1664 2812 +6 1661 1660 1663 1670 1191 1190 +6 1661 1662 1664 1665 1669 1670 +6 1661 1663 1665 1666 2812 2811 +6 1664 1663 1666 1667 1668 1669 +6 1664 1665 1667 2811 2813 2814 +6 1666 1665 1668 2814 2815 2816 +6 1667 1665 1669 2816 2821 2822 +6 1668 1665 1663 1670 1671 2822 +6 1669 1663 1662 1191 1192 1671 +6 1670 1192 1193 1672 2822 1669 +6 1671 1193 1194 1673 2823 2822 +6 1672 1194 1195 1674 3147 2823 +6 1673 1195 1196 1675 3147 3412 +6 1674 1196 1197 1500 1676 3412 +6 1675 1500 1501 1677 3412 3413 +6 1676 1501 1678 3413 3414 3415 +6 1677 1501 1679 3415 5381 5382 +6 1678 1501 1457 1458 1680 5381 +6 1679 1458 1459 1681 1682 5381 +6 1680 1459 1460 1682 1683 1684 +6 1680 1681 1683 3774 5383 5381 +6 1682 1681 1684 3774 3775 3776 +6 1683 1681 1460 1685 1686 3776 +6 1684 1460 1686 1687 1203 1202 +6 1684 1685 1687 3776 3777 3781 +6 1686 1685 1203 1204 1688 3781 +6 1687 1204 1205 1689 3781 3782 +6 1688 1205 1206 1690 1691 3782 +6 1689 1206 1691 1692 1693 1207 +6 1689 1690 1692 3782 3783 3784 +6 1691 1690 1693 3784 3785 3786 +6 1692 1690 1207 1208 1694 3786 +6 1693 1208 1209 1695 3786 3416 +6 1694 1209 1210 1556 1696 3416 +6 1695 1556 1557 1697 3416 3417 +6 1696 1557 1559 1698 3417 3418 +6 1697 1559 1699 1703 2223 3418 +6 1698 1559 1560 1700 1701 1703 +6 1699 1560 1701 1702 1708 1709 +6 1699 1700 1702 1703 1704 1705 +6 1701 1700 1705 1706 1707 1708 +6 1699 1701 1704 1698 2223 2224 +6 1703 1701 1705 2224 2225 2226 +6 1704 1701 1702 1706 2226 2227 +6 1705 1702 1707 2227 2228 2229 +6 1706 1702 1708 2229 2230 2231 +6 1707 1702 1700 1709 1711 2231 +6 1708 1700 1560 1561 1710 1711 +6 1709 1561 1548 1549 1551 1711 +6 1710 1551 1712 2231 1708 1709 +6 1711 1551 1552 1713 2232 2231 +6 1712 1552 1554 1714 2240 2232 +6 1713 1554 1715 2240 2560 2564 +6 1714 1554 1555 1716 2564 2565 +6 1715 1555 1218 1219 1717 2565 +6 1716 1219 1220 1718 2565 2566 +6 1717 1220 1221 1719 2569 2566 +6 1718 1221 1222 1720 3463 2569 +6 1719 1222 1223 1721 3462 3463 +6 1720 1223 1224 1722 3469 3462 +6 1721 1224 1225 1723 1724 3469 +6 1722 1225 1724 1725 1726 1226 +6 1722 1723 1725 2172 3467 3469 +6 1724 1723 1726 2172 2173 2174 +6 1725 1723 1226 1227 1727 2174 +6 1726 1227 1228 1728 2174 2175 +6 1727 1228 1229 1729 2175 2176 +6 1728 1229 1230 1730 1731 2176 +6 1729 1230 1731 1732 1733 1231 +6 1729 1730 1732 2178 2176 2808 +6 1731 1730 1733 3404 2808 3405 +6 1732 1730 1231 1232 1734 3405 +6 1733 1232 1233 1735 3405 3406 +6 1734 1233 1234 1736 3406 3407 +6 1735 1234 1235 1737 3407 3408 +6 1736 1235 1236 1738 3408 3409 +6 1737 1236 1237 1739 3409 3410 +6 1738 1237 1238 1740 3410 3411 +6 1739 1238 1239 1741 3197 3411 +6 1740 1239 1240 1742 3191 3197 +6 1741 1240 1241 1743 3191 1744 +6 1742 1241 1242 1243 1244 1744 +7 1743 1244 1245 1745 3191 1742 3199 +6 1744 1245 1246 1746 2893 3199 +6 1745 1246 1247 1747 2751 2893 +6 1746 1247 1248 1249 1748 2751 +6 1747 1249 1749 2233 2751 2752 +6 1748 1249 1250 1750 2233 2234 +6 1749 1250 1251 1751 2237 2234 +6 1750 1251 1252 1752 2247 2237 +6 1751 1252 1253 1753 2247 2253 +6 1752 1253 1254 1754 2253 2254 +6 1753 1254 1255 1755 2254 2255 +6 1754 1255 1256 1756 2255 2256 +6 1755 1256 1257 1258 1757 2256 +6 1756 1258 1758 2256 2257 2258 +6 1757 1258 1259 1759 2258 2259 +6 1758 1259 1260 1760 2259 2260 +6 1759 1260 1261 1761 2260 2261 +6 1760 1261 1262 1762 2261 2262 +6 1761 1262 1263 1763 2262 2263 +6 1762 1263 1264 1764 2263 2264 +6 1763 1264 1265 1765 2264 2265 +6 1764 1265 1266 1766 2265 2266 +6 1765 1266 1267 1767 2266 2267 +6 1766 1267 1268 1768 2267 2268 +6 1767 1268 1269 1769 2268 2269 +6 1768 1269 1270 1770 2269 2270 +6 1769 1270 1271 1771 2270 2271 +6 1770 1271 1272 1772 2271 2272 +6 1771 1272 1273 1773 2272 2273 +6 1772 1273 1274 1774 2273 2274 +6 1773 1274 1275 1775 2274 2275 +6 1774 1275 1276 1776 2275 2276 +6 1775 1276 1277 1777 2276 2277 +6 1776 1277 1278 1778 2277 2278 +6 1777 1278 1279 1779 2278 2279 +6 1778 1279 1280 1780 2279 2280 +6 1779 1280 1281 1781 2280 2281 +6 1780 1281 1282 1782 2281 2282 +6 1781 1282 1283 1783 2282 2283 +6 1782 1283 1284 1784 2283 2284 +6 1783 1284 1285 1785 2284 2285 +6 1784 1285 1286 1786 2285 2286 +6 1785 1286 1287 1787 2286 2287 +6 1786 1287 1288 1788 2287 2288 +6 1787 1288 1289 1789 2288 2289 +6 1788 1289 1290 1790 2289 2290 +6 1789 1290 1291 1791 2290 2291 +6 1790 1291 1292 1792 2291 2292 +6 1791 1292 1293 1793 2292 2293 +6 1792 1293 1294 1794 2293 2294 +6 1793 1294 1295 1795 2294 2295 +6 1794 1295 1296 1796 2098 2295 +6 1795 1296 1297 1797 2098 2099 +6 1796 1297 1298 1300 2099 2100 +6 1307 1308 1799 2106 2107 2108 +6 1798 1308 1309 1800 2108 2109 +6 1799 1309 1310 1801 2109 2110 +6 1800 1310 1311 1802 2110 2111 +6 1801 1311 1312 1803 2111 2112 +6 1802 1312 1313 1804 2112 2113 +6 1803 1313 1314 1805 2113 2114 +6 1804 1314 1315 1806 2114 2115 +6 1805 1315 1316 1807 2115 2116 +6 1806 1316 1317 1808 2116 2117 +6 1807 1317 1318 1809 2117 2118 +6 1808 1318 1319 1810 2118 2119 +6 1809 1319 1320 1811 2119 2120 +6 1810 1320 1321 1812 2120 2121 +6 1811 1321 1322 1813 2121 2122 +6 1812 1322 1323 1814 2122 2123 +6 1813 1323 1324 1815 2123 2124 +6 1814 1324 1325 1816 2124 2125 +6 1815 1325 1326 1817 2125 2126 +6 1816 1326 1327 1818 2126 2127 +6 1817 1327 1328 1819 2127 2128 +6 1818 1328 1329 1820 2128 2129 +6 1819 1329 1330 1821 2129 2130 +6 1820 1330 1331 1822 2130 2131 +6 1821 1331 1332 1823 2131 2132 +6 1822 1332 1333 1824 2132 2133 +6 1823 1333 1334 1825 2133 2134 +6 1824 1334 1335 1826 2134 2135 +6 1825 1335 1336 1337 1827 2135 +6 1826 1337 1828 2135 2136 2137 +6 1827 1337 1338 1829 2137 2138 +6 1828 1338 1339 1830 2138 2139 +6 1829 1339 1831 2139 2140 2141 +6 1830 1339 1340 1341 1832 2141 +6 1831 1341 1342 1833 2141 2142 +6 1832 1342 1343 1834 2142 2143 +6 1833 1343 1344 1835 2143 2144 +6 1834 1344 1345 1836 2144 2145 +6 1835 1345 1346 1347 1837 2145 +6 1836 1347 1838 2150 2145 2165 +6 1837 1347 1348 1839 2165 2166 +6 1838 1348 1349 1840 2166 2167 +6 1839 1349 1350 1841 2167 2168 +6 1840 1350 1351 1842 2171 2168 +6 1841 1351 1352 1843 2349 2171 +6 1842 1352 1353 1844 2349 2350 +6 1843 1353 1354 1845 2350 2351 +6 1844 1354 1355 1846 2351 2352 +6 1845 1355 1356 1847 2352 2353 +6 1846 1356 1357 1848 2353 2354 +6 1847 1357 1358 1849 2354 2355 +6 1848 1358 1359 1850 2355 2356 +6 1849 1359 1360 1851 2356 2357 +6 1850 1360 1361 1852 2357 2358 +6 1851 1361 1362 1853 2358 2359 +6 1852 1362 1363 1854 2359 2360 +6 1853 1363 1364 1855 2360 2361 +6 1854 1364 1365 1856 1966 2361 +6 1855 1365 1366 1857 1966 1967 +6 1856 1366 1367 1858 1967 1968 +6 1857 1367 1368 1859 1968 1969 +6 1858 1368 1369 1860 1969 1970 +6 1859 1369 1370 1861 1970 1971 +6 1860 1370 1371 1862 1971 1972 +6 1861 1371 1372 1863 1972 1973 +6 1862 1372 1373 1864 1973 1974 +6 1863 1373 1374 1865 1974 1975 +6 1864 1374 1375 1866 1975 1976 +6 1865 1375 1376 1867 1976 1977 +6 1866 1376 1377 1868 1977 1978 +6 1867 1377 1378 1869 1978 1979 +6 1868 1378 1379 1870 1979 1980 +6 1869 1379 1380 1871 1980 1981 +6 1870 1380 1381 1872 1981 1982 +6 1871 1381 1382 1873 1982 1983 +6 1872 1382 1383 1874 1983 1984 +6 1873 1383 1384 1875 1984 1985 +6 1874 1384 1385 1876 1985 1986 +6 1875 1385 1386 1877 1986 1987 +6 1876 1386 1387 1878 1987 1988 +6 1877 1387 1388 1879 1988 1989 +6 1878 1388 1389 1880 1989 1990 +6 1879 1389 1390 1881 1990 1991 +6 1880 1390 1391 1882 1991 1992 +6 1881 1391 1392 1883 1992 1993 +6 1882 1392 1393 1884 1993 1994 +6 1883 1393 1394 1885 1994 1995 +6 1884 1394 1395 1886 1995 1996 +6 1885 1395 1396 1887 1996 1997 +6 1886 1396 1397 1888 1997 1998 +6 1887 1397 1398 1889 1998 1999 +6 1888 1398 1399 1890 1999 2000 +6 1889 1399 1400 1891 2000 2001 +6 1890 1400 1401 1892 2001 2002 +6 1891 1401 1402 1893 2002 2003 +6 1892 1402 1403 1894 2003 2004 +6 1893 1403 1404 1895 2004 2005 +6 1894 1404 1405 1896 2005 2006 +6 1895 1405 1406 1897 2006 2007 +6 1896 1406 1407 1898 2007 2008 +6 1897 1407 1408 1899 2008 2009 +6 1898 1408 1409 1900 2009 2010 +6 1899 1409 1410 1901 2010 2011 +6 1900 1410 1411 1902 2011 2012 +6 1901 1411 1412 1903 2012 2013 +6 1902 1412 1413 1904 2013 2014 +6 1903 1413 1414 1905 2014 2015 +6 1904 1414 1415 1906 2015 2016 +6 1905 1415 1416 1907 2016 2017 +6 1906 1416 1417 1908 2017 2018 +6 1907 1417 1418 1909 2018 2019 +6 1908 1418 1419 1910 2019 2020 +6 1909 1419 1420 1911 2020 2021 +6 1910 1420 1421 1912 2021 2022 +6 1911 1421 1422 1913 2022 2023 +6 1912 1422 1423 1914 2023 2024 +6 1913 1423 1424 1915 2024 2025 +6 1914 1424 1425 1916 2025 2026 +6 1915 1425 1426 1917 2026 2027 +6 1916 1426 1427 1918 2027 2028 +6 1917 1427 1428 1919 2028 2029 +6 1918 1428 1429 1920 2029 2030 +6 1919 1429 1430 1921 2030 2031 +6 1920 1430 1431 1922 2031 2032 +6 1921 1431 1432 1923 2032 2033 +6 1922 1432 1433 1924 2033 2034 +6 1923 1433 1434 1925 2034 2035 +6 1924 1434 1435 1926 2035 1927 +6 1925 1435 1436 1437 1438 1927 +7 1926 1438 1439 1928 2035 1925 2036 +6 1927 1439 1440 1929 2036 2037 +6 1928 1440 1441 1930 2037 2038 +6 1929 1441 1442 1931 2038 2039 +6 1930 1442 1443 1932 2039 2040 +7 1931 1443 1444 1461 1933 2040 2041 +5 1932 1461 1934 2041 2042 +6 1933 1461 1462 1935 2042 2043 +6 1934 1462 1463 1936 2043 2044 +6 1935 1463 1464 1937 2044 2045 +6 1936 1464 1465 1466 1938 2045 +6 1937 1466 1939 2045 2046 2047 +6 1938 1466 1467 1940 2047 2048 +6 1939 1467 1468 1469 1941 2048 +6 1940 1469 1942 2048 2049 2050 +6 1941 1469 1470 1943 2050 2051 +6 1942 1470 1471 1944 2051 2052 +6 1943 1471 1945 2052 2053 2054 +6 1944 1471 1472 1946 2054 1947 +6 1945 1472 1473 1490 1491 1947 +6 1946 1491 1948 2054 1945 2055 +6 1947 1491 1492 1949 1950 2055 +6 1948 1492 1950 1951 1495 1493 +6 1948 1949 1951 2055 2056 2057 +6 1950 1949 1495 1952 2057 2058 +6 1951 1495 1496 1530 1953 2058 +6 1952 1530 1531 1954 2058 2059 +6 1953 1531 1532 1955 2059 2060 +6 1954 1532 1534 1956 2060 2061 +6 1955 1534 1957 1958 2061 2062 +6 1956 1534 1958 1959 1960 1535 +6 1956 1957 1959 2062 2063 2064 +6 1958 1957 1960 2064 2065 2066 +6 1959 1957 1535 1541 1961 2066 +6 1960 1541 1962 2066 2067 2068 +6 1961 1541 1167 1168 1963 2068 +6 1962 1168 1964 1965 2070 2068 +6 1963 1168 1965 887 886 1169 +6 1963 1964 887 2072 2070 2075 +6 1855 1856 1967 2361 2362 2363 +6 1966 1856 1857 1968 2363 2364 +6 1967 1857 1858 1969 2364 2365 +6 1968 1858 1859 1970 2365 2366 +6 1969 1859 1860 1971 2366 2367 +6 1970 1860 1861 1972 2367 2368 +6 1971 1861 1862 1973 2368 2369 +6 1972 1862 1863 1974 2369 2370 +6 1973 1863 1864 1975 2370 2371 +6 1974 1864 1865 1976 2371 2372 +6 1975 1865 1866 1977 2372 2373 +6 1976 1866 1867 1978 2373 2374 +6 1977 1867 1868 1979 2374 2375 +6 1978 1868 1869 1980 2375 2376 +6 1979 1869 1870 1981 2376 2377 +6 1980 1870 1871 1982 2377 2378 +6 1981 1871 1872 1983 2378 2379 +6 1982 1872 1873 1984 2379 2380 +6 1983 1873 1874 1985 2380 2381 +6 1984 1874 1875 1986 2381 2382 +6 1985 1875 1876 1987 2382 2383 +6 1986 1876 1877 1988 2383 2384 +6 1987 1877 1878 1989 2384 2385 +6 1988 1878 1879 1990 2385 2386 +6 1989 1879 1880 1991 2386 2387 +6 1990 1880 1881 1992 2387 2388 +6 1991 1881 1882 1993 2388 2389 +6 1992 1882 1883 1994 2389 2390 +6 1993 1883 1884 1995 2390 2391 +6 1994 1884 1885 1996 2391 2392 +6 1995 1885 1886 1997 2392 2393 +6 1996 1886 1887 1998 2393 2394 +6 1997 1887 1888 1999 2394 2395 +6 1998 1888 1889 2000 2395 2396 +6 1999 1889 1890 2001 2396 2397 +6 2000 1890 1891 2002 2397 2398 +6 2001 1891 1892 2003 2398 2399 +6 2002 1892 1893 2004 2399 2400 +6 2003 1893 1894 2005 2400 2401 +6 2004 1894 1895 2006 2401 2402 +6 2005 1895 1896 2007 2402 2403 +6 2006 1896 1897 2008 2403 2404 +6 2007 1897 1898 2009 2404 2405 +6 2008 1898 1899 2010 2405 2406 +6 2009 1899 1900 2011 2406 2407 +6 2010 1900 1901 2012 2407 2408 +6 2011 1901 1902 2013 2408 2409 +6 2012 1902 1903 2014 2409 2410 +6 2013 1903 1904 2015 2410 2411 +6 2014 1904 1905 2016 2411 2412 +6 2015 1905 1906 2017 2412 2413 +6 2016 1906 1907 2018 2413 2414 +6 2017 1907 1908 2019 2414 2415 +6 2018 1908 1909 2020 2415 2416 +6 2019 1909 1910 2021 2416 2417 +6 2020 1910 1911 2022 2417 2418 +6 2021 1911 1912 2023 2418 2419 +6 2022 1912 1913 2024 2419 2420 +6 2023 1913 1914 2025 2420 2421 +6 2024 1914 1915 2026 2421 2422 +6 2025 1915 1916 2027 2422 2423 +6 2026 1916 1917 2028 2423 2424 +6 2027 1917 1918 2029 2424 2425 +6 2028 1918 1919 2030 2425 2426 +6 2029 1919 1920 2031 2426 2427 +6 2030 1920 1921 2032 2427 2428 +6 2031 1921 1922 2033 2428 2429 +6 2032 1922 1923 2034 2429 2430 +6 2033 1923 1924 2035 2430 2431 +6 2034 1924 1925 1927 2036 2431 +5 2035 1927 1928 2037 2431 +6 2036 1928 1929 2038 2431 2432 +6 2037 1929 1930 2039 2432 2433 +6 2038 1930 1931 2040 2433 2434 +7 2039 1931 1932 2041 2434 2435 2436 +5 2040 1932 1933 2042 2436 +7 2041 1933 1934 2043 2436 2437 2438 +6 2042 1934 1935 2044 2438 2439 +6 2043 1935 1936 2045 2439 2440 +6 2044 1936 1937 1938 2046 2440 +6 2045 1938 2047 2440 2441 2442 +6 2046 1938 1939 2048 2442 2443 +6 2047 1939 1940 1941 2049 2443 +6 2048 1941 2050 2443 2444 2448 +6 2049 1941 1942 2051 2448 2449 +6 2050 1942 1943 2052 2449 2450 +6 2051 1943 1944 2053 2450 2451 +6 2052 1944 2054 2451 2452 2453 +6 2053 1944 1945 1947 2055 2453 +6 2054 1947 1948 1950 2056 2453 +6 2055 1950 2057 2453 2454 2455 +6 2056 1950 1951 2058 2455 2456 +6 2057 1951 1952 1953 2059 2456 +6 2058 1953 1954 2060 2456 2457 +6 2059 1954 1955 2061 2457 2458 +6 2060 1955 1956 2062 2458 2459 +6 2061 1956 1958 2063 2459 2460 +6 2062 1958 2064 2460 2461 2462 +6 2063 1958 1959 2065 2462 2463 +6 2064 1959 2066 2463 2464 2465 +6 2065 1959 1960 1961 2067 2465 +6 2066 1961 2068 2069 2465 2466 +6 2067 1961 1962 2069 2070 1963 +6 2067 2068 2070 2071 2466 2469 +6 2069 2068 1963 2071 2072 1965 +6 2069 2070 2072 2073 2469 2470 +6 2071 2070 1965 2073 2074 2075 +6 2071 2072 2074 2473 2470 2086 +6 2073 2072 2075 2076 2078 2086 +6 2074 2072 1965 887 888 2076 +6 2075 888 889 2077 2078 2074 +6 2076 889 2078 2079 2080 2081 +6 2076 2077 2079 2074 2086 2087 +6 2078 2077 2080 2096 2087 2082 +6 2079 2077 2081 898 901 2082 +6 2080 2077 889 890 894 898 +6 2080 901 903 2083 2096 2079 +6 2082 903 2084 2096 2095 9776 +6 2083 903 904 2085 6093 9776 +6 2084 904 1565 1567 3766 6093 +6 2074 2078 2087 2088 2473 2073 +6 2086 2078 2088 2089 2096 2079 +6 2086 2087 2089 2090 2091 2473 +6 2088 2087 2090 2094 2095 2096 +6 2088 2089 2091 2092 2093 2094 +6 2088 2090 2092 2489 2472 2473 +6 2091 2090 2093 2489 5947 5948 +6 2092 2090 2094 3135 5947 3132 +6 2093 2090 2089 2095 3131 3132 +6 2094 2089 2096 3131 2083 9776 +6 2095 2089 2087 2079 2082 2083 +6 631 403 633 650 649 404 +6 1795 1796 2099 2295 2296 2297 +6 2098 1796 1797 2100 2297 2101 +5 2099 1797 1300 1301 2101 +6 2100 1301 1302 2102 2297 2099 +6 2101 1302 1303 2103 2297 2298 +6 2102 1303 1304 2104 2298 2299 +6 2103 1304 1305 2105 2299 2300 +6 2104 1305 1306 2106 2300 2301 +7 2105 1306 1307 1798 2107 2301 2302 +5 2106 1798 2108 2302 2303 +6 2107 1798 1799 2109 2303 2304 +6 2108 1799 1800 2110 2304 2305 +6 2109 1800 1801 2111 2305 2306 +6 2110 1801 1802 2112 2306 2307 +6 2111 1802 1803 2113 2307 2308 +6 2112 1803 1804 2114 2308 2309 +6 2113 1804 1805 2115 2309 2310 +6 2114 1805 1806 2116 2310 2311 +6 2115 1806 1807 2117 2311 2312 +6 2116 1807 1808 2118 2312 2313 +6 2117 1808 1809 2119 2313 2314 +6 2118 1809 1810 2120 2314 2315 +6 2119 1810 1811 2121 2315 2316 +6 2120 1811 1812 2122 2316 2317 +6 2121 1812 1813 2123 2317 2318 +6 2122 1813 1814 2124 2318 2319 +6 2123 1814 1815 2125 2319 2320 +6 2124 1815 1816 2126 2320 2321 +6 2125 1816 1817 2127 2321 2322 +6 2126 1817 1818 2128 2322 2323 +6 2127 1818 1819 2129 2323 2324 +6 2128 1819 1820 2130 2324 2325 +6 2129 1820 1821 2131 2325 2326 +6 2130 1821 1822 2132 2326 2327 +6 2131 1822 1823 2133 2151 2327 +6 2132 1823 1824 2134 2151 2152 +6 2133 1824 1825 2135 2152 2153 +6 2134 1825 1826 1827 2136 2153 +6 2135 1827 2137 2153 2154 2155 +6 2136 1827 1828 2138 2155 2156 +6 2137 1828 1829 2139 2156 2157 +6 2138 1829 1830 2140 2157 2158 +6 2139 1830 2141 2146 2158 2159 +6 2140 1830 1831 1832 2142 2146 +6 2141 1832 1833 2143 2146 2147 +6 2142 1833 1834 2144 2147 2148 +6 2143 1834 1835 2145 2148 2149 +6 2144 1835 1836 2149 2150 1837 +6 2140 2141 2142 2147 2159 2160 +6 2146 2142 2143 2148 2160 2161 +6 2147 2143 2144 2149 2161 2162 +6 2148 2144 2145 2150 2162 2163 +6 2149 2145 1837 2163 2164 2165 +6 2132 2133 2152 2327 2328 2329 +6 2151 2133 2134 2153 2329 2330 +6 2152 2134 2135 2136 2154 2330 +6 2153 2136 2155 2330 2331 2332 +6 2154 2136 2137 2156 2332 2333 +6 2155 2137 2138 2157 2333 2334 +6 2156 2138 2139 2158 2334 2335 +6 2157 2139 2140 2159 2335 2336 +6 2158 2140 2146 2160 2336 2337 +6 2159 2146 2147 2161 2337 2338 +6 2160 2147 2148 2162 2338 2339 +6 2161 2148 2149 2163 2339 2340 +6 2162 2149 2150 2164 2340 2341 +6 2163 2150 2165 2341 2342 2343 +6 2164 2150 1837 1838 2166 2343 +6 2165 1838 1839 2167 2343 2344 +6 2166 1839 1840 2168 2169 2344 +6 2167 1840 2169 2170 2171 1841 +6 2167 2168 2170 2344 2345 2346 +6 2169 2168 2171 2346 2347 2348 +6 2170 2168 1841 2348 2349 1842 +6 1724 1725 2173 3468 3467 4747 +6 2172 1725 2174 2804 3395 4747 +6 2173 1725 1726 1727 2175 2804 +6 2174 1727 1728 2176 2177 2804 +6 2175 1728 2177 2178 1731 1729 +6 2175 2176 2178 2804 2805 2806 +6 2177 2176 1731 2806 2807 2808 +6 27 28 2180 2181 3851 3852 +6 2179 28 29 2181 2182 2503 +6 2179 2180 2182 2183 2199 3851 +6 2181 2180 2183 2184 2502 2503 +6 2181 2182 2184 2185 2198 2199 +6 2183 2182 2185 2186 2193 2502 +6 2183 2184 2186 2187 2197 2198 +6 2185 2184 2187 2188 2192 2193 +6 2185 2186 2188 2189 2197 9713 +6 2187 2186 2189 2190 2191 2192 +7 2187 2188 2190 9709 9708 9712 9713 +5 2189 2188 2191 9710 9709 +6 2190 2188 2192 2510 2512 9710 +6 2191 2188 2186 2193 2510 2506 +6 2192 2186 2184 2502 2504 2506 +6 415 39 40 2195 9704 6488 +6 2194 40 41 2196 6488 9705 +7 2195 41 42 9705 43 9771 9773 +6 2185 2187 2198 9713 9714 9720 +6 2185 2197 2183 2199 2200 9720 +6 2183 2198 2200 2201 2181 3851 +6 2199 2198 2201 2202 9720 2217 +6 2199 2200 2202 2203 3129 3851 +6 2201 2200 2203 2204 2217 2208 +6 2201 2202 2204 2205 3129 3130 +6 2203 2202 2205 2206 2207 2208 +6 2203 2204 2206 3130 1525 4250 +6 2205 2204 2207 3343 3341 4250 +6 2206 2204 2208 2209 3343 3344 +6 2207 2204 2209 2210 2217 2202 +6 2207 2208 2210 2211 3344 3345 +6 2209 2208 2211 2212 2216 2217 +6 2209 2210 2212 2213 3348 3345 +6 2211 2210 2213 2214 2215 2216 +6 2211 2212 2214 6522 6523 3348 +6 2213 2212 2215 9716 9719 6522 +6 2214 2212 2216 9716 9715 9714 +6 2215 2212 2210 2217 9714 9720 +6 2216 2210 2208 2202 9720 2200 +6 408 59 60 2219 2545 2546 +6 2218 60 61 2220 2549 2546 +6 2219 61 62 2221 2549 2551 +6 2220 62 63 2222 2551 6702 +6 2221 63 6701 6700 6702 64 +6 1698 1703 2224 3418 3419 3420 +6 2223 1703 1704 2225 3420 3421 +6 2224 1704 2226 3421 3422 3426 +6 2225 1704 1705 2227 3426 3427 +6 2226 1705 1706 2228 3427 3428 +6 2227 1706 2229 3428 3429 3430 +6 2228 1706 1707 2230 2238 3430 +6 2229 1707 2231 2232 2238 2239 +6 2230 1707 2232 1712 1711 1708 +6 2230 2231 1712 2239 2240 1713 +6 1748 1749 2234 2235 2242 2752 +6 2233 1749 2235 2236 2237 1750 +6 2233 2234 2236 2242 2243 2244 +6 2235 2234 2237 2244 2245 2246 +6 2236 2234 1750 2246 2247 1751 +6 2229 2230 2239 3430 3431 3435 +6 2238 2230 2232 2240 3435 2561 +6 2239 2232 1713 1714 2560 2561 +6 1187 1188 1659 1657 3097 1184 +6 2233 2235 2243 2752 2753 2754 +6 2242 2235 2244 2754 2755 2756 +6 2243 2235 2236 2245 2756 2757 +6 2244 2236 2246 2757 2758 2759 +6 2245 2236 2237 2247 2759 2760 +6 2246 2237 1751 1752 2253 2760 +6 34 35 2249 3331 3332 3333 +6 2248 35 36 2250 3336 3333 +6 2249 36 37 416 2251 3336 +7 2250 416 2252 6490 6491 9706 3336 +5 2251 416 415 6490 9704 +6 2247 1752 1753 2254 2760 2761 +6 2253 1753 1754 2255 2761 2762 +6 2254 1754 1755 2256 2762 2763 +6 2255 1755 1756 1757 2257 2763 +6 2256 1757 2258 2763 2764 2765 +6 2257 1757 1758 2259 2765 2766 +6 2258 1758 1759 2260 2766 2767 +6 2259 1759 1760 2261 2767 2768 +6 2260 1760 1761 2262 2768 2769 +6 2261 1761 1762 2263 2571 2769 +6 2262 1762 1763 2264 2571 2572 +6 2263 1763 1764 2265 2572 2573 +6 2264 1764 1765 2266 2573 2574 +6 2265 1765 1766 2267 2574 2575 +6 2266 1766 1767 2268 2575 2576 +6 2267 1767 1768 2269 2576 2577 +6 2268 1768 1769 2270 2577 2578 +6 2269 1769 1770 2271 2578 2579 +6 2270 1770 1771 2272 2579 2580 +6 2271 1771 1772 2273 2580 2581 +6 2272 1772 1773 2274 2581 2582 +6 2273 1773 1774 2275 2582 2583 +6 2274 1774 1775 2276 2583 2584 +6 2275 1775 1776 2277 2584 2585 +6 2276 1776 1777 2278 2585 2586 +6 2277 1777 1778 2279 2586 2587 +6 2278 1778 1779 2280 2587 2588 +6 2279 1779 1780 2281 2588 2589 +6 2280 1780 1781 2282 2589 2590 +6 2281 1781 1782 2283 2590 2591 +6 2282 1782 1783 2284 2591 2592 +6 2283 1783 1784 2285 2592 2593 +6 2284 1784 1785 2286 2593 2594 +6 2285 1785 1786 2287 2594 2595 +6 2286 1786 1787 2288 2595 2596 +6 2287 1787 1788 2289 2596 2597 +6 2288 1788 1789 2290 2597 2598 +6 2289 1789 1790 2291 2598 2599 +6 2290 1790 1791 2292 2599 2600 +6 2291 1791 1792 2293 2600 2601 +6 2292 1792 1793 2294 2601 2602 +6 2293 1793 1794 2295 2602 2603 +6 2294 1794 1795 2098 2296 2603 +6 2295 2098 2297 2603 2604 2605 +7 2296 2098 2099 2101 2102 2298 2605 +6 2297 2102 2103 2299 2605 2606 +6 2298 2103 2104 2300 2606 2607 +6 2299 2104 2105 2301 2607 2608 +6 2300 2105 2106 2302 2608 2609 +6 2301 2106 2107 2303 2609 2610 +6 2302 2107 2108 2304 2610 2611 +6 2303 2108 2109 2305 2611 2612 +6 2304 2109 2110 2306 2612 2613 +6 2305 2110 2111 2307 2613 2614 +6 2306 2111 2112 2308 2614 2615 +6 2307 2112 2113 2309 2615 2616 +6 2308 2113 2114 2310 2619 2616 +6 2309 2114 2115 2311 2619 2620 +6 2310 2115 2116 2312 2620 2621 +6 2311 2116 2117 2313 2621 2622 +6 2312 2117 2118 2314 2622 2623 +6 2313 2118 2119 2315 2623 2624 +6 2314 2119 2120 2316 2624 2625 +6 2315 2120 2121 2317 2625 2626 +6 2316 2121 2122 2318 2626 2627 +6 2317 2122 2123 2319 2627 2628 +6 2318 2123 2124 2320 2628 2629 +6 2319 2124 2125 2321 2629 2630 +6 2320 2125 2126 2322 2630 2631 +6 2321 2126 2127 2323 2631 2632 +6 2322 2127 2128 2324 2632 2633 +6 2323 2128 2129 2325 2633 2634 +6 2324 2129 2130 2326 2634 2635 +6 2325 2130 2131 2327 2635 2636 +6 2326 2131 2132 2151 2328 2636 +6 2327 2151 2329 2636 2637 2638 +6 2328 2151 2152 2330 2641 2638 +6 2329 2152 2153 2154 2331 2641 +6 2330 2154 2332 2642 2641 2643 +6 2331 2154 2155 2333 2643 2644 +6 2332 2155 2156 2334 2644 2645 +6 2333 2156 2157 2335 2645 2646 +6 2334 2157 2158 2336 2646 2647 +6 2335 2158 2159 2337 2647 2648 +6 2336 2159 2160 2338 2648 2649 +6 2337 2160 2161 2339 2649 2650 +6 2338 2161 2162 2340 2650 2651 +6 2339 2162 2163 2341 2651 2652 +6 2340 2163 2164 2342 2652 2653 +6 2341 2164 2343 2653 2654 2655 +6 2342 2164 2165 2166 2344 2655 +6 2343 2166 2167 2169 2345 2655 +6 2344 2169 2346 2655 2656 2657 +6 2345 2169 2170 2347 2657 2658 +6 2346 2170 2348 2658 2659 2660 +6 2347 2170 2171 2349 2660 2661 +6 2348 2171 1842 1843 2350 2661 +6 2349 1843 1844 2351 2661 2662 +6 2350 1844 1845 2352 2662 2663 +6 2351 1845 1846 2353 2663 2664 +6 2352 1846 1847 2354 2664 2665 +6 2353 1847 1848 2355 2665 2666 +6 2354 1848 1849 2356 2666 2667 +6 2355 1849 1850 2357 2667 2668 +6 2356 1850 1851 2358 2668 2669 +6 2357 1851 1852 2359 2669 2670 +6 2358 1852 1853 2360 2670 2671 +6 2359 1853 1854 2361 2671 2672 +6 2360 1854 1855 1966 2362 2672 +6 2361 1966 2363 2672 2673 2674 +6 2362 1966 1967 2364 2674 2675 +6 2363 1967 1968 2365 2675 2676 +6 2364 1968 1969 2366 2676 2677 +6 2365 1969 1970 2367 2677 2678 +6 2366 1970 1971 2368 2678 2679 +6 2367 1971 1972 2369 2679 2680 +6 2368 1972 1973 2370 2680 2681 +6 2369 1973 1974 2371 2681 2682 +6 2370 1974 1975 2372 2682 2683 +6 2371 1975 1976 2373 2683 2684 +6 2372 1976 1977 2374 2684 2685 +6 2373 1977 1978 2375 2685 2686 +6 2374 1978 1979 2376 2686 2687 +6 2375 1979 1980 2377 2687 2688 +6 2376 1980 1981 2378 2688 2689 +6 2377 1981 1982 2379 2689 2690 +6 2378 1982 1983 2380 2690 2691 +6 2379 1983 1984 2381 2691 2692 +6 2380 1984 1985 2382 2692 2693 +6 2381 1985 1986 2383 2693 2694 +6 2382 1986 1987 2384 2694 2695 +6 2383 1987 1988 2385 2695 2696 +6 2384 1988 1989 2386 2696 2697 +6 2385 1989 1990 2387 2697 2698 +6 2386 1990 1991 2388 2698 2699 +6 2387 1991 1992 2389 2699 2700 +6 2388 1992 1993 2390 2700 2701 +6 2389 1993 1994 2391 2701 2702 +6 2390 1994 1995 2392 2702 2703 +6 2391 1995 1996 2393 2703 2704 +6 2392 1996 1997 2394 2704 2705 +6 2393 1997 1998 2395 2705 2706 +6 2394 1998 1999 2396 2706 2707 +6 2395 1999 2000 2397 2707 2708 +6 2396 2000 2001 2398 2708 2709 +6 2397 2001 2002 2399 2513 2709 +6 2398 2002 2003 2400 2513 2514 +6 2399 2003 2004 2401 2514 2515 +6 2400 2004 2005 2402 2515 2516 +6 2401 2005 2006 2403 2516 2517 +6 2402 2006 2007 2404 2517 2518 +6 2403 2007 2008 2405 2518 2519 +6 2404 2008 2009 2406 2519 2520 +6 2405 2009 2010 2407 2520 2521 +6 2406 2010 2011 2408 2521 2522 +6 2407 2011 2012 2409 2522 2523 +6 2408 2012 2013 2410 2523 2524 +6 2409 2013 2014 2411 2524 2525 +6 2410 2014 2015 2412 2525 2526 +6 2411 2015 2016 2413 2526 2527 +6 2412 2016 2017 2414 2527 2528 +6 2413 2017 2018 2415 2528 2529 +6 2414 2018 2019 2416 2529 2530 +6 2415 2019 2020 2417 2530 2531 +6 2416 2020 2021 2418 2531 2532 +6 2417 2021 2022 2419 2532 2533 +6 2418 2022 2023 2420 2533 2534 +6 2419 2023 2024 2421 2534 2535 +6 2420 2024 2025 2422 2535 2536 +6 2421 2025 2026 2423 2536 2537 +6 2422 2026 2027 2424 2537 2538 +6 2423 2027 2028 2425 2538 2539 +6 2424 2028 2029 2426 2539 2540 +6 2425 2029 2030 2427 2540 2541 +6 2426 2030 2031 2428 2541 2542 +6 2427 2031 2032 2429 2542 2543 +6 2428 2032 2033 2430 2543 2544 +6 2429 2033 2034 2431 2544 2432 +6 2430 2034 2035 2036 2037 2432 +7 2431 2037 2038 2433 2544 2430 2556 +6 2432 2038 2039 2434 2556 2557 +6 2433 2039 2040 2435 2557 2558 +6 2434 2040 2436 2558 2559 2437 +5 2435 2040 2041 2042 2437 +6 2436 2042 2438 2559 2435 2745 +6 2437 2042 2043 2439 2745 2746 +7 2438 2043 2044 2440 2746 2747 2748 +6 2439 2044 2045 2046 2441 2748 +6 2440 2046 2442 2748 2749 2750 +6 2441 2046 2047 2443 2750 2445 +6 2442 2047 2048 2049 2444 2445 +6 2443 2049 2445 2446 2447 2448 +6 2443 2444 2446 2750 2442 3060 +6 2445 2444 2447 3060 3061 3062 +6 2446 2444 2448 3062 3063 3064 +6 2447 2444 2049 2050 2449 3064 +6 2448 2050 2051 2450 3064 3065 +6 2449 2051 2052 2451 3065 3066 +6 2450 2052 2053 2452 3066 3067 +6 2451 2053 2453 3067 3068 2454 +6 2452 2053 2054 2055 2056 2454 +6 2453 2056 2455 3068 2452 3074 +6 2454 2056 2057 2456 3074 3075 +6 2455 2057 2058 2059 2457 3075 +6 2456 2059 2060 2458 3075 3076 +6 2457 2060 2061 2459 3076 3077 +6 2458 2061 2062 2460 3077 3078 +6 2459 2062 2063 2461 3078 3079 +6 2460 2063 2462 3079 3080 3081 +6 2461 2063 2064 2463 3081 3082 +6 2462 2064 2065 2464 3082 3083 +6 2463 2065 2465 2467 2482 3083 +6 2464 2065 2066 2067 2466 2467 +6 2465 2067 2069 2467 2468 2469 +6 2465 2466 2468 2464 2482 2483 +6 2467 2466 2469 2471 2477 2483 +6 2468 2466 2069 2071 2470 2471 +6 2469 2071 2471 2472 2473 2073 +6 2469 2470 2472 2468 2477 2478 +6 2471 2470 2473 2489 2478 2091 +6 2472 2470 2073 2091 2088 2086 +6 1516 1521 914 915 576 1515 +6 1578 1587 2476 1574 6361 1573 +6 2475 1587 1589 6353 6359 6361 +6 2468 2471 2478 2483 2484 2485 +6 2477 2471 2485 2488 2489 2472 +6 1642 1643 1644 2480 1641 2490 +6 2479 1644 2481 2490 2494 2869 +6 2480 1644 1645 1650 2494 2495 +6 2464 2467 2483 3085 3083 3926 +6 2482 2467 2468 2477 2484 3926 +6 2483 2477 2485 2486 3926 3150 +6 2484 2477 2478 2486 2487 2488 +6 2484 2485 2487 3148 3149 3150 +6 2486 2485 2488 3148 3967 3161 +6 2487 2485 2478 2489 5948 3967 +6 2488 2478 2472 2091 2092 5948 +6 1641 2479 2480 2867 2868 2869 +6 70 71 2492 3436 3437 3441 +6 2491 71 72 409 2493 3436 +6 2492 409 1606 3515 3436 3516 +6 2480 2481 2495 2869 2870 2871 +6 2494 2481 1650 1651 2496 2871 +6 2495 1651 2497 2871 2872 2882 +6 2496 1651 1652 2498 2882 2883 +6 2497 1652 2499 2883 4092 4093 +6 2498 1652 1653 2500 2809 4093 +6 2499 1653 1654 2501 2809 2810 +6 2500 1654 1656 2810 2811 2812 +6 2184 2182 2503 2193 2504 2505 +6 2502 2182 30 2505 29 2180 +6 2193 2502 2505 2506 2507 2508 +6 2504 2502 2508 31 30 2503 +6 2193 2504 2507 2509 2510 2192 +6 2506 2504 2508 2509 3330 3880 +6 2507 2504 2505 31 3330 32 +6 2506 2507 2510 2511 3880 3881 +6 2506 2509 2511 2512 2191 2192 +6 2510 2509 2512 6499 6498 3881 +6 2510 2511 2191 6498 6500 9710 +6 2398 2399 2514 2709 2710 2711 +6 2513 2399 2400 2515 2711 2712 +6 2514 2400 2401 2516 2712 2713 +6 2515 2401 2402 2517 2713 2714 +6 2516 2402 2403 2518 2714 2715 +6 2517 2403 2404 2519 2715 2716 +6 2518 2404 2405 2520 2716 2717 +6 2519 2405 2406 2521 2717 2718 +6 2520 2406 2407 2522 2718 2719 +6 2521 2407 2408 2523 2719 2720 +6 2522 2408 2409 2524 2720 2721 +6 2523 2409 2410 2525 2721 2722 +6 2524 2410 2411 2526 2722 2723 +6 2525 2411 2412 2527 2723 2724 +6 2526 2412 2413 2528 2724 2725 +6 2527 2413 2414 2529 2725 2726 +6 2528 2414 2415 2530 2726 2727 +6 2529 2415 2416 2531 2727 2728 +6 2530 2416 2417 2532 2728 2729 +6 2531 2417 2418 2533 2729 2730 +6 2532 2418 2419 2534 2730 2731 +6 2533 2419 2420 2535 2731 2732 +6 2534 2420 2421 2536 2732 2733 +6 2535 2421 2422 2537 2733 2734 +6 2536 2422 2423 2538 2734 2735 +6 2537 2423 2424 2539 2735 2736 +6 2538 2424 2425 2540 2736 2737 +6 2539 2425 2426 2541 2552 2737 +6 2540 2426 2427 2542 2552 2553 +6 2541 2427 2428 2543 2553 2554 +6 2542 2428 2429 2544 2554 2555 +6 2543 2429 2430 2432 2555 2556 +6 408 2218 2546 2547 2841 2842 +6 2545 2218 2547 2548 2549 2219 +6 2545 2546 2548 2842 2845 2846 +6 2547 2546 2549 2550 2857 2846 +6 2548 2546 2219 2220 2550 2551 +6 2548 2549 2551 6691 2856 2857 +7 2550 2549 2220 2221 6702 6690 6691 +6 2540 2541 2553 2737 2738 2739 +6 2552 2541 2542 2554 2739 2740 +6 2553 2542 2543 2555 2570 2740 +6 2554 2543 2544 2556 2570 2557 +5 2555 2544 2432 2433 2557 +7 2556 2433 2434 2558 2570 2555 2742 +5 2557 2434 2435 2559 2742 +7 2558 2435 2437 2742 2743 2744 2745 +6 2240 1714 2561 2562 2563 2564 +6 2240 2560 2562 3435 2239 3446 +6 2561 2560 2563 3446 3447 3448 +6 2562 2560 2564 3448 3449 2567 +6 2563 2560 1714 1715 2565 2567 +6 2564 1715 1716 1717 2566 2567 +6 2565 1717 2567 2568 2569 1718 +6 2565 2566 2568 3449 2563 2564 +6 2567 2566 2569 3458 3455 3449 +6 2568 2566 1718 3463 3458 1719 +6 2554 2555 2557 2740 2741 2742 +6 2262 2263 2572 2769 2770 2771 +6 2571 2263 2264 2573 2771 2772 +6 2572 2264 2265 2574 2772 2773 +6 2573 2265 2266 2575 2773 2774 +6 2574 2266 2267 2576 2774 2775 +6 2575 2267 2268 2577 2775 2776 +6 2576 2268 2269 2578 2776 2777 +6 2577 2269 2270 2579 2777 2778 +6 2578 2270 2271 2580 2778 2779 +6 2579 2271 2272 2581 2779 2780 +6 2580 2272 2273 2582 2780 2781 +6 2581 2273 2274 2583 2781 2782 +6 2582 2274 2275 2584 2782 2783 +6 2583 2275 2276 2585 2783 2784 +6 2584 2276 2277 2586 2784 2785 +6 2585 2277 2278 2587 2785 2786 +6 2586 2278 2279 2588 2786 2787 +6 2587 2279 2280 2589 2787 2788 +6 2588 2280 2281 2590 2788 2789 +6 2589 2281 2282 2591 2789 2790 +6 2590 2282 2283 2592 2790 2791 +6 2591 2283 2284 2593 2791 2792 +6 2592 2284 2285 2594 2792 2793 +6 2593 2285 2286 2595 2793 2794 +6 2594 2286 2287 2596 2794 2795 +6 2595 2287 2288 2597 2795 2796 +6 2596 2288 2289 2598 2796 2797 +6 2597 2289 2290 2599 2797 2798 +6 2598 2290 2291 2600 2798 2799 +6 2599 2291 2292 2601 2799 2800 +6 2600 2292 2293 2602 2800 2801 +6 2601 2293 2294 2603 2801 2802 +6 2602 2294 2295 2296 2604 2802 +6 2603 2296 2605 2802 2803 2606 +5 2604 2296 2297 2298 2606 +7 2605 2298 2299 2607 2803 2604 2826 +5 2606 2299 2300 2608 2826 +7 2607 2300 2301 2609 2826 2827 2828 +6 2608 2301 2302 2610 2828 2829 +6 2609 2302 2303 2611 2829 2830 +6 2610 2303 2304 2612 2830 2831 +6 2611 2304 2305 2613 2831 2832 +6 2612 2305 2306 2614 2832 2833 +6 2613 2306 2307 2615 2833 2834 +6 2614 2307 2308 2616 2617 2834 +6 2615 2308 2617 2618 2619 2309 +6 2615 2616 2618 2834 2835 2836 +6 2617 2616 2619 2836 2837 2838 +6 2618 2616 2309 2310 2620 2838 +6 2619 2310 2311 2621 2840 2838 +6 2620 2311 2312 2622 2959 2840 +6 2621 2312 2313 2623 2959 2960 +6 2622 2313 2314 2624 2960 2961 +6 2623 2314 2315 2625 2961 2962 +6 2624 2315 2316 2626 2962 2963 +6 2625 2316 2317 2627 2966 2963 +6 2626 2317 2318 2628 2966 2967 +6 2627 2318 2319 2629 2967 2968 +6 2628 2319 2320 2630 2968 2969 +6 2629 2320 2321 2631 2969 2970 +6 2630 2321 2322 2632 2970 2971 +6 2631 2322 2323 2633 2971 2972 +6 2632 2323 2324 2634 2972 2973 +6 2633 2324 2325 2635 2973 2974 +6 2634 2325 2326 2636 2974 2975 +6 2635 2326 2327 2328 2637 2975 +6 2636 2328 2638 2639 2975 2976 +6 2637 2328 2639 2640 2641 2329 +6 2637 2638 2640 2976 2977 2978 +6 2639 2638 2641 2642 2978 2979 +6 2640 2638 2642 2331 2330 2329 +6 2640 2641 2331 2643 2979 2980 +6 2642 2331 2332 2644 2980 2981 +6 2643 2332 2333 2645 2981 2982 +6 2644 2333 2334 2646 2982 2983 +6 2645 2334 2335 2647 2983 2984 +6 2646 2335 2336 2648 2984 2985 +6 2647 2336 2337 2649 2985 2986 +6 2648 2337 2338 2650 2986 2987 +6 2649 2338 2339 2651 2987 2988 +6 2650 2339 2340 2652 2988 2989 +6 2651 2340 2341 2653 2989 2990 +6 2652 2341 2342 2654 2990 2991 +6 2653 2342 2655 2991 2992 2656 +6 2654 2342 2343 2344 2345 2656 +6 2655 2345 2657 2992 2654 2993 +6 2656 2345 2346 2658 2993 2994 +6 2657 2346 2347 2659 2994 2995 +6 2658 2347 2660 2995 2996 2997 +6 2659 2347 2348 2661 2997 2998 +6 2660 2348 2349 2350 2662 2998 +6 2661 2350 2351 2663 2998 2999 +6 2662 2351 2352 2664 2999 3000 +6 2663 2352 2353 2665 3000 3001 +6 2664 2353 2354 2666 3001 3002 +6 2665 2354 2355 2667 3002 3565 +6 2666 2355 2356 2668 3565 3566 +6 2667 2356 2357 2669 3566 3567 +6 2668 2357 2358 2670 3567 3568 +6 2669 2358 2359 2671 3568 3569 +6 2670 2359 2360 2672 3569 3570 +6 2671 2360 2361 2362 2673 3570 +6 2672 2362 2674 3570 3571 3572 +6 2673 2362 2363 2675 3572 3573 +6 2674 2363 2364 2676 3391 3573 +6 2675 2364 2365 2677 3391 3392 +6 2676 2365 2366 2678 3392 3393 +6 2677 2366 2367 2679 3393 3394 +6 2678 2367 2368 2680 3394 3579 +6 2679 2368 2369 2681 3579 3580 +6 2680 2369 2370 2682 3580 3581 +6 2681 2370 2371 2683 3581 3582 +6 2682 2371 2372 2684 3582 3583 +6 2683 2372 2373 2685 3583 3584 +6 2684 2373 2374 2686 3584 3585 +6 2685 2374 2375 2687 3585 3586 +6 2686 2375 2376 2688 3586 3587 +6 2687 2376 2377 2689 3587 3588 +6 2688 2377 2378 2690 3278 3588 +6 2689 2378 2379 2691 3278 3279 +6 2690 2379 2380 2692 3279 3280 +6 2691 2380 2381 2693 3280 3281 +6 2692 2381 2382 2694 3281 3282 +6 2693 2382 2383 2695 3282 3283 +6 2694 2383 2384 2696 3283 3284 +6 2695 2384 2385 2697 3284 3285 +6 2696 2385 2386 2698 3285 3286 +6 2697 2386 2387 2699 3286 3287 +6 2698 2387 2388 2700 3287 3288 +6 2699 2388 2389 2701 3288 3289 +6 2700 2389 2390 2702 3289 3290 +6 2701 2390 2391 2703 3003 3290 +6 2702 2391 2392 2704 3003 3004 +6 2703 2392 2393 2705 3004 3005 +6 2704 2393 2394 2706 3005 3006 +6 2705 2394 2395 2707 3006 3007 +6 2706 2395 2396 2708 3007 3008 +6 2707 2396 2397 2709 3008 3009 +6 2708 2397 2398 2513 2710 3009 +6 2709 2513 2711 3009 3010 3011 +6 2710 2513 2514 2712 3011 3012 +6 2711 2514 2515 2713 3012 3013 +6 2712 2515 2516 2714 3013 3014 +6 2713 2516 2517 2715 3014 3015 +6 2714 2517 2518 2716 3015 3016 +6 2715 2518 2519 2717 3016 3017 +6 2716 2519 2520 2718 3017 3018 +6 2717 2520 2521 2719 3018 3019 +6 2718 2521 2522 2720 3019 3020 +6 2719 2522 2523 2721 3020 3021 +6 2720 2523 2524 2722 3021 3022 +6 2721 2524 2525 2723 3022 3023 +6 2722 2525 2526 2724 3023 3024 +6 2723 2526 2527 2725 3024 3025 +6 2724 2527 2528 2726 3025 3026 +6 2725 2528 2529 2727 3026 3027 +6 2726 2529 2530 2728 3027 3028 +6 2727 2530 2531 2729 3028 3029 +6 2728 2531 2532 2730 3029 3030 +6 2729 2532 2533 2731 3030 3031 +6 2730 2533 2534 2732 3031 3032 +6 2731 2534 2535 2733 3032 3033 +6 2732 2535 2536 2734 3033 3034 +6 2733 2536 2537 2735 3034 3035 +6 2734 2537 2538 2736 3035 3036 +6 2735 2538 2539 2737 3036 3037 +6 2736 2539 2540 2552 2738 3037 +6 2737 2552 2739 3037 3038 3039 +6 2738 2552 2553 2740 3039 3040 +6 2739 2553 2554 2570 2741 3040 +6 2740 2570 2742 3040 3041 2743 +6 2741 2570 2557 2558 2559 2743 +6 2742 2559 2744 3041 2741 3049 +5 2743 2559 2745 3049 3050 +6 2744 2559 2437 2438 2746 3050 +6 2745 2438 2439 2747 3050 3051 +6 2746 2439 2748 3051 3052 2749 +5 2747 2439 2440 2441 2749 +6 2748 2441 2750 3052 2747 3058 +7 2749 2441 2442 2445 3058 3059 3060 +6 1746 1747 1748 2752 2893 2894 +6 2751 1748 2233 2242 2753 2894 +6 2752 2242 2754 2894 2895 2896 +6 2753 2242 2243 2755 2896 2897 +6 2754 2243 2756 2897 2898 2899 +6 2755 2243 2244 2757 2899 2900 +6 2756 2244 2245 2758 2900 2901 +6 2757 2245 2759 2901 2902 2903 +6 2758 2245 2246 2760 2903 2904 +6 2759 2246 2247 2253 2761 2904 +6 2760 2253 2254 2762 2904 2905 +6 2761 2254 2255 2763 2905 2906 +6 2762 2255 2256 2257 2764 2906 +6 2763 2257 2765 2906 2907 2908 +6 2764 2257 2258 2766 2908 2909 +6 2765 2258 2259 2767 2909 2910 +6 2766 2259 2260 2768 2910 2911 +6 2767 2260 2261 2769 2911 2912 +6 2768 2261 2262 2571 2770 2912 +6 2769 2571 2771 2912 2913 2914 +6 2770 2571 2572 2772 2914 2915 +6 2771 2572 2573 2773 2915 2916 +6 2772 2573 2574 2774 2916 2917 +6 2773 2574 2575 2775 2917 2918 +6 2774 2575 2576 2776 2918 2919 +6 2775 2576 2577 2777 2919 2920 +6 2776 2577 2578 2778 2920 2921 +6 2777 2578 2579 2779 2921 2922 +6 2778 2579 2580 2780 2922 2923 +6 2779 2580 2581 2781 2923 2924 +6 2780 2581 2582 2782 2924 2925 +6 2781 2582 2583 2783 2925 2926 +6 2782 2583 2584 2784 2926 2927 +6 2783 2584 2585 2785 2927 2928 +6 2784 2585 2586 2786 2928 2929 +6 2785 2586 2587 2787 2929 2930 +6 2786 2587 2588 2788 2930 2931 +6 2787 2588 2589 2789 2931 2932 +6 2788 2589 2590 2790 2932 2933 +6 2789 2590 2591 2791 2933 2934 +6 2790 2591 2592 2792 2934 2935 +6 2791 2592 2593 2793 2935 2936 +6 2792 2593 2594 2794 2936 2937 +6 2793 2594 2595 2795 2937 2938 +6 2794 2595 2596 2796 2938 2939 +6 2795 2596 2597 2797 2939 2940 +6 2796 2597 2598 2798 2940 2941 +6 2797 2598 2599 2799 2941 2942 +6 2798 2599 2600 2800 2942 2943 +6 2799 2600 2601 2801 2943 2944 +6 2800 2601 2602 2802 2944 2824 +6 2801 2602 2603 2604 2803 2824 +6 2802 2604 2606 2824 2825 2826 +6 2173 2174 2175 2177 2805 3395 +6 2804 2177 2806 3395 3396 3400 +6 2805 2177 2178 2807 3400 3401 +6 2806 2178 2808 3401 3402 3403 +6 2807 2178 1731 3403 3404 1732 +6 2499 2500 2810 4095 4093 4388 +6 2809 2500 2501 2811 4388 2813 +6 2810 2501 2812 1664 1666 2813 +6 2811 2501 1656 1658 1661 1664 +6 2811 1666 2814 3139 4388 2810 +6 2813 1666 1667 2815 2817 3139 +6 2814 1667 2816 2817 2818 2819 +6 2815 1667 1668 2819 2820 2821 +6 2814 2815 2818 3139 3140 3141 +6 2817 2815 2819 3141 3142 3143 +6 2818 2815 2816 2820 3143 3144 +6 2819 2816 2821 3144 3145 3146 +6 2820 2816 1668 2822 2823 3146 +6 2821 1668 2823 1672 1671 1669 +6 2821 2822 1672 3146 3147 1673 +6 2802 2803 2825 2944 2801 2945 +6 2824 2803 2826 2945 2946 2827 +6 2825 2803 2606 2607 2608 2827 +6 2826 2608 2828 2946 2825 2947 +5 2827 2608 2609 2829 2947 +6 2828 2609 2610 2830 2947 2948 +6 2829 2610 2611 2831 2948 2949 +6 2830 2611 2612 2832 2949 2950 +6 2831 2612 2613 2833 2950 2951 +6 2832 2613 2614 2834 2951 2952 +7 2833 2614 2615 2617 2835 2952 2953 +5 2834 2617 2836 2953 2954 +6 2835 2617 2618 2837 2954 2955 +6 2836 2618 2838 2839 2955 2956 +6 2837 2618 2839 2840 2620 2619 +6 2837 2838 2840 2956 2957 2958 +6 2839 2838 2620 2958 2959 2621 +6 408 2545 2842 2843 9690 429 +6 2841 2545 2843 2844 2547 2845 +6 2841 2842 2844 3168 9688 9690 +6 2843 2842 3168 3165 3162 2845 +6 2842 2547 2846 2847 3162 2844 +6 2845 2547 2847 2848 2548 2857 +6 2845 2846 2848 2849 3162 3163 +6 2847 2846 2849 2850 2851 2857 +6 2847 2848 2850 2852 2858 3163 +6 2849 2848 2851 2852 2853 2854 +6 2850 2848 2854 2855 2856 2857 +6 2849 2850 2853 2858 2859 2860 +5 2852 2850 2854 2860 6676 +7 2853 2850 2851 2855 6676 6677 6678 +7 2854 2851 2856 6689 6686 6680 6678 +6 2855 2851 2857 6691 6689 2550 +6 2856 2851 2848 2550 2548 2846 +6 2849 2852 2859 3180 3163 6661 +7 2858 2852 2860 6661 6674 6666 6662 +6 2859 2852 2853 6675 6674 6676 +5 1631 1633 1628 1629 1630 +6 1628 1633 1636 2863 1627 7215 +7 2862 1636 1637 2864 7216 7215 7217 +5 2863 1637 1638 2865 7217 +7 2864 1638 1639 2866 7217 7218 7219 +7 2865 1639 1640 2867 3189 3214 7219 +6 2866 1640 1641 2490 2868 3189 +6 2867 2490 2869 3189 3190 3181 +6 2868 2490 2480 2494 2870 3181 +6 2869 2494 2871 2873 2884 3181 +6 2870 2494 2495 2496 2872 2873 +6 2871 2496 2873 2874 2881 2882 +6 2871 2872 2874 2875 2870 2884 +6 2873 2872 2875 2876 2880 2881 +6 2873 2874 2876 2877 2884 2885 +6 2875 2874 2877 2878 2879 2880 +6 2875 2876 2878 2885 2886 2887 +6 2877 2876 2879 2887 2888 2889 +6 2878 2876 2880 2892 2889 7600 +6 2879 2876 2874 2881 4086 7600 +6 2880 2874 2872 2882 4086 4087 +6 2881 2872 2496 2497 2883 4087 +6 2882 2497 2498 4087 4088 4092 +6 2870 2873 2875 2885 3181 3182 +6 2884 2875 2877 2886 3182 3183 +6 2885 2877 2887 3183 3184 3185 +6 2886 2877 2878 2888 3188 3185 +6 2887 2878 2889 2890 3959 3188 +6 2888 2878 2890 2891 2892 2879 +6 2888 2889 2891 3961 3959 7592 +6 2890 2889 2892 7592 7593 7594 +6 2891 2889 2879 7600 7597 7594 +6 1745 1746 2751 2894 3199 3198 +6 2893 2751 2752 2753 2895 3198 +6 2894 2753 2896 3198 3200 3201 +6 2895 2753 2754 2897 3201 3202 +6 2896 2754 2755 2898 3202 3203 +6 2897 2755 2899 3203 3204 3205 +6 2898 2755 2756 2900 3205 3206 +6 2899 2756 2757 2901 3206 3207 +6 2900 2757 2758 2902 3207 3208 +6 2901 2758 2903 3208 3209 3210 +6 2902 2758 2759 2904 3213 3210 +6 2903 2759 2760 2761 2905 3213 +6 2904 2761 2762 2906 3483 3213 +6 2905 2762 2763 2764 2907 3483 +6 2906 2764 2908 3482 3212 3483 +7 2907 2764 2765 2909 3500 3482 3697 +6 2908 2765 2766 2910 3697 3698 +6 2909 2766 2767 2911 3698 3699 +6 2910 2767 2768 2912 3699 3700 +6 2911 2768 2769 2770 2913 3700 +6 2912 2770 2914 3700 3701 3702 +6 2913 2770 2771 2915 3702 3703 +6 2914 2771 2772 2916 3703 3704 +6 2915 2772 2773 2917 3704 3705 +6 2916 2773 2774 2918 3705 3706 +6 2917 2774 2775 2919 3706 3707 +6 2918 2775 2776 2920 3707 3708 +6 2919 2776 2777 2921 3708 3709 +6 2920 2777 2778 2922 3709 3710 +6 2921 2778 2779 2923 3710 3711 +6 2922 2779 2780 2924 3711 3712 +6 2923 2780 2781 2925 3712 3713 +6 2924 2781 2782 2926 3713 3714 +6 2925 2782 2783 2927 3714 3715 +6 2926 2783 2784 2928 3715 3716 +6 2927 2784 2785 2929 3716 3717 +6 2928 2785 2786 2930 3717 3718 +6 2929 2786 2787 2931 3718 3719 +6 2930 2787 2788 2932 3719 3720 +6 2931 2788 2789 2933 3720 3721 +6 2932 2789 2790 2934 3721 3722 +6 2933 2790 2791 2935 3722 3723 +6 2934 2791 2792 2936 3723 3724 +6 2935 2792 2793 2937 3724 3725 +6 2936 2793 2794 2938 3725 3726 +6 2937 2794 2795 2939 3726 3727 +6 2938 2795 2796 2940 3727 3728 +6 2939 2796 2797 2941 3728 3729 +6 2940 2797 2798 2942 3729 3730 +6 2941 2798 2799 2943 3730 3731 +6 2942 2799 2800 2944 3731 3732 +6 2943 2800 2801 2824 2945 3732 +6 2944 2824 2825 2946 3732 3733 +6 2945 2825 2827 2947 3733 3734 +6 2946 2827 2828 2829 2948 3734 +7 2947 2829 2830 2949 3734 3735 3736 +6 2948 2830 2831 2950 3242 3736 +6 2949 2831 2832 2951 3242 3243 +6 2950 2832 2833 2952 3243 3244 +6 2951 2833 2834 2953 3244 3245 +5 2952 2834 2835 2954 3245 +7 2953 2835 2836 2955 3245 3246 3247 +6 2954 2836 2837 2956 3247 3248 +6 2955 2837 2839 2957 3248 3249 +6 2956 2839 2958 3249 3250 3251 +6 2957 2839 2840 2959 3251 3252 +6 2958 2840 2621 2622 2960 3252 +6 2959 2622 2623 2961 3254 3252 +6 2960 2623 2624 2962 3254 3255 +6 2961 2624 2625 2963 2964 3255 +6 2962 2625 2964 2965 2966 2626 +6 2962 2963 2965 3255 3256 3257 +6 2964 2963 2966 3257 3258 3259 +6 2965 2963 2626 2627 2967 3259 +6 2966 2627 2628 2968 3259 3260 +6 2967 2628 2629 2969 3260 3261 +6 2968 2629 2630 2970 3261 3262 +6 2969 2630 2631 2971 3262 3263 +6 2970 2631 2632 2972 3263 3264 +6 2971 2632 2633 2973 3264 3265 +6 2972 2633 2634 2974 3265 3266 +6 2973 2634 2635 2975 3266 3267 +6 2974 2635 2636 2637 2976 3267 +6 2975 2637 2639 2977 3267 3268 +6 2976 2639 2978 3268 3269 3270 +6 2977 2639 2640 2979 3270 3271 +6 2978 2640 2642 2980 3271 3272 +6 2979 2642 2643 2981 3272 3273 +6 2980 2643 2644 2982 3273 3274 +6 2981 2644 2645 2983 3274 3275 +6 2982 2645 2646 2984 3275 3276 +6 2983 2646 2647 2985 3276 3277 +6 2984 2647 2648 2986 3277 3824 +6 2985 2648 2649 2987 3545 3824 +6 2986 2649 2650 2988 3545 3546 +6 2987 2650 2651 2989 3546 3547 +6 2988 2651 2652 2990 3547 3548 +6 2989 2652 2653 2991 3548 3549 +6 2990 2653 2654 2992 3549 3550 +6 2991 2654 2656 2993 3550 3551 +6 2992 2656 2657 2994 3551 3552 +6 2993 2657 2658 2995 3552 3553 +6 2994 2658 2659 2996 3553 3554 +6 2995 2659 2997 3554 3555 3556 +6 2996 2659 2660 2998 3556 3557 +6 2997 2660 2661 2662 2999 3557 +6 2998 2662 2663 3000 3557 3558 +6 2999 2663 2664 3001 3558 3559 +6 3000 2664 2665 3002 3559 3560 +6 3001 2665 2666 3560 3561 3565 +6 2702 2703 3004 3290 3291 3292 +6 3003 2703 2704 3005 3292 3293 +6 3004 2704 2705 3006 3293 3294 +6 3005 2705 2706 3007 3294 3295 +6 3006 2706 2707 3008 3295 3296 +6 3007 2707 2708 3009 3296 3297 +6 3008 2708 2709 2710 3010 3297 +6 3009 2710 3011 3297 3298 3299 +6 3010 2710 2711 3012 3299 3300 +6 3011 2711 2712 3013 3300 3301 +6 3012 2712 2713 3014 3301 3302 +6 3013 2713 2714 3015 3302 3303 +6 3014 2714 2715 3016 3303 3304 +6 3015 2715 2716 3017 3304 3305 +6 3016 2716 2717 3018 3305 3306 +6 3017 2717 2718 3019 3306 3307 +6 3018 2718 2719 3020 3307 3308 +6 3019 2719 2720 3021 3308 3309 +6 3020 2720 2721 3022 3309 3310 +6 3021 2721 2722 3023 3310 3311 +6 3022 2722 2723 3024 3311 3312 +6 3023 2723 2724 3025 3312 3313 +6 3024 2724 2725 3026 3313 3314 +6 3025 2725 2726 3027 3314 3315 +6 3026 2726 2727 3028 3315 3316 +6 3027 2727 2728 3029 3316 3317 +6 3028 2728 2729 3030 3317 3318 +6 3029 2729 2730 3031 3318 3319 +6 3030 2730 2731 3032 3319 3320 +6 3031 2731 2732 3033 3320 3321 +6 3032 2732 2733 3034 3321 3322 +6 3033 2733 2734 3035 3042 3322 +6 3034 2734 2735 3036 3042 3043 +6 3035 2735 2736 3037 3043 3044 +6 3036 2736 2737 2738 3038 3044 +6 3037 2738 3039 3044 3045 3046 +6 3038 2738 2739 3040 3046 3047 +6 3039 2739 2740 2741 3041 3047 +6 3040 2741 2743 3047 3048 3049 +6 3034 3035 3043 3322 3323 3324 +6 3042 3035 3036 3044 3324 3325 +6 3043 3036 3037 3038 3045 3325 +6 3044 3038 3046 3325 3326 3327 +6 3045 3038 3039 3047 3053 3327 +6 3046 3039 3040 3041 3048 3053 +6 3047 3041 3049 3053 3054 3055 +6 3048 3041 2743 2744 3050 3055 +6 3049 2744 2745 2746 3051 3055 +6 3050 2746 2747 3052 3055 3056 +6 3051 2747 2749 3056 3057 3058 +6 3046 3047 3048 3054 3327 3328 +6 3053 3048 3055 3328 3329 3056 +6 3054 3048 3049 3050 3051 3056 +7 3055 3051 3052 3057 3329 3054 3641 +5 3056 3052 3058 3641 3642 +7 3057 3052 2749 2750 3059 3642 3643 +6 3058 2750 3060 3643 3644 3061 +5 3059 2750 2445 2446 3061 +6 3060 2446 3062 3644 3059 3910 +6 3061 2446 2447 3063 3910 3911 +6 3062 2447 3064 3069 3911 3912 +6 3063 2447 2448 2449 3065 3069 +6 3064 2449 2450 3066 3069 3070 +6 3065 2450 2451 3067 3070 3071 +6 3066 2451 2452 3068 3071 3072 +6 3067 2452 2454 3072 3073 3074 +6 3063 3064 3065 3070 3912 3913 +6 3069 3065 3066 3071 3913 3914 +6 3070 3066 3067 3072 3914 3915 +6 3071 3067 3068 3073 3915 3916 +6 3072 3068 3074 3916 3917 3918 +6 3073 3068 2454 2455 3075 3918 +6 3074 2455 2456 2457 3076 3918 +6 3075 2457 2458 3077 3349 3918 +6 3076 2458 2459 3078 3349 3350 +6 3077 2459 2460 3079 3107 3350 +6 3078 2460 2461 3080 3107 3108 +6 3079 2461 3081 3091 3108 3109 +6 3080 2461 2462 3082 3091 3092 +6 3081 2462 2463 3083 3084 3092 +6 3082 2463 3084 3085 2482 2464 +6 3082 3083 3085 3092 3112 3359 +6 3084 3083 2482 3926 3152 3359 +6 16 17 3087 3088 3089 3090 +6 3086 17 18 3095 3126 3090 +6 16 3086 3089 3098 417 15 +6 3088 3086 3090 3098 3103 3104 +6 3089 3086 3104 3105 3087 3126 +6 3080 3081 3092 3109 3110 3111 +6 3091 3081 3082 3084 3111 3112 +5 1615 1616 3094 4099 3544 +6 3093 1616 1617 4367 4099 1624 +6 3087 18 19 3096 3125 3126 +6 3095 19 20 3125 3128 414 +6 2241 1657 1655 1647 1182 1184 +6 3088 3089 417 3099 3102 3103 +6 417 3098 418 3100 3101 3102 +6 418 3099 3101 3228 3229 3684 +6 3100 3099 3102 3226 3228 3498 +7 3101 3099 3098 3103 3113 3498 3497 +6 3102 3098 3089 3104 3113 3114 +6 3103 3089 3090 3105 3106 3114 +6 3104 3090 3106 3126 3124 3118 +6 3104 3105 3116 3114 3117 3118 +6 3078 3079 3108 3350 3351 3352 +6 3107 3079 3080 3109 3352 3353 +6 3108 3080 3091 3110 3353 3354 +6 3109 3091 3111 3354 3355 3356 +6 3110 3091 3092 3112 3356 3357 +6 3111 3092 3084 3357 3358 3359 +5 3102 3103 3114 3115 3497 +6 3113 3103 3115 3116 3106 3104 +7 3113 3114 3116 3497 3504 3501 3495 +6 3115 3114 3106 3117 6712 3504 +6 3116 3106 3118 3119 6712 6711 +6 3117 3106 3119 3120 3124 3105 +6 3117 3118 3120 3121 6711 6713 +6 3119 3118 3121 3122 3123 3124 +6 3119 3120 3122 3884 3887 6713 +6 3121 3120 3123 3127 3883 3884 +6 3122 3120 3124 3125 3127 3128 +6 3123 3120 3118 3125 3126 3105 +6 3123 3124 3126 3128 3095 3096 +6 3125 3124 3105 3095 3087 3090 +6 3122 3123 3128 3882 3339 3883 +6 3127 3123 3125 414 3882 3096 +6 2201 2203 3130 3851 3852 9781 +6 3129 2203 2205 1525 1526 9781 +6 2094 2095 3132 3133 9776 3138 +6 2094 3131 3133 3134 3135 2093 +6 3132 3131 3134 3136 3137 3138 +6 3132 3133 3135 3136 5946 5945 +6 3132 3134 5945 5943 5947 2093 +6 3134 3133 3137 6090 6091 5946 +6 3136 3133 3138 6090 6089 6092 +6 3137 3133 6092 6093 9776 3131 +6 2813 2814 2817 3140 4388 4386 +6 3139 2817 3141 4385 4384 4386 +6 3140 2817 2818 3142 4390 4385 +6 3141 2818 3143 7767 4390 7768 +6 3142 2818 2819 3144 7774 7768 +6 3143 2819 2820 3145 7774 7775 +6 3144 2820 3146 4231 7775 9791 +6 3145 2820 2821 2823 3147 4231 +6 3146 2823 1673 1674 3412 4231 +6 2486 2487 3149 3156 3157 3161 +6 2486 3148 3150 3151 3155 3156 +6 2486 3149 3151 3152 3926 2484 +6 3150 3149 3152 3153 3154 3155 +6 3150 3151 3153 3926 3085 3359 +6 3152 3151 3154 3358 3359 3360 +6 3153 3151 3155 3360 3361 3362 +6 3154 3151 3149 3156 3677 3362 +6 3155 3149 3148 3157 3158 3677 +6 3156 3148 3158 3159 3160 3161 +6 3156 3157 3159 3676 3677 3945 +6 3158 3157 3160 3945 3946 3962 +6 3159 3157 3161 3962 3963 3964 +6 3160 3157 3148 3967 3964 2487 +6 2845 2847 3163 3164 3165 2844 +6 3162 2847 3164 3180 2858 2849 +6 3162 3163 3165 3166 3177 3180 +6 3162 3164 3166 3167 3168 2844 +6 3165 3164 3167 3177 3174 3171 +6 3165 3166 3168 3169 3170 3171 +6 3165 3167 3169 2843 2844 9688 +6 3168 3167 3170 9687 9686 9688 +5 3169 3167 3171 3172 9687 +6 3170 3167 3172 3173 3174 3166 +6 3170 3171 3173 9691 9687 6653 +7 3172 3171 3174 3175 6654 6652 6653 +6 3173 3171 3175 3176 3177 3166 +5 3173 3174 3176 3450 6654 +6 3175 3174 3177 3178 3179 3450 +6 3176 3174 3178 3166 3164 3180 +6 3176 3177 3179 3180 6660 6661 +6 3176 3178 3450 6657 6659 6660 +6 3177 3164 3178 3163 2858 6661 +6 2869 2870 2884 3182 3190 2868 +6 3181 2884 2885 3183 3216 3190 +6 3182 2885 2886 3184 3193 3216 +6 3183 2886 3185 3186 3192 3193 +6 3184 2886 3186 3187 3188 2887 +6 3184 3185 3187 3192 3196 7584 +6 3186 3185 3188 3958 7586 7584 +6 3187 3185 2887 3958 3959 2888 +6 2867 2868 3190 2866 3214 3215 +6 3189 2868 3181 3215 3216 3182 +6 1741 1742 1744 3197 3198 3199 +6 3184 3186 3193 3194 3195 3196 +6 3184 3192 3194 7222 3216 3183 +7 3193 3192 3195 7222 7221 7204 7203 +6 3194 3192 3196 7196 7197 7203 +6 3195 3192 3186 7583 7196 7584 +6 1740 1741 3191 3198 3411 3200 +7 3197 3191 3199 2893 2894 2895 3200 +5 3198 3191 1744 1745 2893 +6 3198 2895 3201 3411 3197 9751 +6 3200 2895 2896 3202 3470 9751 +6 3201 2896 2897 3203 3470 3471 +6 3202 2897 2898 3204 3471 3472 +6 3203 2898 3205 3472 3473 3474 +6 3204 2898 2899 3206 3474 3475 +6 3205 2899 2900 3207 3475 3476 +6 3206 2900 2901 3208 3476 3477 +6 3207 2901 2902 3209 3477 3478 +6 3208 2902 3210 3211 3478 3479 +6 3209 2902 3211 3212 3213 2903 +6 3209 3210 3212 3479 3480 3481 +7 3211 3210 3213 3481 3482 2907 3483 +6 3212 3210 2903 3483 2905 2904 +6 2866 3189 3215 7220 7219 7221 +6 3214 3189 3190 3216 7221 7222 +6 3215 3190 3182 7222 3193 3183 +6 635 636 3218 4040 3763 3762 +6 3217 636 638 3219 3484 4040 +6 3218 638 3220 3221 3222 3484 +6 3219 638 639 3221 3240 3241 +6 3219 3220 3222 3223 3224 3241 +6 3219 3221 3223 3484 3485 3486 +6 3222 3221 3224 3225 3486 3487 +6 3223 3221 3225 3226 3227 3241 +6 3223 3224 3226 3493 3487 3494 +7 3225 3224 3227 3228 3101 3494 3498 +6 3226 3224 3228 3229 3230 3241 +5 3226 3227 3101 3100 3229 +6 3100 3228 3227 3230 3231 3684 +6 3229 3227 3231 3232 3241 3240 +6 3229 3230 3232 3233 3234 3684 +6 3231 3230 3233 3240 3239 3236 +7 3231 3232 3234 11 10 3235 3236 +5 3231 3233 11 3684 12 +6 10 3233 3236 3237 3238 9 +6 3235 3233 3237 643 3239 3232 +6 3235 3236 3238 647 644 643 +5 3235 3237 9 8 647 +6 643 3236 640 639 3240 3232 +6 639 3239 3220 3241 3230 3232 +6 3220 3240 3221 3224 3227 3230 +6 2949 2950 3243 3736 3737 3738 +6 3242 2950 2951 3244 3738 3739 +6 3243 2951 2952 3245 3739 3740 +7 3244 2952 2953 2954 3246 3740 3741 +5 3245 2954 3247 3741 3742 +6 3246 2954 2955 3248 3742 3743 +6 3247 2955 2956 3249 3743 3744 +6 3248 2956 2957 3250 3744 3745 +6 3249 2957 3251 3745 3746 3747 +6 3250 2957 2958 3252 3253 3747 +6 3251 2958 3253 3254 2960 2959 +6 3251 3252 3254 3747 3748 3749 +6 3253 3252 2960 2961 3255 3749 +6 3254 2961 2962 2964 3256 3749 +6 3255 2964 3257 3749 3750 3751 +6 3256 2964 2965 3258 3751 3752 +6 3257 2965 3259 3752 3753 3754 +6 3258 2965 2966 2967 3260 3754 +6 3259 2967 2968 3261 3754 3755 +6 3260 2968 2969 3262 3755 3756 +6 3261 2969 2970 3263 3756 3757 +6 3262 2970 2971 3264 3757 3758 +6 3263 2971 2972 3265 3758 3759 +7 3264 2972 2973 3266 3759 4054 4051 +5 3265 2973 2974 3267 4054 +6 3266 2974 2975 2976 3268 4054 +7 3267 2976 2977 3269 4054 4053 4055 +5 3268 2977 3270 4055 4056 +6 3269 2977 2978 3271 4056 4057 +6 3270 2978 2979 3272 4057 4058 +6 3271 2979 2980 3273 4058 4059 +6 3272 2980 2981 3274 4059 4060 +6 3273 2981 2982 3275 4060 4061 +6 3274 2982 2983 3276 4064 4061 +6 3275 2983 2984 3277 4064 4065 +6 3276 2984 2985 3826 4065 3824 +6 2689 2690 3279 3588 3589 3590 +6 3278 2690 2691 3280 3590 3591 +6 3279 2691 2692 3281 3591 3592 +6 3280 2692 2693 3282 3592 3593 +6 3281 2693 2694 3283 3593 3594 +6 3282 2694 2695 3284 3594 3595 +6 3283 2695 2696 3285 3595 3596 +6 3284 2696 2697 3286 3596 3597 +6 3285 2697 2698 3287 3597 3598 +6 3286 2698 2699 3288 3598 3599 +6 3287 2699 2700 3289 3599 3600 +6 3288 2700 2701 3290 3600 3601 +6 3289 2701 2702 3003 3291 3601 +6 3290 3003 3292 3601 3602 3603 +6 3291 3003 3004 3293 3603 3604 +6 3292 3004 3005 3294 3604 3605 +6 3293 3005 3006 3295 3605 3606 +6 3294 3006 3007 3296 3606 3607 +6 3295 3007 3008 3297 3607 3608 +6 3296 3008 3009 3010 3298 3608 +6 3297 3010 3299 3608 3609 3610 +6 3298 3010 3011 3300 3610 3611 +6 3299 3011 3012 3301 3611 3612 +6 3300 3012 3013 3302 3612 3613 +6 3301 3013 3014 3303 3613 3614 +6 3302 3014 3015 3304 3614 3615 +6 3303 3015 3016 3305 3615 3616 +6 3304 3016 3017 3306 3616 3617 +6 3305 3017 3018 3307 3617 3618 +6 3306 3018 3019 3308 3618 3619 +6 3307 3019 3020 3309 3619 3620 +6 3308 3020 3021 3310 3620 3621 +6 3309 3021 3022 3311 3621 3622 +6 3310 3022 3023 3312 3622 3623 +6 3311 3023 3024 3313 3623 3624 +6 3312 3024 3025 3314 3624 3625 +6 3313 3025 3026 3315 3625 3626 +6 3314 3026 3027 3316 3626 3627 +6 3315 3027 3028 3317 3627 3628 +6 3316 3028 3029 3318 3628 3629 +6 3317 3029 3030 3319 3629 3630 +6 3318 3030 3031 3320 3630 3631 +6 3319 3031 3032 3321 3631 3632 +6 3320 3032 3033 3322 3632 3633 +6 3321 3033 3034 3042 3323 3633 +6 3322 3042 3324 3633 3634 3635 +6 3323 3042 3043 3325 3635 3636 +6 3324 3043 3044 3045 3326 3636 +6 3325 3045 3327 3636 3637 3638 +6 3326 3045 3046 3053 3328 3638 +6 3327 3053 3054 3329 3638 3639 +6 3328 3054 3056 3639 3640 3641 +6 2507 2508 32 33 3331 3880 +6 3330 33 34 2248 3332 3880 +6 3331 2248 3333 3334 3880 3881 +6 3332 2248 3334 3335 3336 2249 +6 3332 3333 3335 9707 6499 3881 +6 3334 3333 3336 9706 6492 9707 +6 3335 3333 2249 2250 2251 9706 +6 1171 1172 1524 3338 3339 3882 +6 3337 1524 3339 3340 3341 4250 +6 3337 3338 3340 3882 3127 3883 +6 3339 3338 3341 3342 3885 3883 +6 3340 3338 3342 3343 2206 4250 +6 3340 3341 3343 3861 6717 3885 +6 3342 3341 2206 2207 3344 3861 +6 3343 2207 2209 3345 3346 3861 +6 3344 2209 3346 3347 3348 2211 +6 3344 3345 3347 3861 3862 3863 +6 3346 3345 3348 6532 3863 6524 +6 3347 3345 2211 2213 6523 6524 +6 3076 3077 3350 3918 3917 3919 +6 3349 3077 3078 3107 3351 3919 +6 3350 3107 3352 3919 3920 3921 +6 3351 3107 3108 3353 3921 3922 +6 3352 3108 3109 3354 3922 3923 +6 3353 3109 3110 3355 3923 3924 +6 3354 3110 3356 3924 3925 3374 +6 3355 3110 3111 3357 3368 3374 +6 3356 3111 3112 3358 3367 3368 +6 3357 3112 3359 3153 3360 3367 +6 3358 3112 3153 3085 3152 3084 +6 3358 3153 3154 3361 3363 3367 +6 3360 3154 3362 3363 3364 3678 +6 3361 3154 3155 3677 3675 3678 +6 3360 3361 3364 3365 3366 3367 +6 3363 3361 3365 3678 3667 3668 +6 3363 3364 3366 3373 3370 3668 +6 3363 3365 3367 3368 3369 3370 +6 3363 3366 3368 3360 3358 3357 +6 3367 3366 3369 3357 3356 3374 +6 3368 3366 3370 3371 3374 3375 +6 3369 3366 3371 3372 3373 3365 +6 3369 3370 3372 3375 3376 3377 +6 3371 3370 3373 3377 3378 3379 +6 3372 3370 3365 3379 3380 3668 +6 3356 3368 3369 3375 3925 3355 +7 3374 3369 3371 3376 3943 3925 4342 +5 3375 3371 3377 4342 4343 +6 3376 3371 3372 3378 4343 4344 +6 3377 3372 3379 3645 4347 4344 +6 3378 3372 3373 3380 3381 3645 +6 3379 3373 3381 3382 3668 3656 +6 3379 3380 3382 3383 3384 3645 +6 3381 3380 3383 3390 3387 3656 +6 3381 3382 3384 3385 3386 3387 +6 3381 3383 3385 3645 3646 3647 +6 3384 3383 3386 3647 3648 3649 +6 3385 3383 3387 3388 3649 3650 +6 3386 3383 3388 3389 3390 3382 +6 3386 3387 3389 3650 3651 3652 +6 3388 3387 3390 3652 3653 3654 +6 3389 3387 3382 3654 3655 3656 +6 2675 2676 3392 3573 3574 3575 +6 3391 2676 2677 3393 3575 3576 +6 3392 2677 2678 3394 3576 3577 +6 3393 2678 2679 3577 3578 3579 +6 2173 2804 2805 3396 3397 4747 +6 3395 2805 3397 3398 3399 3400 +6 3395 3396 3398 3892 4747 4746 +6 3397 3396 3399 3892 3893 3894 +6 3398 3396 3400 3894 3895 3896 +6 3399 3396 2805 2806 3401 3896 +6 3400 2806 2807 3402 3896 3897 +6 3401 2807 3403 3897 3898 3899 +6 3402 2807 2808 3404 3899 3900 +6 3403 2808 1732 3405 3679 3900 +6 3404 1732 1733 1734 3406 3679 +6 3405 1734 1735 3407 3679 3680 +6 3406 1735 1736 3408 3680 3681 +6 3407 1736 1737 3409 3683 3681 +6 3408 1737 1738 3410 3470 3683 +6 3409 1738 1739 3411 9751 3470 +6 3410 1739 1740 3197 3200 9751 +6 3147 1674 1675 1676 3413 4231 +6 3412 1676 1677 3414 9791 4231 +6 3413 1677 3415 7778 7776 9791 +6 3414 1677 1678 7778 7779 5382 +6 1695 1696 3417 3786 1694 3787 +6 3416 1696 1697 3418 3787 3789 +6 3417 1697 1698 2223 3419 3789 +6 3418 2223 3420 3789 3790 3791 +6 3419 2223 2224 3421 3791 3792 +6 3420 2224 2225 3422 3423 3792 +6 3421 2225 3423 3424 3425 3426 +6 3421 3422 3424 3794 3792 3795 +6 3423 3422 3425 3795 3796 3797 +6 3424 3422 3426 3797 3798 3799 +6 3425 3422 2225 2226 3427 3799 +6 3426 2226 2227 3428 3799 3800 +6 3427 2227 2228 3429 3800 3801 +6 3428 2228 3430 3801 3802 3432 +6 3429 2228 2229 2238 3431 3432 +6 3430 2238 3432 3433 3434 3435 +6 3430 3431 3433 3442 3802 3429 +6 3432 3431 3434 3442 3443 3444 +6 3433 3431 3435 3444 3445 3446 +6 3434 3431 2238 2239 2561 3446 +6 2491 2492 3437 3438 3515 2493 +6 2491 3436 3438 3439 3440 3441 +6 3437 3436 3439 3513 3514 3515 +6 3437 3438 3440 3508 3509 3513 +6 3437 3439 3441 3451 3453 3508 +6 3437 3440 2491 70 3451 69 +6 3432 3433 3443 3802 3803 3804 +6 3442 3433 3444 3804 3805 3806 +6 3443 3433 3434 3445 3806 3807 +6 3444 3434 3446 3807 3808 3447 +6 3445 3434 3435 2561 2562 3447 +6 3446 2562 3448 3808 3445 4107 +6 3447 2562 2563 3449 3454 4107 +6 3448 2563 2567 3454 3455 2568 +7 3175 3176 3179 6655 6654 6656 6657 +6 3441 3440 69 68 3452 3453 +6 68 3451 3453 67 3505 3506 +6 3452 3451 3440 3506 3507 3508 +6 3448 3449 3455 3456 4107 4108 +6 3454 3449 3456 3457 3458 2568 +6 3454 3455 3457 3464 4110 4108 +6 3456 3455 3458 3459 3460 3464 +6 3457 3455 3459 3463 2569 2568 +6 3457 3458 3460 3461 3462 3463 +6 3457 3459 3461 3464 3465 3466 +6 3460 3459 3462 3466 3467 3469 +6 3461 3459 3463 1721 3469 1720 +6 3462 3459 3458 2569 1720 1719 +6 3456 3457 3460 3465 4394 4110 +6 3464 3460 3466 4404 4394 4745 +6 3465 3460 3461 3467 3468 4745 +6 3466 3461 3468 2172 1724 3469 +6 3466 3467 2172 4745 4746 4747 +6 1724 3467 1722 1721 3462 3461 +7 3201 3202 3471 9751 3410 3409 3683 +6 3470 3202 3203 3472 3681 3683 +6 3471 3203 3204 3473 3682 3681 +6 3472 3204 3474 3685 3902 3682 +6 3473 3204 3205 3475 3685 3686 +6 3474 3205 3206 3476 3686 3687 +6 3475 3206 3207 3477 3687 3688 +6 3476 3207 3208 3478 3688 3689 +6 3477 3208 3209 3479 3689 3690 +6 3478 3209 3211 3480 3690 3691 +6 3479 3211 3481 3499 3694 3691 +6 3480 3211 3212 3482 3499 3500 +5 3481 3212 2907 3500 2908 +5 2907 3212 3213 2905 2906 +6 3218 3219 3222 3485 4039 4040 +6 3484 3222 3486 3489 3968 4039 +6 3485 3222 3223 3487 3488 3489 +6 3486 3223 3488 3492 3493 3225 +6 3486 3487 3489 3490 3491 3492 +6 3486 3488 3490 3485 3968 3969 +6 3489 3488 3491 3969 3970 3971 +6 3490 3488 3492 3971 9747 6555 +6 3491 3488 3487 3493 3496 9747 +6 3492 3487 3225 3494 3495 3496 +6 3493 3225 3226 3495 3497 3498 +6 3493 3494 3496 3497 3501 3115 +6 3493 3495 3492 3501 3502 9747 +6 3495 3494 3498 3102 3113 3115 +5 3497 3494 3226 3101 3102 +6 3480 3481 3500 3694 3695 3696 +6 3499 3481 3482 2908 3696 3697 +6 3496 3495 3502 3503 3504 3115 +6 3496 3501 3503 9747 6706 9748 +6 3502 3501 3504 6712 6710 9748 +5 3503 3501 3115 6712 3116 +6 67 3452 3506 6697 6703 66 +6 3505 3452 3453 3507 6697 6704 +6 3506 3453 3508 3510 4522 6704 +6 3507 3453 3440 3439 3509 3510 +6 3508 3439 3510 3511 3512 3513 +6 3508 3509 3511 3770 3507 4522 +6 3510 3509 3512 3770 3771 3772 +6 3511 3509 3513 3772 3773 3520 +6 3512 3509 3439 3438 3514 3520 +6 3513 3438 3515 3520 3521 3517 +6 3514 3438 3436 2493 3516 3517 +6 3515 2493 3517 3518 1607 1606 +6 3515 3516 3518 3521 3514 3522 +6 3517 3516 1607 1613 3522 3523 +5 1613 1607 1605 1608 1610 +6 3513 3514 3521 3773 3512 4531 +6 3520 3514 3517 3522 4116 4531 +6 3521 3517 3518 3523 3525 4116 +6 3522 3518 1613 1614 3524 3525 +6 3523 1614 3525 3526 3527 3528 +6 3523 3524 3526 3522 4116 4117 +6 3525 3524 3527 3529 4117 4118 +6 3526 3524 3528 3529 3530 3543 +6 3527 3524 1614 3543 3544 1615 +6 3526 3527 3530 3531 4118 9786 +6 3529 3527 3531 3532 3542 3543 +6 3529 3530 3532 3533 9786 9787 +6 3531 3530 3533 3534 3541 3542 +6 3531 3532 3534 3535 9787 9788 +6 3533 3532 3535 3536 3540 3541 +6 3533 3534 3536 3537 9788 7178 +6 3535 3534 3537 3538 3539 3540 +6 3535 3536 3538 7182 7179 7178 +6 3537 3536 3539 7182 7183 7184 +6 3538 3536 3540 7184 7185 7212 +6 3539 3536 3534 3541 7212 4372 +6 3540 3534 3532 3542 4372 4097 +6 3541 3532 3530 3543 4096 4097 +6 3542 3530 3527 3528 3544 4096 +6 3543 3528 1615 4099 4096 3093 +6 2986 2987 3546 3824 3825 3829 +6 3545 2987 2988 3547 3829 3830 +6 3546 2988 2989 3548 3830 3831 +6 3547 2989 2990 3549 3831 3832 +6 3548 2990 2991 3550 3832 3833 +6 3549 2991 2992 3551 3809 3833 +6 3550 2992 2993 3552 3809 3810 +6 3551 2993 2994 3553 3810 3811 +6 3552 2994 2995 3554 3811 3812 +6 3553 2995 2996 3555 3812 3813 +6 3554 2996 3556 3813 3814 3815 +6 3555 2996 2997 3557 3815 3816 +6 3556 2997 2998 2999 3558 3816 +6 3557 2999 3000 3559 3816 3817 +6 3558 3000 3001 3560 3817 3818 +6 3559 3001 3002 3561 3562 3818 +6 3560 3002 3562 3563 3564 3565 +6 3560 3561 3563 3818 3819 3820 +6 3562 3561 3564 3820 3821 3822 +6 3563 3561 3565 3822 3823 3566 +6 3564 3561 3002 2666 2667 3566 +6 3565 2667 2668 3567 3823 3564 +6 3566 2668 2669 3568 3850 3823 +6 3567 2669 2670 3569 3879 3850 +6 3568 2670 2671 3570 3891 3879 +6 3569 2671 2672 2673 3571 3891 +6 3570 2673 3572 4237 3891 4257 +6 3571 2673 2674 3573 4257 4258 +6 3572 2674 2675 3391 3574 4258 +6 3573 3391 3575 4258 4259 4263 +6 3574 3391 3392 3576 4263 4264 +6 3575 3392 3393 3577 4264 4265 +6 3576 3393 3394 3578 4265 4266 +6 3577 3394 3579 4266 4267 4268 +6 3578 3394 2679 2680 3580 4268 +6 3579 2680 2681 3581 4141 4268 +6 3580 2681 2682 3582 4141 4142 +6 3581 2682 2683 3583 4142 4143 +6 3582 2683 2684 3584 4143 4144 +6 3583 2684 2685 3585 4144 4145 +6 3584 2685 2686 3586 4145 4146 +6 3585 2686 2687 3587 4146 4147 +6 3586 2687 2688 3588 4147 4148 +6 3587 2688 2689 3278 3589 4148 +6 3588 3278 3590 4148 4149 4150 +6 3589 3278 3279 3591 4150 4151 +6 3590 3279 3280 3592 4151 4152 +6 3591 3280 3281 3593 4152 4153 +6 3592 3281 3282 3594 4153 4154 +6 3593 3282 3283 3595 4154 4155 +6 3594 3283 3284 3596 4155 4156 +6 3595 3284 3285 3597 4156 4157 +6 3596 3285 3286 3598 4157 4158 +6 3597 3286 3287 3599 4158 4159 +6 3598 3287 3288 3600 4159 4160 +6 3599 3288 3289 3601 4160 4161 +6 3600 3289 3290 3291 3602 4161 +6 3601 3291 3603 4161 4162 4163 +6 3602 3291 3292 3604 4163 4164 +6 3603 3292 3293 3605 4164 4165 +6 3604 3293 3294 3606 4165 4166 +6 3605 3294 3295 3607 4166 4167 +6 3606 3295 3296 3608 4167 4168 +6 3607 3296 3297 3298 3609 4168 +6 3608 3298 3610 4168 4169 4170 +6 3609 3298 3299 3611 4170 4171 +6 3610 3299 3300 3612 4171 4172 +6 3611 3300 3301 3613 4172 4173 +6 3612 3301 3302 3614 4173 4174 +6 3613 3302 3303 3615 4174 4175 +6 3614 3303 3304 3616 4175 4176 +6 3615 3304 3305 3617 4176 4177 +6 3616 3305 3306 3618 4177 4178 +6 3617 3306 3307 3619 4178 4179 +6 3618 3307 3308 3620 4179 4180 +6 3619 3308 3309 3621 4180 4181 +6 3620 3309 3310 3622 4181 4182 +6 3621 3310 3311 3623 4182 4183 +6 3622 3311 3312 3624 4183 4184 +6 3623 3312 3313 3625 4184 4185 +6 3624 3313 3314 3626 4185 4186 +6 3625 3314 3315 3627 4186 4187 +6 3626 3315 3316 3628 4187 4188 +6 3627 3316 3317 3629 4188 4189 +6 3628 3317 3318 3630 4189 4190 +6 3629 3318 3319 3631 4190 4191 +6 3630 3319 3320 3632 4191 4192 +6 3631 3320 3321 3633 4192 4193 +6 3632 3321 3322 3323 3634 4193 +6 3633 3323 3635 3903 4193 4194 +6 3634 3323 3324 3636 3903 3904 +6 3635 3324 3325 3326 3637 3904 +6 3636 3326 3638 3904 3905 3906 +6 3637 3326 3327 3328 3639 3906 +6 3638 3328 3329 3640 3906 3907 +6 3639 3329 3641 3907 3908 3642 +5 3640 3329 3056 3057 3642 +7 3641 3057 3058 3643 3908 3640 3927 +6 3642 3058 3059 3644 3909 3927 +5 3643 3059 3061 3909 3910 +6 3381 3384 3646 3379 3378 4347 +6 3645 3384 3647 4347 4348 4349 +6 3646 3384 3385 3648 4352 4349 +6 3647 3385 3649 3657 4352 4353 +6 3648 3385 3386 3650 3657 3658 +6 3649 3386 3388 3651 3658 3659 +6 3650 3388 3652 3659 3660 3661 +6 3651 3388 3389 3653 3661 3662 +6 3652 3389 3654 3662 3663 3664 +6 3653 3389 3390 3655 3664 3665 +6 3654 3390 3656 3665 3666 3667 +6 3655 3390 3382 3667 3668 3380 +6 3648 3649 3658 4353 4354 4358 +6 3657 3649 3650 3659 4371 4358 +6 3658 3650 3651 3660 9793 4371 +6 3659 3651 3661 4906 4908 9793 +6 3660 3651 3652 3662 3669 4906 +6 3661 3652 3653 3663 3669 3670 +6 3662 3653 3664 3670 3671 3672 +6 3663 3653 3654 3665 3672 3673 +6 3664 3654 3655 3666 3673 3674 +6 3665 3655 3667 3674 3675 3678 +6 3666 3655 3656 3668 3364 3678 +6 3667 3656 3380 3364 3365 3373 +6 3661 3662 3670 4903 4905 4906 +6 3669 3662 3663 3671 4902 4903 +6 3670 3663 3672 5918 4902 3951 +6 3671 3663 3664 3673 3950 3951 +6 3672 3664 3665 3674 3944 3950 +6 3673 3665 3666 3675 3676 3944 +6 3674 3666 3676 3677 3362 3678 +6 3674 3675 3677 3158 3944 3945 +6 3676 3675 3158 3156 3155 3362 +6 3362 3675 3361 3364 3667 3666 +6 3404 3405 3406 3680 3900 3901 +6 3679 3406 3407 3681 3682 3901 +7 3680 3407 3682 3472 3471 3683 3408 +6 3680 3681 3472 3901 3902 3473 +5 3471 3681 3408 3409 3470 +7 418 3100 3229 3231 3234 12 13 +7 3473 3474 3686 3902 4665 4664 4688 +5 3685 3474 3475 3687 4688 +7 3686 3475 3476 3688 4688 4689 4690 +6 3687 3476 3477 3689 4690 4691 +6 3688 3477 3478 3690 4691 4692 +6 3689 3478 3479 3691 3692 4692 +6 3690 3479 3692 3693 3694 3480 +6 3690 3691 3693 4692 4693 4694 +6 3692 3691 3694 4694 4695 4696 +6 3693 3691 3480 3499 3695 4696 +6 3694 3499 3696 4696 4697 4698 +6 3695 3499 3500 3697 4698 4699 +6 3696 3500 2908 2909 3698 4699 +6 3697 2909 2910 3699 3972 4699 +6 3698 2910 2911 3700 3972 3973 +6 3699 2911 2912 2913 3701 3973 +6 3700 2913 3702 3973 3974 3975 +6 3701 2913 2914 3703 3975 3976 +6 3702 2914 2915 3704 3976 3977 +6 3703 2915 2916 3705 3977 3978 +6 3704 2916 2917 3706 3978 3979 +6 3705 2917 2918 3707 3979 3980 +6 3706 2918 2919 3708 3980 3981 +6 3707 2919 2920 3709 3981 3982 +6 3708 2920 2921 3710 3982 3983 +6 3709 2921 2922 3711 3983 3984 +6 3710 2922 2923 3712 3984 3985 +6 3711 2923 2924 3713 3985 3986 +6 3712 2924 2925 3714 3986 3987 +6 3713 2925 2926 3715 3987 3988 +6 3714 2926 2927 3716 3988 3989 +6 3715 2927 2928 3717 3989 3990 +6 3716 2928 2929 3718 3990 3991 +6 3717 2929 2930 3719 3991 3992 +6 3718 2930 2931 3720 3992 3993 +6 3719 2931 2932 3721 3993 3994 +6 3720 2932 2933 3722 3994 3995 +6 3721 2933 2934 3723 3995 3996 +6 3722 2934 2935 3724 3996 3997 +6 3723 2935 2936 3725 3997 3998 +6 3724 2936 2937 3726 3998 3999 +6 3725 2937 2938 3727 3999 4000 +6 3726 2938 2939 3728 4000 4001 +6 3727 2939 2940 3729 4001 4002 +6 3728 2940 2941 3730 4002 4003 +6 3729 2941 2942 3731 4003 4004 +6 3730 2942 2943 3732 4004 4005 +6 3731 2943 2944 2945 3733 4005 +6 3732 2945 2946 3734 4005 4006 +6 3733 2946 2947 2948 3735 4006 +6 3734 2948 3736 4006 4007 3737 +5 3735 2948 2949 3242 3737 +6 3736 3242 3738 4007 3735 4012 +6 3737 3242 3243 3739 4012 4013 +6 3738 3243 3244 3740 4013 4014 +6 3739 3244 3245 3741 4014 4015 +6 3740 3245 3246 3742 4015 4016 +6 3741 3246 3247 3743 4016 4017 +6 3742 3247 3248 3744 4017 4018 +6 3743 3248 3249 3745 4018 4019 +6 3744 3249 3250 3746 4019 4020 +6 3745 3250 3747 4020 4021 4022 +6 3746 3250 3251 3253 3748 4022 +6 3747 3253 3749 4022 4023 4024 +7 3748 3253 3254 3255 3256 3750 4024 +5 3749 3256 3751 4024 4025 +6 3750 3256 3257 3752 4025 4026 +6 3751 3257 3258 3753 4029 4026 +7 3752 3258 3754 4037 4029 4046 3755 +5 3753 3258 3259 3260 3755 +6 3754 3260 3261 3756 4046 3753 +6 3755 3261 3262 3757 4046 4047 +6 3756 3262 3263 3758 4047 4048 +6 3757 3263 3264 3759 4048 4049 +6 3758 3264 3265 4049 4050 4051 +6 615 617 3761 3764 3765 3763 +6 3760 617 625 627 3762 3763 +6 3761 627 3763 3217 635 629 +6 3761 3762 3765 3760 4040 3217 +6 615 3760 3765 4038 6557 612 +6 3764 3760 3763 4038 4039 4040 +5 2085 1567 3767 3768 6093 +6 3766 1567 3768 3769 1571 1568 +6 3766 3767 3769 6092 6093 6094 +7 3768 3767 1571 6094 6088 6317 6318 +6 3510 3511 3771 4522 4523 4524 +6 3770 3511 3772 4524 4525 4528 +6 3771 3511 3512 3773 4528 4529 +6 3772 3512 3520 4529 4530 4531 +6 1682 1683 3775 5391 5385 5383 +6 3774 1683 3776 5620 5391 3778 +6 3775 1683 1684 1686 3777 3778 +6 3776 1686 3778 3779 3780 3781 +6 3776 3777 3779 7791 5620 3775 +6 3778 3777 3780 7798 7792 7791 +6 3779 3777 3781 7798 3783 3782 +6 3780 3777 1686 1687 1688 3782 +6 3781 1688 1689 1691 3783 3780 +6 3782 1691 3784 7798 3780 7799 +6 3783 1691 1692 3785 7799 7800 +6 3784 1692 3786 3787 3788 7800 +6 3785 1692 1693 1694 3416 3787 +6 3786 3416 3417 3785 3788 3789 +6 3785 3787 3789 7800 7801 3790 +6 3788 3787 3417 3418 3419 3790 +6 3789 3419 3791 7801 3788 7802 +6 3790 3419 3420 3792 3793 7802 +6 3791 3420 3793 3794 3423 3421 +6 3791 3792 3794 7802 7803 7804 +6 3793 3792 3423 3795 7804 7805 +6 3794 3423 3424 3796 7809 7805 +6 3795 3424 3797 3952 7809 7810 +6 3796 3424 3425 3798 3952 3953 +6 3797 3425 3799 3953 3954 3955 +6 3798 3425 3426 3427 3800 3955 +6 3799 3427 3428 3801 3955 3956 +6 3800 3428 3429 3802 3956 3957 +6 3801 3429 3432 3442 3803 3957 +6 3802 3442 3804 3957 4100 4239 +6 3803 3442 3443 3805 4100 4101 +6 3804 3443 3806 4101 4102 4103 +6 3805 3443 3444 3807 4103 4104 +6 3806 3444 3445 3808 4104 4105 +6 3807 3445 3447 4105 4106 4107 +6 3550 3551 3810 3833 3834 3835 +6 3809 3551 3552 3811 3835 3836 +6 3810 3552 3553 3812 3836 3837 +6 3811 3553 3554 3813 3837 3838 +6 3812 3554 3555 3814 3838 3839 +6 3813 3555 3815 3839 3840 3841 +6 3814 3555 3556 3816 3841 3842 +6 3815 3556 3557 3558 3817 3842 +6 3816 3558 3559 3818 3842 3843 +6 3817 3559 3560 3562 3819 3843 +6 3818 3562 3820 3843 3844 3845 +6 3819 3562 3563 3821 3845 3846 +6 3820 3563 3822 3846 3847 3848 +6 3821 3563 3564 3823 3848 3849 +6 3822 3564 3566 3849 3850 3567 +6 2986 3545 3825 3826 3277 2985 +6 3824 3545 3826 3827 3828 3829 +6 3824 3825 3827 4069 4065 3277 +6 3826 3825 3828 4756 4069 4763 +6 3827 3825 3829 4763 4764 4765 +6 3828 3825 3545 3546 3830 4765 +6 3829 3546 3547 3831 4765 4766 +6 3830 3547 3548 3832 4766 4767 +6 3831 3548 3549 3833 4770 4767 +6 3832 3549 3550 3809 3834 4770 +6 3833 3809 3835 5016 4770 5024 +6 3834 3809 3810 3836 5024 5025 +6 3835 3810 3811 3837 5025 5026 +6 3836 3811 3812 3838 4405 5026 +6 3837 3812 3813 3839 3864 4405 +6 3838 3813 3814 3840 3864 3865 +6 3839 3814 3841 3865 3866 3867 +6 3840 3814 3815 3842 3853 3867 +6 3841 3815 3816 3817 3843 3853 +6 3842 3817 3818 3819 3844 3853 +6 3843 3819 3845 3853 3854 3855 +6 3844 3819 3820 3846 3855 3856 +6 3845 3820 3821 3847 3856 3857 +6 3846 3821 3848 3860 3857 3876 +6 3847 3821 3822 3849 3876 3877 +6 3848 3822 3823 3850 3877 3878 +6 3849 3823 3567 3878 3879 3568 +6 2181 2199 2179 3852 2201 3129 +6 2179 3851 27 26 3129 9781 +6 3841 3842 3843 3844 3854 3867 +6 3853 3844 3855 3867 3868 3869 +6 3854 3844 3845 3856 3869 3870 +6 3855 3845 3846 3857 3858 3870 +6 3856 3846 3858 3859 3860 3847 +6 3856 3857 3859 3870 3871 3872 +6 3858 3857 3860 3872 3873 3874 +6 3859 3857 3847 3874 3875 3876 +6 3343 3344 3346 3862 6717 3342 +6 3861 3346 3863 6716 6715 6717 +7 3862 3346 6532 6531 3347 6533 6716 +6 3838 3839 3865 4405 4406 4407 +6 3864 3839 3840 3866 4407 4408 +6 3865 3840 3867 4408 4409 3868 +6 3866 3840 3841 3853 3854 3868 +6 3867 3854 3869 4409 3866 4420 +6 3868 3854 3855 3870 4420 4421 +6 3869 3855 3856 3858 3871 4421 +6 3870 3858 3872 4421 4422 4423 +6 3871 3858 3859 3873 4423 4424 +6 3872 3859 3874 4424 4425 4426 +6 3873 3859 3860 3875 4426 4427 +6 3874 3860 3876 4427 4428 3888 +6 3875 3860 3847 3848 3877 3888 +6 3876 3848 3849 3878 3888 3889 +6 3877 3849 3850 3879 3889 3890 +6 3878 3850 3568 3890 3891 3569 +6 2507 3330 2509 3881 3331 3332 +6 2509 3880 3334 6499 2511 3332 +6 3337 3339 3127 1171 414 3128 +6 3127 3339 3122 3884 3885 3340 +6 3122 3883 3885 3886 3887 3121 +6 3884 3883 3886 3342 6717 3340 +6 3884 3885 3887 6538 6715 6717 +6 3884 3886 3121 6713 6714 6538 +6 3876 3877 3889 4428 3875 4251 +6 3888 3877 3878 3890 4236 4251 +6 3889 3878 3879 3891 4236 4237 +6 3890 3879 3569 4237 3571 3570 +6 3397 3398 3893 4746 4744 4743 +6 3892 3398 3894 4743 4748 4749 +6 3893 3398 3399 3895 4752 4749 +6 3894 3399 3896 4661 4758 4752 +6 3895 3399 3400 3401 3897 4661 +6 3896 3401 3402 3898 4661 4662 +6 3897 3402 3899 4662 4663 4664 +6 3898 3402 3403 3900 4664 4665 +6 3899 3403 3404 3679 3901 4665 +6 3900 3679 3680 3682 3902 4665 +5 3901 3682 3473 4665 3685 +6 3634 3635 3904 4194 4195 4196 +6 3903 3635 3636 3637 3905 4196 +6 3904 3637 3906 4196 4197 4198 +6 3905 3637 3638 3639 3907 4198 +6 3906 3639 3640 3908 4198 4199 +6 3907 3640 3642 3927 4199 4200 +5 3643 3644 3910 3927 3928 +7 3909 3644 3061 3062 3911 3928 3929 +7 3910 3062 3063 3912 3929 3930 3931 +6 3911 3063 3069 3913 3931 3932 +6 3912 3069 3070 3914 3932 3933 +6 3913 3070 3071 3915 3933 3934 +6 3914 3071 3072 3916 3934 3935 +6 3915 3072 3073 3917 3935 3936 +6 3916 3073 3918 3349 3919 3936 +6 3917 3073 3074 3075 3076 3349 +6 3917 3349 3350 3351 3920 3936 +6 3919 3351 3921 3936 3937 3938 +6 3920 3351 3352 3922 3938 3939 +6 3921 3352 3353 3923 3939 3940 +6 3922 3353 3354 3924 3940 3941 +6 3923 3354 3355 3925 3941 3942 +6 3924 3355 3374 3942 3943 3375 +6 3085 2482 2483 2484 3150 3152 +6 3908 3642 3643 3909 3928 4200 +6 3927 3909 3910 3929 4200 4201 +6 3928 3910 3911 3930 4201 4202 +6 3929 3911 3931 4202 4203 4204 +5 3930 3911 3912 3932 4204 +6 3931 3912 3913 3933 4204 4205 +6 3932 3913 3914 3934 4205 4206 +6 3933 3914 3915 3935 4206 4207 +6 3934 3915 3916 3936 4207 3937 +6 3935 3916 3917 3919 3920 3937 +6 3936 3920 3938 4207 3935 4335 +6 3937 3920 3921 3939 4335 4336 +6 3938 3921 3922 3940 4336 4337 +6 3939 3922 3923 3941 4337 4338 +6 3940 3923 3924 3942 4338 4339 +6 3941 3924 3925 3943 4339 4340 +6 3942 3925 3375 4340 4341 4342 +6 3673 3674 3676 3945 3950 3947 +6 3944 3676 3158 3159 3946 3947 +6 3945 3159 3947 3948 5922 3962 +6 3945 3946 3948 3949 3950 3944 +6 3947 3946 3949 5920 5921 5922 +6 3947 3948 3950 3951 5919 5920 +6 3947 3949 3951 3672 3673 3944 +6 3950 3949 3672 5918 3671 5919 +6 3796 3797 3953 7810 7811 7812 +6 3952 3797 3798 3954 7812 7813 +6 3953 3798 3955 7813 7814 7815 +6 3954 3798 3799 3800 3956 7815 +6 3955 3800 3801 3957 4238 7815 +6 3956 3801 3802 3803 4238 4239 +6 3187 3188 3959 3960 7588 7586 +6 3958 3188 3960 3961 2890 2888 +6 3958 3959 3961 7588 7589 7590 +6 3960 3959 2890 7590 7591 7592 +6 3159 3160 3963 5922 3946 5923 +6 3962 3160 3964 3965 5923 5924 +6 3963 3160 3965 3966 3967 3161 +6 3963 3964 3966 5924 5942 5943 +6 3965 3964 3967 5943 5948 5947 +6 3966 3964 3161 5948 2488 2487 +6 3485 3489 3969 6556 4038 4039 +6 3968 3489 3490 3970 1597 6556 +6 3969 3490 3971 6358 1595 1597 +6 3970 3490 3491 6555 6357 6358 +6 3698 3699 3973 4699 4700 4701 +6 3972 3699 3700 3701 3974 4701 +6 3973 3701 3975 4701 4702 4703 +6 3974 3701 3702 3976 4703 4704 +6 3975 3702 3703 3977 4704 4705 +6 3976 3703 3704 3978 4705 4706 +6 3977 3704 3705 3979 4706 4707 +6 3978 3705 3706 3980 4707 4708 +6 3979 3706 3707 3981 4708 4709 +6 3980 3707 3708 3982 4709 4710 +6 3981 3708 3709 3983 4710 4711 +6 3982 3709 3710 3984 4711 4712 +6 3983 3710 3711 3985 4712 4713 +6 3984 3711 3712 3986 4713 4714 +6 3985 3712 3713 3987 4714 4715 +6 3986 3713 3714 3988 4715 4716 +6 3987 3714 3715 3989 4716 4717 +6 3988 3715 3716 3990 4717 4718 +6 3989 3716 3717 3991 4718 4719 +6 3990 3717 3718 3992 4719 4720 +6 3991 3718 3719 3993 4720 4721 +6 3992 3719 3720 3994 4439 4721 +6 3993 3720 3721 3995 4439 4440 +6 3994 3721 3722 3996 4440 4441 +6 3995 3722 3723 3997 4441 4442 +6 3996 3723 3724 3998 4442 4443 +6 3997 3724 3725 3999 4443 4444 +6 3998 3725 3726 4000 4444 4445 +6 3999 3726 3727 4001 4445 4446 +6 4000 3727 3728 4002 4070 4446 +6 4001 3728 3729 4003 4008 4070 +6 4002 3729 3730 4004 4008 4009 +6 4003 3730 3731 4005 4009 4010 +6 4004 3731 3732 3733 4006 4010 +6 4005 3733 3734 3735 4007 4010 +6 4006 3735 3737 4010 4011 4012 +6 4002 4003 4009 4070 4071 4072 +6 4008 4003 4004 4010 4072 4011 +6 4009 4004 4005 4006 4007 4011 +6 4010 4007 4012 4072 4009 4073 +6 4011 4007 3737 3738 4013 4073 +6 4012 3738 3739 4014 4073 4074 +7 4013 3739 3740 4015 4074 4075 4076 +6 4014 3740 3741 4016 4076 4077 +6 4015 3741 3742 4017 4077 4078 +6 4016 3742 3743 4018 4078 4079 +6 4017 3743 3744 4019 4079 4080 +6 4018 3744 3745 4020 4080 4081 +6 4019 3745 3746 4021 4081 4082 +6 4020 3746 4022 4030 4082 4083 +6 4021 3746 3747 3748 4023 4030 +6 4022 3748 4024 4030 4031 4032 +6 4023 3748 3749 3750 4025 4032 +6 4024 3750 3751 4026 4027 4032 +6 4025 3751 4027 4028 4029 3752 +6 4025 4026 4028 4032 4033 4034 +6 4027 4026 4029 4034 4035 4036 +6 4028 4026 3752 4036 4037 3753 +6 4021 4022 4023 4031 4083 4084 +6 4030 4023 4032 4084 4085 4033 +6 4031 4023 4024 4025 4027 4033 +6 4032 4027 4034 4085 4031 4462 +6 4033 4027 4028 4035 4041 4462 +6 4034 4028 4036 4041 4042 4043 +6 4035 4028 4029 4037 4043 4044 +6 4036 4029 3753 4044 4045 4046 +6 3764 3765 4039 6556 6557 3968 +6 4038 3765 4040 3968 3485 3484 +6 4039 3765 3763 3217 3484 3218 +6 4034 4035 4042 4462 4463 4464 +6 4041 4035 4043 4464 4465 4466 +6 4042 4035 4036 4044 4466 4467 +6 4043 4036 4037 4045 4467 4468 +6 4044 4037 4046 4468 4469 4047 +6 4045 4037 3753 3755 3756 4047 +6 4046 3756 3757 4048 4469 4045 +6 4047 3757 3758 4049 4469 4470 +6 4048 3758 3759 4050 4470 4209 +6 4049 3759 4051 4052 4208 4209 +6 4050 3759 4052 4053 4054 3265 +6 4050 4051 4053 4208 4221 4222 +6 4052 4051 4054 3268 4055 4222 +6 4053 4051 3265 3266 3267 3268 +5 4053 3268 3269 4056 4222 +7 4055 3269 3270 4057 4222 4223 4224 +7 4056 3270 3271 4058 4224 4225 4226 +6 4057 3271 3272 4059 4226 4227 +6 4058 3272 3273 4060 4227 4228 +6 4059 3273 3274 4061 4062 4228 +6 4060 3274 4062 4063 4064 3275 +6 4060 4061 4063 4230 4228 4502 +6 4062 4061 4064 4066 4067 4502 +6 4063 4061 3275 3276 4065 4066 +6 4064 3276 4066 4069 3826 3277 +6 4064 4065 4063 4067 4068 4069 +6 4063 4066 4068 4513 4502 4754 +6 4067 4066 4069 4754 4755 4756 +6 4068 4066 4065 3826 4756 3827 +6 4001 4002 4008 4071 4446 4447 +6 4070 4008 4072 4447 4448 4449 +6 4071 4008 4009 4011 4073 4449 +6 4072 4011 4012 4013 4074 4449 +6 4073 4013 4014 4075 4449 4450 +6 4074 4014 4076 4450 4451 4452 +5 4075 4014 4015 4077 4452 +6 4076 4015 4016 4078 4452 4453 +6 4077 4016 4017 4079 4453 4454 +6 4078 4017 4018 4080 4454 4455 +6 4079 4018 4019 4081 4455 4456 +6 4080 4019 4020 4082 4456 4457 +6 4081 4020 4021 4083 4457 4458 +6 4082 4021 4030 4084 4458 4459 +6 4083 4030 4031 4085 4459 4460 +6 4084 4031 4033 4460 4461 4462 +6 2880 2881 4087 4089 7599 7600 +6 4086 2881 2882 2883 4088 4089 +6 4087 2883 4089 4090 4091 4092 +7 4087 4088 4090 7598 7599 4086 7751 +6 4089 4088 4091 7751 7753 4379 +6 4090 4088 4092 4094 4378 4379 +6 4091 4088 2883 2498 4093 4094 +6 4092 2498 4094 4095 2809 2499 +6 4092 4093 4095 4091 4378 4387 +6 4094 4093 2809 4387 4386 4388 +6 3542 3543 4097 4098 4099 3544 +6 3542 4096 4098 4365 4372 3541 +6 4097 4096 4099 4365 4366 4367 +6 4098 4096 3544 4367 3094 3093 +6 3803 3804 4101 4239 4240 4241 +6 4100 3804 3805 4102 4241 4242 +6 4101 3805 4103 4242 4243 4244 +6 4102 3805 3806 4104 4111 4244 +6 4103 3806 3807 4105 4111 4112 +6 4104 3807 3808 4106 4112 4113 +6 4105 3808 4107 4108 4109 4113 +6 4106 3808 3447 3448 3454 4108 +6 4107 3454 4106 4109 4110 3456 +6 4106 4108 4110 4113 4114 4115 +6 4109 4108 3456 4115 4394 3464 +6 4103 4104 4112 4244 4245 4246 +6 4111 4104 4105 4113 4249 4246 +6 4112 4105 4106 4109 4114 4249 +6 4113 4109 4115 4249 4391 4392 +6 4114 4109 4110 4392 4393 4394 +7 3522 3525 4117 4530 4531 3521 4119 +5 4116 3525 3526 4118 4119 +6 4117 3526 4119 4120 3529 9786 +7 4117 4118 4120 4121 9784 4530 4116 +6 4119 4118 4121 4122 9786 9789 +6 4119 4120 4122 4123 4395 9784 +6 4121 4120 4123 4124 9789 7172 +6 4121 4122 4124 4125 4126 4395 +6 4123 4122 4125 7171 4140 7172 +6 4123 4124 4126 4127 4128 4140 +6 4123 4125 4127 4395 4396 4397 +6 4126 4125 4128 4129 4130 4397 +6 4127 4125 4129 4136 4139 4140 +6 4127 4128 4130 4131 4135 4136 +6 4127 4129 4131 4132 4397 4398 +6 4130 4129 4132 4133 4134 4135 +6 4130 4131 4133 4401 4398 4410 +6 4132 4131 4134 4410 4411 4412 +6 4133 4131 4135 4412 4413 7164 +6 4134 4131 4129 4136 4137 7164 +6 4135 4129 4128 4137 4138 4139 +6 4135 4136 4138 7163 7161 7164 +6 4137 4136 4139 7168 7163 7169 +6 4138 4136 4128 4140 7169 7170 +6 4139 4128 4125 7170 7171 4124 +6 3580 3581 4142 4268 4269 4270 +6 4141 3581 3582 4143 4270 4271 +6 4142 3582 3583 4144 4271 4272 +6 4143 3583 3584 4145 4272 4273 +6 4144 3584 3585 4146 4273 4274 +6 4145 3585 3586 4147 4274 4275 +6 4146 3586 3587 4148 4275 4276 +6 4147 3587 3588 3589 4149 4276 +6 4148 3589 4150 4276 4277 4278 +6 4149 3589 3590 4151 4278 4279 +6 4150 3590 3591 4152 4279 4280 +6 4151 3591 3592 4153 4280 4281 +6 4152 3592 3593 4154 4281 4282 +6 4153 3593 3594 4155 4282 4283 +6 4154 3594 3595 4156 4283 4284 +6 4155 3595 3596 4157 4284 4285 +6 4156 3596 3597 4158 4285 4286 +6 4157 3597 3598 4159 4286 4287 +6 4158 3598 3599 4160 4287 4288 +6 4159 3599 3600 4161 4288 4289 +6 4160 3600 3601 3602 4162 4289 +6 4161 3602 4163 4289 4290 4291 +6 4162 3602 3603 4164 4291 4292 +6 4163 3603 3604 4165 4292 4293 +6 4164 3604 3605 4166 4293 4294 +6 4165 3605 3606 4167 4294 4295 +6 4166 3606 3607 4168 4295 4296 +6 4167 3607 3608 3609 4169 4296 +6 4168 3609 4170 4296 4297 4298 +6 4169 3609 3610 4171 4298 4299 +6 4170 3610 3611 4172 4299 4300 +6 4171 3611 3612 4173 4300 4301 +6 4172 3612 3613 4174 4301 4302 +6 4173 3613 3614 4175 4302 4303 +6 4174 3614 3615 4176 4303 4304 +6 4175 3615 3616 4177 4304 4305 +6 4176 3616 3617 4178 4305 4306 +6 4177 3617 3618 4179 4306 4307 +6 4178 3618 3619 4180 4307 4308 +6 4179 3619 3620 4181 4308 4309 +6 4180 3620 3621 4182 4309 4310 +6 4181 3621 3622 4183 4310 4311 +6 4182 3622 3623 4184 4311 4312 +6 4183 3623 3624 4185 4312 4313 +6 4184 3624 3625 4186 4313 4314 +6 4185 3625 3626 4187 4314 4315 +6 4186 3626 3627 4188 4315 4316 +6 4187 3627 3628 4189 4316 4317 +6 4188 3628 3629 4190 4317 4318 +6 4189 3629 3630 4191 4318 4319 +6 4190 3630 3631 4192 4319 4320 +6 4191 3631 3632 4193 4320 4321 +6 4192 3632 3633 3634 4194 4321 +6 4193 3634 3903 4195 4321 4322 +6 4194 3903 4196 4322 4323 4324 +6 4195 3903 3904 3905 4197 4324 +6 4196 3905 4198 4324 4325 4326 +6 4197 3905 3906 3907 4199 4326 +6 4198 3907 3908 4200 4326 4327 +6 4199 3908 3927 3928 4201 4327 +6 4200 3928 3929 4202 4327 4328 +6 4201 3929 3930 4203 4328 4329 +6 4202 3930 4204 4329 4330 4331 +6 4203 3930 3931 3932 4205 4331 +6 4204 3932 3933 4206 4331 4332 +6 4205 3933 3934 4207 4332 4333 +7 4206 3934 3935 3937 4333 4334 4335 +6 4050 4052 4209 4210 4211 4221 +6 4050 4208 4210 4470 4049 4477 +6 4209 4208 4211 4212 4477 4478 +6 4210 4208 4212 4213 4220 4221 +6 4210 4211 4213 4214 4478 4479 +6 4212 4211 4214 4215 4216 4220 +6 4212 4213 4215 4479 4480 4481 +6 4214 4213 4216 4217 4481 4482 +6 4215 4213 4217 4218 4219 4220 +6 4215 4216 4218 4232 4482 4483 +6 4217 4216 4219 4232 4233 4234 +6 4218 4216 4220 4224 4234 4223 +6 4219 4216 4213 4211 4221 4223 +6 4220 4211 4208 4052 4222 4223 +6 4221 4052 4053 4055 4056 4223 +6 4222 4056 4224 4221 4220 4219 +6 4223 4056 4057 4225 4234 4219 +6 4224 4057 4226 4235 4234 4488 +5 4225 4057 4058 4227 4488 +7 4226 4058 4059 4228 4229 4487 4488 +6 4227 4059 4229 4230 4062 4060 +6 4227 4228 4230 4489 4487 4500 +6 4229 4228 4062 4500 4501 4502 +6 3147 3412 3146 3145 9791 3413 +6 4217 4218 4233 4483 4484 4485 +6 4232 4218 4234 4235 4485 4486 +6 4233 4218 4235 4225 4224 4219 +6 4233 4234 4225 4486 4487 4488 +6 3889 3890 4237 4251 4252 4256 +6 4236 3890 3891 3571 4256 4257 +6 3956 3957 4239 7815 7816 4503 +6 4238 3957 3803 4100 4240 4503 +6 4239 4100 4241 4503 4504 4505 +6 4240 4100 4101 4242 4505 4506 +6 4241 4101 4102 4243 4416 4506 +6 4242 4102 4244 4416 4417 4418 +6 4243 4102 4103 4111 4245 4418 +6 4244 4111 4246 4247 4418 4419 +6 4245 4111 4247 4248 4249 4112 +6 4245 4246 4248 4419 7829 7830 +6 4247 4246 4249 4391 4739 7830 +6 4248 4246 4112 4113 4114 4391 +6 3341 3338 1524 1525 2205 2206 +6 3889 4236 4252 4253 4428 3888 +6 4251 4236 4253 4254 4255 4256 +6 4251 4252 4254 4647 4428 6892 +6 4253 4252 4255 4729 4730 6892 +6 4254 4252 4256 4729 4261 4260 +6 4255 4252 4236 4237 4257 4260 +6 4256 4237 3571 3572 4258 4260 +6 4257 3572 3573 3574 4259 4260 +6 4258 3574 4260 4261 4262 4263 +6 4258 4259 4261 4256 4257 4255 +6 4260 4259 4262 4732 4729 4255 +6 4261 4259 4263 6901 4732 6902 +6 4262 4259 3574 3575 4264 6902 +6 4263 3575 3576 4265 5231 6902 +6 4264 3576 3577 4266 5231 5232 +6 4265 3577 3578 4267 5232 5233 +6 4266 3578 4268 5233 5234 4269 +6 4267 3578 3579 3580 4141 4269 +6 4268 4141 4270 5234 4267 5451 +6 4269 4141 4142 4271 5451 5452 +6 4270 4142 4143 4272 5452 5453 +6 4271 4143 4144 4273 5453 5454 +6 4272 4144 4145 4274 5457 5454 +6 4273 4145 4146 4275 5469 5457 +6 4274 4146 4147 4276 5469 5470 +6 4275 4147 4148 4149 4277 5470 +6 4276 4149 4278 5470 5471 5472 +6 4277 4149 4150 4279 5472 5473 +6 4278 4150 4151 4280 5473 5474 +6 4279 4151 4152 4281 5046 5474 +6 4280 4152 4153 4282 5046 5047 +6 4281 4153 4154 4283 5047 5048 +6 4282 4154 4155 4284 5048 5049 +6 4283 4155 4156 4285 5049 5050 +6 4284 4156 4157 4286 5050 5051 +6 4285 4157 4158 4287 5051 5052 +6 4286 4158 4159 4288 4923 5052 +6 4287 4159 4160 4289 4923 4924 +6 4288 4160 4161 4162 4290 4924 +6 4289 4162 4291 4924 4925 4926 +6 4290 4162 4163 4292 4926 4927 +6 4291 4163 4164 4293 4927 4928 +6 4292 4164 4165 4294 4928 4929 +6 4293 4165 4166 4295 4929 4930 +6 4294 4166 4167 4296 4930 4931 +6 4295 4167 4168 4169 4297 4931 +6 4296 4169 4298 4771 4931 4932 +6 4297 4169 4170 4299 4771 4772 +6 4298 4170 4171 4300 4772 4773 +6 4299 4171 4172 4301 4773 4774 +6 4300 4172 4173 4302 4774 4775 +6 4301 4173 4174 4303 4775 4776 +6 4302 4174 4175 4304 4776 4777 +6 4303 4175 4176 4305 4777 4778 +6 4304 4176 4177 4306 4778 4779 +6 4305 4177 4178 4307 4779 4780 +6 4306 4178 4179 4308 4780 4781 +6 4307 4179 4180 4309 4781 4782 +6 4308 4180 4181 4310 4566 4782 +6 4309 4181 4182 4311 4566 4567 +6 4310 4182 4183 4312 4567 4568 +6 4311 4183 4184 4313 4568 4569 +6 4312 4184 4185 4314 4569 4570 +6 4313 4185 4186 4315 4570 4571 +6 4314 4186 4187 4316 4571 4572 +6 4315 4187 4188 4317 4572 4573 +6 4316 4188 4189 4318 4573 4574 +6 4317 4189 4190 4319 4574 4575 +6 4318 4190 4191 4320 4575 4576 +6 4319 4191 4192 4321 4576 4577 +6 4320 4192 4193 4194 4322 4577 +6 4321 4194 4195 4323 4577 4578 +6 4322 4195 4324 4578 4579 4580 +6 4323 4195 4196 4197 4325 4580 +6 4324 4197 4326 4580 4581 4582 +6 4325 4197 4198 4199 4327 4582 +6 4326 4199 4200 4201 4328 4582 +6 4327 4201 4202 4329 4582 4583 +6 4328 4202 4203 4330 4583 4584 +6 4329 4203 4331 4584 4585 4589 +7 4330 4203 4204 4205 4332 4589 4590 +6 4331 4205 4206 4333 4590 4591 +6 4332 4206 4207 4334 4591 4592 +6 4333 4207 4335 4336 4429 4592 +5 4334 4207 3937 3938 4336 +6 4335 3938 3939 4337 4334 4429 +6 4336 3939 3940 4338 4429 4430 +6 4337 3940 3941 4339 4430 4431 +6 4338 3941 3942 4340 4431 4432 +6 4339 3942 3943 4341 4432 4433 +6 4340 3943 4342 4433 4434 4435 +6 4341 3943 3375 3376 4343 4435 +6 4342 3376 3377 4344 4345 4435 +6 4343 3377 4345 4346 4347 3378 +6 4343 4344 4346 4435 4436 4437 +6 4345 4344 4347 4437 4438 4348 +6 4346 4344 3378 3645 3646 4348 +6 4347 3646 4349 4350 4438 4346 +6 4348 3646 4350 4351 4352 3647 +6 4348 4349 4351 4601 4438 4602 +6 4350 4349 4352 4602 4603 4604 +6 4351 4349 3647 3648 4353 4604 +6 4352 3648 3657 4354 4355 4604 +6 4353 3657 4355 4356 4357 4358 +6 4353 4354 4356 4604 4605 4606 +6 4355 4354 4357 4361 4362 4606 +6 4356 4354 4358 4359 4360 4361 +6 4357 4354 4359 4371 3658 3657 +6 4357 4358 4360 4368 4369 4371 +6 4357 4359 4361 4364 4368 4614 +6 4357 4360 4356 4362 4363 4364 +6 4356 4361 4363 4606 4607 4608 +6 4362 4361 4364 4611 4608 4612 +6 4363 4361 4360 4612 4613 4614 +6 4097 4098 4366 4372 4373 4374 +6 4365 4098 4367 4374 4375 4376 +7 4366 4098 4099 3094 4376 1626 1624 +6 4360 4359 4369 4370 4614 4615 +6 4368 4359 4370 4371 9794 9793 +6 4368 4369 9794 4642 4637 4615 +6 4369 4359 4358 3658 9793 3659 +6 4097 4365 4373 7212 3540 3541 +6 4372 4365 4374 7212 7210 7209 +6 4373 4365 4366 4375 7209 7213 +6 4374 4366 4376 4377 7213 7214 +6 4375 4366 4367 4377 1627 1626 +5 4375 4376 1627 7214 7215 +6 4091 4094 4379 4380 4381 4387 +7 4091 4378 4380 7753 4090 7752 7754 +6 4379 4378 4381 4382 7754 7755 +6 4380 4378 4382 4383 4384 4387 +6 4380 4381 4383 7755 7756 7764 +6 4382 4381 4384 4385 4389 7764 +6 4383 4381 4385 3140 4386 4387 +6 4383 4384 3140 4389 4390 3141 +6 3140 4384 4387 4095 4388 3139 +6 4386 4384 4381 4378 4094 4095 +6 4386 4095 2809 2810 2813 3139 +6 4383 4385 4390 7764 7765 7766 +6 4389 4385 3141 7766 7767 3142 +6 4249 4114 4392 4248 4739 4740 +6 4391 4114 4115 4393 4402 4740 +6 4392 4115 4394 4402 4403 4404 +6 4393 4115 4110 3464 4404 3465 +5 4121 4123 4126 4396 9784 +7 4395 4126 4397 4399 4528 4529 9784 +6 4396 4126 4127 4130 4398 4399 +6 4397 4130 4399 4400 4401 4132 +6 4397 4398 4400 4525 4528 4396 +5 4399 4398 4401 4527 4525 +7 4400 4398 4132 4410 4534 4527 4535 +6 4392 4393 4403 4740 4741 4742 +6 4402 4393 4404 4742 4743 4744 +6 4403 4393 4394 3465 4744 4745 +6 3837 3838 3864 4406 5026 5027 +6 4405 3864 4407 5027 5028 5029 +6 4406 3864 3865 4408 5029 5030 +6 4407 3865 3866 4409 5030 5031 +6 4408 3866 3868 4420 5031 5032 +6 4401 4132 4133 4411 4535 4536 +6 4410 4133 4412 4545 4539 4536 +6 4411 4133 4134 4413 4414 4545 +6 4412 4134 4414 4415 7164 7165 +6 4412 4413 4415 4545 4544 4648 +6 4414 4413 4649 4648 7165 7166 +6 4242 4243 4417 4506 4507 4508 +6 4416 4243 4418 4508 4509 4510 +6 4417 4243 4244 4245 4419 4510 +6 4418 4245 4247 7828 4510 7829 +6 4409 3868 3869 4421 5032 5033 +6 4420 3869 3870 3871 4422 5033 +6 4421 3871 4423 5033 5034 5035 +6 4422 3871 3872 4424 5035 5036 +6 4423 3872 3873 4425 4643 5036 +6 4424 3873 4426 4643 4644 4645 +6 4425 3873 3874 4427 4645 4646 +6 4426 3874 3875 4428 4646 4647 +6 4427 3875 3888 4647 4253 4251 +6 4334 4336 4337 4430 4592 4593 +6 4429 4337 4338 4431 4593 4594 +6 4430 4338 4339 4432 4594 4595 +6 4431 4339 4340 4433 4595 4596 +6 4432 4340 4341 4434 4596 4597 +6 4433 4341 4435 4597 4598 4436 +6 4434 4341 4342 4343 4345 4436 +6 4435 4345 4437 4598 4434 4599 +6 4436 4345 4346 4438 4599 4600 +6 4437 4346 4348 4600 4601 4350 +6 3993 3994 4440 4721 4722 4723 +6 4439 3994 3995 4441 4723 4724 +6 4440 3995 3996 4442 4724 4725 +6 4441 3996 3997 4443 4725 4726 +6 4442 3997 3998 4444 4726 4727 +6 4443 3998 3999 4445 4727 4728 +6 4444 3999 4000 4446 4728 4658 +6 4445 4000 4001 4070 4447 4658 +6 4446 4070 4071 4448 4658 4659 +6 4447 4071 4449 4659 4660 4450 +6 4448 4071 4072 4073 4074 4450 +6 4449 4074 4075 4451 4660 4448 +6 4450 4075 4452 4669 4738 4660 +6 4451 4075 4076 4077 4453 4669 +6 4452 4077 4078 4454 4669 4670 +6 4453 4078 4079 4455 4670 4671 +6 4454 4079 4080 4456 4671 4672 +6 4455 4080 4081 4457 4672 4673 +6 4456 4081 4082 4458 4673 4674 +6 4457 4082 4083 4459 4674 4675 +6 4458 4083 4084 4460 4675 4676 +6 4459 4084 4085 4461 4676 4677 +6 4460 4085 4462 4677 4678 4679 +7 4461 4085 4033 4034 4041 4463 4679 +5 4462 4041 4464 4679 4680 +6 4463 4041 4042 4465 4471 4680 +6 4464 4042 4466 4471 4472 4473 +6 4465 4042 4043 4467 4473 4474 +6 4466 4043 4044 4468 4474 4475 +6 4467 4044 4045 4469 4475 4476 +6 4468 4045 4047 4048 4470 4476 +6 4469 4048 4049 4209 4476 4477 +6 4464 4465 4472 4680 4681 4682 +6 4471 4465 4473 4682 4683 4684 +6 4472 4465 4466 4474 4684 4685 +6 4473 4466 4467 4475 4685 4686 +6 4474 4467 4468 4476 4686 4687 +6 4475 4468 4469 4470 4477 4687 +6 4476 4470 4209 4210 4478 4687 +6 4477 4210 4212 4479 4687 5213 +6 4478 4212 4214 4480 5213 5214 +6 4479 4214 4481 5214 5215 5216 +6 4480 4214 4215 4482 4490 5216 +6 4481 4215 4217 4483 4490 4491 +6 4482 4217 4232 4484 4491 4492 +6 4483 4232 4485 4492 4493 4494 +6 4484 4232 4233 4486 4494 4495 +6 4485 4233 4235 4487 4489 4495 +6 4486 4235 4488 4227 4489 4229 +5 4487 4235 4227 4226 4225 +6 4486 4487 4229 4495 4496 4500 +6 4481 4482 4491 4981 4989 5216 +6 4490 4482 4483 4492 4981 4982 +6 4491 4483 4484 4493 4982 4983 +6 4492 4484 4494 4983 4984 4985 +6 4493 4484 4485 4495 4985 4497 +6 4494 4485 4486 4489 4496 4497 +6 4495 4489 4497 4498 4499 4500 +6 4495 4496 4498 4985 4494 4986 +6 4497 4496 4499 4986 4987 4988 +5 4498 4496 4500 4988 4511 +7 4499 4496 4489 4229 4230 4501 4511 +6 4500 4230 4502 4511 4512 4513 +6 4501 4230 4062 4513 4067 4063 +6 4239 4240 4504 7816 4238 7817 +6 4503 4240 4505 7817 7818 7819 +6 4504 4240 4241 4506 7819 7820 +6 4505 4241 4242 4416 4507 7820 +6 4506 4416 4508 7820 7821 7822 +6 4507 4416 4417 4509 7822 7823 +6 4508 4417 4510 7823 7824 7825 +6 4509 4417 4418 7825 7828 4419 +7 4500 4501 4512 4988 4499 5002 4999 +6 4511 4501 4513 4754 4759 5002 +5 4512 4501 4502 4067 4754 +6 426 411 4515 4516 5611 5612 +6 4514 411 4516 4517 4521 410 +6 4514 4515 4517 4518 5611 5615 +6 4516 4515 4518 4519 4520 4521 +6 4516 4517 4519 9734 7508 5615 +6 4518 4517 4520 5235 9734 9678 +6 4519 4517 4521 5235 5236 5237 +6 4520 4517 4515 410 5237 421 +7 3507 3510 3770 4523 6693 6695 6704 +6 4522 3770 4524 6694 6693 4532 +6 4523 3770 3771 4525 4526 4532 +7 4524 3771 4526 4527 4400 4399 4528 +6 4524 4525 4527 4532 4533 4534 +5 4526 4525 4400 4534 4401 +6 4399 4525 3771 3772 4529 4396 +6 4528 3772 3773 4530 4396 9784 +6 4529 3773 4531 4116 4119 9784 +5 4530 3773 4116 3521 3520 +6 4524 4526 4533 5156 4523 6694 +6 4532 4526 4534 5156 5157 4666 +6 4533 4526 4527 4401 4535 4666 +6 4534 4401 4410 4536 4537 4666 +6 4535 4410 4537 4538 4539 4411 +6 4535 4536 4538 4666 4667 4668 +6 4537 4536 4539 4540 4546 4668 +6 4538 4536 4540 4541 4545 4411 +6 4538 4539 4541 4542 4546 4547 +6 4540 4539 4542 4543 4544 4545 +6 4540 4541 4543 4550 4547 4551 +6 4542 4541 4544 4551 4552 4553 +6 4543 4541 4545 4414 4648 4553 +6 4544 4541 4539 4411 4412 4414 +6 4538 4540 4547 4548 9762 4668 +6 4546 4540 4548 4549 4550 4542 +6 4546 4547 4549 4557 4560 9762 +6 4548 4547 4550 4557 4558 4559 +6 4549 4547 4542 4551 6763 4559 +6 4550 4542 4543 4552 7144 6763 +6 4551 4543 4553 4554 7145 7144 +6 4552 4543 4554 4555 4544 4648 +6 4552 4553 4555 4556 7145 7146 +6 4554 4553 4556 4648 4649 7153 +6 4554 4555 7146 7148 7149 7153 +6 4548 4549 4558 4560 4561 4562 +6 4557 4549 4559 4565 4562 6764 +6 4558 4549 6763 6762 6764 4550 +7 4548 4557 4561 9762 9761 6675 9792 +6 4560 4557 4562 4563 6674 6675 +6 4561 4557 4563 4564 4565 4558 +6 4561 4562 4564 6665 6666 6674 +6 4563 4562 4565 6673 6665 6790 +6 4564 4562 4558 6764 6765 6790 +6 4309 4310 4567 4782 4783 4784 +6 4566 4310 4311 4568 4784 4785 +6 4567 4311 4312 4569 4785 4786 +6 4568 4312 4313 4570 4786 4787 +6 4569 4313 4314 4571 4787 4788 +6 4570 4314 4315 4572 4788 4789 +6 4571 4315 4316 4573 4789 4790 +6 4572 4316 4317 4574 4790 4791 +6 4573 4317 4318 4575 4791 4792 +6 4574 4318 4319 4576 4792 4793 +6 4575 4319 4320 4577 4793 4794 +6 4576 4320 4321 4322 4578 4794 +6 4577 4322 4323 4579 4794 4795 +6 4578 4323 4580 4795 4796 4797 +6 4579 4323 4324 4325 4581 4797 +6 4580 4325 4582 4797 4798 4583 +6 4581 4325 4326 4327 4328 4583 +6 4582 4328 4329 4584 4798 4581 +7 4583 4329 4330 4585 4586 4804 4798 +6 4584 4330 4586 4587 4588 4589 +5 4584 4585 4587 4804 4805 +6 4586 4585 4588 4805 4806 4807 +6 4587 4585 4589 4807 4808 4809 +6 4588 4585 4330 4331 4590 4809 +5 4589 4331 4332 4591 4809 +6 4590 4332 4333 4592 4809 4810 +6 4591 4333 4334 4429 4593 4810 +6 4592 4429 4430 4594 4810 4811 +6 4593 4430 4431 4595 4811 4812 +6 4594 4431 4432 4596 4812 4813 +6 4595 4432 4433 4597 4813 4814 +6 4596 4433 4434 4598 4814 4815 +6 4597 4434 4436 4599 4815 4816 +6 4598 4436 4437 4600 4816 4817 +6 4599 4437 4438 4601 4817 4818 +6 4600 4438 4350 4602 4821 4818 +6 4601 4350 4351 4603 4821 4822 +6 4602 4351 4604 4825 4822 4826 +7 4603 4351 4352 4353 4355 4605 4826 +5 4604 4355 4606 4826 4827 +6 4605 4355 4356 4362 4607 4827 +5 4606 4362 4608 4609 4827 +6 4607 4362 4609 4610 4611 4363 +7 4607 4608 4610 4827 4828 4829 4830 +6 4609 4608 4611 4830 4831 4832 +6 4610 4608 4363 4612 4832 4834 +6 4611 4363 4364 4613 4837 4834 +6 4612 4364 4614 4616 4617 4837 +6 4613 4364 4360 4368 4615 4616 +7 4614 4368 4616 4637 4634 4619 4370 +6 4614 4615 4613 4617 4618 4619 +6 4613 4616 4618 4837 4622 4838 +6 4617 4616 4619 4620 4621 4622 +6 4618 4616 4620 4633 4634 4615 +6 4618 4619 4621 4628 4629 4633 +6 4618 4620 4622 4623 4624 4628 +6 4618 4621 4623 4840 4838 4617 +6 4622 4621 4624 4625 4840 4841 +6 4623 4621 4625 4626 4627 4628 +6 4623 4624 4626 4841 4860 4853 +6 4625 4624 4627 4860 4861 4862 +6 4626 4624 4628 4862 4863 4630 +6 4627 4624 4621 4620 4629 4630 +6 4628 4620 4630 4631 4632 4633 +6 4628 4629 4631 4863 4627 4864 +6 4630 4629 4632 4638 4868 4864 +6 4631 4629 4633 4638 4639 4635 +6 4632 4629 4620 4619 4634 4635 +6 4633 4619 4635 4636 4637 4615 +6 4633 4634 4636 4639 4632 4640 +6 4635 4634 4637 4640 4641 4642 +5 4636 4634 4615 4642 4370 +6 4631 4632 4639 4868 4912 9760 +6 4638 4632 4635 4640 4912 4913 +6 4639 4635 4636 4641 4916 4913 +6 4640 4636 4642 4910 4916 4909 +7 4641 4636 4637 4908 4909 9794 4370 +6 4424 4425 4644 5036 5037 5044 +6 4643 4425 4645 5045 5044 6889 +6 4644 4425 4426 4646 6890 6889 +6 4645 4426 4427 4647 6890 6891 +6 4646 4427 4428 4253 6891 6892 +6 4544 4414 4553 4555 4649 4415 +6 4555 4648 4415 7166 7154 7153 +6 422 52 53 4651 4652 9684 +6 4650 53 4652 4653 4657 54 +6 4650 4651 4653 4654 9683 9684 +6 4652 4651 4654 4655 4656 4657 +6 4652 4653 4655 9682 9680 9683 +6 4654 4653 4656 9682 9685 9686 +7 4655 4653 4657 5380 9688 9686 9689 +6 4656 4653 4651 54 5380 55 +6 4446 4447 4659 4728 4445 4736 +6 4658 4447 4448 4660 4736 4737 +6 4659 4448 4450 4737 4738 4451 +6 3895 3896 3897 4662 7841 4758 +6 4661 3897 3898 4663 7841 7842 +6 4662 3898 4664 7842 4689 4688 +6 4663 3898 3899 4665 3685 4688 +6 4664 3899 3900 3901 3902 3685 +6 4534 4535 4537 4667 5157 4533 +6 4666 4537 4668 9750 5157 9761 +6 4667 4537 4538 9761 9762 4546 +7 4451 4452 4453 4670 4980 4738 5194 +6 4669 4453 4454 4671 5194 5195 +6 4670 4454 4455 4672 5195 5196 +6 4671 4455 4456 4673 5196 5197 +6 4672 4456 4457 4674 5197 5198 +6 4673 4457 4458 4675 5198 5199 +6 4674 4458 4459 4676 5199 5200 +6 4675 4459 4460 4677 5200 5201 +6 4676 4460 4461 4678 5201 5202 +6 4677 4461 4679 5202 5203 5204 +6 4678 4461 4462 4463 4680 5204 +7 4679 4463 4464 4471 4681 5204 5205 +5 4680 4471 4682 5205 5206 +7 4681 4471 4472 4683 5206 5207 5208 +5 4682 4472 4684 5208 5209 +7 4683 4472 4473 4685 5209 5210 5211 +6 4684 4473 4474 4686 5211 5212 +6 4685 4474 4475 4687 5212 5213 +6 4686 4475 4476 4477 4478 5213 +6 4664 3685 3686 3687 4689 4663 +6 4688 3687 4690 7842 4663 7843 +6 4689 3687 3688 4691 7843 7844 +6 4690 3688 3689 4692 5158 7844 +6 4691 3689 3690 3692 4693 5158 +6 4692 3692 4694 5158 5159 5160 +6 4693 3692 3693 4695 5160 5161 +6 4694 3693 4696 5161 5162 5163 +6 4695 3693 3694 3695 4697 5163 +6 4696 3695 4698 5163 5164 5165 +6 4697 3695 3696 4699 5165 4700 +6 4698 3696 3697 3698 3972 4700 +6 4699 3972 4701 5165 4698 7854 +6 4700 3972 3973 3974 4702 7854 +6 4701 3974 4703 7308 7854 7855 +6 4702 3974 3975 4704 7308 7309 +6 4703 3975 3976 4705 7309 7310 +6 4704 3976 3977 4706 7310 7311 +6 4705 3977 3978 4707 7311 7312 +6 4706 3978 3979 4708 5170 7312 +6 4707 3979 3980 4709 5170 5171 +6 4708 3980 3981 4710 5171 5172 +6 4709 3981 3982 4711 5172 5173 +6 4710 3982 3983 4712 5173 5174 +6 4711 3983 3984 4713 5174 5175 +6 4712 3984 3985 4714 5175 5176 +6 4713 3985 3986 4715 5176 5177 +6 4714 3986 3987 4716 4965 5177 +6 4715 3987 3988 4717 4965 4966 +6 4716 3988 3989 4718 4966 4967 +6 4717 3989 3990 4719 4967 4968 +6 4718 3990 3991 4720 4968 4969 +6 4719 3991 3992 4721 4969 4970 +6 4720 3992 3993 4439 4722 4970 +6 4721 4439 4723 4970 4971 4972 +6 4722 4439 4440 4724 4972 4973 +6 4723 4440 4441 4725 4973 4974 +6 4724 4441 4442 4726 4733 4974 +6 4725 4442 4443 4727 4733 4734 +6 4726 4443 4444 4728 4734 4735 +6 4727 4444 4445 4658 4735 4736 +6 4254 4255 4730 4731 4732 4261 +6 4254 4729 4731 6892 6893 6894 +6 4730 4729 4732 6894 6895 6896 +6 4731 4729 4261 6896 6901 4262 +6 4725 4726 4734 4974 4975 4976 +6 4733 4726 4727 4735 4976 4977 +6 4734 4727 4728 4736 4977 4978 +6 4735 4728 4658 4659 4737 4978 +6 4736 4659 4660 4738 4978 4979 +6 4737 4660 4451 4979 4980 4669 +6 4248 4391 4740 5003 7830 7831 +6 4739 4391 4392 4402 4741 5003 +6 4740 4402 4742 4753 5003 5004 +6 4741 4402 4403 4743 4753 4748 +6 4742 4403 4744 3892 3893 4748 +6 4743 4403 4404 4745 4746 3892 +6 4744 4404 3465 3466 3468 4746 +6 4745 3468 4747 3397 3892 4744 +6 4746 3468 2172 2173 3395 3397 +6 4743 3893 4749 4750 4753 4742 +6 4748 3893 4750 4751 4752 3894 +6 4748 4749 4751 5005 4753 7837 +6 4750 4749 4752 4757 7837 7838 +6 4751 4749 3894 4757 4758 3895 +6 4741 4742 4748 5004 5005 4750 +7 4513 4067 4068 4755 4512 4759 4760 +5 4754 4068 4756 4760 4761 +7 4755 4068 4069 3827 4761 4762 4763 +6 4751 4752 4758 7838 7839 7840 +6 4757 4752 3895 7840 7841 4661 +6 4512 4754 4760 5006 5002 5001 +5 4759 4754 4755 4761 5006 +7 4760 4755 4756 4762 5006 5007 5008 +6 4761 4756 4763 5008 5009 5010 +6 4762 4756 3827 3828 4764 5010 +6 4763 3828 4765 5010 5011 5012 +6 4764 3828 3829 3830 4766 5012 +6 4765 3830 3831 4767 4768 5012 +6 4766 3831 4768 4769 4770 3832 +7 4766 4767 4769 5012 5011 5013 5014 +6 4768 4767 4770 5014 5015 5016 +6 4769 4767 3832 5016 3834 3833 +6 4297 4298 4772 4932 4933 4934 +6 4771 4298 4299 4773 4934 4935 +6 4772 4299 4300 4774 4935 4936 +6 4773 4300 4301 4775 4936 4937 +6 4774 4301 4302 4776 4937 4938 +6 4775 4302 4303 4777 4938 4939 +6 4776 4303 4304 4778 4939 4940 +6 4777 4304 4305 4779 4940 4941 +6 4778 4305 4306 4780 4941 4942 +6 4779 4306 4307 4781 4942 4943 +6 4780 4307 4308 4782 4943 4944 +6 4781 4308 4309 4566 4783 4944 +6 4782 4566 4784 4944 4945 4946 +6 4783 4566 4567 4785 4946 4947 +6 4784 4567 4568 4786 4947 4948 +6 4785 4568 4569 4787 4948 4949 +6 4786 4569 4570 4788 4949 4950 +6 4787 4570 4571 4789 4950 4951 +6 4788 4571 4572 4790 4951 4952 +6 4789 4572 4573 4791 4952 4953 +6 4790 4573 4574 4792 4953 4954 +6 4791 4574 4575 4793 4799 4954 +6 4792 4575 4576 4794 4799 4800 +6 4793 4576 4577 4578 4795 4800 +6 4794 4578 4579 4796 4800 4801 +6 4795 4579 4797 4801 4802 4803 +6 4796 4579 4580 4581 4798 4803 +6 4797 4581 4583 4803 4804 4584 +6 4792 4793 4800 4954 4955 4956 +6 4799 4793 4794 4795 4801 4956 +6 4800 4795 4796 4802 4956 4957 +6 4801 4796 4803 4957 4958 4959 +6 4802 4796 4797 4798 4804 4959 +6 4803 4798 4584 4586 4805 4959 +6 4804 4586 4587 4806 4918 4959 +6 4805 4587 4807 4918 4919 4920 +6 4806 4587 4588 4808 4920 4921 +6 4807 4588 4809 4921 4922 4810 +6 4808 4588 4589 4590 4591 4810 +7 4809 4591 4592 4593 4811 4922 4808 +5 4810 4593 4594 4812 4922 +6 4811 4594 4595 4813 4964 4922 +6 4812 4595 4596 4814 5093 4964 +6 4813 4596 4597 4815 5093 5094 +6 4814 4597 4598 4816 5094 5095 +6 4815 4598 4599 4817 5095 5096 +6 4816 4599 4600 4818 4819 5096 +6 4817 4600 4819 4820 4821 4601 +6 4817 4818 4820 5096 5097 5098 +6 4819 4818 4821 5098 5099 4823 +6 4820 4818 4601 4602 4822 4823 +6 4821 4602 4823 4824 4825 4603 +6 4821 4822 4824 5099 4820 5100 +6 4823 4822 4825 5100 5101 5102 +6 4824 4822 4603 4826 5102 5103 +6 4825 4603 4604 4605 4827 5103 +7 4826 4605 4606 4607 4609 4828 5103 +6 4827 4609 4829 5103 5102 5104 +6 4828 4609 4830 5104 5105 5106 +6 4829 4609 4610 4831 5106 5107 +6 4830 4610 4832 4833 5113 5107 +5 4831 4610 4611 4833 4834 +6 4831 4832 4834 4835 5113 5114 +7 4833 4832 4611 4835 4836 4837 4612 +6 4833 4834 4836 5114 4845 4844 +6 4835 4834 4837 4838 4839 4844 +6 4836 4834 4612 4613 4617 4838 +6 4836 4837 4839 4840 4622 4617 +6 4836 4838 4840 4842 4843 4844 +6 4839 4838 4622 4623 4841 4842 +6 4840 4623 4842 4625 4852 4853 +6 4840 4841 4839 4843 4852 4850 +6 4839 4842 4844 4845 4846 4850 +5 4839 4843 4845 4835 4836 +7 4844 4843 4846 4847 5114 4835 5115 +6 4845 4843 4847 4848 4849 4850 +6 4845 4846 4848 5117 5115 5118 +6 4847 4846 4849 5118 5119 5120 +6 4848 4846 4850 4851 5120 5121 +6 4849 4846 4851 4852 4842 4843 +6 4849 4850 4852 4854 4855 5121 +6 4851 4850 4842 4841 4853 4854 +6 4852 4841 4854 4857 4860 4625 +6 4851 4852 4853 4855 4856 4857 +6 4851 4854 4856 5121 5122 5123 +6 4855 4854 4857 4858 5123 5124 +6 4856 4854 4853 4858 4859 4860 +6 4856 4857 4859 5124 5125 5129 +6 4858 4857 4860 5129 5130 4861 +6 4859 4857 4853 4625 4626 4861 +6 4860 4626 4862 5130 4859 5131 +6 4861 4626 4627 4863 4865 5131 +6 4862 4627 4630 4864 4865 4866 +6 4863 4630 4866 4867 4868 4631 +6 4862 4863 4866 5131 5132 5136 +6 4865 4863 4864 4867 5136 5137 +6 4866 4864 4868 4869 4870 5137 +6 4867 4864 4631 4638 4869 9760 +6 4867 4868 4870 4871 4872 9760 +6 4867 4869 4871 5137 5138 5139 +6 4870 4869 4872 4873 5150 5139 +6 4871 4869 4873 4874 4875 9760 +6 4871 4872 4874 5149 5147 5150 +6 4873 4872 4875 4876 4877 5149 +6 4874 4872 4876 9760 4912 4914 +6 4874 4875 4877 4878 4879 4914 +6 4874 4876 4878 5155 5149 4882 +6 4877 4876 4879 4880 4881 4882 +6 4878 4876 4880 4914 4915 9753 +7 4878 4879 4881 9753 9754 9756 9757 +6 4878 4880 4882 4883 4884 9757 +6 4878 4881 4883 5155 4877 5369 +6 4882 4881 4884 4885 5369 5370 +6 4883 4881 4885 4886 9757 4895 +6 4883 4884 4886 4887 4888 5370 +6 4885 4884 4887 4894 4891 4895 +6 4885 4886 4888 4889 4890 4891 +6 4885 4887 4889 5372 5370 5899 +6 4888 4887 4890 5898 5896 5899 +6 4889 4887 4891 4892 5898 5901 +6 4890 4887 4892 4893 4894 4886 +6 4890 4891 4893 5901 5902 5903 +6 4892 4891 4894 5912 5903 5913 +6 4893 4891 4886 4895 4896 5913 +7 4894 4886 4896 4897 9757 9756 4884 +6 4894 4895 4897 4898 4899 5913 +5 4896 4895 4898 9756 9759 +6 4896 4897 4899 4900 4901 9759 +6 4896 4898 4900 5913 5914 5917 +6 4899 4898 4901 4902 5917 5918 +6 4900 4898 4902 4903 4904 9759 +6 4900 4901 4903 5918 3671 3670 +6 4902 4901 4904 4905 3669 3670 +6 4903 4901 4905 9754 4911 9759 +6 4903 4904 3669 4906 4907 4911 +6 3669 4905 4907 4908 3661 3660 +6 4906 4905 4908 4909 4910 4911 +7 4906 4907 4909 4642 3660 9793 9794 +5 4908 4907 4910 4642 4641 +6 4909 4907 4911 4917 4916 4641 +6 4910 4907 4905 9754 4917 4904 +6 4638 4639 4913 4914 9760 4875 +6 4912 4639 4914 4915 4916 4640 +6 4912 4913 4915 4875 4876 4879 +6 4914 4913 4916 4917 9753 4879 +6 4915 4913 4917 4910 4641 4640 +6 4915 4916 4910 9753 9754 4911 +6 4805 4806 4919 4959 4958 4960 +6 4918 4806 4920 4960 4961 4962 +6 4919 4806 4807 4921 4962 4963 +6 4920 4807 4808 4922 4963 4964 +6 4921 4808 4810 4964 4812 4811 +6 4287 4288 4924 5052 5053 5054 +6 4923 4288 4289 4290 4925 5054 +6 4924 4290 4926 5054 5055 5056 +6 4925 4290 4291 4927 5056 5057 +6 4926 4291 4292 4928 5057 5058 +6 4927 4292 4293 4929 5058 5059 +6 4928 4293 4294 4930 5059 5060 +6 4929 4294 4295 4931 5060 5061 +6 4930 4295 4296 4297 4932 5061 +6 4931 4297 4771 4933 5061 5062 +6 4932 4771 4934 5062 5063 5064 +6 4933 4771 4772 4935 5064 5065 +6 4934 4772 4773 4936 5065 5066 +6 4935 4773 4774 4937 5066 5067 +6 4936 4774 4775 4938 5067 5068 +6 4937 4775 4776 4939 5068 5069 +6 4938 4776 4777 4940 5069 5070 +6 4939 4777 4778 4941 5070 5071 +6 4940 4778 4779 4942 5071 5072 +6 4941 4779 4780 4943 5072 5073 +6 4942 4780 4781 4944 5073 5074 +6 4943 4781 4782 4783 4945 5074 +6 4944 4783 4946 5074 5075 5076 +6 4945 4783 4784 4947 5076 5077 +6 4946 4784 4785 4948 5077 5078 +6 4947 4785 4786 4949 5078 5079 +6 4948 4786 4787 4950 5079 5080 +6 4949 4787 4788 4951 5080 5081 +6 4950 4788 4789 4952 5081 5082 +6 4951 4789 4790 4953 5082 5083 +6 4952 4790 4791 4954 5083 5084 +6 4953 4791 4792 4799 4955 5084 +6 4954 4799 4956 5084 5085 5086 +6 4955 4799 4800 4801 4957 5086 +6 4956 4801 4802 4958 5088 5086 +6 4957 4802 4959 4918 4960 5088 +6 4958 4802 4803 4804 4805 4918 +6 4958 4918 4919 4961 5088 5089 +6 4960 4919 4962 5089 5090 5091 +6 4961 4919 4920 4963 5091 5092 +6 4962 4920 4921 4964 5092 5093 +6 4963 4921 4922 4812 5093 4813 +6 4715 4716 4966 5177 5178 5179 +6 4965 4716 4717 4967 5179 5180 +6 4966 4717 4718 4968 5180 5181 +6 4967 4718 4719 4969 5181 5182 +6 4968 4719 4720 4970 5182 5183 +6 4969 4720 4721 4722 4971 5183 +6 4970 4722 4972 5183 5184 5185 +6 4971 4722 4723 4973 5185 5186 +6 4972 4723 4724 4974 5186 5187 +6 4973 4724 4725 4733 4975 5187 +6 4974 4733 4976 5187 5188 5189 +6 4975 4733 4734 4977 5189 5190 +6 4976 4734 4735 4978 5190 5191 +6 4977 4735 4736 4737 4979 5191 +6 4978 4737 4738 4980 5191 5192 +6 4979 4738 4669 5192 5193 5194 +6 4490 4491 4982 4989 4990 4991 +6 4981 4491 4492 4983 4991 4992 +6 4982 4492 4493 4984 4992 4993 +6 4983 4493 4985 4993 4994 4995 +6 4984 4493 4494 4497 4986 4995 +6 4985 4497 4498 4987 4995 4996 +6 4986 4498 4988 4996 4997 4998 +6 4987 4498 4499 4511 4998 4999 +6 4490 4981 4990 5216 5217 5218 +6 4989 4981 4991 5218 5219 5220 +6 4990 4981 4982 4992 5220 5221 +6 4991 4982 4983 4993 5221 5222 +6 4992 4983 4984 4994 5222 5223 +6 4993 4984 4995 5223 5224 5225 +6 4994 4984 4985 4986 4996 5225 +6 4995 4986 4987 4997 5225 5226 +6 4996 4987 4998 5226 5227 5228 +6 4997 4987 4988 4999 5000 5228 +6 4998 4988 5000 5001 5002 4511 +6 4998 4999 5001 5228 5229 5230 +7 5000 4999 5002 4759 5006 5166 5230 +5 5001 4999 4511 4512 4759 +6 4739 4740 4741 5004 7831 7834 +6 5003 4741 4753 5005 7834 7835 +6 5004 4753 4750 7835 7836 7837 +7 4759 4760 4761 5007 5021 5001 5166 +6 5006 4761 5008 5021 5022 5023 +6 5007 4761 4762 5009 5023 5018 +6 5008 4762 5010 5011 5017 5018 +5 5009 4762 4763 4764 5011 +7 5010 4764 5012 4768 5013 5009 5017 +5 5011 4764 4765 4766 4768 +6 5011 4768 5014 5020 5017 5241 +6 5013 4768 4769 5015 5241 5242 +6 5014 4769 5016 5242 5243 5024 +5 5015 4769 4770 3834 5024 +6 5009 5011 5018 5019 5020 5013 +7 5009 5017 5019 5023 5008 5238 6833 +6 5018 5017 5020 5238 5239 5240 +5 5019 5017 5013 5240 5241 +5 5006 5007 5022 5166 5167 +6 5021 5007 5023 5167 5168 5169 +6 5022 5007 5008 5018 5169 6833 +7 5016 3834 3835 5025 5243 5015 5244 +6 5024 3835 3836 5026 5244 5245 +6 5025 3836 3837 4405 5027 5245 +6 5026 4405 4406 5028 5245 5246 +6 5027 4406 5029 5249 5246 6844 +6 5028 4406 4407 5030 6844 6845 +6 5029 4407 4408 5031 6845 6846 +6 5030 4408 4409 5032 6849 6846 +6 5031 4409 4420 5033 6849 6850 +6 5032 4420 4421 4422 5034 6850 +6 5033 4422 5035 6850 6851 6852 +6 5034 4422 4423 5036 6852 5038 +6 5035 4423 4424 4643 5037 5038 +6 5036 4643 5038 5039 5040 5044 +6 5036 5037 5039 6852 5035 6853 +6 5038 5037 5040 5041 6856 6853 +6 5039 5037 5041 5042 5043 5044 +6 5039 5040 5042 6858 6856 6863 +6 5041 5040 5043 6878 6879 6863 +6 5042 5040 5044 5045 6880 6878 +6 5043 5040 5045 4644 4643 5037 +6 5043 5044 4644 6880 6881 6889 +6 4280 4281 5047 5474 5475 5476 +6 5046 4281 4282 5048 5476 5477 +6 5047 4282 4283 5049 5477 5478 +6 5048 4283 4284 5050 5478 5479 +6 5049 4284 4285 5051 5479 5480 +6 5050 4285 4286 5052 5480 5481 +6 5051 4286 4287 4923 5053 5481 +6 5052 4923 5054 5481 5482 5483 +6 5053 4923 4924 4925 5055 5483 +6 5054 4925 5056 5483 5484 5485 +6 5055 4925 4926 5057 5485 5486 +6 5056 4926 4927 5058 5486 5487 +6 5057 4927 4928 5059 5487 5488 +6 5058 4928 4929 5060 5488 5489 +6 5059 4929 4930 5061 5489 5490 +6 5060 4930 4931 4932 5062 5490 +6 5061 4932 4933 5063 5490 5491 +6 5062 4933 5064 5250 5491 5492 +6 5063 4933 4934 5065 5250 5251 +6 5064 4934 4935 5066 5251 5252 +6 5065 4935 4936 5067 5252 5253 +6 5066 4936 4937 5068 5253 5254 +6 5067 4937 4938 5069 5254 5255 +6 5068 4938 4939 5070 5255 5256 +6 5069 4939 4940 5071 5256 5257 +6 5070 4940 4941 5072 5257 5258 +6 5071 4941 4942 5073 5258 5259 +6 5072 4942 4943 5074 5259 5260 +6 5073 4943 4944 4945 5075 5260 +6 5074 4945 5076 5260 5261 5262 +6 5075 4945 4946 5077 5262 5263 +6 5076 4946 4947 5078 5263 5264 +6 5077 4947 4948 5079 5264 5265 +6 5078 4948 4949 5080 5265 5266 +6 5079 4949 4950 5081 5266 5267 +6 5080 4950 4951 5082 5267 5268 +6 5081 4951 4952 5083 5268 5269 +6 5082 4952 4953 5084 5269 5270 +6 5083 4953 4954 4955 5085 5270 +6 5084 4955 5086 5087 5270 5271 +6 5085 4955 4956 5087 5088 4957 +6 5085 5086 5088 5271 5272 5089 +6 5087 5086 4957 4958 4960 5089 +6 5088 4960 4961 5090 5272 5087 +6 5089 4961 5091 5272 5273 5274 +6 5090 4961 4962 5092 5274 5275 +6 5091 4962 4963 5093 5275 5276 +7 5092 4963 4964 4813 4814 5094 5276 +6 5093 4814 4815 5095 5276 5277 +6 5094 4815 4816 5096 5277 5278 +6 5095 4816 4817 4819 5097 5278 +6 5096 4819 5098 5278 5279 5280 +6 5097 4819 4820 5099 5280 5281 +6 5098 4820 4823 5100 5281 5282 +6 5099 4823 4824 5101 5282 5152 +6 5100 4824 5102 5104 5151 5152 +6 5101 4824 4825 5103 4828 5104 +5 5102 4825 4826 4827 4828 +6 5102 4828 4829 5105 5101 5151 +7 5104 4829 5106 5154 5151 5287 5288 +6 5105 4829 4830 5107 5108 5288 +6 5106 4830 5108 5109 5113 4831 +6 5106 5107 5109 5110 5288 5289 +6 5108 5107 5110 5111 5112 5113 +6 5108 5109 5111 5289 5290 5294 +6 5110 5109 5112 5294 5295 5116 +6 5111 5109 5113 5114 5115 5116 +6 5112 5109 5107 4831 4833 5114 +6 5113 4833 4835 4845 5115 5112 +6 5114 4845 5112 5116 5117 4847 +6 5112 5115 5117 5295 5111 5296 +6 5116 5115 4847 5118 5299 5296 +6 5117 4847 4848 5119 5299 5300 +6 5118 4848 5120 5300 5301 5302 +5 5119 4848 4849 5121 5302 +6 5120 4849 4851 4855 5122 5302 +6 5121 4855 5123 5318 5302 5319 +6 5122 4855 4856 5124 5321 5319 +6 5123 4856 4858 5125 5126 5321 +6 5124 4858 5126 5127 5128 5129 +6 5124 5125 5127 5322 5321 5323 +6 5126 5125 5128 5323 5324 5328 +6 5127 5125 5129 5336 5328 5337 +6 5128 5125 4858 4859 5130 5337 +6 5129 4859 4861 5131 5337 5338 +7 5130 4861 4862 4865 5132 5133 5338 +6 5131 4865 5133 5134 5135 5136 +5 5131 5132 5134 5338 5339 +6 5133 5132 5135 5339 5340 5341 +6 5134 5132 5136 5346 5344 5341 +6 5135 5132 4865 4866 5137 5346 +6 5136 4866 4867 4870 5138 5346 +6 5137 4870 5139 5140 5344 5346 +6 5138 4870 5140 5141 4871 5150 +6 5138 5139 5141 5142 5345 5344 +6 5140 5139 5142 5143 5144 5150 +6 5140 5141 5143 5345 5360 5359 +7 5142 5141 5144 5145 5360 5357 5361 +6 5143 5141 5145 5146 5147 5150 +6 5143 5144 5146 5361 5362 5366 +5 5145 5144 5147 5148 5366 +6 5146 5144 5148 5149 4873 5150 +7 5146 5147 5149 5155 5366 5367 5368 +6 5148 5147 4873 5155 4877 4874 +6 4873 5147 4871 5139 5141 5144 +6 5101 5104 5152 5153 5154 5105 +6 5101 5151 5153 5282 5100 5283 +6 5152 5151 5154 5283 5284 5285 +6 5153 5151 5105 5285 5286 5287 +6 5148 5149 4877 4882 5368 5369 +7 4532 4533 5157 6682 6683 6684 6694 +6 5156 4533 4666 6682 9750 4667 +5 4691 4692 4693 5159 7844 +7 5158 4693 5160 7844 7845 7846 7847 +6 5159 4693 4694 5161 7847 7848 +6 5160 4694 4695 5162 7848 7849 +6 5161 4695 5163 7849 7850 7851 +6 5162 4695 4696 4697 5164 7851 +6 5163 4697 5165 7851 7852 7853 +6 5164 4697 4698 4700 7853 7854 +5 5001 5006 5021 5167 5230 +8 5166 5021 5022 5168 5229 5230 6826 6824 +6 5167 5022 5169 6826 6827 6830 +7 5168 5022 5023 6830 6831 6832 6833 +6 4707 4708 5171 7312 7313 7314 +6 5170 4708 4709 5172 7314 7315 +6 5171 4709 4710 5173 7315 7316 +6 5172 4710 4711 5174 7316 7317 +6 5173 4711 4712 5175 7317 7318 +6 5174 4712 4713 5176 7318 7319 +6 5175 4713 4714 5177 7319 7320 +6 5176 4714 4715 4965 5178 7320 +6 5177 4965 5179 7320 7321 7322 +6 5178 4965 4966 5180 7322 7323 +6 5179 4966 4967 5181 5411 7323 +6 5180 4967 4968 5182 5411 5412 +6 5181 4968 4969 5183 5412 5413 +6 5182 4969 4970 4971 5184 5413 +6 5183 4971 5185 5413 5414 5415 +6 5184 4971 4972 5186 5403 5415 +6 5185 4972 4973 5187 5403 5404 +6 5186 4973 4974 4975 5188 5404 +6 5187 4975 5189 5404 5405 5406 +6 5188 4975 4976 5190 5406 5407 +6 5189 4976 4977 5191 5407 5408 +6 5190 4977 4978 4979 5192 5408 +6 5191 4979 4980 5193 5408 5409 +6 5192 4980 5194 5409 5410 5195 +5 5193 4980 4669 4670 5195 +6 5194 4670 4671 5196 5410 5193 +7 5195 4671 4672 5197 5423 5410 5431 +5 5196 4672 4673 5198 5431 +7 5197 4673 4674 5199 5431 5432 5433 +6 5198 4674 4675 5200 5433 5434 +6 5199 4675 4676 5201 5434 5435 +6 5200 4676 4677 5202 5435 5436 +6 5201 4677 4678 5203 5436 5437 +6 5202 4678 5204 5437 5438 5439 +6 5203 4678 4679 4680 5205 5439 +5 5204 4680 4681 5206 5439 +7 5205 4681 4682 5207 5439 5440 5441 +6 5206 4682 5208 5441 5442 5443 +6 5207 4682 4683 5209 5424 5443 +7 5208 4683 4684 5210 5424 5425 5426 +5 5209 4684 5211 5426 5427 +7 5210 4684 4685 5212 5427 5215 5214 +5 5211 4685 4686 5213 5214 +6 5212 4686 4687 4478 4479 5214 +6 5213 4479 4480 5215 5211 5212 +6 5214 4480 5216 5427 5211 5217 +6 5215 4480 4481 4490 4989 5217 +7 5216 4989 5218 5447 5427 5215 6810 +6 5217 4989 4990 5219 6810 6811 +6 5218 4990 5220 6811 6812 6813 +6 5219 4990 4991 5221 6813 6814 +5 5220 4991 4992 5222 6814 +7 5221 4992 4993 5223 6814 6815 6816 +5 5222 4993 4994 5224 6816 +7 5223 4994 5225 6816 6817 6818 6819 +6 5224 4994 4995 4996 5226 6819 +6 5225 4996 4997 5227 6819 6820 +6 5226 4997 5228 6820 6821 6822 +6 5227 4997 4998 5000 5229 6822 +7 5228 5000 5230 5167 6822 6823 6824 +5 5229 5000 5167 5166 5001 +6 4264 4265 5232 6902 6903 5458 +6 5231 4265 4266 5233 5448 5458 +6 5232 4266 4267 5234 5448 5449 +6 5233 4267 4269 5449 5450 5451 +6 4519 4520 5236 9677 9678 9679 +6 5235 4520 5237 9679 9683 9684 +6 5236 4520 4521 422 9684 421 +6 5018 5019 5239 6832 6833 6834 +6 5238 5019 5240 5648 6834 6835 +6 5239 5019 5020 5241 5648 5649 +7 5240 5020 5013 5014 5242 5649 5650 +5 5241 5014 5015 5243 5650 +7 5242 5015 5024 5244 5652 5650 5653 +6 5243 5024 5025 5245 5653 5247 +6 5244 5025 5026 5027 5246 5247 +6 5245 5027 5247 5248 5249 5028 +6 5245 5246 5248 5653 5244 6840 +6 5247 5246 5249 6841 6840 6842 +6 5248 5246 5028 6842 6843 6844 +6 5063 5064 5251 5492 5493 5494 +6 5250 5064 5065 5252 5494 5495 +6 5251 5065 5066 5253 5495 5496 +6 5252 5066 5067 5254 5496 5497 +6 5253 5067 5068 5255 5497 5498 +6 5254 5068 5069 5256 5498 5499 +6 5255 5069 5070 5257 5499 5500 +6 5256 5070 5071 5258 5500 5501 +6 5257 5071 5072 5259 5501 5502 +6 5258 5072 5073 5260 5502 5503 +6 5259 5073 5074 5075 5261 5503 +6 5260 5075 5262 5503 5504 5505 +6 5261 5075 5076 5263 5505 5506 +6 5262 5076 5077 5264 5506 5507 +6 5263 5077 5078 5265 5507 5508 +6 5264 5078 5079 5266 5508 5509 +6 5265 5079 5080 5267 5509 5510 +6 5266 5080 5081 5268 5510 5511 +6 5267 5081 5082 5269 5511 5512 +6 5268 5082 5083 5270 5512 5513 +6 5269 5083 5084 5085 5271 5513 +6 5270 5085 5087 5272 5513 5514 +6 5271 5087 5089 5090 5273 5514 +6 5272 5090 5274 5514 5515 5516 +6 5273 5090 5091 5275 5519 5516 +6 5274 5091 5092 5276 5519 5277 +5 5275 5092 5093 5094 5277 +6 5276 5094 5095 5278 5519 5275 +6 5277 5095 5096 5097 5279 5519 +6 5278 5097 5280 5519 5518 5520 +6 5279 5097 5098 5281 5520 5377 +6 5280 5098 5099 5282 5376 5377 +6 5281 5099 5100 5152 5283 5376 +6 5282 5152 5153 5284 5379 5376 +6 5283 5153 5285 5524 5379 5525 +6 5284 5153 5154 5286 5525 5526 +6 5285 5154 5287 5526 5527 5291 +6 5286 5154 5105 5288 5291 5289 +5 5287 5105 5106 5108 5289 +6 5288 5108 5110 5290 5291 5287 +6 5289 5110 5291 5292 5293 5294 +7 5289 5290 5292 5527 5286 5287 5528 +6 5291 5290 5293 5528 5529 5533 +5 5292 5290 5294 5533 5534 +6 5293 5290 5110 5111 5295 5534 +6 5294 5111 5116 5296 5297 5534 +6 5295 5116 5297 5298 5299 5117 +6 5295 5296 5298 5534 5535 5542 +6 5297 5296 5299 5542 5543 5544 +6 5298 5296 5117 5118 5300 5544 +6 5299 5118 5119 5301 5304 5544 +6 5300 5119 5302 5303 5304 5305 +7 5301 5119 5303 5318 5122 5120 5121 +6 5301 5302 5308 5305 5309 5318 +6 5300 5301 5305 5306 5543 5544 +6 5304 5301 5306 5307 5308 5303 +6 5304 5305 5307 5543 5545 5546 +6 5306 5305 5308 5311 5312 5546 +6 5307 5305 5303 5309 5310 5311 +6 5308 5303 5310 5316 5317 5318 +6 5308 5309 5311 5314 5315 5316 +6 5308 5310 5307 5312 5313 5314 +6 5307 5311 5313 5546 5547 5548 +6 5312 5311 5314 5548 5549 5550 +6 5313 5311 5310 5315 5553 5550 +6 5314 5310 5316 5555 5553 5558 +6 5315 5310 5309 5317 5558 5559 +6 5316 5309 5318 5319 5320 5559 +6 5317 5309 5303 5302 5122 5319 +6 5318 5122 5317 5320 5321 5123 +6 5317 5319 5321 5322 5559 5560 +6 5320 5319 5322 5126 5124 5123 +6 5320 5321 5126 5323 5560 5561 +6 5322 5126 5127 5324 5325 5561 +6 5323 5127 5325 5326 5327 5328 +6 5323 5324 5326 5561 5562 5563 +6 5325 5324 5327 5572 5563 5573 +6 5326 5324 5328 5329 5330 5573 +6 5327 5324 5329 5336 5128 5127 +6 5327 5328 5330 5331 5332 5336 +6 5327 5329 5331 5573 5574 5575 +6 5330 5329 5332 5333 5575 5576 +6 5331 5329 5333 5334 5335 5336 +6 5331 5332 5334 5576 5577 5578 +6 5333 5332 5335 5578 5340 5339 +6 5334 5332 5336 5337 5338 5339 +6 5335 5332 5329 5328 5128 5337 +6 5336 5128 5129 5130 5335 5338 +6 5335 5337 5130 5131 5133 5339 +6 5338 5133 5134 5340 5334 5335 +6 5339 5134 5341 5342 5578 5334 +6 5340 5134 5342 5343 5344 5135 +6 5340 5341 5343 5348 5349 5578 +6 5342 5341 5344 5345 5347 5348 +7 5343 5341 5345 5140 5138 5346 5135 +6 5343 5344 5140 5142 5347 5359 +5 5138 5344 5135 5136 5137 +6 5343 5345 5348 5351 5352 5359 +6 5343 5347 5342 5349 5350 5351 +6 5342 5348 5350 5578 5577 5579 +6 5349 5348 5351 5579 5580 5584 +6 5350 5348 5347 5352 5353 5584 +6 5351 5347 5353 5354 5355 5359 +6 5351 5352 5354 5608 5584 5609 +6 5353 5352 5355 5356 5807 5609 +6 5354 5352 5356 5357 5359 5360 +6 5354 5355 5357 5358 5807 5808 +6 5356 5355 5358 5360 5143 5361 +7 5356 5357 5808 5809 5810 5363 5361 +6 5355 5352 5347 5360 5142 5345 +5 5355 5359 5142 5143 5357 +6 5357 5143 5145 5362 5363 5358 +6 5361 5145 5363 5364 5365 5366 +5 5361 5362 5364 5810 5358 +6 5363 5362 5365 5810 5811 5402 +7 5364 5362 5366 5402 5401 5367 5375 +6 5365 5362 5145 5146 5148 5367 +6 5366 5148 5368 5374 5365 5375 +6 5367 5148 5155 5369 5371 5374 +6 5368 5155 4882 4883 5370 5371 +6 5369 4883 5371 5372 4888 4885 +6 5369 5370 5372 5373 5374 5368 +6 5371 5370 5373 4888 5393 5899 +6 5371 5372 5374 5375 5392 5393 +5 5371 5373 5375 5368 5367 +6 5374 5373 5392 5365 5367 5401 +6 5281 5282 5377 5378 5379 5283 +6 5281 5376 5378 5520 5280 5521 +6 5377 5376 5379 5521 5522 5523 +6 5378 5376 5283 5523 5524 5284 +6 4656 4657 55 9689 430 56 +6 1679 1680 1678 5382 5383 1682 +6 1678 5381 5383 5384 7779 3415 +6 5382 5381 5384 5385 3774 1682 +6 5382 5383 5385 5386 7779 7780 +6 5384 5383 5386 5387 5391 3774 +6 5384 5385 5387 5388 7780 7781 +6 5386 5385 5388 5389 5390 5391 +6 5386 5387 5389 5616 7781 7782 +6 5388 5387 5390 5616 5617 5618 +6 5389 5387 5391 5618 5619 5620 +6 5390 5387 5385 3774 5620 3775 +6 5375 5373 5393 5394 5401 5398 +6 5392 5373 5394 5372 5395 5899 +6 5392 5393 5395 5396 5397 5398 +5 5394 5393 5396 5899 5894 +6 5394 5395 5397 5893 5890 5894 +6 5394 5396 5398 5399 5889 5890 +6 5394 5397 5399 5400 5401 5392 +6 5398 5397 5400 5880 5888 5889 +7 5398 5399 5401 5402 5887 5881 5880 +6 5398 5400 5402 5365 5375 5392 +6 5401 5400 5887 5811 5364 5365 +6 5185 5186 5404 5415 5416 5417 +6 5403 5186 5187 5188 5405 5417 +6 5404 5188 5406 5417 5418 5419 +6 5405 5188 5189 5407 5419 5420 +6 5406 5189 5190 5408 5420 5421 +6 5407 5190 5191 5192 5409 5421 +6 5408 5192 5193 5410 5421 5422 +6 5409 5193 5195 5422 5423 5196 +6 5180 5181 5412 7323 7324 7325 +6 5411 5181 5182 5413 7325 7326 +6 5412 5182 5183 5184 5414 7326 +6 5413 5184 5415 7326 7327 7328 +6 5414 5184 5185 5403 5416 7328 +6 5415 5403 5417 7328 7329 7330 +6 5416 5403 5404 5405 5418 7330 +6 5417 5405 5419 6791 7330 7331 +6 5418 5405 5406 5420 6791 6792 +6 5419 5406 5407 5421 5428 6792 +6 5420 5407 5408 5409 5422 5428 +6 5421 5409 5410 5423 5428 5429 +6 5422 5410 5196 5429 5430 5431 +6 5208 5209 5425 5443 5444 5445 +6 5424 5209 5426 5445 5446 5447 +5 5425 5209 5210 5427 5447 +6 5426 5210 5211 5215 5447 5217 +6 5420 5421 5422 5429 6792 6793 +6 5428 5422 5423 5430 6793 6794 +6 5429 5423 5431 6794 6795 5432 +6 5430 5423 5196 5197 5198 5432 +5 5431 5198 5433 6795 5430 +6 5432 5198 5199 5434 6795 6796 +6 5433 5199 5200 5435 6796 6797 +6 5434 5200 5201 5436 6797 6798 +6 5435 5201 5202 5437 6798 6799 +6 5436 5202 5203 5438 6799 6800 +6 5437 5203 5439 6800 6801 6802 +7 5438 5203 5204 5205 5206 5440 6802 +5 5439 5206 5441 6802 6803 +6 5440 5206 5207 5442 6803 6804 +6 5441 5207 5443 6804 6805 5444 +5 5442 5207 5208 5424 5444 +6 5443 5424 5445 6805 5442 6806 +6 5444 5424 5425 5446 6806 6807 +6 5445 5425 5447 6807 6808 6809 +7 5446 5425 5426 5427 5217 6809 6810 +6 5232 5233 5449 5458 5459 5460 +6 5448 5233 5234 5450 5460 5461 +6 5449 5234 5451 5461 5462 5463 +6 5450 5234 4269 4270 5452 5463 +6 5451 4270 4271 5453 5463 5464 +6 5452 4271 4272 5454 5455 5464 +6 5453 4272 5455 5456 5457 4273 +6 5453 5454 5456 5464 5465 5466 +6 5455 5454 5457 5466 5467 5468 +6 5456 5454 4273 5468 5469 4274 +6 5232 5448 5459 6903 5231 6904 +6 5458 5448 5460 6904 6905 6906 +6 5459 5448 5449 5461 6906 6907 +6 5460 5449 5450 5462 6907 6908 +6 5461 5450 5463 6908 6909 6910 +6 5462 5450 5451 5452 5464 6910 +6 5463 5452 5453 5455 5465 6910 +6 5464 5455 5466 6910 6911 6912 +6 5465 5455 5456 5467 6912 6913 +6 5466 5456 5468 6913 6914 6915 +6 5467 5456 5457 5469 6915 6916 +6 5468 5457 4274 4275 5470 6916 +6 5469 4275 4276 4277 5471 6916 +6 5470 4277 5472 6916 6917 6918 +6 5471 4277 4278 5473 6918 6919 +6 5472 4278 4279 5474 6919 6920 +6 5473 4279 4280 5046 5475 6920 +6 5474 5046 5476 6920 6921 6922 +6 5475 5046 5047 5477 6922 6923 +6 5476 5047 5048 5478 6923 6924 +6 5477 5048 5049 5479 6924 6925 +6 5478 5049 5050 5480 6925 6926 +6 5479 5050 5051 5481 5654 6926 +6 5480 5051 5052 5053 5482 5654 +6 5481 5053 5483 5654 5655 5656 +6 5482 5053 5054 5055 5484 5656 +6 5483 5055 5485 5656 5657 5658 +6 5484 5055 5056 5486 5658 5659 +6 5485 5056 5057 5487 5659 5660 +6 5486 5057 5058 5488 5660 5661 +6 5487 5058 5059 5489 5621 5661 +6 5488 5059 5060 5490 5621 5622 +6 5489 5060 5061 5062 5491 5622 +6 5490 5062 5063 5492 5622 5623 +6 5491 5063 5250 5493 5623 5624 +6 5492 5250 5494 5624 5625 5626 +6 5493 5250 5251 5495 5626 5627 +6 5494 5251 5252 5496 5627 5628 +6 5495 5252 5253 5497 5628 5629 +6 5496 5253 5254 5498 5629 5630 +6 5497 5254 5255 5499 5630 5631 +6 5498 5255 5256 5500 5631 5632 +6 5499 5256 5257 5501 5632 5633 +6 5500 5257 5258 5502 5633 5634 +6 5501 5258 5259 5503 5634 5635 +6 5502 5259 5260 5261 5504 5635 +6 5503 5261 5505 5635 5636 5637 +6 5504 5261 5262 5506 5637 5638 +6 5505 5262 5263 5507 5638 5639 +6 5506 5263 5264 5508 5639 5640 +6 5507 5264 5265 5509 5640 5641 +6 5508 5265 5266 5510 5641 5642 +6 5509 5266 5267 5511 5642 5643 +6 5510 5267 5268 5512 5643 5644 +6 5511 5268 5269 5513 5644 5645 +6 5512 5269 5270 5271 5514 5645 +6 5513 5271 5272 5273 5515 5645 +6 5514 5273 5516 5517 5645 5646 +6 5515 5273 5517 5518 5519 5274 +6 5515 5516 5518 5646 5647 5520 +5 5517 5516 5519 5279 5520 +7 5518 5516 5274 5275 5277 5278 5279 +7 5518 5279 5280 5377 5521 5647 5517 +5 5520 5377 5378 5522 5647 +7 5521 5378 5523 5685 5647 5684 5686 +6 5522 5378 5379 5524 5687 5686 +6 5523 5379 5284 5525 5687 5688 +6 5524 5284 5285 5526 5688 5689 +6 5525 5285 5286 5527 5689 5690 +6 5526 5286 5291 5528 5690 5691 +6 5527 5291 5292 5529 5530 5691 +6 5528 5292 5530 5531 5532 5533 +5 5528 5529 5531 5691 5692 +6 5530 5529 5532 5692 5693 5694 +7 5531 5529 5533 5694 5695 5538 5536 +6 5532 5529 5292 5293 5534 5536 +7 5533 5293 5294 5295 5297 5535 5536 +6 5534 5297 5536 5537 5541 5542 +6 5534 5535 5537 5538 5532 5533 +6 5536 5535 5538 5539 5540 5541 +6 5536 5537 5539 5695 5532 5696 +6 5538 5537 5540 5696 5697 5698 +7 5539 5537 5541 5698 5699 5700 9795 +5 5540 5537 5535 5542 9795 +6 5541 5535 5297 5298 5543 9795 +7 5542 5298 5544 5304 5306 5545 9795 +5 5543 5298 5304 5300 5299 +6 5543 5306 5546 5701 5700 9795 +6 5545 5306 5307 5312 5547 5701 +6 5546 5312 5548 5701 5702 5703 +6 5547 5312 5313 5549 5703 5704 +6 5548 5313 5550 5551 5704 5705 +6 5549 5313 5551 5552 5553 5314 +6 5549 5550 5552 5705 5706 5707 +6 5551 5550 5553 5554 5707 5708 +6 5552 5550 5314 5554 5555 5315 +6 5552 5553 5555 5556 5708 5709 +6 5554 5553 5315 5556 5557 5558 +6 5554 5555 5557 5709 5710 5711 +6 5556 5555 5558 5714 5711 5715 +6 5557 5555 5315 5316 5559 5715 +6 5558 5316 5317 5320 5560 5715 +6 5559 5320 5322 5561 5716 5715 +6 5560 5322 5323 5325 5562 5716 +6 5561 5325 5563 5564 5717 5716 +6 5562 5325 5564 5565 5572 5326 +6 5562 5563 5565 5566 5717 5713 +6 5564 5563 5566 5567 5571 5572 +6 5564 5565 5567 5568 5753 5713 +6 5566 5565 5568 5569 5570 5571 +6 5566 5567 5569 5752 5753 5754 +6 5568 5567 5570 5754 5755 5770 +6 5569 5567 5571 5769 5767 5770 +6 5570 5567 5565 5572 5769 5771 +6 5571 5565 5563 5326 5573 5771 +6 5572 5326 5327 5330 5574 5771 +6 5573 5330 5575 5771 5772 5773 +6 5574 5330 5331 5576 5773 5594 +7 5575 5331 5333 5577 5594 5589 5774 +6 5576 5333 5578 5349 5579 5774 +6 5577 5333 5334 5340 5342 5349 +6 5577 5349 5350 5580 5581 5774 +6 5579 5350 5581 5582 5583 5584 +6 5579 5580 5582 5585 5586 5774 +6 5581 5580 5583 5585 5605 5606 +6 5582 5580 5584 5606 5607 5608 +6 5583 5580 5350 5351 5608 5353 +6 5581 5582 5586 5587 5605 5597 +6 5581 5585 5587 5588 5589 5774 +6 5586 5585 5588 5595 5596 5597 +6 5586 5587 5589 5590 5591 5595 +6 5586 5588 5590 5594 5576 5774 +6 5589 5588 5591 5592 5594 5773 +6 5590 5588 5592 5593 5595 5778 +6 5590 5591 5593 5773 5772 5775 +6 5592 5591 5775 5776 5777 5778 +5 5589 5590 5773 5575 5576 +6 5591 5588 5587 5596 5778 5779 +6 5595 5587 5597 5598 5599 5779 +6 5596 5587 5598 5602 5605 5585 +6 5596 5597 5599 5600 5601 5602 +6 5596 5598 5600 5779 5780 5781 +6 5599 5598 5601 5781 5789 5790 +6 5600 5598 5602 5603 5790 5791 +6 5601 5598 5603 5604 5597 5605 +6 5601 5602 5604 5794 5791 5795 +6 5603 5602 5795 5796 5606 5605 +6 5602 5597 5585 5582 5606 5604 +6 5605 5582 5583 5607 5796 5604 +6 5606 5583 5608 5610 5798 5796 +6 5607 5583 5584 5353 5609 5610 +7 5608 5353 5610 5800 5806 5807 5354 +5 5608 5609 5607 5800 5798 +6 4514 4516 5612 5613 5614 5615 +6 4514 5611 5613 427 426 7500 +6 5612 5611 5614 7500 7501 7505 +6 5613 5611 5615 7505 7506 7507 +6 5614 5611 4516 7507 7508 4518 +6 5388 5389 5617 7782 7783 7784 +6 5616 5389 5618 7784 7785 7786 +6 5617 5389 5390 5619 7786 7789 +6 5618 5390 5620 7789 7790 7791 +6 5619 5390 5391 3775 3778 7791 +6 5488 5489 5622 5661 5662 5663 +6 5621 5489 5490 5491 5623 5663 +6 5622 5491 5492 5624 5663 5664 +6 5623 5492 5493 5625 5664 5665 +6 5624 5493 5626 5665 5666 5667 +6 5625 5493 5494 5627 5667 5668 +6 5626 5494 5495 5628 5668 5669 +6 5627 5495 5496 5629 5669 5670 +6 5628 5496 5497 5630 5670 5671 +6 5629 5497 5498 5631 5671 5672 +6 5630 5498 5499 5632 5672 5673 +6 5631 5499 5500 5633 5673 5674 +6 5632 5500 5501 5634 5674 5675 +6 5633 5501 5502 5635 5675 5676 +6 5634 5502 5503 5504 5636 5676 +6 5635 5504 5637 5676 5677 5678 +6 5636 5504 5505 5638 5678 5679 +6 5637 5505 5506 5639 5679 5680 +6 5638 5506 5507 5640 5680 5681 +6 5639 5507 5508 5641 5681 5682 +6 5640 5508 5509 5642 5682 5683 +6 5641 5509 5510 5643 5683 5684 +6 5642 5510 5511 5644 5684 5685 +6 5643 5511 5512 5645 5685 5646 +6 5644 5512 5513 5514 5515 5646 +6 5645 5515 5517 5647 5685 5644 +6 5646 5517 5520 5685 5522 5521 +6 5239 5240 5649 6835 6836 6837 +6 5648 5240 5241 5650 5651 6837 +6 5649 5241 5651 5652 5243 5242 +6 5649 5650 5652 6837 6838 6839 +6 5651 5650 5243 5653 6839 6840 +5 5652 5243 5244 5247 6840 +6 5480 5481 5482 5655 6926 6927 +6 5654 5482 5656 6927 6928 6929 +6 5655 5482 5483 5484 5657 6929 +6 5656 5484 5658 6929 6930 6931 +6 5657 5484 5485 5659 5831 6931 +6 5658 5485 5486 5660 5831 5832 +6 5659 5486 5487 5661 5832 5833 +6 5660 5487 5488 5621 5662 5833 +6 5661 5621 5663 5833 5834 5835 +6 5662 5621 5622 5623 5664 5835 +6 5663 5623 5624 5665 5835 5813 +6 5664 5624 5625 5666 5812 5813 +6 5665 5625 5667 5812 5816 5817 +6 5666 5625 5626 5668 5859 5817 +6 5667 5626 5627 5669 5859 5860 +6 5668 5627 5628 5670 5860 5861 +6 5669 5628 5629 5671 5861 5862 +6 5670 5629 5630 5672 5862 5863 +6 5671 5630 5631 5673 5863 5864 +6 5672 5631 5632 5674 5864 5865 +6 5673 5632 5633 5675 5865 5866 +6 5674 5633 5634 5676 5866 5867 +6 5675 5634 5635 5636 5677 5867 +6 5676 5636 5678 5867 5868 5693 +6 5677 5636 5637 5679 5693 5869 +6 5678 5637 5638 5680 5869 5870 +6 5679 5638 5639 5681 5870 5871 +6 5680 5639 5640 5682 5871 5688 +6 5681 5640 5641 5683 5688 5687 +6 5682 5641 5642 5684 5686 5687 +6 5683 5642 5643 5685 5522 5686 +6 5684 5643 5644 5646 5647 5522 +5 5684 5522 5683 5687 5523 +6 5683 5686 5523 5524 5688 5682 +7 5687 5524 5525 5689 5871 5681 5682 +5 5688 5525 5526 5690 5871 +7 5689 5526 5527 5691 5871 5870 5692 +5 5690 5527 5528 5530 5692 +7 5691 5530 5531 5693 5870 5690 5869 +7 5692 5531 5694 5868 5677 5678 5869 +6 5693 5531 5532 5695 9698 5868 +6 5694 5532 5538 5696 9699 9698 +6 5695 5538 5539 5697 5718 9699 +6 5696 5539 5698 5718 5719 5720 +6 5697 5539 5540 5699 5720 5721 +6 5698 5540 5700 5701 5721 5722 +5 5699 5540 5701 5545 9795 +7 5699 5700 5545 5546 5547 5702 5722 +6 5701 5547 5703 5722 5723 5727 +6 5702 5547 5548 5704 5727 5728 +6 5703 5548 5549 5705 5728 5729 +6 5704 5549 5551 5706 5732 5729 +6 5705 5551 5707 5732 5733 5734 +6 5706 5551 5552 5708 5737 5734 +6 5707 5552 5554 5709 5737 5738 +6 5708 5554 5556 5710 5747 5738 +6 5709 5556 5711 5712 5747 5748 +6 5710 5556 5712 5713 5714 5557 +6 5710 5711 5713 5748 5749 5753 +7 5712 5711 5714 5717 5564 5753 5566 +6 5713 5711 5557 5715 5716 5717 +6 5714 5557 5716 5560 5559 5558 +6 5714 5715 5717 5562 5561 5560 +5 5714 5716 5562 5564 5713 +7 5696 5697 5719 9696 5865 9697 9699 +6 5718 5697 5720 9696 9695 9700 +6 5719 5697 5698 5721 9700 9701 +7 5720 5698 5699 5722 5723 5724 9701 +5 5721 5699 5701 5702 5723 +7 5722 5702 5721 5724 5725 5726 5727 +6 5721 5723 5725 6095 9701 9702 +6 5724 5723 5726 6095 6096 6097 +6 5725 5723 5727 6097 5730 5728 +5 5726 5723 5702 5703 5728 +6 5727 5703 5704 5729 5730 5726 +6 5728 5704 5730 5731 5732 5705 +7 5728 5729 5731 6097 5726 6098 6099 +6 5730 5729 5732 6099 6100 6101 +6 5731 5729 5705 5706 5733 6101 +6 5732 5706 5734 5735 6101 6102 +6 5733 5706 5735 5736 5737 5707 +6 5733 5734 5736 6105 6102 6106 +6 5735 5734 5737 6106 6107 5739 +6 5736 5734 5707 5708 5738 5739 +6 5737 5708 5739 5740 5747 5709 +6 5737 5738 5740 5741 6107 5736 +6 5739 5738 5741 5742 5746 5747 +6 5739 5740 5742 5743 6107 6108 +6 5741 5740 5743 5744 5745 5746 +6 5741 5742 5744 6111 6108 6112 +6 5743 5742 5745 6112 6113 6114 +6 5744 5742 5746 5750 6121 6114 +6 5745 5742 5740 5747 5748 5750 +6 5746 5740 5738 5709 5710 5748 +6 5747 5710 5712 5749 5746 5750 +6 5748 5712 5750 5751 5752 5753 +6 5746 5748 5745 5749 5751 6121 +5 5750 5749 5752 6121 5949 +6 5751 5749 5753 5568 5754 5949 +6 5752 5749 5712 5713 5568 5566 +6 5752 5568 5569 5755 5756 5949 +6 5754 5569 5756 5757 5758 5770 +6 5754 5755 5757 5949 5950 5951 +6 5756 5755 5758 5759 5951 5952 +6 5757 5755 5759 5760 5761 5770 +6 5757 5758 5760 5952 5953 5957 +6 5759 5758 5761 5762 5763 5957 +6 5760 5758 5762 5766 5767 5770 +6 5760 5761 5763 5764 5765 5766 +6 5760 5762 5764 5957 5958 5988 +6 5763 5762 5765 5989 5988 5990 +6 5764 5762 5766 5990 5991 5776 +6 5765 5762 5761 5767 5768 5776 +6 5766 5761 5768 5769 5570 5770 +6 5766 5767 5769 5772 5775 5776 +6 5768 5767 5570 5571 5771 5772 +6 5570 5767 5569 5761 5755 5758 +6 5769 5571 5572 5573 5574 5772 +7 5771 5574 5773 5592 5775 5769 5768 +6 5772 5574 5575 5594 5590 5592 +6 5589 5576 5586 5581 5579 5577 +5 5772 5592 5593 5776 5768 +7 5775 5593 5777 5991 5765 5768 5766 +6 5776 5593 5778 5992 5991 5782 +6 5777 5593 5591 5595 5779 5782 +6 5778 5595 5596 5599 5780 5782 +6 5779 5599 5781 5782 5783 5784 +6 5780 5599 5600 5784 5785 5789 +6 5779 5780 5783 5992 5777 5778 +6 5782 5780 5784 5993 5992 5996 +7 5783 5780 5781 5785 5786 5996 5997 +6 5784 5781 5786 5787 5788 5789 +6 5784 5785 5787 5997 5998 5999 +6 5786 5785 5788 6002 5999 6003 +6 5787 5785 5789 6009 6003 6199 +6 5788 5785 5781 5600 5790 6199 +6 5789 5600 5601 5791 5792 6199 +6 5790 5601 5792 5793 5794 5603 +6 5790 5791 5793 6198 6199 6197 +6 5792 5791 5794 6197 6200 6221 +6 5793 5791 5603 5795 6221 6219 +6 5794 5603 5604 5796 5797 6219 +6 5795 5604 5797 5798 5607 5606 +6 5795 5796 5798 5799 6218 6219 +6 5797 5796 5607 5799 5800 5610 +6 5797 5798 5800 5801 5802 6218 +7 5799 5798 5610 5609 5801 5805 5806 +6 5799 5800 5802 5803 5804 5805 +6 5799 5801 5803 6217 6209 6218 +6 5802 5801 5804 5823 5824 6217 +6 5803 5801 5805 5823 5830 5839 +6 5804 5801 5800 5806 5808 5839 +5 5805 5800 5609 5807 5808 +5 5806 5609 5354 5356 5808 +7 5807 5356 5358 5809 5839 5805 5806 +6 5808 5358 5810 5838 5839 5886 +7 5809 5358 5363 5364 5811 5885 5886 +6 5810 5364 5884 5885 5887 5402 +6 5665 5666 5813 5814 5815 5816 +6 5665 5812 5814 5835 5664 5842 +6 5813 5812 5815 5842 5843 5844 +6 5814 5812 5816 5819 5820 5844 +6 5815 5812 5666 5817 5818 5819 +6 5816 5666 5818 5859 5857 5667 +6 5816 5817 5819 5822 5857 5854 +6 5816 5818 5815 5820 5821 5822 +6 5815 5819 5821 5844 5845 5846 +6 5820 5819 5822 5852 5849 5846 +6 5821 5819 5818 5852 5853 5854 +6 5803 5804 5824 5825 5826 5830 +5 5803 5823 5825 6216 6217 +7 5824 5823 5826 5827 6216 6215 6021 +6 5825 5823 5827 5828 5829 5830 +6 5825 5826 5828 6019 6020 6021 +6 5827 5826 5829 5836 5872 6019 +6 5828 5826 5830 5836 5837 5838 +6 5829 5826 5823 5804 5838 5839 +6 5658 5659 5832 6931 6932 6933 +6 5831 5659 5660 5833 5840 6933 +6 5832 5660 5661 5662 5834 5840 +6 5833 5662 5835 5840 5841 5842 +6 5834 5662 5663 5664 5813 5842 +6 5828 5829 5837 5872 5873 5883 +6 5836 5829 5838 5885 5883 5886 +6 5837 5829 5830 5839 5809 5886 +6 5838 5830 5809 5808 5805 5804 +6 5832 5833 5834 5841 6933 6934 +6 5840 5834 5842 6934 6935 5843 +6 5841 5834 5835 5813 5814 5843 +6 5842 5814 5844 6018 6935 5841 +6 5843 5814 5815 5820 5845 6018 +6 5844 5820 5846 5847 6018 6940 +6 5845 5820 5847 5848 5849 5821 +6 5845 5846 5848 6940 6941 6942 +6 5847 5846 5849 5850 6945 6942 +6 5848 5846 5850 5851 5852 5821 +5 5848 5849 5851 6945 6385 +6 5850 5849 5852 6103 6104 6385 +6 5851 5849 5821 5822 5853 6103 +6 5852 5822 5854 5855 6100 6103 +6 5853 5822 5855 5856 5857 5818 +6 5853 5854 5856 6098 6099 6100 +6 5855 5854 5857 5858 6384 6098 +6 5856 5854 5858 5859 5817 5818 +6 5856 5857 5859 5860 6383 6384 +6 5858 5857 5817 5667 5668 5860 +6 5859 5668 5669 5861 6383 5858 +6 5860 5669 5670 5862 9703 6383 +6 5861 5670 5671 5863 9694 9703 +6 5862 5671 5672 5864 9694 9695 +6 5863 5672 5673 5865 9695 9696 +7 5864 5673 5674 5866 9696 5718 9697 +5 5865 5674 5675 5867 9697 +7 5866 5675 5676 5677 5868 9697 9698 +5 5867 5677 5693 5694 9698 +5 5693 5678 5679 5870 5692 +6 5869 5679 5680 5871 5690 5692 +6 5870 5680 5681 5688 5689 5690 +6 5828 5836 5873 5874 9736 6019 +6 5872 5836 5874 5875 5882 5883 +6 5872 5873 5875 5876 9736 6041 +6 5874 5873 5876 5877 5878 5882 +6 5874 5875 5877 6048 6041 6042 +6 5876 5875 5878 5879 6049 6048 +6 5877 5875 5879 5880 5881 5882 +6 5877 5878 5880 6049 6050 5888 +6 5879 5878 5881 5400 5399 5888 +6 5880 5878 5882 5884 5887 5400 +6 5881 5878 5875 5873 5883 5884 +6 5882 5873 5836 5884 5885 5837 +6 5882 5883 5885 5811 5881 5887 +6 5884 5883 5837 5811 5810 5886 +5 5810 5885 5837 5838 5809 +5 5881 5884 5811 5402 5400 +6 5880 5399 5889 6053 6050 5879 +6 5888 5399 5397 5890 5891 6053 +6 5889 5397 5891 5892 5893 5396 +6 5889 5890 5892 6056 6053 6057 +6 5891 5890 5893 6057 6058 6059 +6 5892 5890 5396 5894 5895 6059 +6 5893 5396 5895 5896 5899 5395 +6 5893 5894 5896 5897 6059 6061 +6 5895 5894 5897 5898 4889 5899 +6 5895 5896 5898 5900 6061 6062 +6 5897 5896 4889 4890 5900 5901 +7 4889 5896 5894 5395 5393 5372 4888 +6 5897 5898 5901 6065 6062 6066 +6 5900 5898 4890 4892 5902 6066 +6 5901 4892 5903 5904 5905 6066 +6 5902 4892 5904 5911 5912 4893 +6 5902 5903 5905 5906 5907 5911 +6 5902 5904 5906 6066 6070 6067 +7 5905 5904 5907 5908 6075 6072 6070 +6 5906 5904 5908 5909 5910 5911 +5 5906 5907 5909 5934 6075 +7 5908 5907 5910 5932 5929 5933 5934 +6 5909 5907 5911 5932 9752 5915 +6 5910 5907 5904 5903 5912 5915 +6 5911 5903 4893 5913 5914 5915 +6 5912 4893 4894 4896 4899 5914 +6 5913 4899 5912 5915 5916 5917 +6 5912 5914 5916 5911 9752 5910 +6 5915 5914 5917 9752 9755 9758 +6 5916 5914 4899 4900 5918 9758 +7 5917 4900 4902 3671 3951 5919 9758 +6 5918 3951 3949 5920 9755 9758 +5 5919 3949 3948 5921 9755 +6 5920 3948 5922 5930 5931 9755 +6 5921 3948 3946 3962 5923 5930 +6 5922 3962 3963 5924 5925 5930 +6 5923 3963 3965 5925 5926 5942 +6 5923 5924 5926 5927 5929 5930 +6 5925 5924 5927 5928 5941 5942 +5 5925 5926 5928 5929 5933 +7 5927 5926 5935 5933 5936 5940 5941 +7 5925 5927 5930 5931 5932 5909 5933 +6 5925 5929 5931 5923 5922 5921 +6 5930 5929 5921 5932 9752 9755 +5 5931 5929 5909 5910 9752 +6 5909 5929 5934 5935 5928 5927 +6 5909 5933 5935 6074 6075 5908 +6 5934 5933 5928 5936 5937 6074 +6 5935 5928 5937 5938 5939 5940 +5 5935 5936 5938 6074 6076 +6 5937 5936 5939 6076 6077 6086 +6 5938 5936 5940 6087 6086 6091 +7 5939 5936 5928 5941 5944 6091 5946 +5 5940 5928 5926 5942 5944 +6 5941 5926 5924 3965 5943 5944 +7 5942 3965 3966 5944 5945 3135 5947 +6 5942 5943 5941 5940 5945 5946 +5 5944 5943 5946 3134 3135 +6 5944 5945 3134 6091 5940 3136 +6 3135 5943 2093 2092 5948 3966 +6 2092 5947 3966 3967 2488 2489 +6 5754 5756 5950 5752 5751 6121 +6 5949 5756 5951 6166 6120 6121 +6 5950 5756 5757 5952 6166 6164 +6 5951 5757 5759 5953 5954 6164 +6 5952 5759 5954 5955 5956 5957 +6 5952 5953 5955 6162 6161 6164 +6 5954 5953 5956 5960 5967 6162 +6 5955 5953 5957 5958 5959 5960 +6 5956 5953 5759 5760 5763 5958 +6 5957 5763 5956 5959 5963 5988 +6 5956 5958 5960 5961 5962 5963 +6 5956 5959 5961 5964 5967 5955 +6 5960 5959 5962 5964 5965 5982 +6 5961 5959 5963 5983 5982 5984 +6 5962 5959 5958 5987 5984 5988 +6 5960 5961 5965 5966 5967 5968 +6 5964 5961 5966 5982 5980 5971 +6 5964 5965 5968 5969 5970 5971 +6 5960 5964 5955 5968 6163 6162 +7 5967 5964 5966 5969 6156 6157 6163 +6 5968 5966 5970 6447 6445 6156 +6 5969 5966 5971 5972 6447 6448 +6 5970 5966 5972 5973 5965 5980 +6 5970 5971 5973 5974 5975 6448 +6 5972 5971 5974 5978 5979 5980 +6 5972 5973 5975 5976 5977 5978 +6 5972 5974 5976 6448 6449 6450 +6 5975 5974 5977 6450 6608 6609 +6 5976 5974 5978 6609 6612 6613 +6 5977 5974 5973 5979 6613 6614 +6 5978 5973 5980 5981 6640 6614 +6 5979 5973 5981 5982 5965 5971 +6 5979 5980 5982 5983 6640 6641 +6 5981 5980 5983 5962 5961 5965 +6 5981 5982 5962 5984 5985 6641 +6 5983 5962 5985 5986 5987 5963 +6 5983 5984 5986 6643 6641 6168 +6 5985 5984 5987 5994 6167 6168 +6 5986 5984 5963 5988 5989 5994 +6 5987 5963 5958 5989 5764 5763 +6 5987 5988 5764 5990 5993 5994 +6 5989 5764 5765 5991 5992 5993 +5 5990 5765 5992 5777 5776 +6 5990 5991 5777 5993 5783 5782 +7 5990 5992 5783 5989 5994 5995 5996 +6 5989 5993 5995 5986 5987 6167 +6 5994 5993 5996 5997 5998 6167 +5 5995 5993 5783 5784 5997 +5 5995 5996 5998 5784 5786 +7 5995 5997 5786 5999 6000 6169 6167 +6 5998 5786 6000 6001 6002 5787 +5 5998 5999 6001 6169 6170 +6 6000 5999 6002 6170 6171 6005 +6 6001 5999 5787 6003 6004 6005 +6 6002 5787 6004 6008 6009 5788 +6 6002 6003 6005 6006 6007 6008 +6 6002 6004 6006 6171 6001 6172 +6 6005 6004 6007 6010 6172 6173 +6 6006 6004 6008 6010 6011 6015 +6 6007 6004 6003 6009 6017 6015 +6 6008 6003 5788 6198 6017 6199 +6 6006 6007 6011 6012 6179 6173 +6 6010 6007 6012 6013 6014 6015 +6 6010 6011 6013 6180 6179 6186 +6 6012 6011 6014 6190 6187 6186 +6 6013 6011 6015 6016 6190 6191 +6 6014 6011 6016 6017 6008 6007 +6 6014 6015 6017 6191 6194 6195 +6 6016 6015 6008 6198 6195 6009 +6 5843 5844 5845 6937 6935 6940 +6 5827 5828 6020 9736 6038 5872 +6 5827 6019 6021 6022 6023 6038 +6 5827 6020 6022 6215 5825 6222 +6 6021 6020 6023 6024 6025 6222 +6 6022 6020 6024 6037 6028 6038 +6 6022 6023 6025 6026 6027 6028 +6 6022 6024 6026 6222 6225 6223 +6 6025 6024 6027 6225 6226 6032 +6 6026 6024 6028 6029 6031 6032 +6 6027 6024 6029 6030 6037 6023 +6 6027 6028 6030 6031 6033 6034 +6 6029 6028 6034 6035 6036 6037 +6 6027 6029 6032 6033 6247 6239 +6 6027 6031 6226 6026 6227 6239 +6 6031 6029 6034 6247 6246 6248 +6 6033 6029 6030 6035 6248 6249 +6 6034 6030 6036 6249 6263 6264 +6 6035 6030 6037 6039 6040 6264 +6 6036 6030 6028 6023 6038 6039 +6 6037 6023 6039 9736 6019 6020 +6 6037 6038 6036 6040 6041 9736 +7 6036 6039 6041 6042 6043 6265 6264 +6 6040 6039 6042 9736 5874 5876 +6 6040 6041 6043 6044 6048 5876 +5 6040 6042 6044 6045 6265 +6 6043 6042 6045 6046 6047 6048 +7 6043 6044 6046 6262 6265 6261 6266 +6 6045 6044 6047 6269 6266 6280 +6 6046 6044 6048 6049 6051 6280 +6 6047 6044 6042 6049 5877 5876 +6 6047 6048 5877 5879 6050 6051 +6 6049 5879 6051 6052 6053 5888 +6 6049 6050 6052 6054 6280 6047 +6 6051 6050 6053 6054 6055 6056 +6 6052 6050 5888 5889 6056 5891 +7 6051 6052 6055 6279 6280 6278 6281 +6 6054 6052 6056 6283 6281 6284 +6 6055 6052 6053 5891 6057 6284 +6 6056 5891 5892 6058 6060 6284 +6 6057 5892 6059 6060 6287 6288 +6 6058 5892 5893 5895 6061 6288 +6 6057 6058 6284 6285 6286 6287 +6 6059 5895 5897 6062 6063 6288 +6 6061 5897 6063 6064 6065 5900 +7 6061 6062 6064 6288 6291 6289 6292 +5 6063 6062 6065 6292 6068 +6 6064 6062 5900 6066 6067 6068 +6 6065 5900 5901 5902 5905 6067 +6 6065 6066 6068 6069 6070 5905 +7 6065 6067 6069 6292 6064 6293 6294 +5 6068 6067 6070 6071 6294 +6 6069 6067 5905 6071 6072 5906 +7 6069 6070 6072 6073 6296 6294 6297 +6 6071 6070 6073 6074 6075 5906 +6 6071 6072 6074 6297 6078 6076 +7 6073 6072 6075 5934 5935 5937 6076 +5 6074 6072 5934 5908 5906 +6 6074 5937 5938 6077 6078 6073 +6 6076 5938 6078 6079 6086 6083 +6 6076 6077 6079 6080 6297 6073 +6 6078 6077 6080 6081 6082 6083 +6 6078 6079 6081 6297 6298 6301 +6 6080 6079 6082 6301 6302 6314 +6 6081 6079 6083 6084 6313 6314 +6 6082 6079 6084 6085 6086 6077 +7 6082 6083 6085 6088 6313 6315 6318 +6 6084 6083 6086 6087 6088 6089 +6 6085 6083 6087 5939 5938 6077 +6 6085 6086 5939 6089 6090 6091 +6 6084 6085 6089 6094 3769 6318 +7 6088 6085 6087 6090 3137 6092 6094 +5 6089 6087 6091 3136 3137 +6 6090 6087 5939 5940 5946 3136 +6 6089 3137 3138 6093 3768 6094 +7 6092 3138 3768 3766 2085 2084 9776 +5 6092 3768 3769 6088 6089 +6 5724 5725 6096 6383 9702 9703 +6 6095 5725 6097 6098 6383 6384 +5 6096 5725 5726 5730 6098 +7 6096 6097 5730 6099 6384 5856 5855 +5 6098 5730 5731 6100 5855 +7 6099 5731 6101 6102 6103 5855 5853 +5 6100 5731 5732 5733 6102 +7 6101 5733 6100 6103 6104 6105 5735 +6 6100 6102 6104 5853 5852 5851 +6 6103 6102 6105 5851 6385 6386 +5 6104 6102 5735 6106 6386 +7 6105 5735 5736 6107 6386 6387 6109 +6 6106 5736 5739 5741 6108 6109 +6 6107 5741 6109 6110 6111 5743 +6 6107 6108 6110 6387 6106 6388 +6 6109 6108 6111 6388 6389 6390 +6 6110 6108 5743 6112 6393 6390 +6 6111 5743 5744 6113 6115 6393 +6 6112 5744 6114 6115 6116 6117 +6 6113 5744 6120 6117 6121 5745 +6 6112 6113 6116 6393 9737 9738 +6 6115 6113 6117 6118 6122 9738 +6 6116 6113 6118 6119 6120 6114 +6 6116 6117 6119 6122 6123 6165 +5 6118 6117 6120 6166 6165 +6 6119 6117 6114 6121 6166 5950 +7 6120 6114 5745 5750 5751 5949 5950 +6 6116 6118 6123 6124 6131 9738 +6 6122 6118 6124 6125 6165 6160 +6 6122 6123 6125 6126 6127 6131 +6 6124 6123 6126 6152 6160 6158 +6 6124 6125 6127 6128 6151 6152 +6 6124 6126 6128 6129 6130 6131 +6 6127 6126 6129 6150 6149 6151 +6 6127 6128 6130 6150 6137 6134 +6 6127 6129 6131 6132 6133 6134 +6 6127 6130 6132 9738 6122 6124 +6 6131 6130 6133 6398 9737 9738 +6 6132 6130 6134 6135 6397 6398 +6 6133 6130 6135 6136 6137 6129 +6 6133 6134 6136 6397 6399 6400 +6 6135 6134 6137 6138 6400 6401 +6 6136 6134 6138 6139 6150 6129 +6 6136 6137 6139 6140 6401 6402 +6 6138 6137 6140 6141 6148 6150 +6 6138 6139 6141 6142 6402 6403 +6 6140 6139 6142 6143 6144 6148 +6 6140 6141 6143 6403 6404 6405 +6 6142 6141 6144 6145 6405 6436 +6 6143 6141 6145 6146 6147 6148 +6 6143 6144 6146 6437 6436 6438 +6 6145 6144 6147 6438 6439 6440 +6 6146 6144 6148 6149 6440 6441 +6 6147 6144 6141 6139 6149 6150 +6 6147 6148 6150 6128 6151 6441 +6 6149 6148 6139 6137 6129 6128 +6 6149 6128 6126 6152 6153 6441 +6 6151 6126 6125 6153 6154 6158 +6 6151 6152 6154 6155 6441 6442 +6 6153 6152 6155 6156 6157 6158 +6 6153 6154 6156 6444 6442 6445 +6 6155 6154 6157 5969 6445 5968 +6 6156 6154 6158 6159 5968 6163 +6 6157 6154 6152 6159 6160 6125 +6 6157 6158 6160 6161 6162 6163 +6 6159 6158 6125 6161 6123 6165 +6 6159 6160 6162 5954 6164 6165 +6 6159 6161 6163 5967 5955 5954 +5 6159 6162 5967 6157 5968 +6 5954 6161 6165 6166 5951 5952 +7 6164 6161 6166 6119 6118 6123 6160 +6 6164 6165 6119 6120 5950 5951 +6 5994 5995 5986 6168 6169 5998 +6 5986 6167 6169 6643 5985 9783 +6 6168 6167 5998 6000 6170 9783 +7 6169 6000 6001 6171 6789 9783 9782 +7 6170 6001 6005 6172 6788 6786 6789 +6 6171 6005 6006 6173 6174 6788 +6 6172 6006 6174 6175 6010 6179 +6 6172 6173 6175 6176 6784 6788 +6 6174 6173 6176 6177 6178 6179 +6 6174 6175 6177 6782 6781 6784 +6 6176 6175 6178 9796 6782 9797 +6 6177 6175 6179 6180 6181 9796 +6 6178 6175 6180 6012 6010 6173 +6 6178 6179 6181 6182 6186 6012 +6 6178 6180 6182 6183 9796 9799 +6 6181 6180 6183 6184 6185 6186 +6 6181 6182 6184 6362 6645 9799 +6 6183 6182 6185 6362 6363 6367 +6 6184 6182 6186 6187 6188 6367 +6 6185 6182 6180 6187 6012 6013 +6 6185 6186 6188 6189 6190 6013 +6 6185 6187 6189 6367 6368 6369 +6 6188 6187 6190 6369 6372 6192 +6 6189 6187 6013 6014 6191 6192 +6 6190 6014 6016 6192 6193 6194 +6 6190 6191 6193 6372 6189 6373 +6 6192 6191 6194 6382 6373 6203 +6 6193 6191 6016 6195 6196 6203 +6 6194 6016 6196 6197 6198 6017 +6 6194 6195 6197 6200 6201 6203 +6 6196 6195 6198 5792 5793 6200 +6 6197 6195 6017 6009 6199 5792 +6 6198 6009 5792 5790 5789 5788 +6 6197 5793 6196 6201 6202 6221 +6 6196 6200 6202 6203 6204 6205 +6 6201 6200 6205 6206 6220 6221 +6 6196 6201 6204 6382 6193 6194 +6 6203 6201 6205 6382 6459 6381 +6 6204 6201 6202 6206 6207 6459 +6 6205 6202 6207 6208 6209 6220 +6 6205 6206 6208 6210 6211 6459 +6 6207 6206 6209 6210 6214 6217 +6 6208 6206 5802 6217 6218 6220 +6 6207 6208 6211 6212 6213 6214 +6 6207 6210 6212 6456 6458 6459 +7 6211 6210 6213 6223 6224 6454 6456 +5 6212 6210 6214 6215 6223 +6 6213 6210 6208 6215 6216 6217 +7 6213 6214 6216 5825 6021 6222 6223 +5 6215 6214 6217 5824 5825 +7 6216 6214 5824 5803 5802 6209 6208 +6 5802 6209 5799 5797 6219 6220 +6 5797 6218 6220 6221 5794 5795 +6 6219 6218 6209 6206 6202 6221 +6 6219 6220 6202 6200 5793 5794 +5 6215 6021 6022 6025 6223 +7 6215 6222 6213 6212 6224 6225 6025 +7 6212 6223 6225 6454 6231 6226 6228 +5 6224 6223 6025 6026 6226 +6 6225 6026 6032 6227 6228 6224 +6 6226 6032 6228 6229 6238 6239 +6 6226 6227 6229 6230 6231 6224 +6 6228 6227 6230 6237 6234 6238 +6 6228 6229 6231 6232 6233 6234 +6 6228 6230 6232 6454 6224 6455 +6 6231 6230 6233 6455 6460 6461 +6 6232 6230 6234 6235 6461 6462 +6 6233 6230 6235 6236 6237 6229 +6 6233 6234 6236 6462 6463 6471 +6 6235 6234 6237 6473 6471 6476 +6 6236 6234 6229 6238 6476 6241 +6 6237 6229 6227 6239 6240 6241 +6 6238 6227 6240 6247 6031 6032 +6 6238 6239 6241 6242 6243 6247 +6 6238 6240 6242 6476 6237 6477 +6 6241 6240 6243 6244 6477 6479 +6 6242 6240 6244 6245 6246 6247 +6 6242 6243 6245 6481 6479 6482 +6 6244 6243 6246 6482 6253 6251 +6 6245 6243 6247 6033 6248 6251 +6 6246 6243 6240 6239 6031 6033 +6 6246 6033 6034 6249 6250 6251 +6 6248 6034 6035 6250 6263 6255 +6 6248 6249 6251 6252 6254 6255 +6 6248 6250 6252 6253 6245 6246 +6 6251 6250 6253 6254 6484 6485 +6 6251 6252 6482 6245 6483 6484 +6 6252 6250 6255 6256 6257 6485 +6 6254 6250 6256 6263 6260 6249 +6 6254 6255 6257 6258 6259 6260 +6 6254 6256 6258 6485 6493 6494 +6 6257 6256 6259 6494 6495 6496 +7 6258 6256 6260 6261 6496 6273 6267 +6 6259 6256 6261 6262 6263 6255 +6 6259 6260 6262 6045 6266 6267 +6 6261 6260 6263 6264 6265 6045 +6 6262 6260 6264 6255 6249 6035 +6 6262 6263 6265 6035 6040 6036 +5 6262 6264 6045 6043 6040 +6 6045 6261 6267 6268 6269 6046 +6 6261 6266 6268 6272 6273 6259 +6 6267 6266 6269 6270 6271 6272 +6 6268 6266 6046 6270 6279 6280 +6 6268 6269 6271 6277 6278 6279 +6 6268 6270 6272 6275 6276 6277 +6 6268 6271 6267 6273 6274 6275 +6 6267 6272 6274 6496 6259 6497 +6 6273 6272 6275 6500 6497 6501 +6 6274 6272 6271 6276 6501 6502 +6 6275 6271 6277 6502 6503 6504 +6 6276 6271 6270 6278 6504 6505 +7 6277 6270 6279 6054 6281 6282 6505 +5 6278 6270 6269 6280 6054 +6 6279 6269 6046 6054 6051 6047 +5 6278 6054 6282 6283 6055 +6 6278 6281 6283 6506 6505 6507 +6 6282 6281 6055 6284 6507 6285 +6 6283 6055 6056 6057 6060 6285 +6 6284 6060 6286 6507 6283 6508 +7 6285 6060 6287 6508 6328 6511 6290 +6 6286 6060 6058 6288 6289 6290 +6 6287 6058 6059 6061 6063 6289 +5 6287 6288 6290 6291 6063 +5 6287 6289 6291 6328 6286 +7 6290 6289 6063 6292 6326 6327 6328 +6 6291 6063 6064 6068 6293 6326 +6 6292 6068 6294 6295 6325 6326 +6 6293 6068 6069 6295 6296 6071 +6 6293 6294 6296 6299 6324 6325 +6 6295 6294 6071 6297 6298 6299 +6 6296 6071 6073 6078 6080 6298 +6 6297 6080 6296 6299 6300 6301 +5 6296 6298 6300 6324 6295 +6 6299 6298 6301 6303 6323 6324 +6 6300 6298 6080 6081 6302 6303 +6 6301 6081 6303 6304 6308 6314 +6 6301 6302 6304 6305 6323 6300 +6 6303 6302 6305 6306 6307 6308 +6 6303 6304 6306 6323 6337 6338 +6 6305 6304 6307 6338 6341 6342 +6 6306 6304 6308 6309 6342 6343 +6 6307 6304 6302 6309 6310 6314 +6 6307 6308 6310 6311 6343 6346 +6 6309 6308 6311 6312 6313 6314 +6 6309 6310 6312 6321 6322 6346 +6 6311 6310 6313 6315 6316 6321 +6 6312 6310 6314 6082 6084 6315 +6 6313 6310 6082 6081 6302 6308 +6 6313 6084 6312 6316 6317 6318 +6 6312 6315 6317 6319 6320 6321 +6 6316 6315 6318 3769 1571 6319 +5 6317 6315 3769 6084 6088 +5 6317 1571 1572 6320 6316 +7 6319 1572 1573 6316 6321 6322 6360 +5 6316 6320 6322 6312 6311 +7 6321 6320 6311 6347 6346 6348 6360 +6 6303 6305 6300 6324 6335 6337 +7 6300 6323 6299 6295 6325 6336 6335 +6 6295 6324 6293 6326 6336 6331 +6 6293 6325 6292 6291 6327 6331 +6 6291 6326 6328 6329 6330 6331 +6 6291 6327 6329 6511 6286 6290 +6 6328 6327 6330 6510 6511 6519 +7 6329 6327 6331 6332 6333 6519 6518 +6 6330 6327 6332 6336 6325 6326 +6 6330 6331 6333 6334 6335 6336 +5 6330 6332 6334 6518 6520 +6 6333 6332 6335 6520 6528 6529 +7 6334 6332 6336 6324 6323 6337 6529 +5 6335 6332 6331 6325 6324 +6 6335 6323 6305 6338 6339 6529 +6 6337 6305 6306 6339 6340 6341 +6 6337 6338 6340 6530 6527 6529 +5 6339 6338 6341 6545 6530 +6 6340 6338 6306 6342 6546 6545 +6 6341 6306 6307 6343 6344 6546 +6 6342 6307 6344 6345 6346 6309 +6 6342 6343 6345 6546 6543 6547 +6 6344 6343 6346 6347 6549 6547 +6 6345 6343 6347 6322 6311 6309 +6 6345 6346 6322 6348 6349 6549 +6 6347 6322 6349 6350 6359 6360 +6 6347 6348 6350 6351 6550 6549 +6 6349 6348 6351 6352 6353 6359 +6 6349 6350 6352 6552 6550 6553 +6 6351 6350 6353 6354 6355 6553 +6 6352 6350 6354 1589 2476 6359 +7 6352 6353 6355 6356 1594 1590 1589 +6 6352 6354 6356 6357 6553 6554 +5 6355 6354 6357 6358 1594 +6 6355 6356 6358 6554 6555 3971 +6 6357 6356 1594 3971 3970 1595 +6 2476 6353 6350 6348 6360 6361 +6 6359 6348 6361 1573 6320 6322 +5 6359 6360 1573 2475 2476 +6 6183 6184 6363 6364 6644 6645 +6 6362 6184 6364 6365 6366 6367 +6 6362 6363 6365 6644 6648 6649 +6 6364 6363 6366 9727 9673 6649 +6 6365 6363 6367 9727 9728 6368 +6 6366 6363 6184 6185 6188 6368 +6 6367 6188 6369 6370 9728 6366 +6 6368 6188 6189 6370 6371 6372 +6 6368 6369 6371 9728 9729 9730 +6 6370 6369 6372 6374 6375 9730 +6 6371 6369 6189 6192 6373 6374 +6 6372 6192 6374 6382 6380 6193 +6 6372 6373 6371 6375 6376 6380 +6 6371 6374 6376 6377 6467 9730 +6 6375 6374 6377 6378 6379 6380 +5 6375 6376 6378 9693 6467 +7 6377 6376 6379 6457 6455 6460 9693 +6 6378 6376 6380 6381 6457 6458 +6 6379 6376 6381 6382 6373 6374 +6 6379 6380 6382 6459 6458 6204 +6 6381 6380 6373 6193 6203 6204 +7 6095 6096 6384 9703 5861 5860 5858 +5 6383 6096 6098 5856 5858 +6 5851 6104 6386 6945 5850 6946 +7 6385 6104 6105 6106 6387 6946 6947 +5 6386 6106 6109 6388 6947 +6 6387 6109 6110 6389 6947 6948 +6 6388 6110 6390 6391 6948 6949 +6 6389 6110 6391 6392 6393 6111 +6 6389 6390 6392 6394 6395 6949 +6 6391 6390 6393 6394 9737 6398 +6 6392 6390 6111 6112 6115 9737 +6 6391 6392 6395 6396 6397 6398 +6 6391 6394 6396 6949 6950 6951 +6 6395 6394 6397 6951 6952 6399 +6 6396 6394 6398 6133 6135 6399 +6 6397 6394 6133 6132 9737 6392 +6 6397 6135 6400 6952 6396 6953 +6 6399 6135 6136 6401 6953 6954 +6 6400 6136 6138 6402 6954 6960 +6 6401 6138 6140 6403 6960 6410 +6 6402 6140 6142 6404 6408 6410 +6 6403 6142 6405 6406 6407 6408 +6 6404 6142 6143 6406 6436 6434 +6 6404 6405 6407 6431 6429 6434 +6 6404 6406 6408 6409 6428 6429 +6 6404 6407 6409 6403 6410 6411 +6 6408 6407 6411 6412 6413 6428 +6 6403 6408 6411 6959 6960 6402 +6 6410 6408 6409 6412 6959 6961 +6 6411 6409 6413 6414 6963 6961 +6 6412 6409 6414 6415 6427 6428 +6 6412 6413 6415 6416 6963 6964 +6 6414 6413 6416 6417 6418 6427 +6 6414 6415 6417 6558 6559 6964 +6 6416 6415 6418 6419 6558 6565 +6 6417 6415 6419 6420 6427 6424 +6 6417 6418 6420 6421 6573 6565 +6 6419 6418 6421 6422 6423 6424 +6 6419 6420 6422 6573 6572 6574 +6 6421 6420 6423 6580 6577 6574 +6 6422 6420 6424 6425 6580 6581 +6 6423 6420 6425 6426 6427 6418 +6 6423 6424 6426 6584 6581 6430 +6 6425 6424 6427 6428 6429 6430 +6 6426 6424 6418 6415 6413 6428 +6 6427 6413 6409 6407 6426 6429 +6 6426 6428 6407 6430 6431 6406 +6 6426 6429 6431 6432 6584 6425 +6 6430 6429 6406 6432 6433 6434 +6 6430 6431 6433 6584 6585 6586 +6 6432 6431 6434 6435 6589 6586 +6 6433 6431 6435 6436 6405 6406 +6 6433 6434 6436 6437 6589 6590 +6 6435 6434 6405 6437 6145 6143 +6 6435 6436 6145 6438 6590 6591 +6 6437 6145 6146 6439 6591 6592 +6 6438 6146 6440 6595 6592 6443 +6 6439 6146 6147 6441 6442 6443 +6 6440 6147 6149 6151 6153 6442 +6 6441 6153 6440 6443 6444 6155 +6 6440 6442 6444 6595 6439 6453 +6 6443 6442 6155 6445 6446 6453 +6 6444 6155 6446 6447 5969 6156 +6 6444 6445 6447 6449 6452 6453 +6 6446 6445 5969 5970 6448 6449 +5 6447 5970 5972 5975 6449 +7 6448 5975 6447 6450 6451 6452 6446 +7 6449 5975 5976 6451 6607 6598 6608 +6 6449 6450 6452 6596 6597 6598 +5 6449 6451 6446 6453 6596 +6 6446 6452 6595 6443 6444 6596 +5 6212 6224 6231 6455 6456 +7 6454 6231 6456 6457 6378 6232 6460 +6 6454 6455 6457 6458 6211 6212 +5 6456 6455 6378 6379 6458 +6 6457 6379 6456 6211 6459 6381 +6 6211 6458 6207 6381 6204 6205 +5 6455 6232 6461 9693 6378 +6 6460 6232 6233 6462 6465 9693 +6 6461 6233 6235 6463 6464 6465 +6 6462 6235 6464 6469 6470 6471 +6 6462 6463 6465 6466 6468 6469 +6 6462 6464 6461 6466 6467 9693 +6 6465 6464 6467 6468 9731 9732 +7 6465 6466 9693 6377 6375 9730 9731 +6 6466 6464 6469 7509 7510 9732 +7 6468 6464 6463 6470 7507 7509 7506 +6 6469 6463 6471 6472 7506 7505 +6 6470 6463 6235 6472 6473 6236 +6 6470 6471 6473 6474 7504 7505 +6 6472 6471 6236 6474 6475 6476 +7 6472 6473 6475 7503 7504 9692 9780 +6 6474 6473 6476 6477 6478 9692 +6 6475 6473 6236 6237 6241 6477 +6 6476 6241 6242 6475 6478 6479 +7 6475 6477 6479 6480 9692 9778 9779 +6 6478 6477 6242 6480 6481 6244 +6 6478 6479 6481 6487 9705 9778 +6 6480 6479 6244 6482 6486 6487 +6 6481 6244 6245 6253 6483 6486 +5 6482 6253 6484 6486 6489 +7 6483 6253 6252 6485 6489 6490 6491 +7 6484 6252 6254 6257 6491 6492 6493 +6 6482 6483 6481 6487 6488 6489 +5 6481 6486 6488 9705 6480 +7 6487 6486 6489 9704 2194 2195 9705 +6 6488 6486 6483 6484 6490 9704 +6 6489 6484 6491 2251 2252 9704 +6 6490 6484 6485 6492 2251 9706 +6 6491 6485 6493 9706 3335 9707 +5 6492 6485 6257 6494 9707 +6 6493 6257 6258 6495 9707 6499 +6 6494 6258 6496 6497 6498 6499 +5 6495 6258 6259 6273 6497 +6 6496 6273 6495 6498 6500 6274 +6 6495 6497 6499 2511 2512 6500 +7 6495 6498 2511 3334 9707 3881 6494 +6 2512 6498 6497 6274 6501 9710 +6 6500 6274 6275 6502 9709 9710 +6 6501 6275 6276 6503 9708 9709 +6 6502 6276 6504 6512 9708 9711 +6 6503 6276 6277 6505 6506 6512 +5 6504 6277 6506 6282 6278 +7 6504 6505 6282 6507 6512 6513 6509 +6 6506 6282 6283 6285 6508 6509 +6 6507 6285 6286 6509 6510 6511 +6 6507 6508 6510 6513 6506 6514 +7 6509 6508 6511 6329 6514 6515 6519 +5 6510 6508 6329 6328 6286 +6 6503 6504 6506 6513 9711 9717 +5 6512 6506 6509 6514 9717 +7 6513 6509 6510 6515 6516 9717 9718 +6 6514 6510 6516 6517 6518 6519 +6 6514 6515 6517 9718 9719 6522 +6 6516 6515 6518 6520 6521 6522 +6 6517 6515 6519 6330 6333 6520 +5 6518 6515 6510 6329 6330 +7 6518 6333 6334 6517 6521 6525 6528 +6 6517 6520 6522 6523 6524 6525 +7 6517 6521 6523 2214 9719 6516 2213 +5 6522 6521 6524 2213 3348 +7 6523 6521 6525 6526 3348 3347 6532 +6 6524 6521 6520 6526 6527 6528 +6 6524 6525 6527 6530 6531 6532 +6 6526 6525 6528 6530 6339 6529 +5 6527 6525 6520 6334 6529 +6 6528 6334 6335 6339 6527 6337 +7 6526 6527 6531 6340 6545 6339 6534 +6 6526 6530 6532 3863 6533 6534 +5 6526 6531 3863 3347 6524 +6 3863 6531 6534 6535 6536 6716 +6 6533 6531 6535 6544 6545 6530 +6 6533 6534 6536 6537 6544 6541 +6 6533 6535 6537 6538 6715 6716 +6 6536 6535 6538 6539 6540 6541 +7 6536 6537 6539 6714 3887 3886 6715 +6 6538 6537 6540 6714 6718 6719 +6 6539 6537 6541 6542 6719 6708 +6 6540 6537 6542 6543 6544 6535 +6 6540 6541 6543 6547 6548 6708 +6 6542 6541 6544 6546 6344 6547 +6 6543 6541 6535 6534 6545 6546 +6 6544 6534 6546 6341 6340 6530 +6 6544 6545 6543 6341 6342 6344 +6 6543 6344 6542 6548 6549 6345 +6 6542 6547 6549 6550 6551 6708 +6 6548 6547 6345 6347 6550 6349 +6 6548 6549 6551 6552 6351 6349 +6 6548 6550 6552 6705 6707 6708 +6 6551 6550 6351 6553 6554 6705 +5 6552 6351 6352 6355 6554 +6 6553 6355 6357 6555 6552 6705 +7 6554 6357 3971 6705 6706 9747 3491 +6 3969 1597 1598 6557 4038 3968 +6 6556 1598 4038 3764 612 611 +6 6416 6417 6559 6560 6564 6565 +6 6416 6558 6560 6561 6964 6965 +6 6559 6558 6561 6562 6563 6564 +6 6559 6560 6562 6965 6966 6967 +6 6561 6560 6563 6985 6983 6967 +6 6562 6560 6564 6985 6986 6567 +6 6563 6560 6558 6565 6566 6567 +6 6564 6558 6417 6566 6573 6419 +6 6564 6565 6567 6568 6569 6573 +6 6564 6566 6568 6986 6563 6987 +6 6567 6566 6569 6570 6990 6987 +6 6568 6566 6570 6571 6572 6573 +6 6568 6569 6571 6997 6990 6998 +6 6570 6569 6572 6575 7001 6998 +6 6571 6569 6573 6421 6574 6575 +6 6572 6569 6566 6565 6419 6421 +6 6572 6421 6575 6576 6577 6422 +6 6572 6574 6576 7003 7001 6571 +6 6575 6574 6577 6578 7003 7004 +6 6576 6574 6578 6579 6580 6422 +6 6576 6577 6579 7004 7005 7006 +6 6578 6577 6580 7006 7007 6582 +6 6579 6577 6422 6423 6581 6582 +6 6580 6423 6582 6583 6584 6425 +6 6580 6581 6583 7007 6579 7008 +6 6582 6581 6584 6720 7008 6585 +6 6583 6581 6425 6430 6432 6585 +6 6584 6432 6586 6587 6720 6583 +6 6585 6432 6587 6588 6589 6433 +6 6585 6586 6588 6720 6721 6728 +6 6587 6586 6589 6728 6729 6730 +6 6588 6586 6433 6435 6590 6730 +6 6589 6435 6437 6591 6730 6731 +6 6590 6437 6438 6592 6593 6731 +6 6591 6438 6593 6594 6595 6439 +6 6591 6592 6594 6731 6732 6733 +7 6593 6592 6595 6600 6733 6597 6596 +6 6594 6592 6439 6443 6453 6596 +6 6595 6453 6452 6451 6597 6594 +6 6596 6451 6598 6599 6600 6594 +6 6597 6451 6599 6606 6607 6450 +6 6597 6598 6600 6601 6602 6606 +5 6597 6599 6601 6733 6594 +6 6600 6599 6602 6603 6734 6733 +6 6601 6599 6603 6604 6605 6606 +7 6601 6602 6604 6734 6735 6736 6737 +5 6603 6602 6605 6737 6738 +7 6604 6602 6606 6738 6739 6748 6745 +6 6605 6602 6599 6598 6607 6748 +6 6606 6598 6450 6608 6747 6748 +6 6607 6450 5976 6609 6610 6747 +6 6608 5976 5977 6610 6611 6612 +6 6608 6609 6611 6747 6746 6749 +6 6610 6609 6612 6619 6620 6749 +6 6611 6609 5977 6613 6616 6619 +6 6612 5977 5978 6614 6615 6616 +6 6613 5978 6615 6639 6640 5979 +6 6613 6614 6616 6617 6638 6639 +6 6613 6615 6617 6618 6619 6612 +6 6616 6615 6618 6636 6637 6638 +6 6616 6617 6619 6621 6622 6636 +6 6616 6618 6612 6611 6620 6621 +6 6611 6619 6621 6750 6749 6626 +6 6620 6619 6618 6622 6623 6626 +6 6621 6618 6623 6624 6635 6636 +6 6621 6622 6624 6625 6626 6627 +6 6623 6622 6625 6633 6634 6635 +6 6623 6624 6627 6628 6632 6633 +6 6621 6623 6627 6750 6620 6751 +6 6626 6623 6625 6628 6629 6751 +6 6627 6625 6629 6630 6631 6632 +6 6627 6628 6630 6756 6753 6751 +6 6629 6628 6631 6756 6757 6758 +6 6630 6628 6632 6758 6766 6767 +6 6631 6628 6625 6633 6767 6768 +6 6632 6625 6624 6634 6768 6769 +6 6633 6624 6635 6769 6770 6771 +6 6634 6624 6622 6636 9785 6771 +6 6635 6622 6618 6617 6637 9785 +6 6636 6617 6638 6785 6783 9785 +6 6637 6617 6615 6639 9777 6785 +6 6638 6615 6614 6640 9777 6642 +6 6639 6614 5979 5981 6641 6642 +6 6640 5981 5983 6642 6643 5985 +7 6640 6641 6643 9777 6639 6787 9782 +6 6642 6641 5985 6168 9782 9783 +6 6362 6364 6645 6646 6647 6648 +6 6362 6644 6183 6646 9724 9799 +6 6645 6644 6647 9723 9724 6655 +6 6646 6644 6648 6652 6654 6655 +6 6647 6644 6364 6649 6650 6652 +6 6648 6364 6650 6651 9673 6365 +6 6648 6649 6651 6652 6653 9670 +6 6650 6649 9670 9671 9672 9673 +6 6648 6650 6653 6647 6654 3173 +6 6652 6650 9670 9691 3172 3173 +6 6647 6652 3173 6655 3450 3175 +6 6647 6654 3450 6656 9723 6646 +6 6655 3450 6657 6658 9721 9723 +6 6656 3450 6658 3179 6659 6667 +6 6656 6657 6667 6668 6669 9721 +6 6657 3179 6660 6663 6664 6667 +6 6659 3179 3178 6661 6662 6663 +6 6660 3178 3180 2858 2859 6662 +5 6660 6661 6663 6666 2859 +6 6660 6662 6659 6664 6665 6666 +6 6659 6663 6665 6667 6668 6672 +7 6664 6663 6666 6672 6673 4564 4563 +6 6665 6663 6662 4563 6674 2859 +5 6659 6664 6668 6658 6657 +7 6667 6664 6658 6669 6670 6671 6672 +6 6658 6668 6670 6774 6775 9721 +6 6669 6668 6671 6773 6772 6774 +6 6670 6668 6672 6673 6790 6773 +5 6671 6668 6664 6665 6673 +5 6672 6665 4564 6671 6790 +6 4563 6666 4561 6675 2860 2859 +6 4561 6674 2860 6676 4560 9792 +6 6675 2860 2853 2854 6677 9792 +6 6676 2854 6678 6679 6681 9792 +5 6677 2854 6679 6680 2855 +6 6677 6678 6680 6681 6682 6683 +6 6679 6678 6685 6683 6686 2855 +6 6677 6679 6682 9750 9761 9792 +6 6681 6679 6683 5156 5157 9750 +6 6682 6679 5156 6684 6685 6680 +6 5156 6683 6685 6692 6693 6694 +6 6684 6683 6680 6686 6687 6692 +6 6685 6680 6687 6688 6689 2855 +6 6685 6686 6688 6692 6696 6699 +6 6687 6686 6689 6690 6699 6700 +6 6688 6686 6690 6691 2856 2855 +6 6688 6689 6691 6700 6702 2551 +5 6690 6689 2856 2550 2551 +6 6685 6687 6684 6693 6695 6696 +6 6684 6692 6694 4523 4522 6695 +5 6684 6693 4523 4532 5156 +6 4522 6693 6692 6696 6697 6704 +6 6695 6692 6687 6697 6698 6699 +7 6695 6696 6698 6703 3505 3506 6704 +6 6697 6696 6699 6700 6701 6703 +5 6698 6696 6687 6688 6700 +7 6699 6688 6690 6698 6701 2222 6702 +6 6698 6700 2222 64 65 6703 +5 2222 6700 6690 2551 2221 +6 6698 6701 65 66 6697 3505 +5 6697 3506 3507 4522 6695 +7 6552 6554 6555 6706 6551 6707 9749 +6 6705 6555 9747 3502 9748 9749 +6 6551 6705 6708 6709 6710 9749 +7 6551 6707 6709 6719 6540 6548 6542 +6 6708 6707 6710 6711 6718 6719 +7 6709 6707 6711 6712 3503 9748 9749 +7 6709 6710 6712 3117 3119 6713 6718 +6 6711 6710 3503 3504 3116 3117 +6 6711 3119 3121 3887 6714 6718 +5 6713 3887 6538 6539 6718 +6 6538 3886 6536 6716 3862 6717 +5 6536 6715 6533 3863 3862 +6 3862 6715 3861 3342 3885 3886 +6 6714 6539 6713 6711 6709 6719 +5 6718 6539 6540 6709 6708 +6 6585 6587 6721 6722 7008 6583 +6 6720 6587 6722 6723 6727 6728 +6 6720 6721 6723 6724 7009 7008 +6 6722 6721 6724 6725 6726 6727 +6 6722 6723 6725 7009 7010 7011 +6 6724 6723 6726 7022 7011 7023 +6 6725 6723 6727 7023 7026 7027 +6 6726 6723 6721 6728 7027 7030 +6 6727 6721 6587 6588 6729 7030 +6 6728 6588 6730 7030 7031 7032 +6 6729 6588 6589 6590 6731 7032 +6 6730 6590 6591 6593 6732 7032 +6 6731 6593 6733 6734 7032 7033 +6 6732 6593 6734 6601 6600 6594 +6 6732 6733 6601 6603 6735 7033 +6 6734 6603 6736 7033 7034 7035 +6 6735 6603 6737 6740 7035 7036 +5 6736 6603 6604 6738 6740 +7 6737 6604 6605 6739 6740 6741 6742 +6 6738 6605 6742 6743 6744 6745 +6 6736 6737 6738 6741 7036 7037 +6 6740 6738 6742 7037 7038 7039 +6 6741 6738 6739 6743 7039 7040 +7 6742 6739 6744 7040 7041 6754 7042 +5 6743 6739 6745 6746 7042 +6 6744 6739 6746 6747 6748 6605 +7 6744 6745 6747 6610 6749 6750 7042 +6 6746 6745 6748 6607 6608 6610 +5 6747 6745 6607 6605 6606 +5 6746 6610 6750 6620 6611 +7 6746 6749 6620 6626 6751 6752 7042 +6 6750 6626 6752 6753 6629 6627 +5 6750 6751 6753 6754 7042 +6 6752 6751 6754 6755 6756 6629 +7 6752 6753 6755 7041 6743 7042 7141 +5 6754 6753 6756 7141 6759 +6 6755 6753 6629 6630 6757 6759 +6 6756 6630 6758 6759 6760 6761 +6 6757 6630 6631 6761 6762 6766 +6 6756 6757 6760 7141 6755 7142 +6 6759 6757 6761 7142 7143 7144 +6 6760 6757 6758 6762 6763 7144 +6 6761 6758 6763 4559 6764 6766 +6 6761 6762 4559 4551 7144 4550 +6 4559 6762 4558 4565 6765 6766 +5 4565 6764 6766 6790 6767 +6 6765 6764 6762 6758 6631 6767 +6 6766 6631 6632 6768 6790 6765 +6 6767 6632 6633 6769 6773 6790 +6 6768 6633 6634 6770 6772 6773 +6 6769 6634 6771 6772 6777 6778 +6 6770 6634 6778 6779 6635 9785 +6 6769 6770 6773 6670 6774 6777 +6 6769 6772 6670 6671 6790 6768 +6 6670 6772 6669 6775 6776 6777 +6 6669 6774 6776 9721 9722 9798 +7 6775 6774 6777 6778 6780 9797 9798 +5 6776 6774 6772 6770 6778 +6 6777 6770 6771 6779 6780 6776 +6 6778 6771 6780 6781 6783 9785 +6 6778 6779 6781 6782 6776 9797 +6 6780 6779 6782 6176 6783 6784 +5 6780 6781 6176 6177 9797 +6 6781 6779 6784 6785 6637 9785 +7 6781 6783 6176 6174 6785 6786 6788 +7 6784 6783 6786 6787 9777 6638 6637 +6 6784 6785 6787 6788 6171 6789 +6 6786 6785 9777 6642 9782 6789 +5 6784 6786 6171 6172 6174 +5 6171 6786 6170 6787 9782 +8 6671 6673 6773 4564 4565 6765 6768 6767 +6 5418 5419 6792 7331 7332 7333 +6 6791 5419 5420 5428 6793 7333 +6 6792 5428 5429 6794 7333 7334 +6 6793 5429 5430 6795 7334 7335 +6 6794 5430 5432 5433 6796 7335 +6 6795 5433 5434 6797 7335 7336 +6 6796 5434 5435 6798 7336 7337 +6 6797 5435 5436 6799 7337 7338 +6 6798 5436 5437 6800 7338 7339 +6 6799 5437 5438 6801 7339 7340 +6 6800 5438 6802 7340 7341 7342 +6 6801 5438 5439 5440 6803 7342 +6 6802 5440 5441 6804 7342 7343 +6 6803 5441 5442 6805 7343 7344 +6 6804 5442 5444 6806 7344 7345 +6 6805 5444 5445 6807 7345 7346 +6 6806 5445 5446 6808 7346 7347 +6 6807 5446 6809 7347 7348 7349 +6 6808 5446 5447 6810 7349 6811 +5 6809 5447 5217 5218 6811 +6 6810 5218 5219 6812 7349 6809 +5 6811 5219 6813 7349 7350 +6 6812 5219 5220 6814 7350 7351 +7 6813 5220 5221 5222 6815 7351 7352 +5 6814 5222 6816 7352 7353 +7 6815 5222 5223 5224 6817 7353 7354 +5 6816 5224 6818 7354 7355 +6 6817 5224 6819 7355 7356 7357 +6 6818 5224 5225 5226 6820 7357 +5 6819 5226 5227 6821 7357 +6 6820 5227 6822 7357 7358 7359 +7 6821 5227 5228 5229 6823 7359 7360 +5 6822 5229 6824 6825 7360 +5 6823 5229 6825 6826 5167 +7 6823 6824 6826 6827 6828 7362 7360 +5 6825 6824 5167 5168 6827 +6 6826 5168 6825 6828 6829 6830 +6 6825 6827 6829 7362 7363 7364 +6 6828 6827 6830 7364 7365 7366 +6 6829 6827 5168 5169 6831 7366 +7 6830 5169 6832 7366 7367 7368 6834 +5 6831 5169 6833 5238 6834 +5 6832 5169 5238 5018 5023 +6 6832 5238 5239 6835 7368 6831 +6 6834 5239 5648 6836 7375 7368 +7 6835 5648 6837 7375 7374 7376 7377 +6 6836 5648 5649 5651 6838 7377 +6 6837 5651 6839 7377 7378 7379 +6 6838 5651 5652 6840 6841 7379 +6 6839 5652 5653 5247 6841 5248 +6 6839 6840 5248 6842 7379 7380 +6 6841 5248 5249 6843 7380 7381 +6 6842 5249 6844 7381 7382 7383 +6 6843 5249 5028 5029 6845 7383 +6 6844 5029 5030 6846 6847 7383 +6 6845 5030 6847 6848 6849 5031 +6 6845 6846 6848 7384 7383 7385 +6 6847 6846 6849 7385 7386 7387 +6 6848 6846 5031 5032 6850 7387 +6 6849 5032 5033 5034 6851 7387 +6 6850 5034 6852 7387 7388 6854 +6 6851 5034 5035 5038 6853 6854 +6 6852 5038 6854 6855 6856 5039 +6 6852 6853 6855 7388 6851 7389 +6 6854 6853 6856 6857 6859 7389 +6 6855 6853 5039 6857 6858 5041 +6 6855 6856 6858 6859 6860 6861 +6 6857 6856 5041 6861 6862 6863 +6 6855 6857 6860 7389 7390 7397 +6 6859 6857 6861 7397 7398 7399 +6 6860 6857 6858 6862 7399 7400 +6 6861 6858 6863 6864 6865 7400 +6 6862 6858 6864 5042 6879 5041 +6 6862 6863 6865 6866 6879 6873 +6 6862 6864 6866 6867 7400 7401 +6 6865 6864 6867 6868 6872 6873 +6 6865 6866 6868 6869 7401 7402 +6 6867 6866 6869 6870 6871 6872 +6 6867 6868 6870 7405 7402 7406 +6 6869 6868 6871 7412 7406 7413 +6 6870 6868 6872 7419 7416 7413 +6 6871 6868 6866 6873 6874 7419 +6 6872 6866 6874 6875 6864 6879 +6 6872 6873 6875 6876 7419 7418 +6 6874 6873 6876 6877 6878 6879 +6 6874 6875 6877 6883 6884 7418 +6 6876 6875 6878 6880 6882 6883 +6 6877 6875 6879 6880 5043 5042 +6 6878 6875 5042 6863 6864 6873 +6 6877 6878 5043 5045 6881 6882 +6 6880 5045 6882 6887 6888 6889 +6 6880 6881 6877 6883 6886 6887 +6 6877 6882 6876 6884 6885 6886 +6 6876 6883 6885 7418 7420 7426 +6 6884 6883 6886 7426 7427 7428 +6 6885 6883 6882 6887 7428 7429 +6 6886 6882 6881 6888 7429 7430 +6 6887 6881 6889 6890 7430 7433 +6 6888 6881 5045 6890 4645 4644 +6 6888 6889 4645 4646 6891 7433 +6 6890 4646 4647 6892 7433 6893 +6 6891 4647 4253 4254 4730 6893 +6 6892 4730 6894 7433 6891 7432 +6 6893 4730 4731 6895 6897 7432 +6 6894 4731 6896 6897 6898 6899 +6 6895 4731 4732 6899 6900 6901 +6 6894 6895 6898 7432 7431 7434 +6 6897 6895 6899 7434 7435 7436 +6 6898 6895 6896 6900 7436 7437 +6 6899 6896 6901 7437 6904 6903 +6 6900 6896 4732 4262 6902 6903 +6 6901 4262 4263 4264 5231 6903 +6 6902 5231 5458 6904 6900 6901 +6 6903 5458 5459 6905 7437 6900 +6 6904 5459 6906 7437 7438 7439 +6 6905 5459 5460 6907 7439 7440 +6 6906 5460 5461 6908 7262 7440 +6 6907 5461 5462 6909 7262 7263 +6 6908 5462 6910 7263 7264 6911 +6 6909 5462 5463 5464 5465 6911 +6 6910 5465 6912 7264 6909 7265 +6 6911 5465 5466 6913 7265 7266 +6 6912 5466 5467 6914 7266 7267 +6 6913 5467 6915 7267 7268 7269 +6 6914 5467 5468 6916 6917 7269 +6 6915 5468 5469 5470 5471 6917 +6 6915 6916 5471 6918 7269 7270 +6 6917 5471 5472 6919 7270 7271 +6 6918 5472 5473 6920 7271 7272 +6 6919 5473 5474 5475 6921 7272 +6 6920 5475 6922 7274 7272 7275 +6 6921 5475 5476 6923 7275 7276 +6 6922 5476 5477 6924 7276 7277 +6 6923 5477 5478 6925 7277 7278 +6 6924 5478 5479 6926 7278 7279 +6 6925 5479 5480 5654 6927 7279 +6 6926 5654 5655 6928 7281 7279 +6 6927 5655 6929 7281 7282 7283 +6 6928 5655 5656 5657 6930 7283 +6 6929 5657 6931 7283 7284 7285 +6 6930 5657 5658 5831 6932 7285 +6 6931 5831 6933 7285 7286 7287 +6 6932 5831 5832 5840 6934 7287 +6 6933 5840 5841 6935 6936 7287 +6 6934 5841 5843 6936 6937 6018 +6 6934 6935 6937 6938 7287 7288 +6 6936 6935 6018 6938 6939 6940 +6 6936 6937 6939 7288 7289 7290 +6 6938 6937 6940 7290 7291 6941 +6 6939 6937 6018 5845 5847 6941 +6 6940 5847 6942 6943 7291 6939 +6 6941 5847 6943 6944 6945 5848 +6 6941 6942 6944 7291 7292 7293 +6 6943 6942 6945 7293 7294 7295 +7 6944 6942 5848 5850 6385 6946 7295 +6 6945 6385 6386 6947 7295 7296 +6 6946 6386 6387 6388 6948 7296 +6 6947 6388 6389 6949 7296 7297 +7 6948 6389 6391 6395 6950 7297 7298 +6 6949 6395 6951 7298 7300 7301 +6 6950 6395 6396 6952 7043 7301 +6 6951 6396 6399 6953 7043 7044 +6 6952 6399 6400 6954 6955 7044 +6 6953 6400 6401 6955 6956 6960 +6 6953 6954 6956 6957 7044 7045 +6 6955 6954 6957 6958 6959 6960 +6 6955 6956 6958 7045 7048 7049 +6 6957 6956 6959 6961 6962 7049 +6 6958 6956 6960 6410 6411 6961 +6 6959 6956 6954 6401 6402 6410 +6 6959 6411 6958 6962 6963 6412 +6 6958 6961 6963 7051 7049 7052 +6 6962 6961 6412 6414 6964 7052 +6 6963 6414 6416 6559 6965 7052 +6 6964 6559 6561 6966 7052 6971 +6 6965 6561 6967 6968 6970 6971 +6 6966 6561 6968 6969 6562 6983 +6 6966 6967 6969 6970 6974 6975 +6 6968 6967 6981 6975 6982 6983 +6 6966 6968 6971 6972 6973 6974 +6 6966 6970 6972 7052 6965 7051 +6 6971 6970 6973 7051 7050 7053 +6 6972 6970 6974 7062 7053 7063 +6 6973 6970 6968 6975 6976 7063 +6 6974 6968 6976 6977 6981 6969 +6 6974 6975 6977 6978 7063 7064 +6 6976 6975 6978 6979 6980 6981 +6 6976 6977 6979 7064 7065 7066 +6 6978 6977 6980 7066 7067 7071 +6 6979 6977 6981 7071 7072 7073 +6 6980 6977 6975 6969 6982 7073 +6 6981 6969 6983 6984 7073 7074 +6 6982 6969 6984 6985 6562 6967 +6 6982 6983 6985 7074 7075 7076 +6 6984 6983 6562 6563 6986 7076 +6 6985 6563 6567 6987 6988 7076 +6 6986 6567 6988 6989 6990 6568 +6 6986 6987 6989 6991 7076 7077 +6 6988 6987 6990 6991 6992 6996 +6 6989 6987 6996 6997 6570 6568 +6 6988 6989 6992 6993 7077 7078 +6 6991 6989 6993 6994 6995 6996 +6 6991 6992 6994 7078 7081 7082 +6 6993 6992 6995 7082 7085 7086 +6 6994 6992 6996 7086 7087 7088 +6 6995 6992 6989 6990 6997 7088 +6 6996 6990 6570 6998 6999 7088 +6 6997 6570 6999 7000 7001 6571 +6 6997 6998 7000 7088 7089 7092 +6 6999 6998 7001 7002 7092 7093 +6 7000 6998 7002 7003 6575 6571 +6 7000 7001 7003 7093 7094 7095 +6 7002 7001 6575 6576 7004 7095 +6 7003 6576 6578 7005 7095 7096 +6 7004 6578 7006 7096 7097 7098 +6 7005 6578 6579 7007 7012 7098 +6 7006 6579 6582 7008 7009 7012 +6 7007 6582 7009 6722 6720 6583 +6 7007 7008 6722 6724 7010 7012 +6 7009 6724 7011 7012 7013 7014 +6 7010 6724 7022 7020 7014 6725 +6 7009 7010 7007 7006 7013 7098 +6 7012 7010 7014 7015 7098 7099 +6 7013 7010 7015 7016 7020 7011 +6 7013 7014 7016 7017 7099 7100 +6 7015 7014 7017 7018 7019 7020 +6 7015 7016 7018 7107 7100 7113 +6 7017 7016 7019 7114 7113 7115 +6 7018 7016 7020 7021 7115 7116 +6 7019 7016 7014 7021 7022 7011 +6 7019 7020 7022 7024 7116 7117 +6 7021 7020 7011 6725 7023 7024 +6 7022 6725 6726 7024 7025 7026 +6 7021 7022 7023 7025 7117 7118 +6 7024 7023 7026 7118 7119 7120 +6 7025 7023 6726 7027 7028 7120 +6 7026 6726 6727 7028 7029 7030 +6 7026 7027 7029 7122 7120 7123 +6 7028 7027 7030 7123 7034 7031 +6 7029 7027 6727 6728 6729 7031 +6 7030 6729 7032 7034 7029 7033 +6 7031 6729 6730 6731 6732 7033 +6 7032 6732 6734 6735 7034 7031 +6 7033 6735 7035 7123 7029 7031 +5 7034 6735 6736 7036 7123 +6 7035 6736 6740 7037 7123 7122 +7 7036 6740 6741 7038 7122 7124 7125 +6 7037 6741 7039 7135 7125 7136 +6 7038 6741 6742 7040 7136 7137 +6 7039 6742 6743 7041 7137 7138 +5 7040 6743 6754 7141 7138 +6 6754 6743 6744 6746 6750 6752 +6 6951 6952 7044 7301 7302 7046 +6 7043 6952 6953 6955 7045 7046 +6 7044 6955 6957 7046 7047 7048 +6 7044 7045 7047 7302 7043 7303 +6 7046 7045 7048 7303 7056 7054 +6 7047 7045 6957 7049 7050 7054 +6 7048 6957 7050 7051 6962 6958 +6 7048 7049 7051 6972 7053 7054 +6 7050 7049 6962 7052 6971 6972 +6 7051 6962 6963 6964 6965 6971 +6 7050 6972 7054 7055 7062 6973 +6 7050 7053 7055 7056 7047 7048 +6 7054 7053 7056 7057 7058 7062 +6 7054 7055 7057 7303 7047 7304 +6 7056 7055 7058 7059 7307 7304 +6 7057 7055 7059 7060 7061 7062 +6 7057 7058 7060 7307 7476 7477 +6 7059 7058 7061 7477 7478 7479 +6 7060 7058 7062 7063 7064 7479 +6 7061 7058 7055 7053 6973 7063 +6 7062 6973 6974 6976 7061 7064 +6 7061 7063 6976 6978 7065 7479 +6 7064 6978 7066 7479 7480 7481 +6 7065 6978 6979 7067 7068 7481 +6 7066 6979 7068 7069 7070 7071 +6 7066 7067 7069 7483 7481 7462 +6 7068 7067 7070 7462 7484 7485 +6 7069 7067 7071 7485 7486 7487 +6 7070 7067 6979 6980 7072 7487 +6 7071 6980 7073 7487 7488 7492 +6 7072 6980 6981 6982 7074 7492 +6 7073 6982 6984 7075 7493 7492 +6 7074 6984 7076 7493 7079 7077 +6 7075 6984 6985 6986 6988 7077 +6 7076 6988 6991 7078 7079 7075 +6 7077 6991 6993 7079 7080 7081 +6 7077 7078 7080 7691 7493 7075 +6 7079 7078 7081 7223 7224 7691 +6 7080 7078 6993 7082 7083 7223 +6 7081 6993 6994 7083 7084 7085 +6 7081 7082 7084 7226 7223 7227 +6 7083 7082 7085 7227 7228 7229 +6 7084 7082 6994 7086 7232 7229 +6 7085 6994 6995 7087 7232 7233 +6 7086 6995 7088 7089 7090 7233 +6 7087 6995 6996 6997 6999 7089 +6 7088 6999 7087 7090 7091 7092 +6 7087 7089 7091 7233 7234 7235 +6 7090 7089 7092 7235 7236 7237 +6 7091 7089 6999 7000 7093 7237 +6 7092 7000 7002 7094 7237 7238 +6 7093 7002 7095 7238 7239 7103 +6 7094 7002 7003 7004 7096 7103 +6 7095 7004 7005 7097 7102 7103 +6 7096 7005 7098 7099 7101 7102 +6 7097 7005 7006 7012 7013 7099 +6 7098 7013 7015 7100 7101 7097 +6 7099 7015 7101 7106 7107 7017 +6 7099 7100 7097 7102 7105 7106 +6 7097 7101 7096 7103 7104 7105 +6 7096 7102 7104 7239 7094 7095 +6 7103 7102 7105 7241 7239 7242 +6 7104 7102 7101 7106 7242 7243 +6 7105 7101 7100 7107 7108 7243 +6 7106 7100 7017 7108 7109 7113 +6 7106 7107 7109 7110 7243 7244 +6 7108 7107 7110 7111 7112 7113 +6 7108 7109 7111 7247 7244 7248 +6 7110 7109 7112 7248 7249 7250 +6 7111 7109 7113 7114 7250 7251 +6 7112 7109 7114 7018 7017 7107 +6 7112 7113 7018 7115 7251 7254 +6 7114 7018 7019 7116 7254 7255 +6 7115 7019 7021 7117 7258 7255 +6 7116 7021 7024 7118 7258 7259 +6 7117 7024 7025 7119 7259 7128 +6 7118 7025 7120 7121 7127 7128 +6 7119 7025 7121 7122 7028 7026 +6 7119 7120 7122 7124 7126 7127 +7 7121 7120 7028 7123 7036 7037 7124 +6 7122 7028 7029 7034 7035 7036 +5 7122 7037 7125 7126 7121 +5 7124 7037 7126 7135 7038 +7 7124 7125 7121 7127 7130 7131 7135 +6 7121 7126 7119 7128 7129 7130 +6 7119 7127 7129 7261 7259 7118 +6 7128 7127 7130 7261 7532 7530 +6 7129 7127 7126 7131 7132 7532 +6 7130 7126 7132 7133 7134 7135 +6 7130 7131 7133 7532 7531 7533 +6 7132 7131 7134 7533 7534 7535 +6 7133 7131 7135 7535 7536 7136 +6 7134 7131 7126 7125 7038 7136 +6 7135 7038 7039 7137 7536 7134 +6 7136 7039 7040 7138 7139 7536 +6 7137 7040 7139 7140 7141 7041 +6 7137 7138 7140 7148 7150 7536 +6 7139 7138 7141 7142 7147 7148 +7 7140 7138 7041 6754 6755 6759 7142 +6 7140 7141 6759 6760 7143 7147 +6 7142 6760 7144 7145 7146 7147 +7 7143 6760 7145 4552 4551 6763 6761 +5 7143 7144 4552 4554 7146 +6 7145 4554 4556 7143 7147 7148 +5 7143 7146 7148 7140 7142 +7 7147 7146 4556 7140 7139 7149 7150 +6 7148 4556 7150 7151 7152 7153 +6 7148 7149 7139 7151 7536 7535 +6 7150 7149 7152 7535 7534 7537 +6 7151 7149 7153 7154 7155 7537 +6 7152 7149 7154 4649 4555 4556 +6 7152 7153 7155 7156 7166 4649 +6 7152 7154 7156 7157 7537 7538 +6 7155 7154 7157 7158 7159 7166 +6 7155 7156 7158 7538 7539 7554 +6 7157 7156 7159 7160 7554 7555 +6 7158 7156 7160 7161 7162 7166 +6 7158 7159 7161 7163 7167 7555 +6 7160 7159 7162 7163 4137 7164 +5 7161 7159 7164 7165 7166 +6 7160 7161 4137 7167 7168 4138 +7 4137 7161 7162 7165 4413 4134 4135 +5 7164 7162 4413 4415 7166 +7 4415 7165 7162 7159 7156 7154 4649 +6 7160 7163 7168 7555 7556 7560 +7 7167 7163 4138 7169 7560 7561 7562 +5 7168 4138 4139 7170 7562 +7 7169 4139 4140 7171 7562 7563 7564 +6 7170 4140 4124 7172 7173 7564 +6 7171 4124 7173 7174 4122 9789 +6 7171 7172 7174 7175 7176 7564 +6 7173 7172 7175 9788 9787 9789 +6 7173 7174 7176 7177 7178 9788 +7 7173 7175 7177 7564 7563 7568 7569 +6 7176 7175 7178 7179 7180 7569 +6 7177 7175 7179 9788 3535 3537 +6 7177 7178 7180 7181 7182 3537 +6 7177 7179 7181 7570 7569 7571 +6 7180 7179 7182 7571 7572 7573 +6 7181 7179 3537 3538 7183 7573 +6 7182 3538 7184 7575 7573 7187 +6 7183 3538 3539 7185 7186 7187 +6 7184 3539 7186 7211 7210 7212 +6 7184 7185 7187 7188 7211 7192 +6 7184 7186 7188 7189 7575 7183 +6 7187 7186 7189 7190 7191 7192 +6 7187 7188 7190 7575 7576 7579 +6 7189 7188 7191 7193 7579 7580 +6 7190 7188 7192 7193 7194 7198 +6 7191 7188 7198 7199 7211 7186 +6 7190 7191 7194 7195 7580 7581 +6 7193 7191 7195 7196 7197 7198 +6 7193 7194 7196 7581 7582 7583 +6 7195 7194 7197 7583 3196 3195 +6 7196 7194 7198 3195 7200 7203 +6 7197 7194 7191 7192 7199 7200 +6 7198 7192 7200 7201 7211 7208 +6 7198 7199 7201 7202 7203 7197 +6 7200 7199 7202 7206 7207 7208 +6 7200 7201 7203 7204 7205 7206 +6 7200 7202 7204 3194 3195 7197 +6 7203 7202 7205 7220 7221 3194 +6 7204 7202 7206 9745 7218 7220 +6 7205 7202 7201 7207 9745 9746 +6 7206 7201 7208 7209 9746 7213 +6 7207 7201 7209 7210 7211 7199 +6 7207 7208 7210 4373 4374 7213 +6 7209 7208 7211 7185 7212 4373 +6 7210 7208 7199 7192 7186 7185 +6 7210 7185 3539 3540 4372 4373 +6 7209 4374 4375 7214 9746 7207 +6 7213 4375 4377 7215 7216 9746 +6 7214 4377 7216 2863 1627 2862 +6 7214 7215 2863 7217 9745 9746 +6 7216 2863 2864 2865 7218 9745 +6 7217 2865 7219 7220 7205 9745 +5 7218 2865 7220 3214 2866 +6 7218 7219 3214 7221 7205 7204 +6 7220 3214 3215 7222 3194 7204 +5 7221 3215 3216 3193 3194 +6 7080 7081 7224 7225 7226 7083 +6 7080 7223 7225 7691 7690 7692 +6 7224 7223 7226 7692 7693 7674 +6 7225 7223 7083 7227 7674 7694 +6 7226 7083 7084 7228 7694 7695 +6 7227 7084 7229 7230 7695 7696 +6 7228 7084 7230 7231 7232 7085 +6 7228 7229 7231 7696 7697 7701 +6 7230 7229 7232 7701 7702 7703 +6 7231 7229 7085 7086 7233 7703 +6 7232 7086 7087 7090 7234 7703 +6 7233 7090 7235 7718 7704 7703 +6 7234 7090 7091 7236 7718 7717 +6 7235 7091 7237 7717 7719 7720 +6 7236 7091 7092 7093 7238 7720 +6 7237 7093 7094 7239 7240 7720 +6 7238 7094 7103 7240 7241 7104 +6 7238 7239 7241 7720 7721 7722 +6 7240 7239 7104 7242 7722 7725 +6 7241 7104 7105 7243 7245 7725 +6 7242 7105 7106 7108 7244 7245 +6 7243 7108 7245 7246 7247 7110 +6 7243 7244 7246 7728 7725 7242 +6 7245 7244 7247 7964 7728 7965 +6 7246 7244 7110 7248 7965 7966 +6 7247 7110 7111 7249 7966 7967 +6 7248 7111 7250 7511 7967 7968 +6 7249 7111 7112 7251 7252 7511 +6 7250 7112 7114 7252 7253 7254 +6 7250 7251 7253 7511 7512 7516 +6 7252 7251 7254 7256 9775 7516 +6 7253 7251 7114 7115 7255 7256 +6 7254 7115 7256 7257 7258 7116 +6 7254 7255 7257 7523 7253 9775 +6 7256 7255 7258 7260 7524 7523 +6 7257 7255 7116 7117 7259 7260 +6 7258 7117 7118 7260 7261 7128 +6 7258 7259 7261 7529 7524 7257 +6 7260 7259 7128 7129 7530 7529 +6 6907 6908 7263 7440 7442 7443 +6 7262 6908 6909 7264 7443 7444 +6 7263 6909 6911 7265 7444 7445 +6 7264 6911 6912 7266 7445 7446 +6 7265 6912 6913 7267 7449 7446 +6 7266 6913 6914 7268 7449 7450 +6 7267 6914 7269 7450 7451 7452 +6 7268 6914 6915 6917 7270 7452 +6 7269 6917 6918 7271 7452 7453 +6 7270 6918 6919 7272 7273 7453 +6 7271 6919 7273 7274 6921 6920 +6 7271 7272 7274 7453 7454 7455 +6 7273 7272 6921 7275 7455 7456 +6 7274 6921 6922 7276 7456 7457 +6 7275 6922 6923 7277 7457 7458 +6 7276 6923 6924 7278 7458 7459 +6 7277 6924 6925 7279 7280 7459 +6 7278 6925 7280 7281 6927 6926 +6 7278 7279 7281 7459 7460 7464 +6 7280 7279 6927 6928 7282 7464 +6 7281 6928 7283 7464 7465 7466 +6 7282 6928 6929 6930 7284 7466 +6 7283 6930 7285 7466 7467 7468 +6 7284 6930 6931 6932 7286 7468 +6 7285 6932 7287 7468 7469 7288 +6 7286 6932 6933 6934 6936 7288 +6 7287 6936 6938 7289 7469 7286 +6 7288 6938 7290 7469 7470 7471 +6 7289 6938 6939 7291 7471 7472 +6 7290 6939 6941 6943 7292 7472 +6 7291 6943 7293 7472 7473 7474 +6 7292 6943 6944 7294 7474 7299 +6 7293 6944 7295 7297 7298 7299 +6 7294 6944 6945 6946 7296 7297 +5 7295 6946 6947 6948 7297 +6 7296 6948 6949 7295 7294 7298 +6 7294 7297 6949 6950 7299 7300 +5 7294 7298 7300 7474 7293 +7 7299 7298 6950 7301 7474 7305 7302 +5 7300 6950 6951 7043 7302 +6 7301 7043 7046 7303 7305 7300 +6 7302 7046 7047 7056 7304 7305 +6 7303 7056 7305 7306 7307 7057 +6 7303 7304 7306 7474 7300 7302 +6 7305 7304 7307 7474 7473 7475 +6 7306 7304 7057 7059 7475 7476 +5 4702 4703 7309 7855 7856 +6 7308 4703 4704 7310 7856 7857 +6 7309 4704 4705 7311 7857 7858 +6 7310 4705 4706 7312 7858 7859 +6 7311 4706 4707 5170 7313 7859 +6 7312 5170 7314 7859 7860 7861 +6 7313 5170 5171 7315 7861 7862 +6 7314 5171 5172 7316 7862 7863 +6 7315 5172 5173 7317 7863 7864 +6 7316 5173 5174 7318 7864 7865 +6 7317 5174 5175 7319 7865 7866 +6 7318 5175 5176 7320 7866 7867 +6 7319 5176 5177 5178 7321 7867 +6 7320 5178 7322 7867 7868 7869 +6 7321 5178 5179 7323 7869 7870 +6 7322 5179 5180 5411 7324 7870 +6 7323 5411 7325 7870 7871 7872 +6 7324 5411 5412 7326 7872 7873 +6 7325 5412 5413 5414 7327 7873 +6 7326 5414 7328 7873 7874 7875 +6 7327 5414 5415 5416 7329 7875 +6 7328 5416 7330 7875 7876 7877 +6 7329 5416 5417 5418 7331 7877 +6 7330 5418 6791 7332 7877 7878 +6 7331 6791 7333 7878 7879 7880 +6 7332 6791 6792 6793 7334 7880 +6 7333 6793 6794 7335 7880 7881 +6 7334 6794 6795 6796 7336 7881 +6 7335 6796 6797 7337 7881 7882 +6 7336 6797 6798 7338 7882 7883 +6 7337 6798 6799 7339 7883 7884 +6 7338 6799 6800 7340 7884 7885 +6 7339 6800 6801 7341 7885 7886 +6 7340 6801 7342 7886 7887 7888 +6 7341 6801 6802 6803 7343 7888 +6 7342 6803 6804 7344 7888 7889 +6 7343 6804 6805 7345 7889 7890 +6 7344 6805 6806 7346 7890 7891 +6 7345 6806 6807 7347 7891 7892 +6 7346 6807 6808 7348 7892 7893 +6 7347 6808 7349 7893 7894 7895 +7 7348 6808 6809 6811 6812 7350 7895 +6 7349 6812 6813 7351 7895 7896 +6 7350 6813 6814 7352 7896 7897 +5 7351 6814 6815 7353 7897 +7 7352 6815 6816 7354 7897 7898 7899 +5 7353 6816 6817 7355 7899 +7 7354 6817 6818 7356 7899 7900 7901 +6 7355 6818 7357 7901 7902 7903 +7 7356 6818 6819 6820 6821 7358 7903 +6 7357 6821 7359 7903 7904 7905 +6 7358 6821 6822 7360 7361 7905 +6 7359 6822 6823 7361 7362 6825 +6 7359 7360 7362 7905 7906 7907 +6 7361 7360 6825 6828 7363 7907 +6 7362 6828 7364 7907 7908 7909 +5 7363 6828 6829 7365 7909 +7 7364 6829 7366 7369 7371 7909 7910 +6 7365 6829 6830 6831 7367 7369 +6 7366 6831 7368 7369 7370 7375 +5 7367 6831 7375 6835 6834 +6 7366 7367 7370 7365 7371 7372 +6 7369 7367 7372 7373 7374 7375 +6 7365 7369 7372 7910 7911 7912 +6 7371 7369 7370 7373 7912 7913 +6 7372 7370 7374 7913 7914 7915 +6 7373 7370 7375 6836 7376 7915 +6 7374 7370 7367 7368 6835 6836 +6 7374 6836 7377 7915 7916 7917 +6 7376 6836 6837 6838 7378 7917 +5 7377 6838 7379 7601 7917 +6 7378 6838 6839 6841 7380 7601 +6 7379 6841 6842 7381 7601 7602 +6 7380 6842 6843 7382 7605 7602 +6 7381 6843 7383 7384 7605 7606 +6 7382 6843 7384 6847 6845 6844 +6 7382 7383 6847 7385 7606 7607 +6 7384 6847 6848 7386 7607 7392 +6 7385 6848 7387 7388 7391 7392 +6 7386 6848 6849 6850 6851 7388 +6 7387 6851 6854 7389 7391 7386 +6 7388 6854 6855 6859 7390 7391 +6 7389 6859 7391 7396 7393 7397 +6 7389 7390 7388 7386 7392 7393 +6 7386 7391 7393 7394 7607 7385 +6 7392 7391 7394 7395 7396 7390 +6 7392 7393 7395 7607 7608 7611 +6 7394 7393 7396 7611 7612 7622 +6 7395 7393 7390 7397 7622 7623 +6 7396 7390 6859 6860 7398 7623 +5 7397 6860 7399 7623 7624 +6 7398 6860 6861 7400 7624 7625 +7 7399 6861 6862 6865 7401 7625 7626 +6 7400 6865 6867 7402 7403 7626 +6 7401 6867 7403 7404 7405 6869 +6 7401 7402 7404 7626 7627 7628 +6 7403 7402 7405 7408 7628 7629 +6 7404 7402 6869 7406 7407 7408 +6 7405 6869 7407 7411 7412 6870 +6 7405 7406 7408 7409 7410 7411 +6 7405 7407 7404 7409 7632 7629 +6 7408 7407 7410 7632 7633 7634 +6 7409 7407 7411 7634 7635 7642 +6 7410 7407 7406 7412 7642 7643 +6 7411 7406 6870 7413 7414 7643 +6 7412 6870 7414 7415 7416 6871 +6 7412 7413 7415 7643 7644 7645 +6 7414 7413 7416 7417 7645 7646 +6 7415 7413 7417 7418 7419 6871 +6 7415 7416 7418 7420 7421 7646 +7 7417 7416 7419 6874 6876 6884 7420 +5 7418 7416 6871 6872 6874 +6 7418 6884 7417 7421 7422 7426 +6 7417 7420 7422 7423 7646 7647 +6 7421 7420 7423 7424 7425 7426 +6 7421 7422 7424 7647 7648 7649 +6 7423 7422 7425 7649 7650 7651 +6 7424 7422 7426 7651 7652 7427 +6 7425 7422 7420 6884 6885 7427 +6 7426 6885 7428 7652 7425 7653 +6 7427 6885 6886 7429 7653 7654 +6 7428 6886 6887 7430 7431 7654 +6 7429 6887 6888 7431 7432 7433 +6 7429 7430 7432 6897 7434 7654 +6 7431 7430 7433 6893 6894 6897 +6 7432 7430 6888 6890 6891 6893 +6 7431 6897 6898 7435 7655 7654 +6 7434 6898 7436 7655 7656 7660 +6 7435 6898 6899 7437 7660 7438 +6 7436 6899 6900 6904 6905 7438 +6 7437 6905 7439 7660 7436 7661 +6 7438 6905 6906 7440 7441 7661 +6 7439 6906 6907 7262 7441 7442 +6 7439 7440 7442 7661 7662 7663 +6 7441 7440 7262 7443 7663 7664 +6 7442 7262 7263 7444 7664 7665 +6 7443 7263 7264 7445 7665 7666 +6 7444 7264 7265 7446 7447 7666 +6 7445 7265 7447 7448 7449 7266 +6 7445 7446 7448 7668 7666 7671 +6 7447 7446 7449 7671 7676 7673 +6 7448 7446 7266 7267 7450 7676 +6 7449 7267 7268 7451 7676 7677 +6 7450 7268 7452 7677 7678 7682 +6 7451 7268 7269 7270 7453 7682 +6 7452 7270 7271 7273 7454 7682 +6 7453 7273 7455 7682 7681 7683 +6 7454 7273 7274 7456 7686 7683 +6 7455 7274 7275 7457 7686 7687 +6 7456 7275 7276 7458 7687 7688 +6 7457 7276 7277 7459 7688 7461 +6 7458 7277 7278 7280 7460 7461 +6 7459 7280 7461 7462 7463 7464 +6 7459 7460 7462 7688 7458 7484 +7 7461 7460 7463 7483 7068 7069 7484 +6 7462 7460 7464 7483 7482 7465 +6 7463 7460 7280 7281 7282 7465 +6 7464 7282 7466 7482 7463 7494 +6 7465 7282 7283 7284 7467 7494 +6 7466 7284 7468 7494 7495 7496 +6 7467 7284 7285 7286 7469 7496 +6 7468 7286 7288 7289 7470 7496 +6 7469 7289 7471 7496 7497 7498 +6 7470 7289 7290 7472 7498 7475 +6 7471 7290 7291 7292 7473 7475 +5 7472 7292 7474 7306 7475 +7 7473 7292 7293 7299 7300 7305 7306 +7 7473 7306 7307 7476 7498 7471 7472 +5 7475 7307 7059 7477 7498 +6 7476 7059 7060 7478 7497 7498 +7 7477 7060 7479 7480 7497 7495 7499 +6 7478 7060 7061 7064 7065 7480 +6 7478 7479 7065 7481 7482 7499 +6 7480 7065 7482 7483 7068 7066 +7 7480 7481 7483 7463 7465 7494 7499 +5 7482 7481 7068 7462 7463 +5 7462 7069 7485 7688 7461 +6 7484 7069 7070 7486 7687 7688 +6 7485 7070 7487 7686 7687 7685 +7 7486 7070 7071 7072 7488 7489 7685 +6 7487 7072 7489 7490 7491 7492 +5 7487 7488 7490 7685 7684 +6 7489 7488 7491 7684 7689 7690 +6 7490 7488 7492 7493 7690 7691 +6 7491 7488 7493 7074 7073 7072 +6 7491 7492 7074 7075 7691 7079 +6 7482 7465 7466 7467 7495 7499 +6 7494 7467 7496 7497 7478 7499 +6 7495 7467 7468 7469 7470 7497 +6 7496 7470 7498 7477 7478 7495 +6 7497 7470 7471 7477 7476 7475 +5 7495 7478 7480 7482 7494 +6 427 5612 5613 7501 7502 9768 +6 7500 5613 7502 7503 7504 7505 +6 7500 7501 7503 9768 9769 9770 +6 7502 7501 7504 6474 9770 9780 +5 7503 7501 6474 6472 7505 +7 6472 7504 7501 5613 5614 7506 6470 +5 7505 5614 7507 6469 6470 +6 7506 5614 5615 7508 7509 6469 +6 7507 5615 7509 7510 9734 4518 +5 7507 7508 7510 6469 6468 +6 7509 7508 6468 9732 9733 9734 +6 7249 7250 7252 7512 7513 7968 +6 7511 7252 7513 7514 7515 7516 +6 7511 7512 7514 7968 7969 7970 +6 7513 7512 7515 7970 7971 7972 +6 7514 7512 7516 7517 7518 7972 +6 7515 7512 7252 7517 9775 7253 +6 7515 7516 7518 7519 7520 9775 +6 7515 7517 7519 7972 7973 7977 +6 7518 7517 7520 7521 7977 7978 +6 7519 7517 7521 7522 7523 9775 +6 7519 7520 7522 7989 7978 7526 +6 7521 7520 7523 7524 7525 7526 +6 7522 7520 7524 7256 7257 9775 +6 7522 7523 7525 7260 7529 7257 +6 7522 7524 7526 7527 7528 7529 +6 7522 7525 7527 7989 7521 7990 +6 7526 7525 7528 7990 7546 7545 +6 7527 7525 7529 7530 7531 7545 +6 7528 7525 7530 7261 7260 7524 +6 7528 7529 7261 7531 7532 7129 +7 7528 7530 7532 7132 7533 7543 7545 +5 7531 7530 7129 7130 7132 +6 7531 7132 7133 7534 7544 7543 +6 7533 7133 7535 7151 7537 7544 +6 7534 7133 7134 7536 7150 7151 +6 7535 7134 7136 7137 7139 7150 +6 7534 7151 7152 7155 7538 7544 +6 7537 7155 7157 7539 7540 7544 +6 7538 7157 7540 7541 7553 7554 +6 7538 7539 7541 7542 7543 7544 +6 7540 7539 7542 7547 7553 7550 +6 7540 7541 7543 7545 7546 7547 +6 7540 7542 7544 7533 7531 7545 +6 7540 7543 7533 7534 7537 7538 +6 7531 7543 7542 7546 7527 7528 +6 7545 7542 7547 7548 7990 7527 +6 7546 7542 7541 7548 7549 7550 +6 7546 7547 7549 7990 7989 7991 +6 7548 7547 7550 7551 7991 7992 +6 7549 7547 7551 7552 7553 7541 +6 7549 7550 7552 7992 7994 7995 +7 7551 7550 7553 7557 7556 7558 7995 +6 7552 7550 7541 7539 7554 7557 +6 7553 7539 7157 7158 7555 7557 +6 7554 7158 7160 7167 7556 7557 +7 7555 7167 7557 7552 7558 7559 7560 +5 7555 7556 7554 7553 7552 +5 7552 7556 7559 7995 7996 +7 7558 7556 7560 7996 7999 7566 7561 +5 7559 7556 7167 7168 7561 +6 7560 7168 7562 7565 7566 7559 +6 7561 7168 7169 7170 7563 7565 +6 7562 7170 7564 7176 7565 7568 +5 7563 7170 7171 7173 7176 +6 7562 7563 7561 7566 7567 7568 +6 7561 7565 7567 7999 7559 8000 +6 7566 7565 7568 7569 7570 8000 +5 7567 7565 7563 7176 7569 +6 7568 7176 7567 7570 7180 7177 +6 7567 7569 7180 7571 8000 8001 +6 7570 7180 7181 7572 8001 8002 +6 7571 7181 7573 7574 8002 8003 +6 7572 7181 7574 7575 7183 7182 +6 7572 7573 7575 7576 7577 8003 +6 7574 7573 7183 7187 7189 7576 +6 7575 7189 7574 7577 7578 7579 +6 7574 7576 7578 8003 8004 8005 +6 7577 7576 7579 8005 8006 8007 +6 7578 7576 7189 7190 7580 8007 +6 7579 7190 7193 7581 8007 8008 +6 7580 7193 7195 7582 8008 8009 +6 7581 7195 7583 7585 8012 8009 +6 7582 7195 7196 3196 7584 7585 +6 7583 3196 3186 7585 7586 3187 +6 7583 7584 7586 7587 7582 8012 +6 7585 7584 7587 7588 3958 3187 +6 7585 7586 7588 7729 8013 8012 +6 7587 7586 3958 3960 7589 7729 +6 7588 3960 7590 7729 7730 7731 +6 7589 3960 3961 7591 7731 7732 +6 7590 3961 7592 7738 7732 7739 +6 7591 3961 2890 2891 7593 7739 +6 7592 2891 7594 7595 7739 7740 +6 7593 2891 7595 7596 7597 2892 +6 7593 7594 7596 7740 7741 7745 +6 7595 7594 7597 7598 7745 7746 +6 7596 7594 7598 7599 7600 2892 +6 7596 7597 7599 4089 7746 7751 +5 7598 7597 7600 4089 4086 +6 7599 7597 4086 2880 2879 2892 +7 7378 7379 7380 7602 7603 7917 7918 +6 7601 7380 7603 7604 7605 7381 +6 7601 7602 7604 7926 7920 7918 +5 7603 7602 7605 7926 7927 +7 7604 7602 7381 7382 7606 7609 7927 +6 7605 7382 7384 7607 7608 7609 +6 7606 7384 7385 7392 7394 7608 +6 7607 7394 7606 7609 7610 7611 +6 7606 7608 7610 7929 7927 7605 +6 7609 7608 7611 7613 7616 7929 +6 7610 7608 7394 7395 7612 7613 +6 7611 7395 7613 7614 7621 7622 +6 7611 7612 7614 7615 7616 7610 +6 7613 7612 7615 7619 7620 7621 +6 7613 7614 7616 7617 7618 7619 +6 7613 7615 7617 8157 7929 7610 +6 7616 7615 7618 8155 8157 8156 +6 7617 7615 7619 8156 8158 8159 +6 7618 7615 7614 7620 8159 8160 +6 7619 7614 7621 8160 8161 8162 +6 7620 7614 7612 7622 8162 8163 +6 7621 7612 7395 7396 7623 8163 +6 7622 7396 7397 7398 7624 8163 +6 7623 7398 7399 7625 8163 8164 +6 7624 7399 7400 7626 8164 7627 +5 7625 7400 7401 7403 7627 +6 7626 7403 7628 8164 7625 8165 +6 7627 7403 7404 7629 7630 8165 +6 7628 7404 7630 7631 7632 7408 +6 7628 7629 7631 8165 8166 8167 +6 7630 7629 7632 8170 8167 8171 +6 7631 7629 7408 7409 7633 8171 +6 7632 7409 7634 8173 8171 8174 +6 7633 7409 7410 7635 7636 8174 +6 7634 7410 7636 7637 7641 7642 +6 7634 7635 7637 7638 8174 8175 +6 7636 7635 7638 7639 7640 7641 +6 7636 7637 7639 8175 8176 8177 +6 7638 7637 7640 8177 8178 8179 +6 7639 7637 7641 8179 8180 8181 +6 7640 7637 7635 7642 8181 8182 +6 7641 7635 7410 7411 7643 8182 +6 7642 7411 7412 7414 7644 8182 +6 7643 7414 7645 8183 8182 8184 +6 7644 7414 7415 7646 8184 8185 +6 7645 7415 7417 7421 7647 8185 +6 7646 7421 7423 7648 8185 8186 +6 7647 7423 7649 8186 8187 8188 +6 7648 7423 7424 7650 8188 8189 +6 7649 7424 7651 8189 8190 8191 +6 7650 7424 7425 7652 8191 8192 +6 7651 7425 7427 7653 8192 7657 +6 7652 7427 7428 7654 7655 7657 +6 7653 7428 7429 7655 7434 7431 +6 7653 7654 7434 7435 7656 7657 +6 7655 7435 7657 7658 7659 7660 +6 7655 7656 7658 8192 7652 7653 +6 7657 7656 7659 8192 8193 8194 +6 7658 7656 7660 8194 7662 7661 +6 7659 7656 7435 7436 7438 7661 +6 7660 7438 7439 7441 7662 7659 +6 7661 7441 7663 8194 7659 8195 +6 7662 7441 7442 7664 8208 8195 +6 7663 7442 7443 7665 8208 8207 +6 7664 7443 7444 7666 7667 8207 +6 7665 7444 7667 7668 7447 7445 +6 7665 7666 7668 7669 8206 8207 +6 7667 7666 7447 7669 7670 7671 +6 7667 7668 7670 7698 8206 9790 +6 7669 7668 7671 7672 7695 9790 +6 7670 7668 7447 7448 7672 7673 +6 7670 7671 7673 7674 7695 7694 +6 7672 7671 7674 7675 7676 7448 +7 7672 7673 7675 7693 7225 7226 7694 +6 7674 7673 7676 7677 7679 7693 +6 7675 7673 7448 7449 7450 7677 +6 7676 7450 7451 7678 7679 7675 +6 7677 7451 7679 7680 7681 7682 +7 7677 7678 7680 7675 7693 7692 7689 +5 7679 7678 7681 7689 7684 +6 7680 7678 7682 7454 7683 7684 +6 7681 7678 7451 7452 7453 7454 +6 7681 7454 7684 7685 7686 7455 +7 7681 7683 7685 7489 7490 7689 7680 +6 7684 7683 7686 7486 7487 7489 +6 7685 7683 7455 7456 7687 7486 +6 7686 7456 7457 7486 7485 7688 +6 7485 7687 7457 7458 7461 7484 +6 7684 7490 7690 7692 7679 7680 +6 7689 7490 7491 7691 7224 7692 +6 7690 7491 7493 7079 7080 7224 +6 7690 7224 7225 7693 7679 7689 +5 7692 7225 7674 7675 7679 +5 7674 7226 7227 7695 7672 +7 7694 7227 7228 7696 7670 7672 9790 +6 7695 7228 7230 7697 7698 9790 +6 7696 7230 7698 7699 7700 7701 +6 7696 7697 7699 8206 7669 9790 +6 7698 7697 7700 8205 8203 8206 +6 7699 7697 7701 8318 8205 7707 +6 7700 7697 7230 7231 7702 7707 +6 7701 7231 7703 7704 7705 7707 +6 7702 7231 7704 7234 7233 7232 +6 7702 7703 7705 7706 7718 7234 +6 7702 7704 7706 7707 7708 7709 +6 7705 7704 7709 7710 7711 7718 +6 7702 7705 7708 8318 7700 7701 +6 7707 7705 7709 8318 8481 8317 +6 7708 7705 7706 7710 8481 8482 +6 7709 7706 7711 7712 7713 8482 +6 7710 7706 7712 7716 7717 7718 +6 7710 7711 7713 7714 7715 7716 +6 7710 7712 7714 8482 8483 8484 +6 7713 7712 7715 8484 9765 8486 +6 7714 7712 7716 9765 7723 9767 +6 7715 7712 7711 7717 9767 7719 +6 7716 7711 7718 7235 7236 7719 +6 7717 7711 7706 7704 7234 7235 +6 7717 7236 7720 9767 7716 7721 +6 7719 7236 7237 7238 7240 7721 +6 7720 7240 7722 7723 9767 7719 +6 7721 7240 7241 7723 7724 7725 +7 7721 7722 7724 7726 9765 7715 9767 +6 7723 7722 7725 7726 7727 7728 +6 7724 7722 7728 7245 7242 7241 +6 7723 7724 7727 7962 9765 9764 +6 7726 7724 7728 7962 7963 7964 +6 7727 7724 7725 7245 7964 7246 +6 7587 7588 7589 7730 8013 8014 +6 7729 7589 7731 8014 8015 7734 +6 7730 7589 7590 7732 7733 7734 +6 7731 7590 7733 7737 7738 7591 +6 7731 7732 7734 7735 7736 7737 +6 7731 7733 7735 8015 7730 8016 +6 7734 7733 7736 8016 8017 8018 +6 7735 7733 7737 8018 8019 8020 +6 7736 7733 7732 7738 8020 8021 +6 7737 7732 7591 7739 9766 8021 +6 7738 7591 7592 7593 7740 9766 +6 7739 7593 7595 7741 7742 9766 +6 7740 7595 7742 7743 7744 7745 +6 7740 7741 7743 8025 8023 9766 +6 7742 7741 7744 8025 8026 8027 +6 7743 7741 7745 7747 7748 8027 +6 7744 7741 7595 7596 7746 7747 +6 7745 7596 7598 7747 7750 7751 +6 7745 7746 7744 7748 7749 7750 +6 7744 7747 7749 8027 8031 8032 +6 7748 7747 7750 8032 8036 7759 +6 7749 7747 7746 7751 7752 7759 +7 7750 7746 7598 4089 4090 7752 7753 +7 7750 7751 7753 4379 7754 7758 7759 +4 7752 7751 4090 4379 +5 7752 4379 4380 7755 7758 +6 7754 4380 4382 7756 7757 7758 +6 7755 4382 7757 7762 7763 7764 +6 7755 7756 7758 7760 7761 7762 +6 7755 7757 7754 7752 7759 7760 +6 7752 7758 7760 8036 7749 7750 +5 7759 7758 7757 7761 8036 +7 7760 7757 7762 8036 8640 8635 8035 +7 7761 7757 7756 7763 8852 8639 8640 +6 7762 7756 7764 7765 8852 8853 +6 7763 7756 4382 4383 4389 7765 +6 7763 7764 4389 7766 8319 8853 +6 7765 4389 4390 7767 8319 8320 +6 7766 4390 3142 7768 7769 8320 +6 7767 3142 7769 7770 7774 3143 +6 7767 7768 7770 7771 8322 8320 +6 7769 7768 7771 7772 7773 7774 +6 7769 7770 7772 8322 8323 8324 +6 7771 7770 7773 8324 8325 7777 +6 7772 7770 7774 7775 7776 7777 +6 7773 7770 7768 3143 3144 7775 +6 7774 3144 7773 7776 3145 9791 +6 7773 7775 7777 7778 3414 9791 +6 7773 7776 7778 8325 7772 8326 +6 7777 7776 3414 3415 7779 8326 +6 7778 3415 5382 5384 7780 8326 +6 7779 5384 5386 7781 8326 8327 +6 7780 5386 5388 7782 8329 8327 +6 7781 5388 5616 7783 8329 8330 +6 7782 5616 7784 8330 8331 8332 +6 7783 5616 5617 7785 8037 8332 +6 7784 5617 7786 7787 8037 8038 +6 7785 5617 5618 7787 7788 7789 +6 7785 7786 7788 8038 8039 8040 +6 7787 7786 7789 8045 8040 7794 +6 7788 7786 5618 5619 7790 7794 +6 7789 5619 7791 7792 7793 7794 +6 7790 5619 7792 3779 3778 5620 +6 7790 7791 7793 7797 7798 3779 +6 7790 7792 7794 7795 7796 7797 +6 7790 7793 7795 8045 7788 7789 +6 7794 7793 7796 8045 8046 8047 +6 7795 7793 7797 8048 8047 8049 +6 7796 7793 7792 7798 8049 7799 +6 7797 7792 3779 3780 3783 7799 +6 7798 3783 3784 7800 8049 7797 +6 7799 3784 3785 3788 7801 8049 +6 7800 3788 3790 7802 8048 8049 +6 7801 3790 3791 3793 7803 8048 +6 7802 3793 7804 7806 8047 8048 +6 7803 3793 3794 7805 7806 7807 +6 7804 3794 7807 7808 7809 3795 +6 7803 7804 7807 8046 8047 8343 +6 7806 7804 7805 7808 8344 8343 +6 7807 7805 7809 8344 8345 7930 +6 7808 7805 3795 3796 7810 7930 +6 7809 3796 3952 7811 7930 7931 +6 7810 3952 7812 7931 7932 7936 +6 7811 3952 3953 7813 7936 7937 +6 7812 3953 3954 7814 7937 7938 +6 7813 3954 7815 7938 7939 7816 +6 7814 3954 3955 3956 4238 7816 +6 7815 4238 4503 7817 7939 7814 +6 7816 4503 4504 7818 7939 7940 +6 7817 4504 7819 7940 7941 7942 +6 7818 4504 4505 7820 7942 7943 +6 7819 4505 4506 4507 7821 7943 +6 7820 4507 7822 7943 7944 7945 +6 7821 4507 4508 7823 7945 7946 +6 7822 4508 4509 7824 7946 7947 +6 7823 4509 7825 7826 7947 7948 +6 7824 4509 4510 7826 7827 7828 +6 7824 7825 7827 7948 7949 7950 +6 7826 7825 7828 7950 7951 7952 +6 7827 7825 4510 4419 7829 7952 +6 7828 4419 4247 7830 7952 7832 +6 7829 4247 4248 4739 7831 7832 +6 7830 4739 5003 7832 7833 7834 +6 7830 7831 7833 7952 7829 7953 +6 7832 7831 7834 7953 7954 7955 +6 7833 7831 5003 5004 7835 7955 +6 7834 5004 5005 7836 7955 7956 +6 7835 5005 7837 7956 7957 7958 +6 7836 5005 4750 4751 7838 7958 +6 7837 4751 4757 7839 7958 7959 +6 7838 4757 7840 7959 7960 7846 +6 7839 4757 4758 7841 7846 7961 +6 7840 4758 4661 4662 7842 7961 +6 7841 4662 4663 4689 7843 7961 +6 7842 4689 4690 7844 7961 7845 +6 7843 4690 4691 5158 5159 7845 +5 7844 5159 7846 7961 7843 +7 7845 5159 7847 7960 7839 7840 7961 +6 7846 5159 5160 7848 8082 7960 +6 7847 5160 5161 7849 8082 8083 +6 7848 5161 5162 7850 8083 8084 +6 7849 5162 7851 8084 8085 8086 +6 7850 5162 5163 5164 7852 8086 +6 7851 5164 7853 8086 8087 8088 +6 7852 5164 5165 7854 8088 8089 +7 7853 5165 4700 4701 4702 7855 8089 +5 7854 4702 7308 7856 8089 +7 7855 7308 7309 7857 8089 8090 8091 +7 7856 7309 7310 7858 8091 8092 8093 +6 7857 7310 7311 7859 8093 8094 +6 7858 7311 7312 7313 7860 8094 +6 7859 7313 7861 8094 8095 8096 +6 7860 7313 7314 7862 8096 8097 +6 7861 7314 7315 7863 8097 8098 +6 7862 7315 7316 7864 8098 8099 +6 7863 7316 7317 7865 8099 8100 +6 7864 7317 7318 7866 8100 8101 +6 7865 7318 7319 7867 8101 8102 +6 7866 7319 7320 7321 7868 8102 +6 7867 7321 7869 8102 8103 8104 +6 7868 7321 7322 7870 8104 8105 +6 7869 7322 7323 7324 7871 8105 +6 7870 7324 7872 8105 8106 8107 +6 7871 7324 7325 7873 8107 8108 +6 7872 7325 7326 7327 7874 8108 +6 7873 7327 7875 8108 8109 8110 +6 7874 7327 7328 7329 7876 8110 +6 7875 7329 7877 8110 8111 8112 +6 7876 7329 7330 7331 7878 8112 +6 7877 7331 7332 7879 8112 8113 +6 7878 7332 7880 8113 8114 8115 +6 7879 7332 7333 7334 7881 8115 +6 7880 7334 7335 7336 7882 8115 +6 7881 7336 7337 7883 8115 8116 +7 7882 7337 7338 7884 8116 8117 8118 +6 7883 7338 7339 7885 8118 8119 +6 7884 7339 7340 7886 8119 8120 +6 7885 7340 7341 7887 8120 8121 +6 7886 7341 7888 8121 8122 8123 +6 7887 7341 7342 7343 7889 8123 +6 7888 7343 7344 7890 8123 8124 +6 7889 7344 7345 7891 8124 8125 +6 7890 7345 7346 7892 8125 8126 +6 7891 7346 7347 7893 8126 8127 +6 7892 7347 7348 7894 8127 8128 +6 7893 7348 7895 8128 8129 8130 +6 7894 7348 7349 7350 7896 8130 +6 7895 7350 7351 7897 8130 8131 +7 7896 7351 7352 7353 7898 8131 8132 +5 7897 7353 7899 8132 8133 +7 7898 7353 7354 7355 7900 8133 8134 +6 7899 7355 7901 8134 8135 8136 +5 7900 7355 7356 7902 8136 +7 7901 7356 7903 8136 8137 8138 7904 +5 7902 7356 7357 7358 7904 +6 7903 7358 7905 8138 7902 8139 +6 7904 7358 7359 7361 7906 8139 +6 7905 7361 7907 8139 8140 8141 +6 7906 7361 7362 7363 7908 8141 +6 7907 7363 7909 8141 8142 8143 +6 7908 7363 7364 7365 7910 8143 +6 7909 7365 7371 7911 8143 8144 +6 7910 7371 7912 8144 8145 8146 +5 7911 7371 7372 7913 8146 +7 7912 7372 7373 7914 8146 8147 8148 +6 7913 7373 7915 8148 8149 8150 +6 7914 7373 7374 7376 7916 8150 +6 7915 7376 7917 7918 7919 8150 +6 7916 7376 7377 7378 7601 7918 +6 7917 7601 7916 7919 7920 7603 +6 7916 7918 7920 7921 7922 8150 +6 7919 7918 7921 7925 7926 7603 +6 7919 7920 7922 7923 7924 7925 +6 7919 7921 7923 8150 8151 8149 +6 7922 7921 7924 8151 8152 8153 +6 7923 7921 7925 8153 8154 8155 +6 7924 7921 7920 7926 8155 7928 +6 7925 7920 7603 7604 7927 7928 +6 7926 7604 7928 7929 7609 7605 +6 7926 7927 7929 8155 7925 8157 +6 7928 7927 7609 8157 7616 7610 +6 7809 7810 7931 8050 8345 7808 +6 7930 7810 7811 7932 7933 8050 +6 7931 7811 7933 7934 7935 7936 +6 7931 7932 7934 8050 8051 8052 +6 7933 7932 7935 8052 8053 8057 +6 7934 7932 7936 8059 8057 8060 +6 7935 7932 7811 7812 7937 8060 +6 7936 7812 7813 7938 8060 8061 +6 7937 7813 7814 7939 8061 8062 +6 7938 7814 7816 7817 7940 8062 +6 7939 7817 7818 7941 8062 8063 +6 7940 7818 7942 8063 8064 8065 +6 7941 7818 7819 7943 8065 8066 +6 7942 7819 7820 7821 7944 8066 +6 7943 7821 7945 8066 8067 8068 +6 7944 7821 7822 7946 8068 8069 +6 7945 7822 7823 7947 8069 8070 +6 7946 7823 7824 7948 8070 8071 +6 7947 7824 7826 7949 8071 8072 +6 7948 7826 7950 8072 8073 8074 +6 7949 7826 7827 7951 8074 8075 +6 7950 7827 7952 8075 8076 7953 +6 7951 7827 7828 7829 7832 7953 +6 7952 7832 7833 7954 8076 7951 +6 7953 7833 7955 8076 8077 8078 +6 7954 7833 7834 7835 7956 8078 +6 7955 7835 7836 7957 8078 8079 +6 7956 7836 7958 8079 8080 8081 +6 7957 7836 7837 7838 7959 8081 +6 7958 7838 7839 7960 8081 8082 +5 7959 7839 7846 8082 7847 +6 7846 7840 7841 7842 7843 7845 +6 7726 7727 7963 8466 8468 9764 +6 7962 7727 7964 8466 8487 8488 +6 7963 7727 7728 7246 7965 8488 +6 7964 7246 7247 7966 8488 8489 +6 7965 7247 7248 7967 8489 8490 +6 7966 7248 7249 7968 8490 8491 +6 7967 7249 7511 7513 7969 8491 +6 7968 7513 7970 8493 8491 8494 +6 7969 7513 7514 7971 8494 8495 +6 7970 7514 7972 8495 8496 7974 +6 7971 7514 7515 7518 7973 7974 +6 7972 7518 7974 7975 7976 7977 +6 7972 7973 7975 8496 7971 8497 +6 7974 7973 7976 8500 8497 7981 +6 7975 7973 7977 7979 7980 7981 +6 7976 7973 7518 7519 7978 7979 +6 7977 7519 7979 7988 7989 7521 +6 7977 7978 7976 7980 7987 7988 +6 7976 7979 7981 7982 7986 7987 +6 7976 7980 7982 7983 8500 7975 +6 7981 7980 7983 7984 7985 7986 +6 7981 7982 7984 8500 8501 8502 +6 7983 7982 7985 8502 8503 8504 +6 7984 7982 7986 8504 8505 8506 +6 7985 7982 7980 7987 8506 7993 +7 7986 7980 7979 7988 7991 7992 7993 +5 7987 7979 7978 7989 7991 +7 7988 7978 7521 7526 7990 7548 7991 +5 7989 7526 7527 7546 7548 +6 7989 7548 7549 7992 7987 7988 +6 7991 7549 7551 7987 7993 7994 +6 7987 7992 7994 8506 7986 8507 +6 7993 7992 7551 8507 7997 7995 +6 7551 7552 7558 7996 7997 7994 +6 7995 7558 7559 7997 7998 7999 +6 7995 7996 7998 8507 7994 8508 +6 7997 7996 7999 8508 8509 8510 +6 7998 7996 7559 7566 8000 8510 +6 7999 7566 7567 7570 8001 8510 +7 8000 7570 7571 8002 8510 8522 8511 +6 8001 7571 7572 8003 8522 8523 +7 8002 7572 7574 7577 8004 8520 8523 +7 8003 7577 8005 8519 8517 8520 8541 +5 8004 7577 7578 8006 8541 +6 8005 7578 8007 8610 8540 8541 +6 8006 7578 7579 7580 8008 8610 +6 8007 7580 7581 8009 8010 8610 +6 8008 7581 8010 8011 8012 7582 +8 8008 8009 8011 8609 8537 8538 8540 8610 +5 8010 8009 8012 8013 8609 +6 8011 8009 8013 7587 7582 7585 +7 8011 8012 7587 7729 8014 8608 8609 +6 8013 7729 7730 8015 8607 8608 +6 8014 7730 7734 8016 8611 8607 +6 8015 7734 7735 8017 8611 8612 +6 8016 7735 8018 8612 8613 8614 +6 8017 7735 7736 8019 8614 8615 +6 8018 7736 8020 8615 8618 8619 +6 8019 7736 7737 8021 8022 8619 +6 8020 7737 8022 8023 9766 7738 +6 8020 8021 8023 8024 8619 8620 +6 8022 8021 8024 8025 7742 9766 +6 8022 8023 8025 8620 8621 8028 +6 8024 8023 7742 7743 8026 8028 +6 8025 7743 8027 8028 8029 8030 +6 8026 7743 7744 7748 8030 8031 +6 8025 8026 8029 8621 8024 8622 +6 8028 8026 8030 8628 8622 8629 +6 8029 8026 8027 8031 8033 8629 +6 8030 8027 7748 8032 8033 8034 +6 8031 7748 7749 8034 8035 8036 +6 8030 8031 8034 8629 8630 8631 +6 8033 8031 8032 8035 8631 8632 +6 8034 8032 8036 7761 8635 8632 +6 8035 8032 7749 7759 7760 7761 +6 7784 7785 8038 8332 8333 8334 +6 8037 7785 7787 8039 8041 8334 +6 8038 7787 8040 8041 8042 8043 +6 8039 7787 8043 8044 8045 7788 +6 8038 8039 8042 8334 8335 8336 +6 8041 8039 8043 8336 8337 8341 +6 8042 8039 8040 8044 8341 8342 +6 8043 8040 8045 8342 8343 8046 +6 8044 8040 7788 7794 7795 8046 +6 8045 7795 8047 7806 8343 8044 +6 8046 7795 7806 7803 8048 7796 +6 7803 8047 7796 7802 7801 8049 +6 7801 8048 7796 7797 7799 7800 +6 7930 7931 7933 8051 8345 8346 +6 8050 7933 8052 8346 8347 8348 +6 8051 7933 7934 8053 8054 8348 +6 8052 7934 8054 8055 8056 8057 +6 8052 8053 8055 8348 8349 8350 +6 8054 8053 8056 8350 8351 8352 +6 8055 8053 8057 8058 8352 8353 +6 8056 8053 8058 8059 7935 7934 +6 8056 8057 8059 8353 8354 8355 +6 8058 8057 7935 8060 8355 8356 +6 8059 7935 7936 7937 8061 8356 +6 8060 7937 7938 8062 8356 8358 +6 8061 7938 7939 7940 8063 8358 +6 8062 7940 7941 8064 8359 8358 +6 8063 7941 8065 8359 8360 8361 +6 8064 7941 7942 8066 8361 8362 +6 8065 7942 7943 7944 8067 8362 +6 8066 7944 8068 8362 8363 8364 +6 8067 7944 7945 8069 8364 8365 +6 8068 7945 7946 8070 8365 8366 +6 8069 7946 7947 8071 8366 8367 +6 8070 7947 7948 8072 8367 8368 +6 8071 7948 7949 8073 8368 8369 +6 8072 7949 8074 8369 8370 8371 +6 8073 7949 7950 8075 8371 8372 +6 8074 7950 7951 8076 8372 8373 +6 8075 7951 7953 7954 8077 8373 +6 8076 7954 8078 8375 8373 8376 +6 8077 7954 7955 7956 8079 8376 +6 8078 7956 7957 8080 8376 8377 +6 8079 7957 8081 8209 8377 8378 +6 8080 7957 7958 7959 8082 8209 +7 8081 7959 7960 7847 7848 8083 8209 +6 8082 7848 7849 8084 8209 8210 +6 8083 7849 7850 8085 8210 8211 +6 8084 7850 8086 8211 8212 8213 +6 8085 7850 7851 7852 8087 8213 +6 8086 7852 8088 8213 8214 8215 +6 8087 7852 7853 8089 8215 8090 +6 8088 7853 7854 7855 7856 8090 +5 8089 7856 8091 8215 8088 +7 8090 7856 7857 8092 8215 8216 8217 +5 8091 7857 8093 8217 8218 +6 8092 7857 7858 8094 8218 8219 +6 8093 7858 7859 7860 8095 8219 +6 8094 7860 8096 8219 8220 8221 +6 8095 7860 7861 8097 8221 8222 +6 8096 7861 7862 8098 8222 8223 +6 8097 7862 7863 8099 8223 8224 +6 8098 7863 7864 8100 8224 8225 +6 8099 7864 7865 8101 8225 8226 +6 8100 7865 7866 8102 8226 8227 +6 8101 7866 7867 7868 8103 8227 +6 8102 7868 8104 8227 8228 8229 +6 8103 7868 7869 8105 8229 8230 +6 8104 7869 7870 7871 8106 8230 +6 8105 7871 8107 8230 8231 8232 +6 8106 7871 7872 8108 8232 8233 +6 8107 7872 7873 7874 8109 8233 +6 8108 7874 8110 8233 8234 8235 +6 8109 7874 7875 7876 8111 8235 +6 8110 7876 8112 8235 8236 8237 +6 8111 7876 7877 7878 8113 8237 +6 8112 7878 7879 8114 8237 8238 +6 8113 7879 8115 8238 8239 8116 +6 8114 7879 7880 7881 7882 8116 +6 8115 7882 7883 8117 8239 8114 +6 8116 7883 8118 8239 8240 8241 +5 8117 7883 7884 8119 8241 +6 8118 7884 7885 8120 8241 8242 +6 8119 7885 7886 8121 8242 8243 +6 8120 7886 7887 8122 8243 8244 +6 8121 7887 8123 8244 8245 8246 +6 8122 7887 7888 7889 8124 8246 +6 8123 7889 7890 8125 8246 8247 +6 8124 7890 7891 8126 8247 8248 +6 8125 7891 7892 8127 8248 8249 +6 8126 7892 7893 8128 8249 8250 +6 8127 7893 7894 8129 8250 8251 +6 8128 7894 8130 8251 8252 8253 +6 8129 7894 7895 7896 8131 8253 +6 8130 7896 7897 8132 8253 8254 +5 8131 7897 7898 8133 8254 +7 8132 7898 7899 8134 8254 8255 8256 +5 8133 7899 7900 8135 8256 +7 8134 7900 8136 8256 8257 8258 8259 +6 8135 7900 7901 7902 8137 8259 +6 8136 7902 8138 8259 8260 8261 +6 8137 7902 7904 8139 8261 8262 +6 8138 7904 7905 7906 8140 8262 +6 8139 7906 8141 8262 8263 8264 +6 8140 7906 7907 7908 8142 8264 +6 8141 7908 8143 8264 8265 8266 +6 8142 7908 7909 7910 8144 8266 +6 8143 7910 7911 8145 8266 8267 +6 8144 7911 8146 8267 8268 8269 +6 8145 7911 7912 7913 8147 8269 +6 8146 7913 8148 8269 8270 8271 +6 8147 7913 7914 8149 8151 8271 +5 8148 7914 8150 8151 7922 +6 8149 7914 7915 7916 7919 7922 +7 8148 8149 7922 7923 8152 8271 8272 +5 8151 7923 8153 8272 8273 +7 8152 7923 7924 8154 8273 8274 8275 +6 8153 7924 8155 8156 8275 8276 +7 8154 7924 8156 7925 7928 8157 7617 +6 8154 8155 7617 7618 8158 8276 +5 8155 7928 7929 7616 7617 +6 8156 7618 8159 8276 8277 8278 +6 8158 7618 7619 8160 8278 8279 +7 8159 7619 7620 8161 8279 8280 8281 +5 8160 7620 8162 8281 8282 +7 8161 7620 7621 8163 8282 8283 8164 +6 8162 7621 7622 7623 7624 8164 +7 8163 7624 7625 7627 8165 8283 8162 +6 8164 7627 7628 7630 8166 8283 +6 8165 7630 8167 8168 8283 8282 +6 8166 7630 8168 8169 8170 7631 +6 8166 8167 8169 8282 8284 8285 +6 8168 8167 8170 8285 8286 8287 +6 8169 8167 7631 8171 8172 8287 +6 8170 7631 8172 8173 7633 7632 +6 8170 8171 8173 8287 8288 8289 +6 8172 8171 7633 8174 8289 8290 +6 8173 7633 7634 7636 8175 8290 +6 8174 7636 7638 8176 8290 8291 +6 8175 7638 8177 8291 8292 8293 +6 8176 7638 7639 8178 8293 8294 +6 8177 7639 8179 8294 8295 8296 +6 8178 7639 7640 8180 8296 8297 +6 8179 7640 8181 8307 8297 8308 +6 8180 7640 7641 8182 8183 8308 +6 8181 7641 8183 7644 7643 7642 +6 8181 8182 7644 8184 8308 8309 +6 8183 7644 7645 8185 8309 8310 +7 8184 7645 7646 7647 8186 8310 8311 +6 8185 7647 7648 8187 8311 8312 +6 8186 7648 8188 8312 8313 8314 +6 8187 7648 7649 8189 8314 8315 +6 8188 7649 7650 8190 8315 8200 +6 8189 7650 8191 8197 8199 8200 +6 8190 7650 7651 8192 8197 8193 +6 8191 7651 7652 7657 7658 8193 +6 8192 7658 8194 8196 8197 8191 +6 8193 7658 7659 7662 8195 8196 +6 8194 7662 8196 8208 8204 7663 +6 8194 8195 8193 8197 8198 8204 +6 8193 8196 8198 8199 8190 8191 +6 8197 8196 8199 8202 8203 8204 +6 8197 8198 8190 8200 8201 8202 +6 8190 8199 8201 8315 8189 8316 +6 8200 8199 8202 8316 8317 8318 +6 8201 8199 8198 8203 8205 8318 +6 8202 8198 8204 8205 7699 8206 +7 8203 8198 8206 8207 8208 8195 8196 +5 8202 8203 7699 8318 7700 +7 7699 8203 8204 7698 7669 7667 8207 +6 7667 8206 8204 8208 7664 7665 +5 8207 8204 8195 7663 7664 +6 8080 8081 8082 8083 8210 8378 +5 8209 8083 8084 8211 8378 +6 8210 8084 8085 8212 8378 8379 +6 8211 8085 8213 8379 8380 8381 +6 8212 8085 8086 8087 8214 8381 +6 8213 8087 8215 8381 8382 8216 +6 8214 8087 8088 8090 8091 8216 +6 8215 8091 8217 8382 8214 8383 +6 8216 8091 8092 8218 8383 8384 +6 8217 8092 8093 8219 8384 8385 +6 8218 8093 8094 8095 8220 8385 +5 8219 8095 8221 8385 8386 +6 8220 8095 8096 8222 8386 8387 +6 8221 8096 8097 8223 8387 8388 +6 8222 8097 8098 8224 8388 8389 +6 8223 8098 8099 8225 8389 8390 +6 8224 8099 8100 8226 8390 8391 +6 8225 8100 8101 8227 8391 8392 +6 8226 8101 8102 8103 8228 8392 +6 8227 8103 8229 8392 8393 8394 +6 8228 8103 8104 8230 8394 8395 +6 8229 8104 8105 8106 8231 8395 +6 8230 8106 8232 8395 8396 8397 +6 8231 8106 8107 8233 8397 8398 +6 8232 8107 8108 8109 8234 8398 +6 8233 8109 8235 8398 8399 8400 +6 8234 8109 8110 8111 8236 8400 +6 8235 8111 8237 8400 8401 8402 +6 8236 8111 8112 8113 8238 8402 +6 8237 8113 8114 8239 8402 8403 +6 8238 8114 8116 8117 8240 8403 +6 8239 8117 8241 8403 8404 8405 +6 8240 8117 8118 8119 8242 8405 +6 8241 8119 8120 8243 8405 8406 +6 8242 8120 8121 8244 8406 8407 +6 8243 8121 8122 8245 8407 8408 +6 8244 8122 8246 8408 8409 8410 +6 8245 8122 8123 8124 8247 8410 +6 8246 8124 8125 8248 8410 8411 +6 8247 8125 8126 8249 8411 8412 +6 8248 8126 8127 8250 8412 8413 +6 8249 8127 8128 8251 8413 8414 +6 8250 8128 8129 8252 8414 8415 +6 8251 8129 8253 8415 8416 8417 +6 8252 8129 8130 8131 8254 8417 +7 8253 8131 8132 8133 8255 8417 8418 +5 8254 8133 8256 8418 8419 +7 8255 8133 8134 8135 8257 8419 8420 +5 8256 8135 8258 8420 8421 +6 8257 8135 8259 8421 8422 8260 +5 8258 8135 8136 8137 8260 +6 8259 8137 8261 8422 8258 8423 +6 8260 8137 8138 8262 8423 8424 +6 8261 8138 8139 8140 8263 8424 +6 8262 8140 8264 8424 8425 8426 +6 8263 8140 8141 8142 8265 8426 +6 8264 8142 8266 8426 8427 8428 +7 8265 8142 8143 8144 8267 8428 8429 +6 8266 8144 8145 8268 8429 8430 +6 8267 8145 8269 8430 8431 8432 +6 8268 8145 8146 8147 8270 8432 +6 8269 8147 8271 8432 8433 8434 +6 8270 8147 8148 8151 8272 8434 +5 8271 8151 8152 8273 8434 +7 8272 8152 8153 8274 8434 8435 8436 +6 8273 8153 8275 8436 8437 8438 +6 8274 8153 8154 8276 8438 8277 +5 8275 8154 8156 8158 8277 +6 8276 8158 8278 8438 8275 8439 +6 8277 8158 8159 8279 8439 8440 +7 8278 8159 8160 8280 8440 8441 8445 +6 8279 8160 8281 8445 8446 8284 +5 8280 8160 8161 8282 8284 +7 8281 8161 8162 8283 8166 8168 8284 +5 8282 8162 8164 8165 8166 +6 8282 8168 8285 8446 8280 8281 +6 8284 8168 8169 8286 8446 8447 +6 8285 8169 8287 8447 8449 8450 +6 8286 8169 8170 8172 8288 8450 +6 8287 8172 8289 8450 8451 8452 +6 8288 8172 8173 8290 8452 8453 +6 8289 8173 8174 8175 8291 8453 +6 8290 8175 8176 8292 8453 8454 +6 8291 8176 8293 8454 8455 8456 +6 8292 8176 8177 8294 8456 8457 +6 8293 8177 8178 8295 8457 8458 +6 8294 8178 8296 8461 8458 8299 +6 8295 8178 8179 8297 8298 8299 +6 8296 8179 8298 8307 8305 8180 +6 8296 8297 8299 8300 8301 8305 +6 8296 8298 8300 8461 8295 8462 +6 8299 8298 8301 8302 8462 8463 +6 8300 8298 8302 8303 8304 8305 +6 8300 8301 8303 8463 8464 8465 +6 8302 8301 8304 8465 8466 8467 +6 8303 8301 8305 8306 8470 8467 +6 8304 8301 8298 8306 8307 8297 +6 8304 8305 8307 8470 8471 8472 +6 8306 8305 8297 8180 8308 8472 +6 8307 8180 8181 8183 8309 8472 +6 8308 8183 8184 8310 8472 8473 +6 8309 8184 8185 8311 8473 8474 +5 8310 8185 8186 8312 8474 +6 8311 8186 8187 8313 8474 8475 +6 8312 8187 8314 8478 8475 8479 +6 8313 8187 8188 8315 8479 8480 +6 8314 8188 8189 8200 8316 8480 +5 8315 8200 8201 8317 8480 +6 8316 8201 8318 8480 8481 7708 +7 8317 8201 8202 8205 7700 7707 7708 +6 7765 7766 8320 8321 8853 8854 +6 8319 7766 7767 8321 8322 7769 +7 8319 8320 8322 8854 8855 8856 8323 +5 8321 8320 7769 7771 8323 +6 8322 7771 8324 8856 8321 8857 +6 8323 7771 7772 8325 8857 8328 +6 8324 7772 7777 8326 8327 8328 +6 8325 7777 7778 7779 7780 8327 +6 8326 7780 8325 8328 8329 7781 +6 8325 8327 8329 8857 8324 8858 +6 8328 8327 7781 7782 8330 8858 +6 8329 7782 7783 8331 8858 8859 +6 8330 7783 8332 8865 8862 8859 +6 8331 7783 7784 8037 8333 8865 +6 8332 8037 8334 8866 8865 8867 +6 8333 8037 8038 8041 8335 8867 +6 8334 8041 8336 8867 8868 8869 +6 8335 8041 8042 8337 8338 8869 +6 8336 8042 8338 8339 8340 8341 +6 8336 8337 8339 8869 8870 8874 +6 8338 8337 8340 8874 8875 8347 +6 8339 8337 8341 8347 8346 8876 +6 8340 8337 8042 8043 8342 8876 +6 8341 8043 8044 8343 8344 8876 +6 8342 8044 8344 7807 7806 8046 +6 8342 8343 7807 7808 8345 8876 +6 8344 7808 7930 8050 8346 8876 +6 8345 8050 8051 8347 8340 8876 +6 8346 8051 8348 8875 8339 8340 +6 8347 8051 8052 8054 8349 8875 +6 8348 8054 8350 8902 8875 8901 +6 8349 8054 8055 8351 8901 8903 +6 8350 8055 8352 8903 8904 8905 +6 8351 8055 8056 8353 8905 8906 +6 8352 8056 8058 8354 8906 8907 +6 8353 8058 8355 8907 8908 8909 +6 8354 8058 8059 8356 8357 8909 +6 8355 8059 8060 8061 8357 8358 +6 8355 8356 8358 8359 8909 8910 +6 8357 8356 8061 8062 8359 8063 +6 8357 8358 8063 8064 8360 8910 +6 8359 8064 8361 8912 8910 8913 +6 8360 8064 8065 8362 8913 8914 +6 8361 8065 8066 8067 8363 8914 +6 8362 8067 8364 8916 8914 8917 +6 8363 8067 8068 8365 8917 8918 +6 8364 8068 8069 8366 8918 8919 +6 8365 8069 8070 8367 8919 8920 +6 8366 8070 8071 8368 8920 8921 +6 8367 8071 8072 8369 8921 8922 +6 8368 8072 8073 8370 8922 8923 +6 8369 8073 8371 8923 8924 8925 +6 8370 8073 8074 8372 8925 8926 +6 8371 8074 8075 8373 8374 8926 +6 8372 8075 8076 8374 8375 8077 +6 8372 8373 8375 8926 8927 8928 +6 8374 8373 8077 8376 8928 8929 +6 8375 8077 8078 8079 8377 8929 +6 8376 8079 8080 8378 8929 8379 +6 8377 8080 8209 8210 8211 8379 +7 8378 8211 8212 8380 8929 8377 8930 +5 8379 8212 8381 8930 8931 +7 8380 8212 8213 8214 8382 8743 8931 +6 8381 8214 8216 8383 8641 8743 +6 8382 8216 8217 8384 8641 8642 +6 8383 8217 8218 8385 8642 8643 +6 8384 8218 8219 8220 8386 8643 +7 8385 8220 8221 8387 8643 8644 8645 +6 8386 8221 8222 8388 8645 8646 +6 8387 8222 8223 8389 8646 8647 +6 8388 8223 8224 8390 8647 8648 +7 8389 8224 8225 8391 8648 8649 8650 +6 8390 8225 8226 8392 8650 8651 +6 8391 8226 8227 8228 8393 8651 +6 8392 8228 8394 8651 8652 8653 +6 8393 8228 8229 8395 8653 8654 +6 8394 8229 8230 8231 8396 8654 +5 8395 8231 8397 8654 8655 +6 8396 8231 8232 8398 8655 8656 +7 8397 8232 8233 8234 8399 8656 8657 +5 8398 8234 8400 8657 8658 +7 8399 8234 8235 8236 8401 8658 8659 +5 8400 8236 8402 8659 8660 +6 8401 8236 8237 8238 8403 8660 +6 8402 8238 8239 8240 8404 8660 +6 8403 8240 8405 8660 8661 8662 +6 8404 8240 8241 8242 8406 8662 +6 8405 8242 8243 8407 8662 8663 +7 8406 8243 8244 8408 8663 8664 8665 +6 8407 8244 8245 8409 8665 8666 +6 8408 8245 8410 8666 8667 8668 +6 8409 8245 8246 8247 8411 8668 +6 8410 8247 8248 8412 8668 8669 +6 8411 8248 8249 8413 8669 8670 +6 8412 8249 8250 8414 8670 8671 +6 8413 8250 8251 8415 8671 8672 +6 8414 8251 8252 8416 8672 8673 +6 8415 8252 8417 8673 8674 8675 +6 8416 8252 8253 8254 8418 8675 +6 8417 8254 8255 8419 8675 8676 +6 8418 8255 8256 8420 8676 8677 +6 8419 8256 8257 8421 8677 8678 +6 8420 8257 8258 8422 8678 8679 +6 8421 8258 8260 8423 8679 8680 +7 8422 8260 8261 8424 8680 8681 8682 +6 8423 8261 8262 8263 8425 8682 +6 8424 8263 8426 8682 8683 8687 +6 8425 8263 8264 8265 8427 8687 +6 8426 8265 8428 8687 8688 8689 +6 8427 8265 8266 8429 8689 8690 +5 8428 8266 8267 8430 8690 +6 8429 8267 8268 8431 8542 8690 +6 8430 8268 8432 8542 8543 8544 +6 8431 8268 8269 8270 8433 8544 +6 8432 8270 8434 8544 8545 8546 +7 8433 8270 8271 8272 8273 8435 8546 +6 8434 8273 8436 8546 8547 8548 +6 8435 8273 8274 8437 8548 8549 +6 8436 8274 8438 8549 8550 8439 +5 8437 8274 8275 8277 8439 +7 8438 8277 8278 8440 8550 8437 8551 +6 8439 8278 8279 8441 8442 8551 +6 8440 8279 8442 8443 8444 8445 +6 8440 8441 8443 8551 8552 8553 +6 8442 8441 8444 8553 8554 8555 +7 8443 8441 8445 8446 8447 8448 8555 +5 8444 8441 8279 8280 8446 +6 8445 8280 8284 8285 8447 8444 +6 8446 8285 8286 8444 8448 8449 +5 8444 8447 8449 8555 8556 +6 8448 8447 8286 8450 8556 8557 +7 8449 8286 8287 8288 8451 8557 8558 +6 8450 8288 8452 8558 8559 8560 +6 8451 8288 8289 8453 8560 8561 +6 8452 8289 8290 8291 8454 8561 +6 8453 8291 8292 8455 8561 8562 +6 8454 8292 8456 8562 8563 8564 +6 8455 8292 8293 8457 8564 8565 +6 8456 8293 8294 8458 8459 8565 +6 8457 8294 8459 8460 8461 8295 +6 8457 8458 8460 8565 8566 8567 +6 8459 8458 8461 8567 8568 8569 +6 8460 8458 8295 8299 8462 8569 +6 8461 8299 8300 8463 8569 8570 +6 8462 8300 8302 8464 8570 8571 +6 8463 8302 8465 8571 8572 8573 +6 8464 8302 8303 8466 8573 8487 +7 8465 8303 8467 8468 7962 7963 8487 +6 8466 8303 8468 8469 8470 8304 +6 8466 8467 8469 7962 9763 9764 +7 8468 8467 8470 9094 8485 9763 8486 +6 8469 8467 8304 8306 8471 9094 +6 8470 8306 8472 8476 9094 8473 +6 8471 8306 8307 8308 8309 8473 +6 8472 8309 8310 8474 8476 8471 +6 8473 8310 8311 8312 8475 8476 +6 8474 8312 8476 8477 8478 8313 +7 8474 8475 8477 8485 9094 8471 8473 +6 8476 8475 8478 8483 8484 8485 +6 8477 8475 8313 8479 8483 8482 +6 8478 8313 8314 8480 8482 8481 +6 8479 8314 8315 8316 8317 8481 +6 8480 8317 7708 7709 8482 8479 +7 8481 7709 7710 7713 8483 8478 8479 +5 8482 7713 8484 8477 8478 +6 8483 7713 7714 8477 8485 8486 +6 8477 8484 8486 8469 9094 8476 +6 8485 8484 9765 9763 8469 7714 +5 8466 7963 8488 8573 8465 +7 8487 7963 7964 7965 8489 8573 8574 +5 8488 7965 7966 8490 8574 +7 8489 7966 7967 8491 8492 8574 8575 +6 8490 7967 8492 8493 7969 7968 +5 8490 8491 8493 8575 8576 +6 8492 8491 7969 8494 8576 8577 +6 8493 7969 7970 8495 8577 8578 +6 8494 7970 7971 8496 8578 8579 +6 8495 7971 7974 8497 8498 8579 +6 8496 7974 8498 8499 8500 7975 +6 8496 8497 8499 8579 8580 8581 +6 8498 8497 8500 8581 8582 8501 +6 8499 8497 7975 7981 7983 8501 +6 8500 7983 8502 8582 8499 8583 +6 8501 7983 7984 8503 8586 8583 +6 8502 7984 8504 8527 8586 8526 +6 8503 7984 7985 8505 8526 8588 +6 8504 7985 8506 8588 8513 8589 +6 8505 7985 7986 7993 8507 8589 +6 8506 7993 7994 7997 8508 8589 +6 8507 7997 7998 8509 8513 8589 +6 8508 7998 8510 8511 8512 8513 +6 8509 7998 7999 8000 8001 8511 +6 8509 8510 8512 8521 8522 8001 +6 8509 8511 8513 8514 8515 8521 +7 8509 8512 8514 8588 8505 8589 8508 +6 8513 8512 8515 8516 8526 8588 +6 8514 8512 8516 8517 8520 8521 +6 8514 8515 8517 8518 8524 8526 +6 8516 8515 8518 8519 8004 8520 +6 8516 8517 8519 8524 8525 8531 +6 8518 8517 8004 8541 8539 8531 +6 8004 8517 8003 8515 8521 8523 +6 8520 8515 8512 8511 8522 8523 +5 8521 8511 8001 8002 8523 +5 8522 8002 8521 8520 8003 +6 8516 8518 8525 8526 8527 8528 +6 8524 8518 8528 8529 8530 8531 +7 8516 8524 8527 8503 8504 8588 8514 +5 8526 8524 8528 8586 8503 +6 8527 8524 8525 8529 8587 8586 +6 8528 8525 8530 8602 8587 8603 +6 8529 8525 8531 8532 8533 8603 +6 8530 8525 8532 8519 8539 8518 +6 8530 8531 8533 8534 8538 8539 +6 8530 8532 8534 8535 8603 8604 +6 8533 8532 8535 8536 8537 8538 +6 8533 8534 8536 8604 8605 8606 +6 8535 8534 8537 8606 8607 8608 +6 8536 8534 8538 8608 8609 8010 +6 8537 8534 8532 8539 8540 8010 +6 8538 8532 8540 8541 8519 8531 +6 8538 8539 8541 8010 8610 8006 +6 8540 8539 8519 8006 8005 8004 +6 8430 8431 8543 8690 8691 8692 +6 8542 8431 8544 8692 8693 8694 +6 8543 8431 8432 8433 8545 8694 +6 8544 8433 8546 8694 8695 8547 +5 8545 8433 8434 8435 8547 +6 8546 8435 8548 8695 8545 8696 +6 8547 8435 8436 8549 8696 8697 +6 8548 8436 8437 8550 8697 8698 +6 8549 8437 8439 8551 8698 8552 +5 8550 8439 8440 8442 8552 +7 8551 8442 8553 8698 8550 8699 8700 +6 8552 8442 8443 8554 8700 8701 +6 8553 8443 8555 8701 8702 8703 +6 8554 8443 8444 8448 8556 8703 +6 8555 8448 8449 8557 8703 8704 +6 8556 8449 8450 8558 8704 8705 +6 8557 8450 8451 8559 8705 8706 +6 8558 8451 8560 8706 8707 8708 +5 8559 8451 8452 8561 8708 +6 8560 8452 8453 8454 8562 8708 +6 8561 8454 8455 8563 8708 8709 +6 8562 8455 8564 8709 8710 8711 +6 8563 8455 8456 8565 8711 8712 +7 8564 8456 8457 8459 8566 8712 8713 +5 8565 8459 8567 8713 8714 +6 8566 8459 8460 8568 8714 8715 +6 8567 8460 8569 8715 8716 8717 +6 8568 8460 8461 8462 8570 8717 +7 8569 8462 8463 8571 8590 8592 8717 +5 8570 8463 8464 8572 8590 +7 8571 8464 8573 8574 8575 8576 8590 +6 8572 8464 8465 8487 8488 8574 +6 8573 8488 8489 8490 8575 8572 +5 8574 8490 8492 8576 8572 +7 8575 8492 8493 8577 8572 8590 8591 +6 8576 8493 8494 8578 8594 8591 +6 8577 8494 8495 8579 8594 8595 +6 8578 8495 8496 8498 8580 8595 +6 8579 8498 8581 8595 8596 8597 +6 8580 8498 8499 8582 8597 8598 +6 8581 8499 8501 8583 8584 8598 +6 8582 8501 8584 8585 8586 8502 +6 8582 8583 8585 8598 8599 8600 +6 8584 8583 8586 8587 8600 8601 +7 8585 8583 8587 8528 8527 8503 8502 +6 8585 8586 8528 8601 8602 8529 +5 8526 8504 8505 8513 8514 +5 8513 8505 8506 8508 8507 +6 8572 8576 8591 8571 8570 8592 +6 8590 8576 8592 8593 8594 8577 +5 8570 8590 8591 8593 8717 +7 8592 8591 8594 8717 8716 8718 8719 +6 8593 8591 8577 8578 8595 8719 +7 8594 8578 8579 8580 8596 8719 8720 +6 8595 8580 8597 8720 8721 8722 +6 8596 8580 8581 8598 8722 8723 +6 8597 8581 8582 8584 8599 8723 +6 8598 8584 8600 8723 8724 8725 +6 8599 8584 8585 8601 8725 8726 +6 8600 8585 8587 8602 8726 8727 +5 8601 8587 8529 8603 8727 +6 8602 8529 8530 8533 8604 8727 +6 8603 8533 8535 8605 8727 8728 +6 8604 8535 8606 8728 8731 8732 +6 8605 8535 8536 8607 8611 8732 +6 8606 8536 8608 8611 8015 8014 +6 8607 8536 8537 8609 8014 8013 +5 8608 8537 8010 8013 8011 +5 8010 8540 8008 8007 8006 +6 8606 8607 8015 8016 8612 8732 +6 8611 8016 8017 8613 8732 8733 +6 8612 8017 8614 8733 8734 8735 +6 8613 8017 8018 8615 8616 8735 +6 8614 8018 8019 8616 8617 8618 +6 8614 8615 8617 8735 8736 8737 +6 8616 8615 8618 8737 8738 8739 +6 8617 8615 8019 8619 8739 8742 +6 8618 8019 8020 8022 8620 8742 +6 8619 8022 8024 8621 8624 8742 +6 8620 8024 8028 8622 8623 8624 +6 8621 8028 8623 8627 8628 8029 +6 8621 8622 8624 8625 8626 8627 +6 8621 8623 8625 8741 8742 8620 +6 8624 8623 8626 8837 8741 8838 +6 8625 8623 8627 8838 8839 8840 +6 8626 8623 8622 8628 8840 8841 +6 8627 8622 8029 8629 8841 8842 +6 8628 8029 8030 8033 8630 8842 +6 8629 8033 8631 8842 8843 8844 +6 8630 8033 8034 8632 8633 8844 +6 8631 8034 8633 8634 8635 8035 +6 8631 8632 8634 8844 8845 8846 +6 8633 8632 8635 8636 8637 8846 +6 8634 8632 8636 8640 7761 8035 +6 8634 8635 8637 8638 8639 8640 +6 8634 8636 8638 8846 8848 8849 +6 8637 8636 8639 8849 8850 8851 +6 8638 8636 8640 8851 8852 7762 +5 8639 8636 8635 7761 7762 +6 8382 8383 8642 8743 8744 8745 +6 8641 8383 8384 8643 8745 8746 +6 8642 8384 8385 8386 8644 8746 +6 8643 8386 8645 8746 8747 8748 +6 8644 8386 8387 8646 8748 8749 +6 8645 8387 8388 8647 8749 8750 +6 8646 8388 8389 8648 8750 8751 +6 8647 8389 8390 8649 8751 8752 +6 8648 8390 8650 8752 8753 8754 +5 8649 8390 8391 8651 8754 +6 8650 8391 8392 8393 8652 8754 +6 8651 8393 8653 8754 8755 8756 +6 8652 8393 8394 8654 8756 8757 +6 8653 8394 8395 8396 8655 8757 +6 8654 8396 8397 8656 8757 8758 +7 8655 8397 8398 8657 8758 8759 8760 +5 8656 8398 8399 8658 8760 +7 8657 8399 8400 8659 8760 8761 8762 +5 8658 8400 8401 8660 8762 +8 8659 8401 8402 8403 8404 8661 8762 8763 +5 8660 8404 8662 8763 8764 +6 8661 8404 8405 8406 8663 8764 +6 8662 8406 8407 8664 8764 8765 +6 8663 8407 8665 8765 8766 8767 +5 8664 8407 8408 8666 8767 +6 8665 8408 8409 8667 8767 8768 +6 8666 8409 8668 8768 8769 8770 +6 8667 8409 8410 8411 8669 8770 +6 8668 8411 8412 8670 8770 8771 +6 8669 8412 8413 8671 8771 8772 +6 8670 8413 8414 8672 8772 8773 +6 8671 8414 8415 8673 8773 8774 +6 8672 8415 8416 8674 8774 8775 +6 8673 8416 8675 8775 8776 8777 +6 8674 8416 8417 8418 8676 8777 +6 8675 8418 8419 8677 8777 8778 +6 8676 8419 8420 8678 8778 8779 +6 8677 8420 8421 8679 8779 8780 +6 8678 8421 8422 8680 8780 8781 +6 8679 8422 8423 8681 8781 8782 +6 8680 8423 8682 8782 8783 8684 +6 8681 8423 8424 8425 8683 8684 +6 8682 8425 8684 8685 8686 8687 +5 8682 8683 8685 8783 8681 +6 8684 8683 8686 8783 8784 8785 +6 8685 8683 8687 8785 8786 8787 +7 8686 8683 8425 8426 8427 8688 8787 +5 8687 8427 8689 8787 8788 +6 8688 8427 8428 8690 8788 8789 +7 8689 8428 8429 8430 8542 8691 8789 +6 8690 8542 8692 8789 8790 8791 +5 8691 8542 8543 8693 8791 +7 8692 8543 8694 8791 8792 8793 8794 +6 8693 8543 8544 8545 8695 8794 +6 8694 8545 8547 8696 8794 8795 +7 8695 8547 8548 8697 8795 8796 8797 +6 8696 8548 8549 8698 8797 8798 +6 8697 8549 8550 8552 8699 8798 +6 8698 8552 8700 8798 8799 8800 +6 8699 8552 8553 8701 8800 8803 +6 8700 8553 8554 8702 8803 8804 +6 8701 8554 8703 8804 8805 8806 +6 8702 8554 8555 8556 8704 8806 +6 8703 8556 8557 8705 8806 8807 +6 8704 8557 8558 8706 8807 8808 +6 8705 8558 8559 8707 8808 8809 +6 8706 8559 8708 8809 8810 8811 +7 8707 8559 8560 8561 8562 8709 8811 +5 8708 8562 8563 8710 8811 +7 8709 8563 8711 8811 8812 8813 8814 +6 8710 8563 8564 8712 8814 8815 +6 8711 8564 8565 8713 8815 8816 +5 8712 8565 8566 8714 8816 +7 8713 8566 8567 8715 8816 8817 8818 +6 8714 8567 8568 8716 8818 8819 +6 8715 8568 8717 8593 8718 8819 +6 8716 8568 8569 8570 8592 8593 +6 8716 8593 8719 8819 8820 8720 +5 8718 8593 8594 8595 8720 +6 8719 8595 8596 8721 8820 8718 +6 8720 8596 8722 8820 8821 8822 +5 8721 8596 8597 8723 8822 +6 8722 8597 8598 8599 8724 8822 +6 8723 8599 8725 8822 8823 8824 +6 8724 8599 8600 8726 8824 8825 +6 8725 8600 8601 8727 8825 8729 +7 8726 8601 8602 8603 8604 8728 8729 +6 8727 8604 8605 8729 8730 8731 +5 8727 8728 8730 8825 8726 +6 8729 8728 8731 8825 8827 8828 +6 8730 8728 8605 8732 8828 8829 +7 8731 8605 8606 8611 8612 8733 8829 +6 8732 8612 8613 8734 8830 8829 +6 8733 8613 8735 8830 8831 8736 +5 8734 8613 8614 8616 8736 +6 8735 8616 8737 8831 8734 8832 +6 8736 8616 8617 8738 8832 8833 +6 8737 8617 8739 8740 8833 8834 +6 8738 8617 8618 8740 8741 8742 +6 8738 8739 8741 8834 8835 8836 +7 8740 8739 8742 8624 8836 8837 8625 +6 8741 8739 8624 8620 8619 8618 +6 8381 8382 8641 8744 8931 8932 +5 8743 8641 8745 8932 8933 +6 8744 8641 8642 8746 8933 8934 +6 8745 8642 8643 8644 8747 8934 +6 8746 8644 8748 8934 8935 8936 +6 8747 8644 8645 8749 8936 8937 +6 8748 8645 8646 8750 8937 8938 +6 8749 8646 8647 8751 8938 8939 +6 8750 8647 8648 8752 8939 8940 +6 8751 8648 8649 8753 8940 8941 +6 8752 8649 8754 8941 8942 8943 +7 8753 8649 8650 8651 8652 8755 8943 +5 8754 8652 8756 8943 8944 +6 8755 8652 8653 8757 8944 8945 +6 8756 8653 8654 8655 8758 8945 +7 8757 8655 8656 8759 8945 8946 8947 +5 8758 8656 8760 8947 8948 +6 8759 8656 8657 8658 8761 8948 +6 8760 8658 8762 8948 8949 8950 +6 8761 8658 8659 8660 8763 8950 +5 8762 8660 8661 8764 8950 +7 8763 8661 8662 8663 8765 8950 8951 +6 8764 8663 8664 8766 8951 8952 +6 8765 8664 8767 8952 8953 8954 +6 8766 8664 8665 8666 8768 8954 +6 8767 8666 8667 8769 8954 8955 +6 8768 8667 8770 8955 8956 8957 +6 8769 8667 8668 8669 8771 8957 +6 8770 8669 8670 8772 8957 8958 +6 8771 8670 8671 8773 8958 8959 +6 8772 8671 8672 8774 8959 8960 +6 8773 8672 8673 8775 8960 8961 +6 8774 8673 8674 8776 8961 8962 +6 8775 8674 8777 8962 8963 8964 +6 8776 8674 8675 8676 8778 8964 +6 8777 8676 8677 8779 8964 8965 +6 8778 8677 8678 8780 8965 8966 +6 8779 8678 8679 8781 8966 8967 +6 8780 8679 8680 8782 8967 8968 +6 8781 8680 8681 8783 8968 8969 +6 8782 8681 8684 8685 8784 8969 +6 8783 8685 8785 8969 8970 8971 +6 8784 8685 8686 8786 8971 8972 +6 8785 8686 8787 8972 8973 8974 +6 8786 8686 8687 8688 8788 8974 +6 8787 8688 8689 8789 8974 8975 +6 8788 8689 8690 8691 8790 8975 +6 8789 8691 8791 8975 8976 8977 +6 8790 8691 8692 8693 8792 8977 +6 8791 8693 8793 8977 8978 8979 +6 8792 8693 8794 8979 8980 8795 +5 8793 8693 8694 8695 8795 +6 8794 8695 8696 8796 8980 8793 +6 8795 8696 8797 8980 8981 8982 +6 8796 8696 8697 8798 8982 8799 +5 8797 8697 8698 8699 8799 +6 8798 8699 8800 8801 8982 8797 +6 8799 8699 8700 8801 8802 8803 +6 8799 8800 8802 8982 8983 8984 +6 8801 8800 8803 8984 8985 8986 +6 8802 8800 8700 8701 8804 8986 +6 8803 8701 8702 8805 8986 8987 +6 8804 8702 8806 8987 8988 8989 +6 8805 8702 8703 8704 8807 8989 +6 8806 8704 8705 8808 8989 8990 +7 8807 8705 8706 8809 8992 8990 8993 +5 8808 8706 8707 8810 8993 +6 8809 8707 8811 8993 8994 8812 +6 8810 8707 8708 8709 8710 8812 +6 8811 8710 8813 8994 8810 8995 +6 8812 8710 8814 8995 8996 8997 +6 8813 8710 8711 8815 8997 8998 +5 8814 8711 8712 8816 8998 +7 8815 8712 8713 8714 8817 8998 8999 +6 8816 8714 8818 8999 9000 9001 +6 8817 8714 8715 8819 9001 9002 +6 8818 8715 8716 8718 8820 9002 +6 8819 8718 8720 8721 8821 9002 +6 8820 8721 8822 9002 9003 8823 +6 8821 8721 8722 8723 8724 8823 +6 8822 8724 8824 9003 8821 9004 +6 8823 8724 8725 8825 8826 9004 +7 8824 8725 8726 8729 8730 8826 8827 +6 8824 8825 8827 9004 9005 9006 +6 8826 8825 8730 8828 9012 9006 +6 8827 8730 8731 8829 8830 9012 +5 8828 8731 8830 8733 8732 +7 8828 8829 8733 8734 8831 9011 9012 +6 8830 8734 8736 8832 9013 9011 +7 8831 8736 8737 8833 9013 9014 9015 +6 8832 8737 8738 8834 9015 9016 +6 8833 8738 8740 8835 9016 9017 +6 8834 8740 8836 9017 9018 9019 +6 8835 8740 8741 8837 9019 9020 +5 8836 8741 8625 8838 9020 +6 8837 8625 8626 8839 9020 9021 +6 8838 8626 8840 9021 9022 9023 +6 8839 8626 8627 8841 9023 9024 +6 8840 8627 8628 8842 9024 9025 +6 8841 8628 8629 8630 8843 9025 +6 8842 8630 8844 9025 9026 9030 +6 8843 8630 8631 8633 8845 9030 +6 8844 8633 8846 8847 9031 9030 +6 8845 8633 8634 8637 8847 8848 +6 8845 8846 8848 9031 9032 9033 +6 8847 8846 8637 8849 9042 9033 +6 8848 8637 8638 8850 9043 9042 +6 8849 8638 8851 9043 9044 9045 +6 8850 8638 8639 8852 9045 9048 +6 8851 8639 7762 7763 8853 9048 +6 8852 7763 7765 8319 8854 9048 +6 8853 8319 8321 8855 9047 9048 +6 8854 8321 8856 9047 9049 9050 +5 8855 8321 8323 8857 9050 +7 8856 8323 8324 8328 8858 9050 8860 +6 8857 8328 8329 8330 8859 8860 +6 8858 8330 8860 8861 8862 8331 +6 8858 8859 8861 9050 8857 9051 +6 8860 8859 8862 8863 9051 9052 +6 8861 8859 8863 8864 8865 8331 +6 8861 8862 8864 8877 9058 9052 +6 8863 8862 8865 8866 8877 8878 +6 8864 8862 8866 8333 8332 8331 +6 8864 8865 8333 8867 8878 8879 +6 8866 8333 8334 8335 8868 8879 +6 8867 8335 8869 8879 8880 8871 +6 8868 8335 8336 8338 8870 8871 +6 8869 8338 8871 8872 8873 8874 +6 8869 8870 8872 8894 8880 8868 +6 8871 8870 8873 8896 8894 8897 +6 8872 8870 8874 8897 8898 8902 +6 8873 8870 8338 8339 8875 8902 +6 8874 8339 8347 8902 8349 8348 +6 8346 8340 8341 8342 8344 8345 +5 8863 8864 8878 9058 8882 +6 8877 8864 8866 8879 8881 8882 +6 8878 8866 8867 8868 8880 8881 +6 8879 8868 8881 8893 8894 8871 +6 8879 8880 8878 8882 8883 8893 +6 8878 8881 8883 8884 9058 8877 +6 8882 8881 8884 8885 8892 8893 +6 8882 8883 8885 8886 8887 9058 +6 8884 8883 8886 8890 8891 8892 +6 8884 8885 8887 8888 8889 8890 +6 8884 8886 8888 9058 9057 9059 +6 8887 8886 8889 9059 9060 9061 +6 8888 8886 8890 9061 9062 9063 +6 8889 8886 8885 8891 9063 9064 +6 8890 8885 8892 9064 9065 9066 +6 8891 8885 8883 8893 9066 8895 +6 8892 8883 8881 8880 8894 8895 +6 8893 8880 8895 8896 8872 8871 +6 8893 8894 8896 9066 8892 9067 +6 8895 8894 8872 8897 9067 9068 +6 8896 8872 8873 8898 8899 9068 +6 8897 8873 8899 8900 8901 8902 +6 8897 8898 8900 9068 9069 9070 +6 8899 8898 8901 9070 9071 8903 +6 8900 8898 8902 8349 8350 8903 +6 8901 8898 8873 8874 8875 8349 +6 8901 8350 8351 8904 9071 8900 +6 8903 8351 8905 9071 9072 9073 +6 8904 8351 8352 8906 9073 9074 +6 8905 8352 8353 8907 9074 9075 +6 8906 8353 8354 8908 9075 9076 +6 8907 8354 8909 9076 9077 8911 +6 8908 8354 8355 8357 8910 8911 +6 8909 8357 8911 8912 8360 8359 +6 8909 8910 8912 9077 8908 9078 +6 8911 8910 8360 8913 9078 9079 +6 8912 8360 8361 8914 8915 9079 +6 8913 8361 8362 8915 8916 8363 +6 8913 8914 8916 9079 9080 9081 +6 8915 8914 8363 8917 9081 9082 +6 8916 8363 8364 8918 9082 9083 +6 8917 8364 8365 8919 9083 9084 +6 8918 8365 8366 8920 9093 9084 +6 8919 8366 8367 8921 9093 9100 +6 8920 8367 8368 8922 9100 9101 +6 8921 8368 8369 8923 9101 9102 +6 8922 8369 8370 8924 9102 9103 +6 8923 8370 8925 9103 9104 9105 +6 8924 8370 8371 8926 9105 9106 +6 8925 8371 8372 8374 8927 9106 +6 8926 8374 8928 9106 9107 8931 +6 8927 8374 8375 8929 8931 8930 +6 8928 8375 8376 8377 8379 8930 +5 8929 8379 8380 8931 8928 +8 8930 8380 8381 8743 8932 9107 8927 8928 +5 8931 8743 8744 8933 9107 +8 8932 8744 8745 8934 9107 9106 9105 9108 +6 8933 8745 8746 8747 8935 9108 +6 8934 8747 8936 9108 9109 9110 +6 8935 8747 8748 8937 9110 9111 +6 8936 8748 8749 8938 9111 9112 +6 8937 8749 8750 8939 9112 9113 +6 8938 8750 8751 8940 9113 9114 +6 8939 8751 8752 8941 9114 9115 +6 8940 8752 8753 8942 9115 9116 +6 8941 8753 8943 9116 9117 8944 +5 8942 8753 8754 8755 8944 +7 8943 8755 8756 8945 9117 8942 9118 +7 8944 8756 8757 8758 8946 9118 9119 +5 8945 8758 8947 9119 9120 +6 8946 8758 8759 8948 9120 9121 +7 8947 8759 8760 8761 8949 9121 9122 +6 8948 8761 8950 9122 9123 8951 +6 8949 8761 8762 8763 8764 8951 +6 8950 8764 8765 8952 9123 8949 +6 8951 8765 8766 8953 9123 9124 +6 8952 8766 8954 9124 9125 9126 +6 8953 8766 8767 8768 8955 9126 +6 8954 8768 8769 8956 9126 9127 +6 8955 8769 8957 9127 9128 9129 +6 8956 8769 8770 8771 8958 9129 +6 8957 8771 8772 8959 9129 9130 +6 8958 8772 8773 8960 9130 9131 +6 8959 8773 8774 8961 9131 9132 +6 8960 8774 8775 8962 9132 9133 +6 8961 8775 8776 8963 9133 9134 +6 8962 8776 8964 9134 9135 9136 +6 8963 8776 8777 8778 8965 9136 +6 8964 8778 8779 8966 9136 9137 +6 8965 8779 8780 8967 9137 9138 +6 8966 8780 8781 8968 9138 9139 +6 8967 8781 8782 8969 9139 9140 +7 8968 8782 8783 8784 8970 9140 9141 +5 8969 8784 8971 9141 9142 +7 8970 8784 8785 8972 9142 9143 9144 +6 8971 8785 8786 8973 9144 9145 +6 8972 8786 8974 9145 9146 9147 +6 8973 8786 8787 8788 8975 9147 +6 8974 8788 8789 8790 8976 9147 +6 8975 8790 8977 9147 9148 9149 +6 8976 8790 8791 8792 8978 9149 +6 8977 8792 8979 9149 9150 9151 +6 8978 8792 8793 8980 9151 9152 +6 8979 8793 8795 8796 8981 9152 +6 8980 8796 8982 9152 9153 8983 +6 8981 8796 8797 8799 8801 8983 +6 8982 8801 8984 9153 8981 9154 +6 8983 8801 8802 8985 9154 9155 +6 8984 8802 8986 9155 9156 9157 +7 8985 8802 8803 8804 8987 9157 9158 +5 8986 8804 8805 8988 9158 +7 8987 8805 8989 8990 8991 9158 9159 +5 8988 8805 8806 8807 8990 +6 8989 8807 8988 8991 8992 8808 +6 8988 8990 8992 9159 9160 9161 +6 8991 8990 8808 8993 9164 9161 +6 8992 8808 8809 8810 8994 9164 +6 8993 8810 8812 8995 9164 9165 +7 8994 8812 8813 8996 9165 9167 9168 +5 8995 8813 8997 9168 9169 +6 8996 8813 8814 8998 9169 9170 +7 8997 8814 8815 8816 8999 9170 9171 +5 8998 8816 8817 9000 9171 +6 8999 8817 9001 9171 9172 9173 +6 9000 8817 8818 9002 9173 9003 +6 9001 8818 8819 8820 8821 9003 +6 9002 8821 8823 9004 9173 9001 +6 9003 8823 8824 8826 9005 9173 +6 9004 8826 9006 9007 9008 9173 +6 9005 8826 9007 9011 9012 8827 +6 9005 9006 9008 9009 9010 9011 +6 9005 9007 9009 9173 9172 9174 +5 9008 9007 9010 9174 9177 +6 9009 9007 9011 9013 9177 9014 +7 9010 9007 9006 9012 9013 8831 8830 +5 9011 9006 8830 8828 8827 +5 9010 9011 8831 8832 9014 +6 9013 8832 9015 9177 9010 9178 +6 9014 8832 8833 9016 9181 9178 +5 9015 8833 8834 9017 9181 +7 9016 8834 8835 9018 9181 9182 9188 +6 9017 8835 9019 9188 9189 9190 +6 9018 8835 8836 9020 9190 9191 +6 9019 8836 8837 8838 9021 9191 +6 9020 8838 8839 9022 9191 9192 +6 9021 8839 9023 9192 9195 9196 +6 9022 8839 8840 9024 9196 9197 +6 9023 8840 8841 9025 9197 9027 +6 9024 8841 8842 8843 9026 9027 +6 9025 8843 9027 9028 9029 9030 +6 9025 9026 9028 9197 9024 9198 +6 9027 9026 9029 9198 9199 9203 +5 9028 9026 9030 9031 9203 +6 9029 9026 8843 9031 8845 8844 +7 9029 9030 8845 8847 9032 9203 9204 +6 9031 8847 9033 9034 9204 9205 +6 9032 8847 9034 9035 9042 8848 +6 9032 9033 9035 9036 9037 9205 +6 9034 9033 9036 9040 9041 9042 +6 9034 9035 9037 9038 9039 9040 +6 9034 9036 9038 9205 9206 9207 +6 9037 9036 9039 9207 9208 9209 +6 9038 9036 9040 9209 9062 9061 +6 9039 9036 9035 9041 9061 9060 +6 9040 9035 9042 9043 9060 9210 +6 9041 9035 9033 8848 9043 8849 +6 9041 9042 8849 8850 9044 9210 +7 9043 8850 9045 9046 9055 9056 9210 +6 9044 8850 8851 9046 9047 9048 +6 9044 9045 9047 9053 9055 9049 +6 9046 9045 9048 8854 8855 9049 +6 9047 9045 8851 8854 8853 8852 +6 9047 8855 9050 9051 9053 9046 +6 9049 8855 8856 8857 8860 9051 +6 9050 8860 8861 9052 9053 9049 +6 9051 8861 9053 9054 9058 8863 +6 9051 9052 9054 9055 9046 9049 +6 9053 9052 9055 9056 9057 9058 +5 9053 9054 9046 9044 9056 +6 9044 9055 9054 9057 9059 9210 +5 9056 9054 9058 8887 9059 +8 9057 9054 9052 8863 8877 8882 8884 8887 +6 9057 8887 8888 9060 9210 9056 +6 9059 8888 9061 9040 9041 9210 +6 9060 8888 8889 9062 9039 9040 +6 9061 8889 9063 9209 9039 9211 +6 9062 8889 8890 9064 9211 9212 +6 9063 8890 8891 9065 9212 9213 +6 9064 8891 9066 9213 9214 9215 +6 9065 8891 8892 8895 9067 9215 +6 9066 8895 8896 9068 9215 9216 +6 9067 8896 8897 8899 9069 9216 +6 9068 8899 9070 9216 9217 9218 +6 9069 8899 8900 9071 9218 9219 +7 9070 8900 8903 8904 9072 9219 9220 +5 9071 8904 9073 9220 9221 +7 9072 8904 8905 9074 9221 9222 9223 +6 9073 8905 8906 9075 9223 9225 +6 9074 8906 8907 9076 9225 9226 +5 9075 8907 8908 9077 9226 +7 9076 8908 8911 9078 9226 9227 9228 +5 9077 8911 8912 9079 9228 +6 9078 8912 8913 8915 9080 9228 +6 9079 8915 9081 9228 9229 9230 +6 9080 8915 8916 9082 9230 9231 +6 9081 8916 8917 9083 9231 9232 +6 9082 8917 8918 9084 9085 9232 +6 9083 8918 9085 9086 9093 8919 +6 9083 9084 9086 9087 9232 9233 +6 9085 9084 9087 9088 9092 9093 +6 9085 9086 9088 9089 9233 9234 +6 9087 9086 9089 9090 9091 9092 +6 9087 9088 9090 9095 9234 9235 +6 9089 9088 9091 9095 9096 9097 +6 9090 9088 9092 9097 9098 9099 +6 9091 9088 9086 9093 9099 9100 +6 9092 9086 9084 8919 8920 9100 +5 8469 8470 8485 8476 8471 +6 9089 9090 9096 9235 9236 9237 +6 9095 9090 9097 9237 9238 9239 +6 9096 9090 9091 9098 9239 9240 +6 9097 9091 9099 9240 9241 9242 +6 9098 9091 9092 9100 9242 9101 +6 9099 9092 9093 8920 8921 9101 +6 9100 8921 8922 9102 9242 9099 +6 9101 8922 8923 9103 9242 9243 +6 9102 8923 8924 9104 9243 9244 +6 9103 8924 9105 9109 9244 9108 +6 9104 8924 8925 9106 8933 9108 +6 9105 8925 8926 8927 9107 8933 +5 9106 8927 8931 8932 8933 +6 9105 8933 8934 8935 9109 9104 +5 9108 8935 9110 9244 9104 +7 9109 8935 8936 9111 9245 9244 9348 +6 9110 8936 8937 9112 9350 9348 +5 9111 8937 8938 9113 9350 +6 9112 8938 8939 9114 9350 9351 +6 9113 8939 8940 9115 9351 9352 +6 9114 8940 8941 9116 9352 9353 +6 9115 8941 8942 9117 9246 9353 +6 9116 8942 8944 9118 9246 9247 +6 9117 8944 8945 9119 9247 9248 +5 9118 8945 8946 9120 9248 +7 9119 8946 8947 9121 9248 9249 9250 +6 9120 8947 8948 9122 9250 9251 +5 9121 8948 8949 9123 9251 +6 9122 8949 8951 8952 9124 9251 +6 9123 8952 8953 9125 9251 9252 +6 9124 8953 9126 9252 9253 9254 +6 9125 8953 8954 8955 9127 9254 +6 9126 8955 8956 9128 9254 9255 +6 9127 8956 9129 9255 9256 9257 +6 9128 8956 8957 8958 9130 9257 +6 9129 8958 8959 9131 9257 9258 +6 9130 8959 8960 9132 9258 9259 +6 9131 8960 8961 9133 9259 9260 +6 9132 8961 8962 9134 9260 9261 +6 9133 8962 8963 9135 9261 9262 +6 9134 8963 9136 9262 9263 9264 +6 9135 8963 8964 8965 9137 9264 +6 9136 8965 8966 9138 9264 9265 +6 9137 8966 8967 9139 9265 9266 +6 9138 8967 8968 9140 9266 9267 +6 9139 8968 8969 9141 9267 9268 +5 9140 8969 8970 9142 9268 +7 9141 8970 8971 9143 9268 9269 9270 +6 9142 8971 9144 9270 9271 9272 +5 9143 8971 8972 9145 9272 +6 9144 8972 8973 9146 9272 9273 +6 9145 8973 9147 9273 9274 9148 +6 9146 8973 8974 8975 8976 9148 +6 9147 8976 9149 9274 9146 9275 +6 9148 8976 8977 8978 9150 9275 +6 9149 8978 9151 9275 9276 9277 +6 9150 8978 8979 9152 9277 9278 +7 9151 8979 8980 8981 9153 9278 9279 +6 9152 8981 8983 9154 9279 9280 +6 9153 8983 8984 9155 9280 9281 +6 9154 8984 8985 9156 9281 9282 +6 9155 8985 9157 9282 9283 9284 +6 9156 8985 8986 9158 9284 9285 +6 9157 8986 8987 8988 9159 9285 +6 9158 8988 8991 9160 9285 9286 +6 9159 8991 9161 9162 9286 9287 +6 9160 8991 9162 9163 9164 8992 +6 9160 9161 9163 9287 9288 9289 +6 9162 9161 9164 9165 9166 9289 +6 9163 9161 8992 8993 8994 9165 +6 9164 8994 8995 9163 9166 9167 +6 9163 9165 9167 9289 9290 9186 +6 9166 9165 8995 9168 9186 9185 +6 9167 8995 8996 9169 9185 9184 +7 9168 8996 8997 9170 9184 9179 9176 +6 9169 8997 8998 9171 9176 9175 +6 9170 8998 8999 9000 9172 9175 +6 9171 9000 9173 9008 9174 9175 +7 9172 9000 9001 9003 9004 9005 9008 +6 9172 9008 9009 9175 9176 9177 +5 9172 9174 9176 9170 9171 +6 9175 9174 9177 9179 9169 9170 +7 9176 9174 9009 9010 9014 9178 9179 +6 9177 9014 9179 9180 9181 9015 +6 9177 9178 9180 9184 9169 9176 +6 9179 9178 9181 9182 9183 9184 +6 9180 9178 9015 9016 9017 9182 +6 9181 9017 9180 9183 9187 9188 +6 9180 9182 9184 9185 9186 9187 +6 9180 9183 9185 9168 9169 9179 +5 9184 9183 9186 9167 9168 +6 9185 9183 9187 9290 9166 9167 +6 9186 9183 9182 9188 9290 9291 +6 9187 9182 9017 9018 9189 9291 +5 9188 9018 9190 9291 9292 +6 9189 9018 9019 9191 9292 9193 +6 9190 9019 9020 9021 9192 9193 +6 9191 9021 9022 9193 9194 9195 +6 9191 9192 9194 9292 9190 9293 +6 9193 9192 9195 9293 9294 9295 +6 9194 9192 9022 9196 9295 9296 +6 9195 9022 9023 9197 9302 9296 +7 9196 9023 9024 9027 9198 9302 9303 +6 9197 9027 9028 9199 9200 9303 +6 9198 9028 9200 9201 9202 9203 +6 9198 9199 9201 9303 9301 9304 +6 9200 9199 9202 9304 9305 9306 +6 9201 9199 9203 9306 9307 9204 +6 9202 9199 9028 9029 9031 9204 +7 9203 9031 9032 9205 9307 9202 9206 +5 9204 9032 9034 9037 9206 +6 9205 9037 9207 9307 9204 9308 +6 9206 9037 9038 9208 9308 9309 +6 9207 9038 9209 9309 9310 9314 +6 9208 9038 9039 9062 9211 9314 +6 9060 9041 9043 9059 9056 9044 +6 9209 9062 9063 9212 9314 9315 +6 9211 9063 9064 9213 9315 9316 +6 9212 9064 9065 9214 9319 9316 +6 9213 9065 9215 9319 9320 9321 +6 9214 9065 9066 9067 9216 9321 +6 9215 9067 9068 9069 9217 9321 +7 9216 9069 9218 9321 9320 9322 9323 +5 9217 9069 9070 9219 9323 +7 9218 9070 9071 9220 9323 9324 9325 +5 9219 9071 9072 9221 9325 +7 9220 9072 9073 9222 9325 9326 9327 +6 9221 9073 9223 9224 9327 9328 +5 9222 9073 9074 9224 9225 +6 9222 9223 9225 9328 9329 9330 +6 9224 9223 9074 9075 9226 9330 +7 9225 9075 9076 9077 9227 9330 9331 +6 9226 9077 9228 9331 9332 9229 +6 9227 9077 9078 9079 9080 9229 +7 9228 9080 9230 9332 9227 9333 9334 +6 9229 9080 9081 9231 9334 9335 +6 9230 9081 9082 9232 9335 9336 +7 9231 9082 9083 9085 9233 9336 9337 +5 9232 9085 9087 9234 9337 +7 9233 9087 9089 9235 9337 9338 9339 +5 9234 9089 9095 9236 9339 +7 9235 9095 9237 9339 9340 9341 9342 +6 9236 9095 9096 9238 9342 9343 +6 9237 9096 9239 9343 9344 9345 +6 9238 9096 9097 9240 9345 9346 +6 9239 9097 9098 9241 9346 9347 +6 9240 9098 9242 9347 9245 9243 +6 9241 9098 9099 9101 9102 9243 +6 9242 9102 9103 9244 9245 9241 +6 9243 9103 9245 9110 9109 9104 +6 9243 9244 9110 9347 9241 9348 +6 9116 9117 9247 9353 9354 9355 +6 9246 9117 9118 9248 9355 9356 +6 9247 9118 9119 9120 9249 9356 +6 9248 9120 9250 9356 9357 9358 +6 9249 9120 9121 9251 9358 9252 +6 9250 9121 9122 9123 9124 9252 +7 9251 9124 9125 9253 9358 9250 9359 +5 9252 9125 9254 9359 9360 +7 9253 9125 9126 9127 9255 9360 9361 +6 9254 9127 9128 9256 9361 9362 +6 9255 9128 9257 9362 9363 9364 +6 9256 9128 9129 9130 9258 9364 +7 9257 9130 9131 9259 9364 9365 9366 +6 9258 9131 9132 9260 9366 9367 +6 9259 9132 9133 9261 9367 9368 +6 9260 9133 9134 9262 9368 9369 +6 9261 9134 9135 9263 9369 9370 +6 9262 9135 9264 9370 9371 9372 +6 9263 9135 9136 9137 9265 9372 +6 9264 9137 9138 9266 9372 9373 +6 9265 9138 9139 9267 9373 9374 +6 9266 9139 9140 9268 9374 9375 +7 9267 9140 9141 9142 9269 9375 9376 +5 9268 9142 9270 9376 9377 +6 9269 9142 9143 9271 9377 9381 +6 9270 9143 9272 9381 9382 9383 +6 9271 9143 9144 9145 9273 9383 +6 9272 9145 9146 9274 9383 9384 +6 9273 9146 9148 9275 9384 9385 +7 9274 9148 9149 9150 9276 9385 9386 +5 9275 9150 9277 9386 9388 +6 9276 9150 9151 9278 9388 9389 +6 9277 9151 9152 9279 9389 9390 +6 9278 9152 9153 9280 9390 9391 +5 9279 9153 9154 9281 9391 +6 9280 9154 9155 9282 9393 9391 +6 9281 9155 9156 9283 9393 9394 +6 9282 9156 9284 9394 9395 9396 +6 9283 9156 9157 9285 9396 9397 +6 9284 9157 9158 9159 9286 9397 +6 9285 9159 9160 9287 9397 9398 +5 9286 9160 9162 9288 9398 +7 9287 9162 9289 9398 9399 9400 9401 +6 9288 9162 9163 9166 9290 9401 +7 9289 9166 9186 9187 9291 9402 9401 +6 9290 9187 9188 9189 9292 9402 +7 9291 9189 9190 9193 9293 9402 9400 +6 9292 9193 9194 9294 9400 9403 +6 9293 9194 9295 9403 9404 9405 +6 9294 9194 9195 9296 9297 9405 +6 9295 9195 9297 9298 9302 9196 +6 9295 9296 9298 9299 9405 9406 +6 9297 9296 9299 9300 9301 9302 +6 9297 9298 9300 9409 9406 9410 +6 9299 9298 9301 9410 9411 9412 +7 9300 9298 9302 9303 9200 9304 9412 +6 9301 9298 9296 9196 9197 9303 +5 9302 9197 9198 9200 9301 +5 9301 9200 9201 9305 9412 +7 9304 9201 9306 9412 9413 9414 9418 +5 9305 9201 9202 9307 9418 +6 9306 9202 9204 9206 9308 9418 +6 9307 9206 9207 9309 9417 9418 +6 9308 9207 9208 9310 9311 9417 +6 9309 9208 9311 9312 9313 9314 +6 9309 9310 9312 9416 9417 9419 +6 9311 9310 9313 9419 9420 9424 +7 9312 9310 9314 9424 9425 9317 9315 +6 9313 9310 9208 9209 9211 9315 +6 9314 9211 9212 9316 9317 9313 +6 9315 9212 9317 9318 9319 9213 +6 9315 9316 9318 9425 9313 9426 +6 9317 9316 9319 9426 9427 9428 +6 9318 9316 9213 9214 9320 9428 +6 9319 9214 9321 9217 9322 9428 +5 9320 9214 9215 9216 9217 +6 9320 9217 9323 9428 9429 9430 +6 9322 9217 9218 9219 9324 9430 +6 9323 9219 9325 9430 9431 9432 +6 9324 9219 9220 9221 9326 9432 +6 9325 9221 9327 9432 9433 9434 +6 9326 9221 9222 9328 9434 9435 +5 9327 9222 9224 9329 9435 +7 9328 9224 9330 9435 9436 9437 9438 +6 9329 9224 9225 9226 9331 9438 +6 9330 9226 9227 9332 9438 9439 +6 9331 9227 9229 9333 9442 9439 +6 9332 9229 9334 9442 9443 9446 +5 9333 9229 9230 9335 9446 +6 9334 9230 9231 9336 9446 9447 +6 9335 9231 9232 9337 9447 9448 +6 9336 9232 9233 9234 9338 9448 +6 9337 9234 9339 9448 9449 9450 +6 9338 9234 9235 9236 9340 9450 +6 9339 9236 9341 9450 9451 9452 +6 9340 9236 9342 9452 9453 9454 +6 9341 9236 9237 9343 9454 9455 +5 9342 9237 9238 9344 9455 +7 9343 9238 9345 9455 9456 9457 9458 +6 9344 9238 9239 9346 9458 9349 +5 9345 9239 9240 9347 9349 +6 9346 9240 9241 9245 9348 9349 +6 9347 9245 9349 9350 9111 9110 +7 9347 9348 9350 9458 9345 9346 9351 +6 9349 9348 9111 9112 9113 9351 +7 9350 9113 9114 9352 9458 9349 9459 +6 9351 9114 9115 9353 9459 9460 +6 9352 9115 9116 9246 9354 9460 +6 9353 9246 9355 9460 9461 9462 +6 9354 9246 9247 9356 9462 9463 +6 9355 9247 9248 9249 9357 9463 +6 9356 9249 9358 9463 9464 9465 +6 9357 9249 9250 9252 9359 9465 +5 9358 9252 9253 9360 9465 +7 9359 9253 9254 9361 9465 9466 9467 +5 9360 9254 9255 9362 9467 +6 9361 9255 9256 9363 9467 9468 +6 9362 9256 9364 9468 9469 9470 +6 9363 9256 9257 9258 9365 9470 +6 9364 9258 9366 9470 9471 9472 +5 9365 9258 9259 9367 9472 +6 9366 9259 9260 9368 9472 9473 +6 9367 9260 9261 9369 9473 9474 +6 9368 9261 9262 9370 9474 9475 +6 9369 9262 9263 9371 9475 9476 +6 9370 9263 9372 9476 9477 9478 +6 9371 9263 9264 9265 9373 9478 +6 9372 9265 9266 9374 9478 9479 +6 9373 9266 9267 9375 9479 9480 +6 9374 9267 9268 9376 9480 9481 +6 9375 9268 9269 9377 9378 9481 +7 9376 9269 9270 9378 9379 9380 9381 +5 9376 9377 9379 9481 9482 +6 9378 9377 9380 9482 9483 9484 +6 9379 9377 9381 9484 9485 9382 +5 9380 9377 9270 9271 9382 +6 9381 9271 9383 9485 9380 9486 +7 9382 9271 9272 9273 9384 9486 9487 +6 9383 9273 9274 9385 9487 9488 +6 9384 9274 9275 9386 9387 9488 +5 9385 9275 9276 9387 9388 +6 9385 9386 9388 9488 9489 9490 +7 9387 9386 9276 9277 9389 9490 9491 +6 9388 9277 9278 9390 9491 9492 +6 9389 9278 9279 9391 9392 9492 +6 9390 9279 9392 9393 9281 9280 +6 9390 9391 9393 9492 9493 9494 +6 9392 9391 9281 9282 9394 9494 +6 9393 9282 9283 9395 9494 9495 +6 9394 9283 9396 9495 9496 9497 +6 9395 9283 9284 9397 9498 9497 +6 9396 9284 9285 9286 9398 9498 +6 9397 9286 9287 9288 9399 9498 +6 9398 9288 9400 9498 9404 9403 +7 9399 9288 9401 9402 9292 9293 9403 +5 9400 9288 9402 9290 9289 +5 9400 9401 9290 9291 9292 +5 9400 9293 9294 9404 9399 +6 9403 9294 9405 9498 9399 9407 +6 9404 9294 9295 9297 9406 9407 +6 9405 9297 9407 9408 9409 9299 +6 9405 9406 9408 9497 9498 9404 +6 9407 9406 9409 9496 9497 9499 +6 9408 9406 9299 9410 9499 9500 +6 9409 9299 9300 9411 9500 9501 +6 9410 9300 9412 9501 9502 9413 +6 9411 9300 9301 9304 9305 9413 +6 9412 9305 9414 9415 9502 9411 +6 9413 9305 9415 9416 9417 9418 +6 9413 9414 9416 9502 9503 9504 +6 9415 9414 9417 9311 9419 9504 +6 9416 9414 9418 9308 9309 9311 +6 9417 9414 9308 9307 9306 9305 +6 9416 9311 9312 9420 9421 9504 +6 9419 9312 9421 9422 9423 9424 +6 9419 9420 9422 9504 9505 9506 +6 9421 9420 9423 9506 9507 9508 +6 9422 9420 9424 9511 9508 9512 +6 9423 9420 9312 9313 9425 9512 +5 9424 9313 9317 9426 9512 +6 9425 9317 9318 9427 9512 9513 +6 9426 9318 9428 9513 9514 9429 +6 9427 9318 9319 9320 9322 9429 +6 9428 9322 9430 9517 9514 9427 +6 9429 9322 9323 9324 9431 9517 +6 9430 9324 9432 9524 9517 9525 +6 9431 9324 9325 9326 9433 9525 +6 9432 9326 9434 9525 9526 9527 +6 9433 9326 9327 9435 9527 9528 +6 9434 9327 9328 9329 9436 9528 +6 9435 9329 9437 9528 9530 9531 +6 9436 9329 9438 9531 9532 9440 +6 9437 9329 9330 9331 9439 9440 +6 9438 9331 9440 9441 9442 9332 +5 9438 9439 9441 9532 9437 +7 9440 9439 9442 9443 9444 9532 9533 +5 9441 9439 9332 9333 9443 +6 9442 9333 9441 9444 9445 9446 +5 9441 9443 9445 9533 9534 +6 9444 9443 9446 9534 9535 9536 +7 9445 9443 9333 9334 9335 9447 9536 +6 9446 9335 9336 9448 9536 9537 +6 9447 9336 9337 9338 9449 9537 +6 9448 9338 9450 9537 9538 9451 +5 9449 9338 9339 9340 9451 +7 9450 9340 9452 9538 9449 9539 9540 +6 9451 9340 9341 9453 9540 9541 +6 9452 9341 9454 9541 9542 9543 +6 9453 9341 9342 9455 9543 9544 +6 9454 9342 9343 9344 9456 9544 +6 9455 9344 9457 9544 9545 9461 +6 9456 9344 9458 9461 9460 9459 +6 9457 9344 9345 9349 9351 9459 +5 9458 9351 9352 9460 9457 +6 9459 9352 9353 9354 9461 9457 +6 9460 9354 9462 9545 9456 9457 +5 9461 9354 9355 9463 9545 +7 9462 9355 9356 9357 9464 9545 9546 +6 9463 9357 9465 9546 9547 9548 +7 9464 9357 9358 9359 9360 9466 9548 +6 9465 9360 9467 9548 9549 9550 +6 9466 9360 9361 9362 9468 9550 +6 9467 9362 9363 9469 9550 9551 +6 9468 9363 9470 9551 9552 9553 +6 9469 9363 9364 9365 9471 9553 +6 9470 9365 9472 9553 9554 9555 +6 9471 9365 9366 9367 9473 9555 +6 9472 9367 9368 9474 9555 9556 +6 9473 9368 9369 9475 9556 9557 +6 9474 9369 9370 9476 9557 9558 +6 9475 9370 9371 9477 9558 9559 +6 9476 9371 9478 9559 9560 9561 +6 9477 9371 9372 9373 9479 9561 +6 9478 9373 9374 9480 9561 9562 +6 9479 9374 9375 9481 9562 9563 +6 9480 9375 9376 9378 9482 9563 +6 9481 9378 9379 9483 9563 9564 +6 9482 9379 9484 9564 9565 9566 +6 9483 9379 9380 9485 9566 9567 +6 9484 9380 9382 9486 9567 9568 +6 9485 9382 9383 9487 9568 9569 +6 9486 9383 9384 9488 9569 9570 +6 9487 9384 9385 9387 9489 9570 +6 9488 9387 9490 9570 9571 9572 +6 9489 9387 9388 9491 9572 9573 +6 9490 9388 9389 9492 9573 9574 +6 9491 9389 9390 9392 9493 9574 +6 9492 9392 9494 9574 9575 9576 +6 9493 9392 9393 9394 9495 9576 +6 9494 9394 9395 9496 9576 9577 +6 9495 9395 9497 9408 9499 9577 +6 9496 9395 9408 9407 9498 9396 +7 9407 9497 9396 9397 9398 9399 9404 +5 9496 9408 9409 9500 9577 +7 9499 9409 9410 9501 9577 9578 9579 +6 9500 9410 9411 9502 9579 9580 +6 9501 9411 9413 9415 9503 9580 +6 9502 9415 9504 9580 9581 9582 +7 9503 9415 9416 9419 9421 9505 9582 +5 9504 9421 9506 9582 9583 +6 9505 9421 9422 9507 9583 9584 +6 9506 9422 9508 9509 9584 9585 +6 9507 9422 9509 9510 9511 9423 +6 9507 9508 9510 9585 9586 9587 +6 9509 9508 9511 9518 9587 9521 +6 9510 9508 9423 9512 9518 9519 +7 9511 9423 9424 9425 9426 9513 9519 +6 9512 9426 9427 9514 9515 9519 +6 9513 9427 9515 9516 9517 9429 +6 9513 9514 9516 9519 9518 9520 +6 9515 9514 9517 9523 9520 9524 +6 9516 9514 9429 9430 9524 9431 +6 9510 9511 9519 9515 9520 9521 +5 9518 9511 9512 9513 9515 +6 9518 9515 9521 9522 9523 9516 +6 9518 9520 9522 9587 9510 9588 +6 9521 9520 9523 9588 9589 9590 +6 9522 9520 9516 9524 9590 9591 +6 9523 9516 9517 9431 9525 9591 +7 9524 9431 9432 9433 9526 9591 9592 +5 9525 9433 9527 9592 9593 +6 9526 9433 9434 9528 9529 9593 +6 9527 9434 9435 9436 9529 9530 +6 9527 9528 9530 9593 9594 9595 +6 9529 9528 9436 9531 9595 9596 +6 9530 9436 9437 9532 9596 9597 +7 9531 9437 9440 9441 9533 9597 9598 +5 9532 9441 9444 9534 9598 +7 9533 9444 9445 9535 9598 9599 9600 +6 9534 9445 9536 9600 9601 9602 +7 9535 9445 9446 9447 9537 9602 9603 +6 9536 9447 9448 9449 9538 9603 +6 9537 9449 9451 9539 9603 9604 +6 9538 9451 9540 9604 9605 9606 +6 9539 9451 9452 9541 9606 9607 +5 9540 9452 9453 9542 9607 +7 9541 9453 9543 9607 9608 9609 9610 +5 9542 9453 9454 9544 9610 +7 9543 9454 9455 9456 9545 9610 9546 +6 9544 9456 9461 9462 9463 9546 +6 9545 9463 9464 9547 9610 9544 +6 9546 9464 9548 9610 9609 9549 +5 9547 9464 9465 9466 9549 +6 9548 9466 9550 9609 9547 9611 +6 9549 9466 9467 9468 9551 9611 +6 9550 9468 9469 9552 9611 9612 +6 9551 9469 9553 9612 9613 9614 +6 9552 9469 9470 9471 9554 9614 +6 9553 9471 9555 9614 9615 9616 +6 9554 9471 9472 9473 9556 9616 +6 9555 9473 9474 9557 9616 9617 +6 9556 9474 9475 9558 9617 9618 +6 9557 9475 9476 9559 9618 9619 +6 9558 9476 9477 9560 9619 9620 +6 9559 9477 9561 9620 9621 9622 +6 9560 9477 9478 9479 9562 9622 +6 9561 9479 9480 9563 9622 9623 +6 9562 9480 9481 9482 9564 9623 +6 9563 9482 9483 9565 9623 9624 +6 9564 9483 9566 9624 9625 9626 +6 9565 9483 9484 9567 9626 9627 +6 9566 9484 9485 9568 9627 9628 +7 9567 9485 9486 9569 9628 9629 9630 +6 9568 9486 9487 9570 9630 9631 +6 9569 9487 9488 9489 9571 9631 +6 9570 9489 9572 9631 9632 9633 +6 9571 9489 9490 9573 9633 9634 +6 9572 9490 9491 9574 9634 9635 +6 9573 9491 9492 9493 9575 9635 +6 9574 9493 9576 9635 9636 9578 +6 9575 9493 9494 9495 9577 9578 +6 9576 9495 9496 9499 9500 9578 +6 9577 9500 9579 9636 9575 9576 +6 9578 9500 9501 9580 9636 9581 +5 9579 9501 9502 9503 9581 +6 9580 9503 9582 9636 9579 9637 +6 9581 9503 9504 9505 9583 9637 +6 9582 9505 9506 9584 9637 9638 +6 9583 9506 9507 9585 9638 9633 +6 9584 9507 9509 9586 9633 9632 +6 9585 9509 9587 9632 9639 9629 +6 9586 9509 9510 9521 9588 9629 +6 9587 9521 9522 9589 9629 9628 +6 9588 9522 9590 9628 9627 9640 +6 9589 9522 9523 9591 9640 9641 +6 9590 9523 9524 9525 9592 9641 +6 9591 9525 9526 9593 9641 9642 +7 9592 9526 9527 9529 9594 9642 9643 +5 9593 9529 9595 9643 9644 +6 9594 9529 9530 9596 9644 9645 +6 9595 9530 9531 9597 9645 9646 +6 9596 9531 9532 9598 9646 9647 +6 9597 9532 9533 9534 9599 9647 +5 9598 9534 9600 9647 9648 +7 9599 9534 9535 9601 9648 9649 9650 +5 9600 9535 9602 9650 9651 +6 9601 9535 9536 9603 9651 9604 +5 9602 9536 9537 9538 9604 +6 9603 9538 9539 9605 9651 9602 +6 9604 9539 9606 9651 9652 9653 +6 9605 9539 9540 9607 9653 9613 +6 9606 9540 9541 9542 9608 9613 +6 9607 9542 9609 9613 9612 9611 +6 9608 9542 9610 9547 9549 9611 +6 9609 9542 9543 9544 9546 9547 +6 9609 9549 9550 9551 9612 9608 +5 9611 9551 9552 9613 9608 +7 9612 9552 9614 9653 9606 9607 9608 +6 9613 9552 9553 9554 9615 9653 +6 9614 9554 9616 9653 9652 9654 +6 9615 9554 9555 9556 9617 9654 +6 9616 9556 9557 9618 9654 9655 +6 9617 9557 9558 9619 9655 9656 +6 9618 9558 9559 9620 9656 9657 +6 9619 9559 9560 9621 9657 9658 +6 9620 9560 9622 9658 9659 9660 +6 9621 9560 9561 9562 9623 9660 +6 9622 9562 9563 9564 9624 9660 +7 9623 9564 9565 9625 9660 9661 9662 +5 9624 9565 9626 9662 9663 +7 9625 9565 9566 9627 9663 9664 9640 +6 9626 9566 9567 9628 9589 9640 +6 9627 9567 9568 9629 9588 9589 +7 9628 9568 9630 9639 9586 9587 9588 +5 9629 9568 9569 9631 9639 +6 9630 9569 9570 9571 9632 9639 +6 9631 9571 9633 9585 9586 9639 +7 9632 9571 9572 9634 9638 9584 9585 +6 9633 9572 9573 9635 9637 9638 +6 9634 9573 9574 9575 9636 9637 +6 9635 9575 9578 9579 9581 9637 +7 9636 9581 9582 9583 9638 9635 9634 +5 9637 9583 9584 9633 9634 +5 9632 9586 9629 9630 9631 +6 9627 9589 9590 9641 9664 9626 +6 9640 9590 9591 9592 9642 9664 +6 9641 9592 9593 9643 9664 9663 +6 9642 9593 9594 9644 9663 9662 +7 9643 9594 9595 9645 9662 9661 9665 +7 9644 9595 9596 9646 9665 9659 9666 +6 9645 9596 9597 9647 9666 9667 +6 9646 9597 9598 9599 9648 9667 +6 9647 9599 9600 9649 9667 9668 +6 9648 9600 9650 9668 9656 9655 +6 9649 9600 9601 9651 9655 9669 +7 9650 9601 9602 9604 9605 9652 9669 +6 9651 9605 9653 9615 9654 9669 +6 9652 9605 9606 9613 9614 9615 +6 9652 9615 9616 9617 9655 9669 +7 9654 9617 9618 9656 9649 9650 9669 +6 9655 9618 9619 9657 9668 9649 +5 9656 9619 9620 9658 9668 +6 9657 9620 9621 9659 9668 9666 +6 9658 9621 9660 9665 9645 9666 +7 9659 9621 9622 9623 9624 9661 9665 +5 9660 9624 9662 9644 9665 +6 9661 9624 9625 9663 9643 9644 +6 9662 9625 9626 9664 9642 9643 +5 9663 9626 9640 9641 9642 +5 9661 9644 9645 9659 9660 +6 9659 9645 9646 9667 9668 9658 +5 9666 9646 9647 9648 9668 +7 9667 9648 9649 9656 9657 9658 9666 +5 9655 9650 9651 9652 9654 +6 6653 6650 6651 9671 9691 9681 +6 9670 6651 9672 9676 9680 9681 +6 9671 6651 9673 9674 9675 9676 +6 9672 6651 9674 6649 9727 6365 +6 9672 9673 9675 9725 9726 9727 +6 9672 9674 9676 9677 9678 9725 +6 9672 9675 9677 9679 9680 9671 +5 9676 9675 9678 5235 9679 +7 9677 9675 5235 9734 4519 9725 9733 +6 9677 5235 5236 9676 9680 9683 +7 9676 9679 9671 9681 9682 4654 9683 +6 9671 9680 9682 9691 9670 9685 +5 9681 9680 4654 4655 9685 +6 4654 9680 9679 5236 4652 9684 +6 4652 9683 4650 422 5237 5236 +6 9682 4655 9686 9687 9691 9681 +6 9685 4655 9687 3169 9688 4656 +6 9685 9686 3169 3170 9691 3172 +7 3169 9686 4656 9689 3168 2843 9690 +5 9688 4656 5380 430 9690 +6 2843 9688 9689 430 2841 429 +6 9685 9687 3172 6653 9670 9681 +6 6475 6478 6474 9779 9774 9780 +6 6460 6461 6465 6467 6377 6378 +6 5862 5863 9695 9702 9703 9700 +6 9694 5863 5864 9696 5719 9700 +5 9695 5864 5865 5718 5719 +6 5718 5865 5866 5867 9698 9699 +6 9697 5867 9699 5695 5694 5868 +5 9697 9698 5695 5696 5718 +6 9695 5719 5720 9701 9702 9694 +5 9700 5720 5721 5724 9702 +6 9701 5724 6095 9703 9694 9700 +6 9702 6095 6383 9694 5862 5861 +6 6490 2252 415 2194 6488 6489 +7 6488 2195 6487 6480 2196 9773 9778 +5 2251 6491 3336 6492 3335 +6 3335 6492 3334 6499 6493 6494 +6 6502 6503 9709 2189 9711 9712 +6 6502 9708 2189 6501 9710 2190 +6 6501 9709 6500 2190 2191 2512 +7 9708 6503 6512 9712 9715 9716 9717 +5 9708 9711 2189 9713 9715 +6 2189 9712 2187 2197 9714 9715 +6 2197 9713 9715 2215 2216 9720 +6 9714 9713 9712 9711 9716 2215 +7 9715 9711 9717 9718 9719 2214 2215 +6 9716 9711 6512 6513 6514 9718 +5 9717 6514 6516 9719 9716 +5 9718 6516 9716 2214 6522 +6 9714 2216 2217 2200 2198 2197 +6 6669 6775 9722 9723 6656 6658 +5 9721 6775 9723 9724 9798 +6 9721 9722 9724 6646 6656 6655 +6 9723 9722 6646 6645 9799 9798 +6 9675 9674 9726 9678 9733 9735 +6 9725 9674 9727 9729 9735 9728 +6 9726 9674 9673 6365 6366 9728 +6 9727 6366 6368 6370 9729 9726 +6 9728 6370 9730 9731 9735 9726 +6 9729 6370 6371 6375 6467 9731 +6 9730 6467 6466 9732 9735 9729 +6 9731 6466 6468 7510 9733 9735 +6 9732 7510 9734 9735 9678 9725 +6 9733 7510 7508 4518 4519 9678 +6 9732 9733 9731 9729 9726 9725 +6 6041 6039 6038 6019 5872 5874 +6 6132 6398 6392 6393 6115 9738 +6 9737 6115 6116 6132 6131 6122 +6 569 571 9740 9744 568 9743 +6 9739 571 573 9741 9742 9743 +6 9740 573 916 917 9742 918 +6 9740 9741 918 9743 921 919 +6 9740 9742 921 563 9744 9739 +6 9743 563 564 567 568 9739 +6 7205 7206 9746 7218 7217 7216 +6 9745 7206 7207 7213 7216 7214 +6 3491 3492 3496 3502 6706 6555 +5 6706 3502 9749 3503 6710 +5 6706 9748 6710 6707 6705 +5 6682 5157 4667 6681 9761 +5 3201 3470 3410 3200 3411 +6 5932 5910 5915 5916 9755 5931 +5 4915 4917 9754 4880 4879 +7 9753 4917 4911 4880 9756 4904 9759 +7 9752 5916 5931 5921 5920 5919 9758 +6 4880 9754 9757 4895 4897 9759 +5 4880 9756 4895 4884 4881 +5 5919 9755 5918 5916 5917 +6 9754 4904 4901 4898 4897 9756 +6 4638 4912 4875 4872 4869 4868 +7 6681 9750 4667 4668 9762 4560 9792 +5 9761 4668 4546 4548 4560 +5 8468 8469 9764 9765 8486 +5 8468 9763 9765 7726 7962 +7 9764 9763 8486 7714 7715 7723 7726 +6 8023 8021 7738 7739 7740 7742 +5 7723 7715 7716 7719 7721 +6 427 7500 7502 9769 46 45 +6 9768 7502 9770 9772 44 45 +7 9769 7502 7503 9771 9772 9774 9780 +7 2196 43 1 9772 9770 9773 9774 +5 9771 1 9770 9769 44 +6 2196 9771 9774 9705 9778 9779 +6 9773 9771 9770 9779 9692 9780 +6 7253 7256 7523 7520 7517 7516 +6 2095 2083 2084 6093 3138 3131 +5 6638 6639 6642 6787 6785 +5 9705 9773 9779 6478 6480 +5 9778 9773 9774 9692 6478 +5 9692 9774 6474 9770 7503 +6 3852 3129 26 25 1526 3130 +6 6787 6642 6643 9783 6789 6170 +5 9782 6643 6168 6169 6170 +6 4396 4529 4395 4121 4119 4530 +6 6637 6783 6779 6636 6635 6771 +6 4118 3529 3531 9787 9789 4120 +6 9786 3531 3533 9788 7174 9789 +6 9787 3533 3535 7178 7175 7174 +6 9787 7174 9786 4120 4122 7172 +5 7670 7695 7696 7698 7669 +6 7775 3145 4231 3413 3414 7776 +6 4560 6675 6676 6677 6681 9761 +6 3659 3660 4908 9794 4369 4371 +5 9793 4908 4642 4370 4369 +6 5543 5545 5700 5540 5541 5542 +6 6177 6178 9797 9798 6181 9799 +6 6782 6177 9796 9798 6776 6780 +7 9797 9796 6776 9799 9724 9722 6775 +6 9796 6181 6183 6645 9724 9798 diff --git a/scotch_6.0.3/src/check/data/bump_b1.grf b/scotch_6.0.3/src/check/data/bump_b1.grf new file mode 100644 index 00000000..42fe857c --- /dev/null +++ b/scotch_6.0.3/src/check/data/bump_b1.grf @@ -0,0 +1,9803 @@ +0 +9800 57978 +1 000 +3 414 408 7 +4 9772 44 9773 45 +4 77 1475 1476 78 +3 1243 148 149 +3 694 207 208 +3 522 349 350 +4 8 413 414 1 +4 7 413 9 648 +4 10 3239 648 8 +4 3236 3239 9 11 +4 12 3234 3236 10 +4 3235 3234 11 13 +4 3685 3235 12 14 +4 15 419 3685 13 +4 16 418 419 14 +4 15 418 17 3089 +4 18 3087 3089 16 +4 17 3087 3088 19 +4 3088 18 3096 20 +4 3096 19 3097 21 +4 22 415 3097 20 +4 21 415 1172 23 +4 1172 22 1173 24 +4 1173 23 1174 25 +4 1174 24 1527 26 +4 1527 25 27 9782 +4 28 3853 9782 26 +4 29 2180 3853 27 +4 28 2180 2181 30 +4 2181 29 31 2504 +4 32 2506 2504 30 +4 2509 2506 31 33 +4 3331 2509 34 32 +4 3331 33 3332 35 +4 36 2249 3332 34 +4 35 2249 2250 37 +4 2250 36 2251 38 +4 39 417 2251 37 +4 40 416 417 38 +4 39 416 2195 41 +4 2195 40 2196 42 +4 2196 41 2197 43 +3 2197 42 44 +4 43 2197 9772 2 +4 9770 9773 2 46 +4 47 9769 9770 45 +4 48 428 9769 46 +4 49 427 428 47 +4 48 427 50 412 +4 51 411 412 49 +4 50 411 52 422 +4 51 422 423 53 +4 423 52 4651 54 +4 4651 53 4652 55 +4 4658 4652 54 56 +4 5381 4658 55 57 +4 58 431 5381 56 +4 57 431 430 59 +4 60 409 430 58 +4 59 409 2219 61 +4 2219 60 2220 62 +4 2220 61 2221 63 +4 2221 62 2222 64 +4 2222 63 2223 65 +4 6702 2223 64 66 +4 6702 65 6704 67 +4 6704 66 3506 68 +4 69 3453 3506 67 +4 70 3452 3453 68 +4 3442 3452 69 71 +4 72 2492 3442 70 +4 71 2492 2493 73 +4 74 410 2493 72 +4 73 410 75 429 +4 74 429 76 1604 +4 75 1604 1605 77 +4 3 1475 1605 76 +4 1476 3 1477 79 +4 1477 78 1478 80 +4 1478 79 1479 81 +4 1479 80 1480 82 +4 1480 81 1481 83 +4 1481 82 1482 84 +4 1482 83 1483 85 +4 1483 84 1484 86 +4 87 1161 1484 85 +4 86 1161 1162 88 +4 1162 87 1163 89 +4 1163 88 1164 90 +4 1164 89 1187 91 +4 1187 90 1186 92 +4 1186 91 1188 93 +4 1188 92 1189 94 +4 1189 93 1190 95 +4 1190 94 1191 96 +4 1191 95 1192 97 +4 1192 96 1193 98 +4 1193 97 1194 99 +4 1194 98 1195 100 +4 1195 99 1196 101 +4 1196 100 1197 102 +4 1197 101 1198 103 +4 1198 102 1199 104 +4 1199 103 1200 105 +4 1200 104 1201 106 +4 1201 105 1202 107 +4 1202 106 1203 108 +4 1203 107 1204 109 +4 1204 108 1205 110 +4 1205 109 1206 111 +4 1206 110 1207 112 +4 1207 111 1208 113 +4 1208 112 1209 114 +4 1209 113 1210 115 +4 1210 114 1211 116 +4 1211 115 1212 117 +4 1212 116 1213 118 +4 1213 117 1214 119 +4 1214 118 1215 120 +4 1215 119 1216 121 +4 1216 120 1217 122 +4 1217 121 1218 123 +4 1218 122 1219 124 +4 1219 123 1220 125 +4 1220 124 1221 126 +4 1221 125 1222 127 +4 1222 126 1223 128 +4 1223 127 1224 129 +4 1224 128 1225 130 +4 1225 129 1226 131 +4 1226 130 1227 132 +4 1227 131 1228 133 +4 1228 132 1229 134 +4 1229 133 1230 135 +4 1230 134 1231 136 +4 1231 135 1232 137 +4 1232 136 1233 138 +4 1233 137 1234 139 +4 1234 138 1235 140 +4 1235 139 1236 141 +4 1236 140 1237 142 +4 1237 141 1238 143 +4 1238 142 1239 144 +4 1239 143 1240 145 +4 1240 144 1241 146 +4 1241 145 1242 147 +4 1242 146 1243 148 +3 1243 147 4 +4 1243 4 1244 150 +4 1244 149 1245 151 +4 1245 150 1246 152 +4 1246 151 1247 153 +4 1247 152 1248 154 +4 1248 153 1249 155 +4 156 924 1249 154 +4 155 924 925 157 +4 925 156 926 158 +4 926 157 927 159 +4 927 158 928 160 +4 928 159 929 161 +4 929 160 930 162 +4 930 161 931 163 +4 931 162 932 164 +4 165 652 932 163 +4 164 652 653 166 +4 653 165 654 167 +4 654 166 655 168 +4 655 167 656 169 +4 656 168 657 170 +4 657 169 658 171 +4 658 170 659 172 +4 659 171 660 173 +4 660 172 661 174 +4 661 173 662 175 +4 662 174 663 176 +4 663 175 664 177 +4 664 176 665 178 +4 665 177 666 179 +4 666 178 667 180 +4 667 179 668 181 +4 668 180 669 182 +4 669 181 670 183 +4 670 182 671 184 +4 671 183 672 185 +4 672 184 673 186 +4 673 185 674 187 +4 674 186 675 188 +4 675 187 676 189 +4 676 188 677 190 +4 677 189 678 191 +4 678 190 679 192 +4 679 191 680 193 +4 680 192 681 194 +4 681 193 682 195 +4 682 194 683 196 +4 683 195 684 197 +4 684 196 685 198 +4 685 197 686 199 +4 686 198 687 200 +4 687 199 688 201 +4 688 200 689 202 +4 689 201 690 203 +4 690 202 691 204 +4 691 203 692 205 +4 692 204 693 206 +3 693 205 207 +4 693 206 694 5 +3 694 5 209 +4 694 208 695 210 +4 695 209 696 211 +4 696 210 697 212 +4 697 211 698 213 +4 698 212 699 214 +4 699 213 700 215 +4 700 214 701 216 +4 701 215 702 217 +4 702 216 703 218 +4 703 217 704 219 +4 704 218 705 220 +4 705 219 706 221 +4 706 220 707 222 +4 707 221 708 223 +4 708 222 709 224 +4 709 223 710 225 +4 710 224 711 226 +4 711 225 712 227 +4 712 226 713 228 +4 713 227 714 229 +4 714 228 715 230 +4 715 229 716 231 +4 716 230 717 232 +4 717 231 718 233 +4 718 232 719 234 +4 719 233 720 235 +4 720 234 721 236 +4 721 235 722 237 +4 722 236 723 238 +4 723 237 724 239 +4 724 238 725 240 +4 725 239 726 241 +4 726 240 727 242 +4 727 241 728 243 +4 728 242 729 244 +4 729 243 730 245 +4 730 244 731 246 +4 731 245 732 247 +4 732 246 733 248 +4 733 247 734 249 +4 734 248 735 250 +4 735 249 736 251 +4 736 250 737 252 +4 737 251 738 253 +4 738 252 739 254 +4 739 253 740 255 +4 740 254 741 256 +4 741 255 742 257 +4 742 256 743 258 +4 259 432 743 257 +4 258 432 433 260 +4 433 259 434 261 +4 434 260 435 262 +4 435 261 436 263 +4 436 262 437 264 +4 437 263 438 265 +4 438 264 439 266 +4 439 265 440 267 +4 440 266 441 268 +4 441 267 442 269 +4 442 268 443 270 +4 443 269 444 271 +4 444 270 445 272 +4 445 271 446 273 +4 446 272 447 274 +4 447 273 448 275 +4 448 274 449 276 +4 449 275 450 277 +4 450 276 451 278 +4 451 277 452 279 +4 452 278 453 280 +4 453 279 454 281 +4 454 280 455 282 +4 455 281 456 283 +4 456 282 457 284 +4 457 283 458 285 +4 458 284 459 286 +4 459 285 460 287 +4 460 286 461 288 +4 461 287 462 289 +4 462 288 463 290 +4 463 289 464 291 +4 464 290 465 292 +4 465 291 466 293 +4 466 292 467 294 +4 467 293 468 295 +4 468 294 469 296 +4 469 295 470 297 +4 470 296 471 298 +4 471 297 472 299 +4 472 298 473 300 +4 473 299 474 301 +4 474 300 475 302 +4 475 301 476 303 +4 476 302 477 304 +4 477 303 478 305 +4 478 304 479 306 +4 479 305 480 307 +4 480 306 481 308 +4 481 307 482 309 +4 482 308 483 310 +4 483 309 484 311 +4 484 310 485 312 +4 485 311 486 313 +4 486 312 487 314 +4 487 313 488 315 +4 488 314 489 316 +4 489 315 490 317 +4 490 316 491 318 +4 491 317 492 319 +4 492 318 493 320 +4 493 319 494 321 +4 494 320 495 322 +4 495 321 496 323 +4 496 322 497 324 +4 497 323 498 325 +4 498 324 499 326 +4 499 325 500 327 +4 500 326 501 328 +4 501 327 502 329 +4 502 328 503 330 +4 503 329 504 331 +4 504 330 505 332 +4 505 331 506 333 +4 506 332 507 334 +4 507 333 508 335 +4 508 334 509 336 +4 509 335 510 337 +4 510 336 511 338 +4 511 337 512 339 +4 512 338 513 340 +4 513 339 514 341 +4 514 340 515 342 +4 515 341 516 343 +4 516 342 517 344 +4 517 343 518 345 +4 518 344 519 346 +4 519 345 520 347 +4 520 346 521 348 +4 521 347 522 349 +3 522 348 6 +4 522 6 523 351 +4 523 350 524 352 +4 524 351 525 353 +4 525 352 526 354 +4 526 353 527 355 +4 527 354 528 356 +4 528 355 529 357 +4 529 356 530 358 +4 530 357 531 359 +4 531 358 532 360 +4 532 359 533 361 +4 533 360 534 362 +4 534 361 535 363 +4 535 362 536 364 +4 536 363 537 365 +4 537 364 538 366 +4 538 365 539 367 +4 539 366 540 368 +4 540 367 541 369 +4 541 368 542 370 +4 542 369 543 371 +4 543 370 544 372 +4 544 371 545 373 +4 545 372 546 374 +4 546 373 547 375 +4 547 374 548 376 +4 551 548 375 377 +4 551 376 552 378 +4 552 377 553 379 +4 553 378 554 380 +4 557 554 379 381 +4 567 557 380 382 +4 567 381 568 383 +4 568 382 569 384 +4 569 383 570 385 +4 570 384 571 386 +4 426 571 387 385 +4 388 424 426 386 +4 387 424 425 389 +4 580 425 390 388 +4 585 580 389 391 +4 585 390 586 392 +4 586 391 587 393 +4 587 392 421 394 +4 395 420 421 393 +4 394 420 595 396 +4 397 597 595 395 +4 623 597 396 398 +4 623 397 624 399 +4 624 398 625 400 +4 399 625 627 401 +4 627 400 629 402 +4 631 629 403 401 +4 631 402 632 404 +4 403 632 2098 405 +4 406 650 2098 404 +4 649 650 405 407 +4 649 406 414 408 +3 414 407 1 +6 59 60 430 2219 2546 2842 +6 73 74 2493 2494 1607 429 +6 50 51 412 4522 4516 422 +6 50 411 49 427 4515 4516 +6 7 8 414 648 647 649 +6 7 413 649 407 408 1 +6 21 22 1172 3883 3129 3097 +6 39 40 417 2195 2253 9705 +6 39 416 38 2251 2252 2253 +6 15 16 419 3089 3099 3100 +6 15 418 14 3100 3101 3685 +6 394 395 421 594 589 595 +6 394 420 587 393 588 589 +6 51 52 423 5238 4522 411 +6 422 52 53 4651 9685 5238 +6 387 388 425 426 578 576 +6 424 388 578 579 580 389 +6 387 424 573 571 386 576 +6 48 49 428 412 4515 5613 +6 48 427 47 5613 7501 9769 +6 74 75 1604 1606 1607 410 +6 59 409 431 58 2842 9691 +6 57 58 430 9690 5381 9691 +6 258 259 433 743 744 745 +6 432 259 260 434 745 746 +6 433 260 261 435 746 747 +6 434 261 262 436 747 748 +6 435 262 263 437 748 749 +6 436 263 264 438 749 750 +6 437 264 265 439 750 751 +6 438 265 266 440 751 752 +6 439 266 267 441 752 753 +6 440 267 268 442 753 754 +6 441 268 269 443 754 755 +6 442 269 270 444 755 756 +6 443 270 271 445 756 757 +6 444 271 272 446 757 758 +6 445 272 273 447 758 759 +6 446 273 274 448 759 760 +6 447 274 275 449 760 761 +6 448 275 276 450 761 762 +6 449 276 277 451 762 763 +6 450 277 278 452 763 764 +6 451 278 279 453 764 765 +6 452 279 280 454 765 766 +6 453 280 281 455 766 767 +6 454 281 282 456 767 768 +6 455 282 283 457 768 769 +6 456 283 284 458 769 770 +6 457 284 285 459 770 771 +6 458 285 286 460 771 772 +6 459 286 287 461 772 773 +6 460 287 288 462 773 774 +6 461 288 289 463 774 775 +6 462 289 290 464 775 776 +6 463 290 291 465 776 777 +6 464 291 292 466 777 778 +6 465 292 293 467 778 779 +6 466 293 294 468 779 780 +6 467 294 295 469 780 781 +6 468 295 296 470 781 782 +6 469 296 297 471 782 783 +6 470 297 298 472 783 784 +6 471 298 299 473 784 785 +6 472 299 300 474 785 786 +6 473 300 301 475 786 787 +6 474 301 302 476 787 788 +6 475 302 303 477 788 789 +6 476 303 304 478 789 790 +6 477 304 305 479 790 791 +6 478 305 306 480 791 792 +6 479 306 307 481 792 793 +6 480 307 308 482 793 794 +6 481 308 309 483 794 795 +6 482 309 310 484 795 796 +6 483 310 311 485 796 797 +6 484 311 312 486 797 798 +6 485 312 313 487 798 799 +6 486 313 314 488 799 800 +6 487 314 315 489 800 801 +6 488 315 316 490 801 802 +6 489 316 317 491 802 803 +6 490 317 318 492 803 804 +6 491 318 319 493 804 805 +6 492 319 320 494 805 806 +6 493 320 321 495 806 807 +6 494 321 322 496 807 808 +6 495 322 323 497 808 809 +6 496 323 324 498 809 810 +6 497 324 325 499 810 811 +6 498 325 326 500 811 812 +6 499 326 327 501 812 813 +6 500 327 328 502 813 814 +6 501 328 329 503 814 815 +6 502 329 330 504 815 816 +6 503 330 331 505 816 817 +6 504 331 332 506 817 818 +6 505 332 333 507 818 819 +6 506 333 334 508 819 820 +6 507 334 335 509 820 821 +6 508 335 336 510 821 822 +6 509 336 337 511 822 823 +6 510 337 338 512 823 824 +6 511 338 339 513 824 825 +6 512 339 340 514 825 826 +6 513 340 341 515 826 827 +6 514 341 342 516 827 828 +6 515 342 343 517 828 829 +6 516 343 344 518 829 830 +6 517 344 345 519 830 831 +6 518 345 346 520 831 832 +6 519 346 347 521 832 833 +6 520 347 348 522 833 834 +7 521 348 349 6 350 523 834 +6 522 350 351 524 834 835 +5 523 351 352 525 835 +6 524 352 353 526 835 836 +6 525 353 354 527 836 837 +6 526 354 355 528 837 838 +6 527 355 356 529 838 839 +6 528 356 357 530 839 840 +6 529 357 358 531 840 841 +6 530 358 359 532 841 842 +6 531 359 360 533 842 843 +6 532 360 361 534 843 844 +6 533 361 362 535 844 845 +6 534 362 363 536 845 846 +6 535 363 364 537 846 847 +6 536 364 365 538 847 848 +6 537 365 366 539 848 849 +6 538 366 367 540 849 850 +6 539 367 368 541 850 851 +6 540 368 369 542 854 851 +6 541 369 370 543 856 854 +6 542 370 371 544 856 857 +6 543 371 372 545 857 858 +6 544 372 373 546 858 859 +6 545 373 374 547 859 860 +6 546 374 375 548 549 860 +6 547 375 549 550 551 376 +6 547 548 550 860 861 862 +6 549 548 551 862 863 864 +6 550 548 376 377 552 864 +6 551 377 378 553 864 865 +6 552 378 379 554 555 865 +6 553 379 555 556 557 380 +6 553 554 556 558 865 866 +6 555 554 557 558 559 566 +6 556 554 380 566 567 381 +6 555 556 559 560 866 867 +6 558 556 560 561 562 566 +6 558 559 561 867 868 869 +6 560 559 562 563 923 869 +6 561 559 563 564 565 566 +6 561 562 564 922 921 923 +6 563 562 565 9744 922 9745 +6 564 562 566 567 9745 568 +6 565 562 559 556 557 567 +6 566 557 381 382 568 565 +6 567 382 383 569 9745 565 +6 568 383 384 570 9745 9740 +6 569 384 385 571 572 9740 +6 570 385 572 573 426 386 +6 570 571 573 574 9740 9741 +6 572 571 426 574 575 576 +6 572 573 575 9741 9742 917 +6 574 573 576 577 917 916 +6 575 573 426 577 578 424 +6 575 576 578 916 2475 1516 +6 577 576 424 425 579 1516 +6 578 425 580 581 582 1516 +6 579 425 389 581 585 390 +6 579 580 582 583 584 585 +6 579 581 583 1516 1517 1518 +6 582 581 584 1518 1509 1507 +6 583 581 585 586 590 1507 +6 584 581 580 390 391 586 +6 585 391 392 587 590 584 +6 586 392 393 421 588 590 +6 587 421 589 590 591 592 +6 588 421 592 593 594 420 +6 587 588 591 586 584 1507 +6 590 588 592 1507 1508 1515 +6 591 588 589 593 600 1515 +6 592 589 594 598 599 600 +6 593 589 420 595 596 598 +6 594 420 395 596 597 396 +6 594 595 597 598 622 607 +6 596 595 622 623 397 396 +6 594 596 593 599 606 607 +6 593 598 600 601 605 606 +6 593 599 601 602 1515 592 +6 600 599 602 603 604 605 +6 600 601 603 1514 1515 1540 +6 602 601 604 1540 1541 1584 +6 603 601 605 1603 1584 609 +6 604 601 599 606 608 609 +6 605 599 598 607 608 615 +6 606 598 622 621 596 615 +6 605 606 609 610 611 615 +6 605 608 610 1603 604 1601 +6 609 608 611 612 1600 1601 +6 610 608 612 613 614 615 +6 610 611 613 6558 1599 1600 +6 612 611 614 616 3765 6558 +6 613 611 615 616 617 621 +6 614 611 621 607 606 608 +6 613 614 617 618 3761 3765 +6 616 614 618 619 620 621 +6 616 617 619 3761 3762 626 +6 618 617 620 624 625 626 +6 619 617 621 622 624 623 +6 620 617 614 615 622 607 +6 620 621 607 596 597 623 +6 622 597 397 398 624 620 +6 623 398 399 625 619 620 +6 624 399 619 626 627 400 +6 619 625 627 628 3762 618 +6 626 625 628 629 400 401 +6 626 627 629 630 3762 3763 +6 628 627 630 631 402 401 +6 628 629 631 636 3763 633 +6 630 629 402 403 632 633 +6 631 403 633 634 404 2098 +6 631 632 634 635 636 630 +6 633 632 635 2098 651 642 +6 633 634 636 637 638 642 +6 633 635 637 3218 3763 630 +6 636 635 638 639 3218 3219 +6 637 635 639 640 641 642 +6 637 638 640 3219 3220 3221 +6 639 638 641 3221 3240 3241 +6 640 638 642 643 644 3240 +6 641 638 643 634 651 635 +6 641 642 644 645 646 651 +6 641 643 645 3238 3237 3240 +6 644 643 646 647 648 3238 +6 645 643 647 649 650 651 +5 645 646 648 413 649 +7 645 647 413 9 3239 3238 8 +7 413 647 646 650 406 407 414 +6 649 646 651 406 405 2098 +6 650 646 634 2098 642 643 +6 164 165 653 932 933 934 +6 652 165 166 654 934 935 +6 653 166 167 655 935 936 +6 654 167 168 656 936 937 +6 655 168 169 657 937 938 +6 656 169 170 658 938 939 +6 657 170 171 659 939 940 +6 658 171 172 660 940 941 +6 659 172 173 661 941 942 +6 660 173 174 662 942 943 +6 661 174 175 663 943 944 +6 662 175 176 664 944 945 +6 663 176 177 665 945 946 +6 664 177 178 666 946 947 +6 665 178 179 667 947 948 +6 666 179 180 668 948 949 +6 667 180 181 669 949 950 +6 668 181 182 670 950 951 +6 669 182 183 671 951 952 +6 670 183 184 672 952 953 +6 671 184 185 673 953 954 +6 672 185 186 674 954 955 +6 673 186 187 675 955 956 +6 674 187 188 676 956 957 +6 675 188 189 677 957 958 +6 676 189 190 678 958 959 +6 677 190 191 679 959 960 +6 678 191 192 680 960 961 +6 679 192 193 681 961 962 +6 680 193 194 682 962 963 +6 681 194 195 683 963 964 +6 682 195 196 684 964 965 +6 683 196 197 685 965 966 +6 684 197 198 686 966 967 +6 685 198 199 687 967 968 +6 686 199 200 688 968 969 +6 687 200 201 689 969 970 +6 688 201 202 690 970 971 +6 689 202 203 691 971 972 +6 690 203 204 692 972 973 +6 691 204 205 693 973 974 +7 692 205 206 207 694 974 695 +6 693 207 5 208 209 695 +7 694 209 210 696 974 693 975 +6 695 210 211 697 975 976 +6 696 211 212 698 976 977 +6 697 212 213 699 977 978 +6 698 213 214 700 978 979 +6 699 214 215 701 979 980 +6 700 215 216 702 980 981 +6 701 216 217 703 981 982 +6 702 217 218 704 982 983 +6 703 218 219 705 983 984 +6 704 219 220 706 984 985 +6 705 220 221 707 985 986 +6 706 221 222 708 986 987 +6 707 222 223 709 987 988 +6 708 223 224 710 988 989 +6 709 224 225 711 989 990 +6 710 225 226 712 990 991 +6 711 226 227 713 991 992 +6 712 227 228 714 992 993 +6 713 228 229 715 993 994 +6 714 229 230 716 994 995 +6 715 230 231 717 995 996 +6 716 231 232 718 996 997 +6 717 232 233 719 997 998 +6 718 233 234 720 998 999 +6 719 234 235 721 999 1000 +6 720 235 236 722 1000 1001 +6 721 236 237 723 1001 1002 +6 722 237 238 724 1002 1003 +6 723 238 239 725 1003 1004 +6 724 239 240 726 1004 1005 +6 725 240 241 727 1005 1006 +6 726 241 242 728 1006 1007 +6 727 242 243 729 1007 1008 +6 728 243 244 730 1008 1009 +6 729 244 245 731 1009 1010 +6 730 245 246 732 1010 1011 +6 731 246 247 733 1011 1012 +6 732 247 248 734 1012 1013 +6 733 248 249 735 1013 1014 +6 734 249 250 736 1017 1014 +6 735 250 251 737 1017 1018 +6 736 251 252 738 1018 1019 +6 737 252 253 739 1019 1020 +6 738 253 254 740 1020 1021 +6 739 254 255 741 1021 1022 +6 740 255 256 742 1022 1023 +6 741 256 257 743 1023 1024 +6 742 257 258 432 744 1024 +6 743 432 745 1024 1025 1026 +6 744 432 433 746 1026 1027 +6 745 433 434 747 1027 1028 +6 746 434 435 748 1028 1029 +6 747 435 436 749 1029 1030 +6 748 436 437 750 1030 1031 +6 749 437 438 751 1031 1032 +6 750 438 439 752 1032 1033 +6 751 439 440 753 1033 1034 +6 752 440 441 754 1034 1035 +6 753 441 442 755 1035 1036 +6 754 442 443 756 1036 1037 +6 755 443 444 757 1037 1038 +6 756 444 445 758 1038 1039 +6 757 445 446 759 1039 1040 +6 758 446 447 760 1040 1041 +6 759 447 448 761 1041 1042 +6 760 448 449 762 1042 1043 +6 761 449 450 763 1043 1044 +6 762 450 451 764 1044 1045 +6 763 451 452 765 1045 1046 +6 764 452 453 766 1046 1047 +6 765 453 454 767 1047 1048 +6 766 454 455 768 1048 1049 +6 767 455 456 769 1049 1050 +6 768 456 457 770 1050 1051 +6 769 457 458 771 1051 1052 +6 770 458 459 772 1052 1053 +6 771 459 460 773 1053 1054 +6 772 460 461 774 1054 1055 +6 773 461 462 775 1055 1056 +6 774 462 463 776 1056 1057 +6 775 463 464 777 1057 1058 +6 776 464 465 778 1058 1059 +6 777 465 466 779 1059 1060 +6 778 466 467 780 1060 1061 +6 779 467 468 781 1061 1062 +6 780 468 469 782 1062 1063 +6 781 469 470 783 1063 1064 +6 782 470 471 784 1064 1065 +6 783 471 472 785 1065 1066 +6 784 472 473 786 1066 1067 +6 785 473 474 787 1067 1068 +6 786 474 475 788 1068 1069 +6 787 475 476 789 1069 1070 +6 788 476 477 790 1070 1071 +6 789 477 478 791 1071 1072 +6 790 478 479 792 1072 1073 +6 791 479 480 793 1073 1074 +6 792 480 481 794 1074 1075 +6 793 481 482 795 1075 1076 +6 794 482 483 796 1076 1077 +6 795 483 484 797 1077 1078 +6 796 484 485 798 1078 1079 +6 797 485 486 799 1079 1080 +6 798 486 487 800 1080 1081 +6 799 487 488 801 1081 1082 +6 800 488 489 802 1082 1083 +6 801 489 490 803 1083 1084 +6 802 490 491 804 1084 1085 +6 803 491 492 805 1085 1086 +6 804 492 493 806 1086 1087 +6 805 493 494 807 1087 1088 +6 806 494 495 808 1088 1089 +6 807 495 496 809 1089 1090 +6 808 496 497 810 1090 1091 +6 809 497 498 811 1091 1092 +6 810 498 499 812 1092 1093 +6 811 499 500 813 1093 1094 +6 812 500 501 814 1094 1095 +6 813 501 502 815 1095 1096 +6 814 502 503 816 1096 1097 +6 815 503 504 817 1097 1098 +6 816 504 505 818 1098 1099 +6 817 505 506 819 1099 1100 +6 818 506 507 820 1100 1101 +6 819 507 508 821 1101 1102 +6 820 508 509 822 1102 1103 +6 821 509 510 823 1103 1104 +6 822 510 511 824 1104 1105 +6 823 511 512 825 1105 1106 +6 824 512 513 826 1106 1107 +6 825 513 514 827 1107 1108 +6 826 514 515 828 1108 1109 +6 827 515 516 829 1109 1110 +6 828 516 517 830 1110 1111 +6 829 517 518 831 1111 1112 +6 830 518 519 832 1112 1113 +6 831 519 520 833 1113 1114 +6 832 520 521 834 1114 1115 +6 833 521 522 523 835 1115 +6 834 523 524 525 836 1115 +7 835 525 526 837 1115 1116 1117 +6 836 526 527 838 1117 1118 +6 837 527 528 839 1118 1119 +6 838 528 529 840 1119 1120 +6 839 529 530 841 1120 1121 +6 840 530 531 842 1121 1122 +6 841 531 532 843 1122 1123 +6 842 532 533 844 1123 1124 +6 843 533 534 845 1124 1125 +6 844 534 535 846 1125 1126 +6 845 535 536 847 1126 1127 +6 846 536 537 848 1127 1128 +6 847 537 538 849 1128 1129 +6 848 538 539 850 1129 1130 +6 849 539 540 851 852 1130 +6 850 540 852 853 854 541 +6 850 851 853 1130 1131 1132 +6 852 851 854 855 1132 1133 +6 853 851 855 856 542 541 +6 853 854 856 1133 1134 1135 +6 855 854 542 543 857 1135 +6 856 543 544 858 1135 1136 +6 857 544 545 859 1136 1137 +6 858 545 546 860 1137 1138 +6 859 546 547 549 861 1138 +6 860 549 862 1138 1139 1140 +6 861 549 550 863 1140 1141 +6 862 550 864 1141 1142 1143 +6 863 550 551 552 865 1143 +6 864 552 553 555 866 1143 +6 865 555 558 867 1143 1144 +6 866 558 560 868 1144 1145 +6 867 560 869 870 1145 1146 +6 868 560 870 871 923 561 +6 868 869 871 872 1146 1147 +6 870 869 872 873 874 923 +6 870 871 873 1147 1148 1149 +6 872 871 874 875 1152 1149 +6 873 871 875 876 923 921 +6 873 874 876 877 1171 1152 +6 875 874 877 878 920 921 +6 875 876 878 879 880 1171 +6 877 876 879 919 883 920 +6 877 878 880 881 882 883 +6 877 879 881 885 887 1171 +6 880 879 882 885 886 892 +6 881 879 883 884 892 893 +6 882 879 884 918 919 878 +6 882 883 913 893 914 918 +6 880 881 886 887 888 889 +6 885 881 889 890 891 892 +6 880 885 888 1965 1170 1171 +6 887 885 889 1966 1965 2076 +6 888 885 886 890 2076 2077 +6 889 886 891 2077 2078 2082 +6 890 886 892 894 895 2082 +6 891 886 881 882 893 894 +6 892 882 894 897 913 884 +6 892 893 891 895 896 897 +6 891 894 896 898 899 2082 +6 895 894 897 898 910 911 +6 896 894 893 911 912 913 +6 895 896 899 900 901 910 +6 895 898 900 902 2082 2081 +6 899 898 901 902 903 907 +6 900 898 907 908 909 910 +6 899 900 903 904 2081 2083 +6 902 900 904 905 906 907 +6 902 903 905 2083 2084 2085 +6 904 903 906 2085 2086 1566 +6 905 903 907 1564 1565 1566 +6 906 903 900 901 908 1564 +6 907 901 909 1544 1564 1537 +6 908 901 910 1523 1524 1537 +6 909 901 898 896 911 1523 +6 910 896 897 912 1521 1523 +6 911 897 913 1522 1521 915 +6 912 897 893 884 914 915 +6 913 884 915 916 917 918 +6 913 914 916 2475 1522 912 +6 915 914 917 575 577 2475 +6 916 914 918 9742 574 575 +6 917 914 884 883 919 9742 +6 918 883 878 920 9743 9742 +6 919 878 876 921 922 9743 +6 920 876 922 563 923 874 +6 920 921 563 9744 9743 564 +6 563 921 874 871 869 561 +6 155 156 925 1249 1250 1251 +6 924 156 157 926 1251 1252 +6 925 157 158 927 1252 1253 +6 926 158 159 928 1253 1254 +6 927 159 160 929 1254 1255 +6 928 160 161 930 1255 1256 +6 929 161 162 931 1256 1257 +6 930 162 163 932 1257 1258 +6 931 163 164 652 933 1258 +6 932 652 934 1258 1259 1260 +6 933 652 653 935 1260 1261 +6 934 653 654 936 1261 1262 +6 935 654 655 937 1262 1263 +6 936 655 656 938 1263 1264 +6 937 656 657 939 1264 1265 +6 938 657 658 940 1265 1266 +6 939 658 659 941 1266 1267 +6 940 659 660 942 1267 1268 +6 941 660 661 943 1268 1269 +6 942 661 662 944 1269 1270 +6 943 662 663 945 1270 1271 +6 944 663 664 946 1271 1272 +6 945 664 665 947 1272 1273 +6 946 665 666 948 1273 1274 +6 947 666 667 949 1274 1275 +6 948 667 668 950 1275 1276 +6 949 668 669 951 1276 1277 +6 950 669 670 952 1277 1278 +6 951 670 671 953 1278 1279 +6 952 671 672 954 1279 1280 +6 953 672 673 955 1280 1281 +6 954 673 674 956 1281 1282 +6 955 674 675 957 1282 1283 +6 956 675 676 958 1283 1284 +6 957 676 677 959 1284 1285 +6 958 677 678 960 1285 1286 +6 959 678 679 961 1286 1287 +6 960 679 680 962 1287 1288 +6 961 680 681 963 1288 1289 +6 962 681 682 964 1289 1290 +6 963 682 683 965 1290 1291 +6 964 683 684 966 1291 1292 +6 965 684 685 967 1292 1293 +6 966 685 686 968 1293 1294 +6 967 686 687 969 1294 1295 +6 968 687 688 970 1295 1296 +6 969 688 689 971 1296 1297 +6 970 689 690 972 1297 1298 +6 971 690 691 973 1298 1299 +6 972 691 692 974 1299 1300 +6 973 692 693 695 975 1300 +5 974 695 696 976 1300 +6 975 696 697 977 1300 1301 +6 976 697 698 978 1301 1302 +6 977 698 699 979 1302 1303 +6 978 699 700 980 1303 1304 +6 979 700 701 981 1304 1305 +6 980 701 702 982 1305 1306 +6 981 702 703 983 1306 1307 +6 982 703 704 984 1307 1308 +6 983 704 705 985 1308 1309 +6 984 705 706 986 1309 1310 +6 985 706 707 987 1310 1311 +6 986 707 708 988 1311 1312 +6 987 708 709 989 1312 1313 +6 988 709 710 990 1313 1314 +6 989 710 711 991 1314 1315 +6 990 711 712 992 1315 1316 +6 991 712 713 993 1316 1317 +6 992 713 714 994 1317 1318 +6 993 714 715 995 1318 1319 +6 994 715 716 996 1319 1320 +6 995 716 717 997 1320 1321 +6 996 717 718 998 1321 1322 +6 997 718 719 999 1322 1323 +6 998 719 720 1000 1323 1324 +6 999 720 721 1001 1324 1325 +6 1000 721 722 1002 1325 1326 +6 1001 722 723 1003 1326 1327 +6 1002 723 724 1004 1327 1328 +6 1003 724 725 1005 1328 1329 +6 1004 725 726 1006 1329 1330 +6 1005 726 727 1007 1330 1331 +6 1006 727 728 1008 1331 1332 +6 1007 728 729 1009 1332 1333 +6 1008 729 730 1010 1333 1334 +6 1009 730 731 1011 1334 1335 +6 1010 731 732 1012 1335 1336 +6 1011 732 733 1013 1336 1337 +6 1012 733 734 1014 1015 1337 +6 1013 734 1015 1016 1017 735 +6 1013 1014 1016 1337 1338 1339 +6 1015 1014 1017 1339 1340 1341 +6 1016 1014 735 736 1018 1341 +6 1017 736 737 1019 1341 1342 +6 1018 737 738 1020 1342 1343 +6 1019 738 739 1021 1343 1344 +6 1020 739 740 1022 1344 1345 +6 1021 740 741 1023 1345 1346 +6 1022 741 742 1024 1346 1347 +6 1023 742 743 744 1025 1347 +6 1024 744 1026 1347 1348 1349 +6 1025 744 745 1027 1349 1350 +6 1026 745 746 1028 1350 1351 +6 1027 746 747 1029 1351 1352 +6 1028 747 748 1030 1352 1353 +6 1029 748 749 1031 1353 1354 +6 1030 749 750 1032 1354 1355 +6 1031 750 751 1033 1355 1356 +6 1032 751 752 1034 1356 1357 +6 1033 752 753 1035 1357 1358 +6 1034 753 754 1036 1358 1359 +6 1035 754 755 1037 1359 1360 +6 1036 755 756 1038 1360 1361 +6 1037 756 757 1039 1361 1362 +6 1038 757 758 1040 1362 1363 +6 1039 758 759 1041 1363 1364 +6 1040 759 760 1042 1364 1365 +6 1041 760 761 1043 1365 1366 +6 1042 761 762 1044 1366 1367 +6 1043 762 763 1045 1367 1368 +6 1044 763 764 1046 1368 1369 +6 1045 764 765 1047 1369 1370 +6 1046 765 766 1048 1370 1371 +6 1047 766 767 1049 1371 1372 +6 1048 767 768 1050 1372 1373 +6 1049 768 769 1051 1373 1374 +6 1050 769 770 1052 1374 1375 +6 1051 770 771 1053 1375 1376 +6 1052 771 772 1054 1376 1377 +6 1053 772 773 1055 1377 1378 +6 1054 773 774 1056 1378 1379 +6 1055 774 775 1057 1379 1380 +6 1056 775 776 1058 1380 1381 +6 1057 776 777 1059 1381 1382 +6 1058 777 778 1060 1382 1383 +6 1059 778 779 1061 1383 1384 +6 1060 779 780 1062 1384 1385 +6 1061 780 781 1063 1385 1386 +6 1062 781 782 1064 1386 1387 +6 1063 782 783 1065 1387 1388 +6 1064 783 784 1066 1388 1389 +6 1065 784 785 1067 1389 1390 +6 1066 785 786 1068 1390 1391 +6 1067 786 787 1069 1391 1392 +6 1068 787 788 1070 1392 1393 +6 1069 788 789 1071 1393 1394 +6 1070 789 790 1072 1394 1395 +6 1071 790 791 1073 1395 1396 +6 1072 791 792 1074 1396 1397 +6 1073 792 793 1075 1397 1398 +6 1074 793 794 1076 1398 1399 +6 1075 794 795 1077 1399 1400 +6 1076 795 796 1078 1400 1401 +6 1077 796 797 1079 1401 1402 +6 1078 797 798 1080 1402 1403 +6 1079 798 799 1081 1403 1404 +6 1080 799 800 1082 1404 1405 +6 1081 800 801 1083 1405 1406 +6 1082 801 802 1084 1406 1407 +6 1083 802 803 1085 1407 1408 +6 1084 803 804 1086 1408 1409 +6 1085 804 805 1087 1409 1410 +6 1086 805 806 1088 1410 1411 +6 1087 806 807 1089 1411 1412 +6 1088 807 808 1090 1412 1413 +6 1089 808 809 1091 1413 1414 +6 1090 809 810 1092 1414 1415 +6 1091 810 811 1093 1415 1416 +6 1092 811 812 1094 1416 1417 +6 1093 812 813 1095 1417 1418 +6 1094 813 814 1096 1418 1419 +6 1095 814 815 1097 1419 1420 +6 1096 815 816 1098 1420 1421 +6 1097 816 817 1099 1421 1422 +6 1098 817 818 1100 1422 1423 +6 1099 818 819 1101 1423 1424 +6 1100 819 820 1102 1424 1425 +6 1101 820 821 1103 1425 1426 +6 1102 821 822 1104 1426 1427 +6 1103 822 823 1105 1427 1428 +6 1104 823 824 1106 1428 1429 +6 1105 824 825 1107 1429 1430 +6 1106 825 826 1108 1430 1431 +6 1107 826 827 1109 1431 1432 +6 1108 827 828 1110 1432 1433 +6 1109 828 829 1111 1433 1434 +6 1110 829 830 1112 1434 1435 +6 1111 830 831 1113 1435 1436 +6 1112 831 832 1114 1436 1437 +6 1113 832 833 1115 1437 1116 +6 1114 833 834 835 836 1116 +6 1115 836 1117 1437 1114 1438 +5 1116 836 837 1118 1438 +6 1117 837 838 1119 1438 1439 +6 1118 838 839 1120 1439 1440 +6 1119 839 840 1121 1440 1441 +6 1120 840 841 1122 1441 1442 +6 1121 841 842 1123 1442 1443 +6 1122 842 843 1124 1443 1444 +6 1123 843 844 1125 1444 1445 +6 1124 844 845 1126 1445 1446 +6 1125 845 846 1127 1446 1447 +6 1126 846 847 1128 1447 1448 +6 1127 847 848 1129 1448 1449 +6 1128 848 849 1130 1449 1450 +6 1129 849 850 852 1131 1450 +6 1130 852 1132 1450 1451 1452 +6 1131 852 853 1133 1452 1453 +6 1132 853 855 1134 1453 1454 +6 1133 855 1135 1457 1454 1153 +6 1134 855 856 857 1136 1153 +6 1135 857 858 1137 1153 1154 +6 1136 858 859 1138 1154 1155 +6 1137 859 860 861 1139 1155 +6 1138 861 1140 1155 1156 1157 +6 1139 861 862 1141 1157 1158 +6 1140 862 863 1142 1158 1159 +6 1141 863 1143 1159 1160 1144 +6 1142 863 864 865 866 1144 +6 1143 866 867 1145 1160 1142 +6 1144 867 868 1146 1499 1160 +6 1145 868 870 1147 1499 1500 +6 1146 870 872 1148 1165 1500 +6 1147 872 1149 1150 1165 1166 +6 1148 872 1150 1151 1152 873 +6 1148 1149 1151 1166 1167 1168 +6 1150 1149 1152 1168 1169 1170 +6 1151 1149 873 1170 1171 875 +6 1135 1136 1154 1474 1457 1134 +6 1153 1136 1137 1155 1474 1491 +6 1154 1137 1138 1139 1156 1491 +6 1155 1139 1157 1491 1492 1493 +6 1156 1139 1140 1158 1493 1494 +6 1157 1140 1141 1159 1494 1495 +6 1158 1141 1142 1160 1498 1495 +6 1159 1142 1144 1145 1499 1498 +6 86 87 1162 1484 1485 1489 +6 1161 87 88 1163 1175 1489 +6 1162 88 89 1164 1175 1176 +6 1163 89 90 1176 1178 1187 +6 1147 1148 1166 1500 1528 1529 +6 1165 1148 1150 1167 1529 1534 +6 1166 1150 1168 1536 1534 1542 +6 1167 1150 1151 1169 1542 1963 +6 1168 1151 1170 1963 1964 1965 +6 1169 1151 1152 1171 887 1965 +6 1170 1152 875 887 880 877 +6 415 22 23 1173 3338 3883 +6 1172 23 24 1174 1525 3338 +6 1173 24 25 1525 1526 1527 +6 1162 1163 1176 1177 1489 1490 +6 1175 1163 1177 1164 1178 1179 +6 1175 1176 1490 1643 1644 1179 +6 1176 1164 1179 1180 1187 1184 +6 1176 1178 1180 1181 1644 1177 +6 1179 1178 1181 1182 1183 1184 +6 1179 1180 1182 1644 1645 1646 +6 1181 1180 1183 1646 1647 1648 +6 1182 1180 1184 1185 3098 1648 +6 1183 1180 1185 1186 1187 1178 +6 1183 1184 1186 3098 2242 1188 +6 1185 1184 1187 91 92 1188 +6 1186 1184 1178 1164 90 91 +6 1186 92 93 1189 2242 1185 +6 1188 93 94 1190 2242 1660 +6 1189 94 95 1191 1661 1660 +6 1190 95 96 1192 1663 1661 +6 1191 96 97 1193 1671 1663 +6 1192 97 98 1194 1671 1672 +6 1193 98 99 1195 1672 1673 +6 1194 99 100 1196 1673 1674 +6 1195 100 101 1197 1674 1675 +6 1196 101 102 1198 1675 1676 +6 1197 102 103 1199 1501 1676 +6 1198 103 104 1200 1458 1501 +6 1199 104 105 1201 1458 1459 +6 1200 105 106 1202 1459 1460 +6 1201 106 107 1203 1460 1461 +6 1202 107 108 1204 1461 1686 +6 1203 108 109 1205 1688 1686 +6 1204 109 110 1206 1688 1689 +6 1205 110 111 1207 1689 1690 +6 1206 111 112 1208 1690 1691 +6 1207 112 113 1209 1694 1691 +6 1208 113 114 1210 1694 1695 +6 1209 114 115 1211 1695 1696 +6 1210 115 116 1212 1557 1696 +6 1211 116 117 1213 1547 1557 +6 1212 117 118 1214 1547 1548 +6 1213 118 119 1215 1548 1549 +6 1214 119 120 1216 1549 1550 +6 1215 120 121 1217 1550 1551 +6 1216 121 122 1218 1554 1551 +6 1217 122 123 1219 1556 1554 +6 1218 123 124 1220 1717 1556 +6 1219 124 125 1221 1717 1718 +6 1220 125 126 1222 1718 1719 +6 1221 126 127 1223 1719 1720 +6 1222 127 128 1224 1720 1721 +6 1223 128 129 1225 1721 1722 +6 1224 129 130 1226 1722 1723 +6 1225 130 131 1227 1723 1724 +6 1226 131 132 1228 1727 1724 +6 1227 132 133 1229 1727 1728 +6 1228 133 134 1230 1728 1729 +6 1229 134 135 1231 1729 1730 +6 1230 135 136 1232 1730 1731 +6 1231 136 137 1233 1734 1731 +6 1232 137 138 1234 1734 1735 +6 1233 138 139 1235 1735 1736 +6 1234 139 140 1236 1736 1737 +6 1235 140 141 1237 1737 1738 +6 1236 141 142 1238 1738 1739 +6 1237 142 143 1239 1739 1740 +6 1238 143 144 1240 1740 1741 +6 1239 144 145 1241 1741 1742 +6 1240 145 146 1242 1742 1743 +6 1241 146 147 1243 1743 1744 +7 1242 147 148 4 149 1244 1744 +5 1243 149 150 1245 1744 +6 1244 150 151 1246 1744 1745 +6 1245 151 152 1247 1745 1746 +6 1246 152 153 1248 1746 1747 +6 1247 153 154 1249 1747 1748 +6 1248 154 155 924 1250 1748 +6 1249 924 1251 1748 1749 1750 +6 1250 924 925 1252 1750 1751 +6 1251 925 926 1253 1751 1752 +6 1252 926 927 1254 1752 1753 +6 1253 927 928 1255 1753 1754 +6 1254 928 929 1256 1754 1755 +6 1255 929 930 1257 1755 1756 +6 1256 930 931 1258 1756 1757 +6 1257 931 932 933 1259 1757 +6 1258 933 1260 1757 1758 1759 +6 1259 933 934 1261 1759 1760 +6 1260 934 935 1262 1760 1761 +6 1261 935 936 1263 1761 1762 +6 1262 936 937 1264 1762 1763 +6 1263 937 938 1265 1763 1764 +6 1264 938 939 1266 1764 1765 +6 1265 939 940 1267 1765 1766 +6 1266 940 941 1268 1766 1767 +6 1267 941 942 1269 1767 1768 +6 1268 942 943 1270 1768 1769 +6 1269 943 944 1271 1769 1770 +6 1270 944 945 1272 1770 1771 +6 1271 945 946 1273 1771 1772 +6 1272 946 947 1274 1772 1773 +6 1273 947 948 1275 1773 1774 +6 1274 948 949 1276 1774 1775 +6 1275 949 950 1277 1775 1776 +6 1276 950 951 1278 1776 1777 +6 1277 951 952 1279 1777 1778 +6 1278 952 953 1280 1778 1779 +6 1279 953 954 1281 1779 1780 +6 1280 954 955 1282 1780 1781 +6 1281 955 956 1283 1781 1782 +6 1282 956 957 1284 1782 1783 +6 1283 957 958 1285 1783 1784 +6 1284 958 959 1286 1784 1785 +6 1285 959 960 1287 1785 1786 +6 1286 960 961 1288 1786 1787 +6 1287 961 962 1289 1787 1788 +6 1288 962 963 1290 1788 1789 +6 1289 963 964 1291 1789 1790 +6 1290 964 965 1292 1790 1791 +6 1291 965 966 1293 1791 1792 +6 1292 966 967 1294 1792 1793 +6 1293 967 968 1295 1793 1794 +6 1294 968 969 1296 1794 1795 +6 1295 969 970 1297 1795 1796 +6 1296 970 971 1298 1796 1797 +6 1297 971 972 1299 1797 1798 +6 1298 972 973 1300 1798 1301 +6 1299 973 974 975 976 1301 +7 1300 976 977 1302 1798 1299 2101 +6 1301 977 978 1303 2101 2102 +6 1302 978 979 1304 2102 2103 +6 1303 979 980 1305 2103 2104 +6 1304 980 981 1306 2104 2105 +6 1305 981 982 1307 2105 2106 +6 1306 982 983 1308 2106 2107 +6 1307 983 984 1309 1799 2107 +6 1308 984 985 1310 1799 1800 +6 1309 985 986 1311 1800 1801 +6 1310 986 987 1312 1801 1802 +6 1311 987 988 1313 1802 1803 +6 1312 988 989 1314 1803 1804 +6 1313 989 990 1315 1804 1805 +6 1314 990 991 1316 1805 1806 +6 1315 991 992 1317 1806 1807 +6 1316 992 993 1318 1807 1808 +6 1317 993 994 1319 1808 1809 +6 1318 994 995 1320 1809 1810 +6 1319 995 996 1321 1810 1811 +6 1320 996 997 1322 1811 1812 +6 1321 997 998 1323 1812 1813 +6 1322 998 999 1324 1813 1814 +6 1323 999 1000 1325 1814 1815 +6 1324 1000 1001 1326 1815 1816 +6 1325 1001 1002 1327 1816 1817 +6 1326 1002 1003 1328 1817 1818 +6 1327 1003 1004 1329 1818 1819 +6 1328 1004 1005 1330 1819 1820 +6 1329 1005 1006 1331 1820 1821 +6 1330 1006 1007 1332 1821 1822 +6 1331 1007 1008 1333 1822 1823 +6 1332 1008 1009 1334 1823 1824 +6 1333 1009 1010 1335 1824 1825 +6 1334 1010 1011 1336 1825 1826 +6 1335 1011 1012 1337 1826 1827 +6 1336 1012 1013 1015 1338 1827 +6 1337 1015 1339 1827 1828 1829 +6 1338 1015 1016 1340 1829 1830 +6 1339 1016 1341 1830 1831 1832 +6 1340 1016 1017 1018 1342 1832 +6 1341 1018 1019 1343 1832 1833 +6 1342 1019 1020 1344 1833 1834 +6 1343 1020 1021 1345 1834 1835 +6 1344 1021 1022 1346 1835 1836 +6 1345 1022 1023 1347 1836 1837 +6 1346 1023 1024 1025 1348 1837 +6 1347 1025 1349 1837 1838 1839 +6 1348 1025 1026 1350 1839 1840 +6 1349 1026 1027 1351 1840 1841 +6 1350 1027 1028 1352 1841 1842 +6 1351 1028 1029 1353 1842 1843 +6 1352 1029 1030 1354 1843 1844 +6 1353 1030 1031 1355 1844 1845 +6 1354 1031 1032 1356 1845 1846 +6 1355 1032 1033 1357 1846 1847 +6 1356 1033 1034 1358 1847 1848 +6 1357 1034 1035 1359 1848 1849 +6 1358 1035 1036 1360 1849 1850 +6 1359 1036 1037 1361 1850 1851 +6 1360 1037 1038 1362 1851 1852 +6 1361 1038 1039 1363 1852 1853 +6 1362 1039 1040 1364 1853 1854 +6 1363 1040 1041 1365 1854 1855 +6 1364 1041 1042 1366 1855 1856 +6 1365 1042 1043 1367 1856 1857 +6 1366 1043 1044 1368 1857 1858 +6 1367 1044 1045 1369 1858 1859 +6 1368 1045 1046 1370 1859 1860 +6 1369 1046 1047 1371 1860 1861 +6 1370 1047 1048 1372 1861 1862 +6 1371 1048 1049 1373 1862 1863 +6 1372 1049 1050 1374 1863 1864 +6 1373 1050 1051 1375 1864 1865 +6 1374 1051 1052 1376 1865 1866 +6 1375 1052 1053 1377 1866 1867 +6 1376 1053 1054 1378 1867 1868 +6 1377 1054 1055 1379 1868 1869 +6 1378 1055 1056 1380 1869 1870 +6 1379 1056 1057 1381 1870 1871 +6 1380 1057 1058 1382 1871 1872 +6 1381 1058 1059 1383 1872 1873 +6 1382 1059 1060 1384 1873 1874 +6 1383 1060 1061 1385 1874 1875 +6 1384 1061 1062 1386 1875 1876 +6 1385 1062 1063 1387 1876 1877 +6 1386 1063 1064 1388 1877 1878 +6 1387 1064 1065 1389 1878 1879 +6 1388 1065 1066 1390 1879 1880 +6 1389 1066 1067 1391 1880 1881 +6 1390 1067 1068 1392 1881 1882 +6 1391 1068 1069 1393 1882 1883 +6 1392 1069 1070 1394 1883 1884 +6 1393 1070 1071 1395 1884 1885 +6 1394 1071 1072 1396 1885 1886 +6 1395 1072 1073 1397 1886 1887 +6 1396 1073 1074 1398 1887 1888 +6 1397 1074 1075 1399 1888 1889 +6 1398 1075 1076 1400 1889 1890 +6 1399 1076 1077 1401 1890 1891 +6 1400 1077 1078 1402 1891 1892 +6 1401 1078 1079 1403 1892 1893 +6 1402 1079 1080 1404 1893 1894 +6 1403 1080 1081 1405 1894 1895 +6 1404 1081 1082 1406 1895 1896 +6 1405 1082 1083 1407 1896 1897 +6 1406 1083 1084 1408 1897 1898 +6 1407 1084 1085 1409 1898 1899 +6 1408 1085 1086 1410 1899 1900 +6 1409 1086 1087 1411 1900 1901 +6 1410 1087 1088 1412 1901 1902 +6 1411 1088 1089 1413 1902 1903 +6 1412 1089 1090 1414 1903 1904 +6 1413 1090 1091 1415 1904 1905 +6 1414 1091 1092 1416 1905 1906 +6 1415 1092 1093 1417 1906 1907 +6 1416 1093 1094 1418 1907 1908 +6 1417 1094 1095 1419 1908 1909 +6 1418 1095 1096 1420 1909 1910 +6 1419 1096 1097 1421 1910 1911 +6 1420 1097 1098 1422 1911 1912 +6 1421 1098 1099 1423 1912 1913 +6 1422 1099 1100 1424 1913 1914 +6 1423 1100 1101 1425 1914 1915 +6 1424 1101 1102 1426 1915 1916 +6 1425 1102 1103 1427 1916 1917 +6 1426 1103 1104 1428 1917 1918 +6 1427 1104 1105 1429 1918 1919 +6 1428 1105 1106 1430 1919 1920 +6 1429 1106 1107 1431 1920 1921 +6 1430 1107 1108 1432 1921 1922 +6 1431 1108 1109 1433 1922 1923 +6 1432 1109 1110 1434 1923 1924 +6 1433 1110 1111 1435 1924 1925 +6 1434 1111 1112 1436 1925 1926 +6 1435 1112 1113 1437 1926 1927 +6 1436 1113 1114 1116 1438 1927 +6 1437 1116 1117 1118 1439 1927 +6 1438 1118 1119 1440 1927 1928 +6 1439 1119 1120 1441 1928 1929 +6 1440 1120 1121 1442 1929 1930 +6 1441 1121 1122 1443 1930 1931 +6 1442 1122 1123 1444 1931 1932 +6 1443 1123 1124 1445 1932 1933 +6 1444 1124 1125 1446 1462 1933 +6 1445 1125 1126 1447 1462 1463 +6 1446 1126 1127 1448 1463 1464 +6 1447 1127 1128 1449 1464 1465 +6 1448 1128 1129 1450 1465 1466 +6 1449 1129 1130 1131 1451 1466 +6 1450 1131 1452 1466 1467 1468 +6 1451 1131 1132 1453 1468 1469 +6 1452 1132 1133 1454 1455 1469 +6 1453 1133 1455 1456 1457 1134 +6 1453 1454 1456 1469 1470 1471 +6 1455 1454 1457 1471 1472 1473 +6 1456 1454 1134 1473 1474 1153 +6 1199 1200 1459 1501 1502 1680 +6 1458 1200 1201 1460 1680 1681 +6 1459 1201 1202 1461 1681 1682 +6 1460 1202 1203 1682 1685 1686 +6 1445 1446 1463 1933 1934 1935 +6 1462 1446 1447 1464 1935 1936 +6 1463 1447 1448 1465 1936 1937 +6 1464 1448 1449 1466 1937 1938 +6 1465 1449 1450 1451 1467 1938 +6 1466 1451 1468 1938 1939 1940 +6 1467 1451 1452 1469 1940 1941 +6 1468 1452 1453 1455 1470 1941 +6 1469 1455 1471 1941 1942 1943 +6 1470 1455 1456 1472 1943 1944 +6 1471 1456 1473 1944 1945 1946 +6 1472 1456 1457 1474 1946 1947 +6 1473 1457 1153 1154 1491 1947 +7 77 3 1476 1609 1605 1610 1619 +6 1475 3 78 1477 1621 1619 +6 1476 78 79 1478 1621 1622 +6 1477 79 80 1479 1622 1623 +6 1478 80 81 1480 1631 1623 +6 1479 81 82 1481 1631 1632 +6 1480 82 83 1482 1632 1633 +6 1481 83 84 1483 1636 1633 +6 1482 84 85 1484 1486 1636 +6 1483 85 86 1161 1485 1486 +6 1484 1161 1486 1487 1488 1489 +6 1484 1485 1487 1503 1636 1483 +6 1486 1485 1488 1503 1504 1505 +6 1487 1485 1489 1505 1506 1490 +6 1488 1485 1161 1162 1175 1490 +6 1489 1175 1177 1506 1488 1643 +6 1474 1154 1155 1156 1492 1947 +6 1491 1156 1493 1947 1948 1949 +6 1492 1156 1157 1494 1949 1950 +6 1493 1157 1158 1495 1496 1950 +6 1494 1158 1496 1497 1498 1159 +6 1494 1495 1497 1952 1950 1953 +6 1496 1495 1498 1953 1531 1530 +6 1497 1495 1159 1160 1499 1530 +6 1145 1146 1500 1160 1498 1530 +6 1499 1146 1147 1165 1528 1530 +6 1198 1199 1458 1502 1676 1677 +6 1501 1458 1677 1678 1679 1680 +6 1486 1487 1504 1638 1635 1636 +6 1503 1487 1505 1638 1639 1640 +6 1504 1487 1488 1506 1640 1641 +6 1505 1488 1490 1641 1642 1643 +6 584 590 591 1508 1509 583 +6 1507 591 1509 1510 1514 1515 +6 1507 1508 1510 1511 1518 583 +6 1509 1508 1511 1512 1513 1514 +6 1509 1510 1512 1518 1519 1520 +6 1511 1510 1513 1524 1520 1538 +6 1512 1510 1514 1538 1539 1540 +6 1513 1510 1508 1515 602 1540 +6 1514 1508 602 600 592 591 +6 578 579 582 1517 2475 577 +6 1516 582 1518 1519 1522 2475 +6 1517 582 583 1509 1511 1519 +6 1518 1511 1520 1521 1522 1517 +6 1519 1511 1521 1523 1524 1512 +6 1519 1520 1522 912 911 1523 +6 1519 1521 912 1517 2475 915 +6 911 1521 1520 1524 909 910 +6 1523 1520 1512 909 1537 1538 +6 1173 1174 1526 3338 3339 4251 +6 1525 1174 1527 3131 2206 4251 +6 1526 1174 25 26 3131 9782 +6 1500 1165 1529 1530 1531 1532 +6 1528 1165 1166 1532 1533 1534 +6 1498 1499 1500 1528 1531 1497 +6 1530 1528 1532 1953 1497 1954 +6 1531 1528 1529 1533 1954 1955 +6 1532 1529 1534 1535 1955 1956 +6 1533 1529 1535 1536 1167 1166 +6 1533 1534 1536 1956 1957 1958 +6 1535 1534 1167 1542 1961 1958 +6 909 1524 1538 1543 1544 908 +6 1537 1524 1512 1513 1539 1543 +6 1538 1513 1540 1541 1546 1543 +6 1539 1513 1514 602 603 1541 +6 1540 603 1539 1583 1546 1584 +6 1536 1167 1168 1961 1962 1963 +6 1537 1538 1544 1545 1546 1539 +6 1537 1543 1545 1563 1564 908 +6 1544 1543 1546 1563 1581 1578 +6 1545 1543 1539 1583 1581 1541 +6 1212 1213 1548 1557 1558 1559 +6 1547 1213 1214 1549 1562 1559 +6 1548 1214 1215 1550 1711 1562 +6 1549 1215 1216 1551 1552 1711 +6 1550 1216 1552 1553 1554 1217 +6 1550 1551 1553 1711 1712 1713 +6 1552 1551 1554 1555 1713 1714 +6 1553 1551 1555 1556 1218 1217 +6 1553 1554 1556 1714 1715 1716 +6 1555 1554 1218 1716 1717 1219 +6 1211 1212 1547 1558 1696 1697 +6 1557 1547 1559 1560 1697 1698 +6 1558 1547 1560 1561 1562 1548 +6 1558 1559 1561 1698 1699 1700 +6 1560 1559 1562 1700 1701 1710 +6 1561 1559 1548 1710 1711 1549 +6 1544 1545 1564 1565 1577 1578 +6 1544 1563 1565 906 908 907 +6 1564 1563 906 1566 1567 1577 +6 906 1565 1567 1568 2086 905 +6 1566 1565 1568 1569 1570 1577 +6 1566 1567 1569 2086 3767 3768 +6 1568 1567 1570 1571 1572 3768 +6 1569 1567 1571 1575 1576 1577 +6 1569 1570 1572 1573 1574 1575 +7 1569 1571 1573 3770 3768 6318 6320 +5 1572 1571 1574 6320 6321 +7 1573 1571 1575 6321 6362 6361 2476 +6 1574 1571 1570 1576 1579 2476 +6 1575 1570 1577 1578 1579 1580 +6 1576 1570 1567 1565 1563 1578 +6 1577 1563 1576 1580 1581 1545 +6 1575 1576 1580 1587 1588 2476 +6 1579 1576 1578 1581 1582 1587 +6 1580 1578 1545 1582 1583 1546 +6 1580 1581 1583 1585 1586 1587 +6 1582 1581 1546 1541 1584 1585 +6 1583 1541 1585 1603 604 603 +6 1583 1584 1582 1586 1602 1603 +6 1582 1585 1587 1592 1589 1602 +6 1582 1586 1580 1579 1588 1589 +6 1579 1587 1589 1590 2476 2477 +6 1588 1587 1590 1591 1592 1586 +6 1588 1589 1591 6355 6354 2477 +6 1590 1589 1592 1593 1595 6355 +6 1591 1589 1586 1593 1594 1602 +6 1591 1592 1594 1595 1596 1597 +6 1593 1592 1600 1597 1601 1602 +6 1591 1593 1596 6359 6357 6355 +6 1595 1593 1597 1598 3971 6359 +6 1596 1593 1598 1599 1600 1594 +6 1596 1597 1599 3971 3970 6557 +6 1598 1597 1600 6557 6558 612 +6 1599 1597 1594 1601 612 610 +6 1600 1594 1602 1603 609 610 +6 1601 1594 1592 1586 1585 1603 +6 1601 1602 1585 1584 604 609 +6 75 76 1605 429 1606 1609 +5 1604 76 77 1609 1475 +6 429 1604 1607 1608 1609 3520 +6 429 1606 1608 2494 410 3517 +6 1607 1606 3519 3517 1614 3520 +7 1606 1604 1605 1475 1610 1611 3520 +5 1609 1475 1611 1612 1619 +6 1609 1610 1612 1613 1614 3520 +6 1611 1610 1613 1617 1618 1619 +6 1611 1612 1614 1615 1616 1617 +7 1611 1613 1615 3519 1608 3520 3524 +6 1614 1613 1616 3524 3525 3529 +6 1615 1613 1617 3094 3545 3529 +6 1616 1613 1612 1618 3094 3095 +6 1617 1612 1619 1620 3095 1625 +7 1618 1612 1620 1621 1476 1610 1475 +6 1618 1619 1621 1622 1624 1625 +5 1620 1619 1476 1477 1622 +6 1621 1477 1478 1623 1624 1620 +6 1622 1478 1624 1630 1631 1479 +6 1622 1623 1620 1625 1626 1630 +7 1620 1624 1626 1627 1618 3095 4368 +6 1625 1624 1627 1628 1629 1630 +5 1625 1626 1628 4377 4368 +7 1627 1626 1629 4378 4377 2863 7216 +6 1628 1626 1630 2862 1634 2863 +6 1629 1626 1624 1623 1631 2862 +6 1630 1623 1479 1480 1632 2862 +6 1631 1480 1481 1633 1634 2862 +6 1632 1481 1634 1635 1636 1482 +7 1632 1633 1635 1637 2862 1629 2863 +6 1634 1633 1636 1637 1638 1503 +6 1635 1633 1482 1503 1486 1483 +5 1634 1635 1638 2863 2864 +7 1637 1635 1503 1504 1639 2864 2865 +5 1638 1504 1640 2865 2866 +6 1639 1504 1505 1641 2866 2867 +6 1640 1505 1506 1642 2867 2868 +6 1641 1506 1643 2480 2491 2868 +6 1642 1506 1490 1177 1644 2480 +6 1643 1177 1179 1181 1645 2480 +6 1644 1181 1646 2480 2481 2482 +6 1645 1181 1182 1647 2482 1651 +6 1646 1182 1648 1649 1650 1651 +6 1647 1182 1649 1656 3098 1183 +6 1647 1648 1650 1654 1655 1656 +6 1647 1649 1651 1652 1653 1654 +6 1647 1650 1652 2482 1646 2496 +6 1651 1650 1653 2496 2497 2498 +6 1652 1650 1654 2498 2499 2500 +6 1653 1650 1649 1655 2500 2501 +6 1654 1649 1656 1657 2501 2502 +6 1655 1649 1648 1657 1658 3098 +6 1655 1656 1658 1659 2502 2813 +6 1657 1656 1659 1660 2242 3098 +6 1657 1658 1660 1661 1662 2813 +6 1659 1658 1661 1190 1189 2242 +6 1659 1660 1662 1663 1191 1190 +6 1659 1661 1663 1664 1665 2813 +6 1662 1661 1664 1671 1192 1191 +6 1662 1663 1665 1666 1670 1671 +6 1662 1664 1666 1667 2813 2812 +6 1665 1664 1667 1668 1669 1670 +6 1665 1666 1668 2812 2814 2815 +6 1667 1666 1669 2815 2816 2817 +6 1668 1666 1670 2817 2822 2823 +6 1669 1666 1664 1671 1672 2823 +6 1670 1664 1663 1192 1193 1672 +6 1671 1193 1194 1673 2823 1670 +6 1672 1194 1195 1674 2824 2823 +6 1673 1195 1196 1675 3148 2824 +6 1674 1196 1197 1676 3148 3413 +6 1675 1197 1198 1501 1677 3413 +6 1676 1501 1502 1678 3413 3414 +6 1677 1502 1679 3414 3415 3416 +6 1678 1502 1680 3416 5382 5383 +6 1679 1502 1458 1459 1681 5382 +6 1680 1459 1460 1682 1683 5382 +6 1681 1460 1461 1683 1684 1685 +6 1681 1682 1684 3775 5384 5382 +6 1683 1682 1685 3775 3776 3777 +6 1684 1682 1461 1686 1687 3777 +6 1685 1461 1687 1688 1204 1203 +6 1685 1686 1688 3777 3778 3782 +6 1687 1686 1204 1205 1689 3782 +6 1688 1205 1206 1690 3782 3783 +6 1689 1206 1207 1691 1692 3783 +6 1690 1207 1692 1693 1694 1208 +6 1690 1691 1693 3783 3784 3785 +6 1692 1691 1694 3785 3786 3787 +6 1693 1691 1208 1209 1695 3787 +6 1694 1209 1210 1696 3787 3417 +6 1695 1210 1211 1557 1697 3417 +6 1696 1557 1558 1698 3417 3418 +6 1697 1558 1560 1699 3418 3419 +6 1698 1560 1700 1704 2224 3419 +6 1699 1560 1561 1701 1702 1704 +6 1700 1561 1702 1703 1709 1710 +6 1700 1701 1703 1704 1705 1706 +6 1702 1701 1706 1707 1708 1709 +6 1700 1702 1705 1699 2224 2225 +6 1704 1702 1706 2225 2226 2227 +6 1705 1702 1703 1707 2227 2228 +6 1706 1703 1708 2228 2229 2230 +6 1707 1703 1709 2230 2231 2232 +6 1708 1703 1701 1710 1712 2232 +6 1709 1701 1561 1562 1711 1712 +6 1710 1562 1549 1550 1552 1712 +6 1711 1552 1713 2232 1709 1710 +6 1712 1552 1553 1714 2233 2232 +6 1713 1553 1555 1715 2241 2233 +6 1714 1555 1716 2241 2561 2565 +6 1715 1555 1556 1717 2565 2566 +6 1716 1556 1219 1220 1718 2566 +6 1717 1220 1221 1719 2566 2567 +6 1718 1221 1222 1720 2570 2567 +6 1719 1222 1223 1721 3464 2570 +6 1720 1223 1224 1722 3463 3464 +6 1721 1224 1225 1723 3470 3463 +6 1722 1225 1226 1724 1725 3470 +6 1723 1226 1725 1726 1727 1227 +6 1723 1724 1726 2173 3468 3470 +6 1725 1724 1727 2173 2174 2175 +6 1726 1724 1227 1228 1728 2175 +6 1727 1228 1229 1729 2175 2176 +6 1728 1229 1230 1730 2176 2177 +6 1729 1230 1231 1731 1732 2177 +6 1730 1231 1732 1733 1734 1232 +6 1730 1731 1733 2179 2177 2809 +6 1732 1731 1734 3405 2809 3406 +6 1733 1731 1232 1233 1735 3406 +6 1734 1233 1234 1736 3406 3407 +6 1735 1234 1235 1737 3407 3408 +6 1736 1235 1236 1738 3408 3409 +6 1737 1236 1237 1739 3409 3410 +6 1738 1237 1238 1740 3410 3411 +6 1739 1238 1239 1741 3411 3412 +6 1740 1239 1240 1742 3198 3412 +6 1741 1240 1241 1743 3192 3198 +6 1742 1241 1242 1744 3192 1745 +6 1743 1242 1243 1244 1245 1745 +7 1744 1245 1246 1746 3192 1743 3200 +6 1745 1246 1247 1747 2894 3200 +6 1746 1247 1248 1748 2752 2894 +6 1747 1248 1249 1250 1749 2752 +6 1748 1250 1750 2234 2752 2753 +6 1749 1250 1251 1751 2234 2235 +6 1750 1251 1252 1752 2238 2235 +6 1751 1252 1253 1753 2248 2238 +6 1752 1253 1254 1754 2248 2254 +6 1753 1254 1255 1755 2254 2255 +6 1754 1255 1256 1756 2255 2256 +6 1755 1256 1257 1757 2256 2257 +6 1756 1257 1258 1259 1758 2257 +6 1757 1259 1759 2257 2258 2259 +6 1758 1259 1260 1760 2259 2260 +6 1759 1260 1261 1761 2260 2261 +6 1760 1261 1262 1762 2261 2262 +6 1761 1262 1263 1763 2262 2263 +6 1762 1263 1264 1764 2263 2264 +6 1763 1264 1265 1765 2264 2265 +6 1764 1265 1266 1766 2265 2266 +6 1765 1266 1267 1767 2266 2267 +6 1766 1267 1268 1768 2267 2268 +6 1767 1268 1269 1769 2268 2269 +6 1768 1269 1270 1770 2269 2270 +6 1769 1270 1271 1771 2270 2271 +6 1770 1271 1272 1772 2271 2272 +6 1771 1272 1273 1773 2272 2273 +6 1772 1273 1274 1774 2273 2274 +6 1773 1274 1275 1775 2274 2275 +6 1774 1275 1276 1776 2275 2276 +6 1775 1276 1277 1777 2276 2277 +6 1776 1277 1278 1778 2277 2278 +6 1777 1278 1279 1779 2278 2279 +6 1778 1279 1280 1780 2279 2280 +6 1779 1280 1281 1781 2280 2281 +6 1780 1281 1282 1782 2281 2282 +6 1781 1282 1283 1783 2282 2283 +6 1782 1283 1284 1784 2283 2284 +6 1783 1284 1285 1785 2284 2285 +6 1784 1285 1286 1786 2285 2286 +6 1785 1286 1287 1787 2286 2287 +6 1786 1287 1288 1788 2287 2288 +6 1787 1288 1289 1789 2288 2289 +6 1788 1289 1290 1790 2289 2290 +6 1789 1290 1291 1791 2290 2291 +6 1790 1291 1292 1792 2291 2292 +6 1791 1292 1293 1793 2292 2293 +6 1792 1293 1294 1794 2293 2294 +6 1793 1294 1295 1795 2294 2295 +6 1794 1295 1296 1796 2295 2296 +6 1795 1296 1297 1797 2099 2296 +6 1796 1297 1298 1798 2099 2100 +6 1797 1298 1299 1301 2100 2101 +6 1308 1309 1800 2107 2108 2109 +6 1799 1309 1310 1801 2109 2110 +6 1800 1310 1311 1802 2110 2111 +6 1801 1311 1312 1803 2111 2112 +6 1802 1312 1313 1804 2112 2113 +6 1803 1313 1314 1805 2113 2114 +6 1804 1314 1315 1806 2114 2115 +6 1805 1315 1316 1807 2115 2116 +6 1806 1316 1317 1808 2116 2117 +6 1807 1317 1318 1809 2117 2118 +6 1808 1318 1319 1810 2118 2119 +6 1809 1319 1320 1811 2119 2120 +6 1810 1320 1321 1812 2120 2121 +6 1811 1321 1322 1813 2121 2122 +6 1812 1322 1323 1814 2122 2123 +6 1813 1323 1324 1815 2123 2124 +6 1814 1324 1325 1816 2124 2125 +6 1815 1325 1326 1817 2125 2126 +6 1816 1326 1327 1818 2126 2127 +6 1817 1327 1328 1819 2127 2128 +6 1818 1328 1329 1820 2128 2129 +6 1819 1329 1330 1821 2129 2130 +6 1820 1330 1331 1822 2130 2131 +6 1821 1331 1332 1823 2131 2132 +6 1822 1332 1333 1824 2132 2133 +6 1823 1333 1334 1825 2133 2134 +6 1824 1334 1335 1826 2134 2135 +6 1825 1335 1336 1827 2135 2136 +6 1826 1336 1337 1338 1828 2136 +6 1827 1338 1829 2136 2137 2138 +6 1828 1338 1339 1830 2138 2139 +6 1829 1339 1340 1831 2139 2140 +6 1830 1340 1832 2140 2141 2142 +6 1831 1340 1341 1342 1833 2142 +6 1832 1342 1343 1834 2142 2143 +6 1833 1343 1344 1835 2143 2144 +6 1834 1344 1345 1836 2144 2145 +6 1835 1345 1346 1837 2145 2146 +6 1836 1346 1347 1348 1838 2146 +6 1837 1348 1839 2151 2146 2166 +6 1838 1348 1349 1840 2166 2167 +6 1839 1349 1350 1841 2167 2168 +6 1840 1350 1351 1842 2168 2169 +6 1841 1351 1352 1843 2172 2169 +6 1842 1352 1353 1844 2350 2172 +6 1843 1353 1354 1845 2350 2351 +6 1844 1354 1355 1846 2351 2352 +6 1845 1355 1356 1847 2352 2353 +6 1846 1356 1357 1848 2353 2354 +6 1847 1357 1358 1849 2354 2355 +6 1848 1358 1359 1850 2355 2356 +6 1849 1359 1360 1851 2356 2357 +6 1850 1360 1361 1852 2357 2358 +6 1851 1361 1362 1853 2358 2359 +6 1852 1362 1363 1854 2359 2360 +6 1853 1363 1364 1855 2360 2361 +6 1854 1364 1365 1856 2361 2362 +6 1855 1365 1366 1857 1967 2362 +6 1856 1366 1367 1858 1967 1968 +6 1857 1367 1368 1859 1968 1969 +6 1858 1368 1369 1860 1969 1970 +6 1859 1369 1370 1861 1970 1971 +6 1860 1370 1371 1862 1971 1972 +6 1861 1371 1372 1863 1972 1973 +6 1862 1372 1373 1864 1973 1974 +6 1863 1373 1374 1865 1974 1975 +6 1864 1374 1375 1866 1975 1976 +6 1865 1375 1376 1867 1976 1977 +6 1866 1376 1377 1868 1977 1978 +6 1867 1377 1378 1869 1978 1979 +6 1868 1378 1379 1870 1979 1980 +6 1869 1379 1380 1871 1980 1981 +6 1870 1380 1381 1872 1981 1982 +6 1871 1381 1382 1873 1982 1983 +6 1872 1382 1383 1874 1983 1984 +6 1873 1383 1384 1875 1984 1985 +6 1874 1384 1385 1876 1985 1986 +6 1875 1385 1386 1877 1986 1987 +6 1876 1386 1387 1878 1987 1988 +6 1877 1387 1388 1879 1988 1989 +6 1878 1388 1389 1880 1989 1990 +6 1879 1389 1390 1881 1990 1991 +6 1880 1390 1391 1882 1991 1992 +6 1881 1391 1392 1883 1992 1993 +6 1882 1392 1393 1884 1993 1994 +6 1883 1393 1394 1885 1994 1995 +6 1884 1394 1395 1886 1995 1996 +6 1885 1395 1396 1887 1996 1997 +6 1886 1396 1397 1888 1997 1998 +6 1887 1397 1398 1889 1998 1999 +6 1888 1398 1399 1890 1999 2000 +6 1889 1399 1400 1891 2000 2001 +6 1890 1400 1401 1892 2001 2002 +6 1891 1401 1402 1893 2002 2003 +6 1892 1402 1403 1894 2003 2004 +6 1893 1403 1404 1895 2004 2005 +6 1894 1404 1405 1896 2005 2006 +6 1895 1405 1406 1897 2006 2007 +6 1896 1406 1407 1898 2007 2008 +6 1897 1407 1408 1899 2008 2009 +6 1898 1408 1409 1900 2009 2010 +6 1899 1409 1410 1901 2010 2011 +6 1900 1410 1411 1902 2011 2012 +6 1901 1411 1412 1903 2012 2013 +6 1902 1412 1413 1904 2013 2014 +6 1903 1413 1414 1905 2014 2015 +6 1904 1414 1415 1906 2015 2016 +6 1905 1415 1416 1907 2016 2017 +6 1906 1416 1417 1908 2017 2018 +6 1907 1417 1418 1909 2018 2019 +6 1908 1418 1419 1910 2019 2020 +6 1909 1419 1420 1911 2020 2021 +6 1910 1420 1421 1912 2021 2022 +6 1911 1421 1422 1913 2022 2023 +6 1912 1422 1423 1914 2023 2024 +6 1913 1423 1424 1915 2024 2025 +6 1914 1424 1425 1916 2025 2026 +6 1915 1425 1426 1917 2026 2027 +6 1916 1426 1427 1918 2027 2028 +6 1917 1427 1428 1919 2028 2029 +6 1918 1428 1429 1920 2029 2030 +6 1919 1429 1430 1921 2030 2031 +6 1920 1430 1431 1922 2031 2032 +6 1921 1431 1432 1923 2032 2033 +6 1922 1432 1433 1924 2033 2034 +6 1923 1433 1434 1925 2034 2035 +6 1924 1434 1435 1926 2035 2036 +6 1925 1435 1436 1927 2036 1928 +6 1926 1436 1437 1438 1439 1928 +7 1927 1439 1440 1929 2036 1926 2037 +6 1928 1440 1441 1930 2037 2038 +6 1929 1441 1442 1931 2038 2039 +6 1930 1442 1443 1932 2039 2040 +6 1931 1443 1444 1933 2040 2041 +7 1932 1444 1445 1462 1934 2041 2042 +5 1933 1462 1935 2042 2043 +6 1934 1462 1463 1936 2043 2044 +6 1935 1463 1464 1937 2044 2045 +6 1936 1464 1465 1938 2045 2046 +6 1937 1465 1466 1467 1939 2046 +6 1938 1467 1940 2046 2047 2048 +6 1939 1467 1468 1941 2048 2049 +6 1940 1468 1469 1470 1942 2049 +6 1941 1470 1943 2049 2050 2051 +6 1942 1470 1471 1944 2051 2052 +6 1943 1471 1472 1945 2052 2053 +6 1944 1472 1946 2053 2054 2055 +6 1945 1472 1473 1947 2055 1948 +6 1946 1473 1474 1491 1492 1948 +6 1947 1492 1949 2055 1946 2056 +6 1948 1492 1493 1950 1951 2056 +6 1949 1493 1951 1952 1496 1494 +6 1949 1950 1952 2056 2057 2058 +6 1951 1950 1496 1953 2058 2059 +6 1952 1496 1497 1531 1954 2059 +6 1953 1531 1532 1955 2059 2060 +6 1954 1532 1533 1956 2060 2061 +6 1955 1533 1535 1957 2061 2062 +6 1956 1535 1958 1959 2062 2063 +6 1957 1535 1959 1960 1961 1536 +6 1957 1958 1960 2063 2064 2065 +6 1959 1958 1961 2065 2066 2067 +6 1960 1958 1536 1542 1962 2067 +6 1961 1542 1963 2067 2068 2069 +6 1962 1542 1168 1169 1964 2069 +6 1963 1169 1965 1966 2071 2069 +6 1964 1169 1966 888 887 1170 +6 1964 1965 888 2073 2071 2076 +6 1856 1857 1968 2362 2363 2364 +6 1967 1857 1858 1969 2364 2365 +6 1968 1858 1859 1970 2365 2366 +6 1969 1859 1860 1971 2366 2367 +6 1970 1860 1861 1972 2367 2368 +6 1971 1861 1862 1973 2368 2369 +6 1972 1862 1863 1974 2369 2370 +6 1973 1863 1864 1975 2370 2371 +6 1974 1864 1865 1976 2371 2372 +6 1975 1865 1866 1977 2372 2373 +6 1976 1866 1867 1978 2373 2374 +6 1977 1867 1868 1979 2374 2375 +6 1978 1868 1869 1980 2375 2376 +6 1979 1869 1870 1981 2376 2377 +6 1980 1870 1871 1982 2377 2378 +6 1981 1871 1872 1983 2378 2379 +6 1982 1872 1873 1984 2379 2380 +6 1983 1873 1874 1985 2380 2381 +6 1984 1874 1875 1986 2381 2382 +6 1985 1875 1876 1987 2382 2383 +6 1986 1876 1877 1988 2383 2384 +6 1987 1877 1878 1989 2384 2385 +6 1988 1878 1879 1990 2385 2386 +6 1989 1879 1880 1991 2386 2387 +6 1990 1880 1881 1992 2387 2388 +6 1991 1881 1882 1993 2388 2389 +6 1992 1882 1883 1994 2389 2390 +6 1993 1883 1884 1995 2390 2391 +6 1994 1884 1885 1996 2391 2392 +6 1995 1885 1886 1997 2392 2393 +6 1996 1886 1887 1998 2393 2394 +6 1997 1887 1888 1999 2394 2395 +6 1998 1888 1889 2000 2395 2396 +6 1999 1889 1890 2001 2396 2397 +6 2000 1890 1891 2002 2397 2398 +6 2001 1891 1892 2003 2398 2399 +6 2002 1892 1893 2004 2399 2400 +6 2003 1893 1894 2005 2400 2401 +6 2004 1894 1895 2006 2401 2402 +6 2005 1895 1896 2007 2402 2403 +6 2006 1896 1897 2008 2403 2404 +6 2007 1897 1898 2009 2404 2405 +6 2008 1898 1899 2010 2405 2406 +6 2009 1899 1900 2011 2406 2407 +6 2010 1900 1901 2012 2407 2408 +6 2011 1901 1902 2013 2408 2409 +6 2012 1902 1903 2014 2409 2410 +6 2013 1903 1904 2015 2410 2411 +6 2014 1904 1905 2016 2411 2412 +6 2015 1905 1906 2017 2412 2413 +6 2016 1906 1907 2018 2413 2414 +6 2017 1907 1908 2019 2414 2415 +6 2018 1908 1909 2020 2415 2416 +6 2019 1909 1910 2021 2416 2417 +6 2020 1910 1911 2022 2417 2418 +6 2021 1911 1912 2023 2418 2419 +6 2022 1912 1913 2024 2419 2420 +6 2023 1913 1914 2025 2420 2421 +6 2024 1914 1915 2026 2421 2422 +6 2025 1915 1916 2027 2422 2423 +6 2026 1916 1917 2028 2423 2424 +6 2027 1917 1918 2029 2424 2425 +6 2028 1918 1919 2030 2425 2426 +6 2029 1919 1920 2031 2426 2427 +6 2030 1920 1921 2032 2427 2428 +6 2031 1921 1922 2033 2428 2429 +6 2032 1922 1923 2034 2429 2430 +6 2033 1923 1924 2035 2430 2431 +6 2034 1924 1925 2036 2431 2432 +6 2035 1925 1926 1928 2037 2432 +5 2036 1928 1929 2038 2432 +6 2037 1929 1930 2039 2432 2433 +6 2038 1930 1931 2040 2433 2434 +6 2039 1931 1932 2041 2434 2435 +7 2040 1932 1933 2042 2435 2436 2437 +5 2041 1933 1934 2043 2437 +7 2042 1934 1935 2044 2437 2438 2439 +6 2043 1935 1936 2045 2439 2440 +6 2044 1936 1937 2046 2440 2441 +6 2045 1937 1938 1939 2047 2441 +6 2046 1939 2048 2441 2442 2443 +6 2047 1939 1940 2049 2443 2444 +6 2048 1940 1941 1942 2050 2444 +6 2049 1942 2051 2444 2445 2449 +6 2050 1942 1943 2052 2449 2450 +6 2051 1943 1944 2053 2450 2451 +6 2052 1944 1945 2054 2451 2452 +6 2053 1945 2055 2452 2453 2454 +6 2054 1945 1946 1948 2056 2454 +6 2055 1948 1949 1951 2057 2454 +6 2056 1951 2058 2454 2455 2456 +6 2057 1951 1952 2059 2456 2457 +6 2058 1952 1953 1954 2060 2457 +6 2059 1954 1955 2061 2457 2458 +6 2060 1955 1956 2062 2458 2459 +6 2061 1956 1957 2063 2459 2460 +6 2062 1957 1959 2064 2460 2461 +6 2063 1959 2065 2461 2462 2463 +6 2064 1959 1960 2066 2463 2464 +6 2065 1960 2067 2464 2465 2466 +6 2066 1960 1961 1962 2068 2466 +6 2067 1962 2069 2070 2466 2467 +6 2068 1962 1963 2070 2071 1964 +6 2068 2069 2071 2072 2467 2470 +6 2070 2069 1964 2072 2073 1966 +6 2070 2071 2073 2074 2470 2471 +6 2072 2071 1966 2074 2075 2076 +6 2072 2073 2075 2474 2471 2087 +6 2074 2073 2076 2077 2079 2087 +6 2075 2073 1966 888 889 2077 +6 2076 889 890 2078 2079 2075 +6 2077 890 2079 2080 2081 2082 +6 2077 2078 2080 2075 2087 2088 +6 2079 2078 2081 2097 2088 2083 +6 2080 2078 2082 899 902 2083 +6 2081 2078 890 891 895 899 +6 2081 902 904 2084 2097 2080 +6 2083 904 2085 2097 2096 9777 +6 2084 904 905 2086 6094 9777 +6 2085 905 1566 1568 3767 6094 +6 2075 2079 2088 2089 2474 2074 +6 2087 2079 2089 2090 2097 2080 +6 2087 2088 2090 2091 2092 2474 +6 2089 2088 2091 2095 2096 2097 +6 2089 2090 2092 2093 2094 2095 +6 2089 2091 2093 2490 2473 2474 +6 2092 2091 2094 2490 5948 5949 +6 2093 2091 2095 3136 5948 3133 +6 2094 2091 2090 2096 3132 3133 +6 2095 2090 2097 3132 2084 9777 +6 2096 2090 2088 2080 2083 2084 +6 632 404 634 651 650 405 +6 1796 1797 2100 2296 2297 2298 +6 2099 1797 1798 2101 2298 2102 +5 2100 1798 1301 1302 2102 +6 2101 1302 1303 2103 2298 2100 +6 2102 1303 1304 2104 2298 2299 +6 2103 1304 1305 2105 2299 2300 +6 2104 1305 1306 2106 2300 2301 +6 2105 1306 1307 2107 2301 2302 +7 2106 1307 1308 1799 2108 2302 2303 +5 2107 1799 2109 2303 2304 +6 2108 1799 1800 2110 2304 2305 +6 2109 1800 1801 2111 2305 2306 +6 2110 1801 1802 2112 2306 2307 +6 2111 1802 1803 2113 2307 2308 +6 2112 1803 1804 2114 2308 2309 +6 2113 1804 1805 2115 2309 2310 +6 2114 1805 1806 2116 2310 2311 +6 2115 1806 1807 2117 2311 2312 +6 2116 1807 1808 2118 2312 2313 +6 2117 1808 1809 2119 2313 2314 +6 2118 1809 1810 2120 2314 2315 +6 2119 1810 1811 2121 2315 2316 +6 2120 1811 1812 2122 2316 2317 +6 2121 1812 1813 2123 2317 2318 +6 2122 1813 1814 2124 2318 2319 +6 2123 1814 1815 2125 2319 2320 +6 2124 1815 1816 2126 2320 2321 +6 2125 1816 1817 2127 2321 2322 +6 2126 1817 1818 2128 2322 2323 +6 2127 1818 1819 2129 2323 2324 +6 2128 1819 1820 2130 2324 2325 +6 2129 1820 1821 2131 2325 2326 +6 2130 1821 1822 2132 2326 2327 +6 2131 1822 1823 2133 2327 2328 +6 2132 1823 1824 2134 2152 2328 +6 2133 1824 1825 2135 2152 2153 +6 2134 1825 1826 2136 2153 2154 +6 2135 1826 1827 1828 2137 2154 +6 2136 1828 2138 2154 2155 2156 +6 2137 1828 1829 2139 2156 2157 +6 2138 1829 1830 2140 2157 2158 +6 2139 1830 1831 2141 2158 2159 +6 2140 1831 2142 2147 2159 2160 +6 2141 1831 1832 1833 2143 2147 +6 2142 1833 1834 2144 2147 2148 +6 2143 1834 1835 2145 2148 2149 +6 2144 1835 1836 2146 2149 2150 +6 2145 1836 1837 2150 2151 1838 +6 2141 2142 2143 2148 2160 2161 +6 2147 2143 2144 2149 2161 2162 +6 2148 2144 2145 2150 2162 2163 +6 2149 2145 2146 2151 2163 2164 +6 2150 2146 1838 2164 2165 2166 +6 2133 2134 2153 2328 2329 2330 +6 2152 2134 2135 2154 2330 2331 +6 2153 2135 2136 2137 2155 2331 +6 2154 2137 2156 2331 2332 2333 +6 2155 2137 2138 2157 2333 2334 +6 2156 2138 2139 2158 2334 2335 +6 2157 2139 2140 2159 2335 2336 +6 2158 2140 2141 2160 2336 2337 +6 2159 2141 2147 2161 2337 2338 +6 2160 2147 2148 2162 2338 2339 +6 2161 2148 2149 2163 2339 2340 +6 2162 2149 2150 2164 2340 2341 +6 2163 2150 2151 2165 2341 2342 +6 2164 2151 2166 2342 2343 2344 +6 2165 2151 1838 1839 2167 2344 +6 2166 1839 1840 2168 2344 2345 +6 2167 1840 1841 2169 2170 2345 +6 2168 1841 2170 2171 2172 1842 +6 2168 2169 2171 2345 2346 2347 +6 2170 2169 2172 2347 2348 2349 +6 2171 2169 1842 2349 2350 1843 +6 1725 1726 2174 3469 3468 4748 +6 2173 1726 2175 2805 3396 4748 +6 2174 1726 1727 1728 2176 2805 +6 2175 1728 1729 2177 2178 2805 +6 2176 1729 2178 2179 1732 1730 +6 2176 2177 2179 2805 2806 2807 +6 2178 2177 1732 2807 2808 2809 +6 28 29 2181 2182 3852 3853 +6 2180 29 30 2182 2183 2504 +6 2180 2181 2183 2184 2200 3852 +6 2182 2181 2184 2185 2503 2504 +6 2182 2183 2185 2186 2199 2200 +6 2184 2183 2186 2187 2194 2503 +6 2184 2185 2187 2188 2198 2199 +6 2186 2185 2188 2189 2193 2194 +6 2186 2187 2189 2190 2198 9714 +6 2188 2187 2190 2191 2192 2193 +7 2188 2189 2191 9710 9709 9713 9714 +5 2190 2189 2192 9711 9710 +6 2191 2189 2193 2511 2513 9711 +6 2192 2189 2187 2194 2511 2507 +6 2193 2187 2185 2503 2505 2507 +6 416 40 41 2196 9705 6489 +6 2195 41 42 2197 6489 9706 +7 2196 42 43 9706 44 9772 9774 +6 2186 2188 2199 9714 9715 9721 +6 2186 2198 2184 2200 2201 9721 +6 2184 2199 2201 2202 2182 3852 +6 2200 2199 2202 2203 9721 2218 +6 2200 2201 2203 2204 3130 3852 +6 2202 2201 2204 2205 2218 2209 +6 2202 2203 2205 2206 3130 3131 +6 2204 2203 2206 2207 2208 2209 +6 2204 2205 2207 3131 1526 4251 +6 2206 2205 2208 3344 3342 4251 +6 2207 2205 2209 2210 3344 3345 +6 2208 2205 2210 2211 2218 2203 +6 2208 2209 2211 2212 3345 3346 +6 2210 2209 2212 2213 2217 2218 +6 2210 2211 2213 2214 3349 3346 +6 2212 2211 2214 2215 2216 2217 +6 2212 2213 2215 6523 6524 3349 +6 2214 2213 2216 9717 9720 6523 +6 2215 2213 2217 9717 9716 9715 +6 2216 2213 2211 2218 9715 9721 +6 2217 2211 2209 2203 9721 2201 +6 409 60 61 2220 2546 2547 +6 2219 61 62 2221 2550 2547 +6 2220 62 63 2222 2550 2552 +6 2221 63 64 2223 2552 6703 +6 2222 64 6702 6701 6703 65 +6 1699 1704 2225 3419 3420 3421 +6 2224 1704 1705 2226 3421 3422 +6 2225 1705 2227 3422 3423 3427 +6 2226 1705 1706 2228 3427 3428 +6 2227 1706 1707 2229 3428 3429 +6 2228 1707 2230 3429 3430 3431 +6 2229 1707 1708 2231 2239 3431 +6 2230 1708 2232 2233 2239 2240 +6 2231 1708 2233 1713 1712 1709 +6 2231 2232 1713 2240 2241 1714 +6 1749 1750 2235 2236 2243 2753 +6 2234 1750 2236 2237 2238 1751 +6 2234 2235 2237 2243 2244 2245 +6 2236 2235 2238 2245 2246 2247 +6 2237 2235 1751 2247 2248 1752 +6 2230 2231 2240 3431 3432 3436 +6 2239 2231 2233 2241 3436 2562 +6 2240 2233 1714 1715 2561 2562 +6 1188 1189 1660 1658 3098 1185 +6 2234 2236 2244 2753 2754 2755 +6 2243 2236 2245 2755 2756 2757 +6 2244 2236 2237 2246 2757 2758 +6 2245 2237 2247 2758 2759 2760 +6 2246 2237 2238 2248 2760 2761 +6 2247 2238 1752 1753 2254 2761 +6 35 36 2250 3332 3333 3334 +6 2249 36 37 2251 3337 3334 +6 2250 37 38 417 2252 3337 +7 2251 417 2253 6491 6492 9707 3337 +5 2252 417 416 6491 9705 +6 2248 1753 1754 2255 2761 2762 +6 2254 1754 1755 2256 2762 2763 +6 2255 1755 1756 2257 2763 2764 +6 2256 1756 1757 1758 2258 2764 +6 2257 1758 2259 2764 2765 2766 +6 2258 1758 1759 2260 2766 2767 +6 2259 1759 1760 2261 2767 2768 +6 2260 1760 1761 2262 2768 2769 +6 2261 1761 1762 2263 2769 2770 +6 2262 1762 1763 2264 2572 2770 +6 2263 1763 1764 2265 2572 2573 +6 2264 1764 1765 2266 2573 2574 +6 2265 1765 1766 2267 2574 2575 +6 2266 1766 1767 2268 2575 2576 +6 2267 1767 1768 2269 2576 2577 +6 2268 1768 1769 2270 2577 2578 +6 2269 1769 1770 2271 2578 2579 +6 2270 1770 1771 2272 2579 2580 +6 2271 1771 1772 2273 2580 2581 +6 2272 1772 1773 2274 2581 2582 +6 2273 1773 1774 2275 2582 2583 +6 2274 1774 1775 2276 2583 2584 +6 2275 1775 1776 2277 2584 2585 +6 2276 1776 1777 2278 2585 2586 +6 2277 1777 1778 2279 2586 2587 +6 2278 1778 1779 2280 2587 2588 +6 2279 1779 1780 2281 2588 2589 +6 2280 1780 1781 2282 2589 2590 +6 2281 1781 1782 2283 2590 2591 +6 2282 1782 1783 2284 2591 2592 +6 2283 1783 1784 2285 2592 2593 +6 2284 1784 1785 2286 2593 2594 +6 2285 1785 1786 2287 2594 2595 +6 2286 1786 1787 2288 2595 2596 +6 2287 1787 1788 2289 2596 2597 +6 2288 1788 1789 2290 2597 2598 +6 2289 1789 1790 2291 2598 2599 +6 2290 1790 1791 2292 2599 2600 +6 2291 1791 1792 2293 2600 2601 +6 2292 1792 1793 2294 2601 2602 +6 2293 1793 1794 2295 2602 2603 +6 2294 1794 1795 2296 2603 2604 +6 2295 1795 1796 2099 2297 2604 +6 2296 2099 2298 2604 2605 2606 +7 2297 2099 2100 2102 2103 2299 2606 +6 2298 2103 2104 2300 2606 2607 +6 2299 2104 2105 2301 2607 2608 +6 2300 2105 2106 2302 2608 2609 +6 2301 2106 2107 2303 2609 2610 +6 2302 2107 2108 2304 2610 2611 +6 2303 2108 2109 2305 2611 2612 +6 2304 2109 2110 2306 2612 2613 +6 2305 2110 2111 2307 2613 2614 +6 2306 2111 2112 2308 2614 2615 +6 2307 2112 2113 2309 2615 2616 +6 2308 2113 2114 2310 2616 2617 +6 2309 2114 2115 2311 2620 2617 +6 2310 2115 2116 2312 2620 2621 +6 2311 2116 2117 2313 2621 2622 +6 2312 2117 2118 2314 2622 2623 +6 2313 2118 2119 2315 2623 2624 +6 2314 2119 2120 2316 2624 2625 +6 2315 2120 2121 2317 2625 2626 +6 2316 2121 2122 2318 2626 2627 +6 2317 2122 2123 2319 2627 2628 +6 2318 2123 2124 2320 2628 2629 +6 2319 2124 2125 2321 2629 2630 +6 2320 2125 2126 2322 2630 2631 +6 2321 2126 2127 2323 2631 2632 +6 2322 2127 2128 2324 2632 2633 +6 2323 2128 2129 2325 2633 2634 +6 2324 2129 2130 2326 2634 2635 +6 2325 2130 2131 2327 2635 2636 +6 2326 2131 2132 2328 2636 2637 +6 2327 2132 2133 2152 2329 2637 +6 2328 2152 2330 2637 2638 2639 +6 2329 2152 2153 2331 2642 2639 +6 2330 2153 2154 2155 2332 2642 +6 2331 2155 2333 2643 2642 2644 +6 2332 2155 2156 2334 2644 2645 +6 2333 2156 2157 2335 2645 2646 +6 2334 2157 2158 2336 2646 2647 +6 2335 2158 2159 2337 2647 2648 +6 2336 2159 2160 2338 2648 2649 +6 2337 2160 2161 2339 2649 2650 +6 2338 2161 2162 2340 2650 2651 +6 2339 2162 2163 2341 2651 2652 +6 2340 2163 2164 2342 2652 2653 +6 2341 2164 2165 2343 2653 2654 +6 2342 2165 2344 2654 2655 2656 +6 2343 2165 2166 2167 2345 2656 +6 2344 2167 2168 2170 2346 2656 +6 2345 2170 2347 2656 2657 2658 +6 2346 2170 2171 2348 2658 2659 +6 2347 2171 2349 2659 2660 2661 +6 2348 2171 2172 2350 2661 2662 +6 2349 2172 1843 1844 2351 2662 +6 2350 1844 1845 2352 2662 2663 +6 2351 1845 1846 2353 2663 2664 +6 2352 1846 1847 2354 2664 2665 +6 2353 1847 1848 2355 2665 2666 +6 2354 1848 1849 2356 2666 2667 +6 2355 1849 1850 2357 2667 2668 +6 2356 1850 1851 2358 2668 2669 +6 2357 1851 1852 2359 2669 2670 +6 2358 1852 1853 2360 2670 2671 +6 2359 1853 1854 2361 2671 2672 +6 2360 1854 1855 2362 2672 2673 +6 2361 1855 1856 1967 2363 2673 +6 2362 1967 2364 2673 2674 2675 +6 2363 1967 1968 2365 2675 2676 +6 2364 1968 1969 2366 2676 2677 +6 2365 1969 1970 2367 2677 2678 +6 2366 1970 1971 2368 2678 2679 +6 2367 1971 1972 2369 2679 2680 +6 2368 1972 1973 2370 2680 2681 +6 2369 1973 1974 2371 2681 2682 +6 2370 1974 1975 2372 2682 2683 +6 2371 1975 1976 2373 2683 2684 +6 2372 1976 1977 2374 2684 2685 +6 2373 1977 1978 2375 2685 2686 +6 2374 1978 1979 2376 2686 2687 +6 2375 1979 1980 2377 2687 2688 +6 2376 1980 1981 2378 2688 2689 +6 2377 1981 1982 2379 2689 2690 +6 2378 1982 1983 2380 2690 2691 +6 2379 1983 1984 2381 2691 2692 +6 2380 1984 1985 2382 2692 2693 +6 2381 1985 1986 2383 2693 2694 +6 2382 1986 1987 2384 2694 2695 +6 2383 1987 1988 2385 2695 2696 +6 2384 1988 1989 2386 2696 2697 +6 2385 1989 1990 2387 2697 2698 +6 2386 1990 1991 2388 2698 2699 +6 2387 1991 1992 2389 2699 2700 +6 2388 1992 1993 2390 2700 2701 +6 2389 1993 1994 2391 2701 2702 +6 2390 1994 1995 2392 2702 2703 +6 2391 1995 1996 2393 2703 2704 +6 2392 1996 1997 2394 2704 2705 +6 2393 1997 1998 2395 2705 2706 +6 2394 1998 1999 2396 2706 2707 +6 2395 1999 2000 2397 2707 2708 +6 2396 2000 2001 2398 2708 2709 +6 2397 2001 2002 2399 2709 2710 +6 2398 2002 2003 2400 2514 2710 +6 2399 2003 2004 2401 2514 2515 +6 2400 2004 2005 2402 2515 2516 +6 2401 2005 2006 2403 2516 2517 +6 2402 2006 2007 2404 2517 2518 +6 2403 2007 2008 2405 2518 2519 +6 2404 2008 2009 2406 2519 2520 +6 2405 2009 2010 2407 2520 2521 +6 2406 2010 2011 2408 2521 2522 +6 2407 2011 2012 2409 2522 2523 +6 2408 2012 2013 2410 2523 2524 +6 2409 2013 2014 2411 2524 2525 +6 2410 2014 2015 2412 2525 2526 +6 2411 2015 2016 2413 2526 2527 +6 2412 2016 2017 2414 2527 2528 +6 2413 2017 2018 2415 2528 2529 +6 2414 2018 2019 2416 2529 2530 +6 2415 2019 2020 2417 2530 2531 +6 2416 2020 2021 2418 2531 2532 +6 2417 2021 2022 2419 2532 2533 +6 2418 2022 2023 2420 2533 2534 +6 2419 2023 2024 2421 2534 2535 +6 2420 2024 2025 2422 2535 2536 +6 2421 2025 2026 2423 2536 2537 +6 2422 2026 2027 2424 2537 2538 +6 2423 2027 2028 2425 2538 2539 +6 2424 2028 2029 2426 2539 2540 +6 2425 2029 2030 2427 2540 2541 +6 2426 2030 2031 2428 2541 2542 +6 2427 2031 2032 2429 2542 2543 +6 2428 2032 2033 2430 2543 2544 +6 2429 2033 2034 2431 2544 2545 +6 2430 2034 2035 2432 2545 2433 +6 2431 2035 2036 2037 2038 2433 +7 2432 2038 2039 2434 2545 2431 2557 +6 2433 2039 2040 2435 2557 2558 +6 2434 2040 2041 2436 2558 2559 +6 2435 2041 2437 2559 2560 2438 +5 2436 2041 2042 2043 2438 +6 2437 2043 2439 2560 2436 2746 +6 2438 2043 2044 2440 2746 2747 +7 2439 2044 2045 2441 2747 2748 2749 +6 2440 2045 2046 2047 2442 2749 +6 2441 2047 2443 2749 2750 2751 +6 2442 2047 2048 2444 2751 2446 +6 2443 2048 2049 2050 2445 2446 +6 2444 2050 2446 2447 2448 2449 +6 2444 2445 2447 2751 2443 3061 +6 2446 2445 2448 3061 3062 3063 +6 2447 2445 2449 3063 3064 3065 +6 2448 2445 2050 2051 2450 3065 +6 2449 2051 2052 2451 3065 3066 +6 2450 2052 2053 2452 3066 3067 +6 2451 2053 2054 2453 3067 3068 +6 2452 2054 2454 3068 3069 2455 +6 2453 2054 2055 2056 2057 2455 +6 2454 2057 2456 3069 2453 3075 +6 2455 2057 2058 2457 3075 3076 +6 2456 2058 2059 2060 2458 3076 +6 2457 2060 2061 2459 3076 3077 +6 2458 2061 2062 2460 3077 3078 +6 2459 2062 2063 2461 3078 3079 +6 2460 2063 2064 2462 3079 3080 +6 2461 2064 2463 3080 3081 3082 +6 2462 2064 2065 2464 3082 3083 +6 2463 2065 2066 2465 3083 3084 +6 2464 2066 2466 2468 2483 3084 +6 2465 2066 2067 2068 2467 2468 +6 2466 2068 2070 2468 2469 2470 +6 2466 2467 2469 2465 2483 2484 +6 2468 2467 2470 2472 2478 2484 +6 2469 2467 2070 2072 2471 2472 +6 2470 2072 2472 2473 2474 2074 +6 2470 2471 2473 2469 2478 2479 +6 2472 2471 2474 2490 2479 2092 +6 2473 2471 2074 2092 2089 2087 +6 1517 1522 915 916 577 1516 +6 1579 1588 2477 1575 6362 1574 +6 2476 1588 1590 6354 6360 6362 +6 2469 2472 2479 2484 2485 2486 +6 2478 2472 2486 2489 2490 2473 +6 1643 1644 1645 2481 1642 2491 +6 2480 1645 2482 2491 2495 2870 +6 2481 1645 1646 1651 2495 2496 +6 2465 2468 2484 3086 3084 3927 +6 2483 2468 2469 2478 2485 3927 +6 2484 2478 2486 2487 3927 3151 +6 2485 2478 2479 2487 2488 2489 +6 2485 2486 2488 3149 3150 3151 +6 2487 2486 2489 3149 3968 3162 +6 2488 2486 2479 2490 5949 3968 +6 2489 2479 2473 2092 2093 5949 +6 1642 2480 2481 2868 2869 2870 +6 71 72 2493 3437 3438 3442 +6 2492 72 73 410 2494 3437 +6 2493 410 1607 3516 3437 3517 +6 2481 2482 2496 2870 2871 2872 +6 2495 2482 1651 1652 2497 2872 +6 2496 1652 2498 2872 2873 2883 +6 2497 1652 1653 2499 2883 2884 +6 2498 1653 2500 2884 4093 4094 +6 2499 1653 1654 2501 2810 4094 +6 2500 1654 1655 2502 2810 2811 +6 2501 1655 1657 2811 2812 2813 +6 2185 2183 2504 2194 2505 2506 +6 2503 2183 31 2506 30 2181 +6 2194 2503 2506 2507 2508 2509 +6 2505 2503 2509 32 31 2504 +6 2194 2505 2508 2510 2511 2193 +6 2507 2505 2509 2510 3331 3881 +6 2508 2505 2506 32 3331 33 +6 2507 2508 2511 2512 3881 3882 +6 2507 2510 2512 2513 2192 2193 +6 2511 2510 2513 6500 6499 3882 +6 2511 2512 2192 6499 6501 9711 +6 2399 2400 2515 2710 2711 2712 +6 2514 2400 2401 2516 2712 2713 +6 2515 2401 2402 2517 2713 2714 +6 2516 2402 2403 2518 2714 2715 +6 2517 2403 2404 2519 2715 2716 +6 2518 2404 2405 2520 2716 2717 +6 2519 2405 2406 2521 2717 2718 +6 2520 2406 2407 2522 2718 2719 +6 2521 2407 2408 2523 2719 2720 +6 2522 2408 2409 2524 2720 2721 +6 2523 2409 2410 2525 2721 2722 +6 2524 2410 2411 2526 2722 2723 +6 2525 2411 2412 2527 2723 2724 +6 2526 2412 2413 2528 2724 2725 +6 2527 2413 2414 2529 2725 2726 +6 2528 2414 2415 2530 2726 2727 +6 2529 2415 2416 2531 2727 2728 +6 2530 2416 2417 2532 2728 2729 +6 2531 2417 2418 2533 2729 2730 +6 2532 2418 2419 2534 2730 2731 +6 2533 2419 2420 2535 2731 2732 +6 2534 2420 2421 2536 2732 2733 +6 2535 2421 2422 2537 2733 2734 +6 2536 2422 2423 2538 2734 2735 +6 2537 2423 2424 2539 2735 2736 +6 2538 2424 2425 2540 2736 2737 +6 2539 2425 2426 2541 2737 2738 +6 2540 2426 2427 2542 2553 2738 +6 2541 2427 2428 2543 2553 2554 +6 2542 2428 2429 2544 2554 2555 +6 2543 2429 2430 2545 2555 2556 +6 2544 2430 2431 2433 2556 2557 +6 409 2219 2547 2548 2842 2843 +6 2546 2219 2548 2549 2550 2220 +6 2546 2547 2549 2843 2846 2847 +6 2548 2547 2550 2551 2858 2847 +6 2549 2547 2220 2221 2551 2552 +6 2549 2550 2552 6692 2857 2858 +7 2551 2550 2221 2222 6703 6691 6692 +6 2541 2542 2554 2738 2739 2740 +6 2553 2542 2543 2555 2740 2741 +6 2554 2543 2544 2556 2571 2741 +6 2555 2544 2545 2557 2571 2558 +5 2556 2545 2433 2434 2558 +7 2557 2434 2435 2559 2571 2556 2743 +5 2558 2435 2436 2560 2743 +7 2559 2436 2438 2743 2744 2745 2746 +6 2241 1715 2562 2563 2564 2565 +6 2241 2561 2563 3436 2240 3447 +6 2562 2561 2564 3447 3448 3449 +6 2563 2561 2565 3449 3450 2568 +6 2564 2561 1715 1716 2566 2568 +6 2565 1716 1717 1718 2567 2568 +6 2566 1718 2568 2569 2570 1719 +6 2566 2567 2569 3450 2564 2565 +6 2568 2567 2570 3459 3456 3450 +6 2569 2567 1719 3464 3459 1720 +6 2555 2556 2558 2741 2742 2743 +6 2263 2264 2573 2770 2771 2772 +6 2572 2264 2265 2574 2772 2773 +6 2573 2265 2266 2575 2773 2774 +6 2574 2266 2267 2576 2774 2775 +6 2575 2267 2268 2577 2775 2776 +6 2576 2268 2269 2578 2776 2777 +6 2577 2269 2270 2579 2777 2778 +6 2578 2270 2271 2580 2778 2779 +6 2579 2271 2272 2581 2779 2780 +6 2580 2272 2273 2582 2780 2781 +6 2581 2273 2274 2583 2781 2782 +6 2582 2274 2275 2584 2782 2783 +6 2583 2275 2276 2585 2783 2784 +6 2584 2276 2277 2586 2784 2785 +6 2585 2277 2278 2587 2785 2786 +6 2586 2278 2279 2588 2786 2787 +6 2587 2279 2280 2589 2787 2788 +6 2588 2280 2281 2590 2788 2789 +6 2589 2281 2282 2591 2789 2790 +6 2590 2282 2283 2592 2790 2791 +6 2591 2283 2284 2593 2791 2792 +6 2592 2284 2285 2594 2792 2793 +6 2593 2285 2286 2595 2793 2794 +6 2594 2286 2287 2596 2794 2795 +6 2595 2287 2288 2597 2795 2796 +6 2596 2288 2289 2598 2796 2797 +6 2597 2289 2290 2599 2797 2798 +6 2598 2290 2291 2600 2798 2799 +6 2599 2291 2292 2601 2799 2800 +6 2600 2292 2293 2602 2800 2801 +6 2601 2293 2294 2603 2801 2802 +6 2602 2294 2295 2604 2802 2803 +6 2603 2295 2296 2297 2605 2803 +6 2604 2297 2606 2803 2804 2607 +5 2605 2297 2298 2299 2607 +7 2606 2299 2300 2608 2804 2605 2827 +5 2607 2300 2301 2609 2827 +7 2608 2301 2302 2610 2827 2828 2829 +6 2609 2302 2303 2611 2829 2830 +6 2610 2303 2304 2612 2830 2831 +6 2611 2304 2305 2613 2831 2832 +6 2612 2305 2306 2614 2832 2833 +6 2613 2306 2307 2615 2833 2834 +6 2614 2307 2308 2616 2834 2835 +6 2615 2308 2309 2617 2618 2835 +6 2616 2309 2618 2619 2620 2310 +6 2616 2617 2619 2835 2836 2837 +6 2618 2617 2620 2837 2838 2839 +6 2619 2617 2310 2311 2621 2839 +6 2620 2311 2312 2622 2841 2839 +6 2621 2312 2313 2623 2960 2841 +6 2622 2313 2314 2624 2960 2961 +6 2623 2314 2315 2625 2961 2962 +6 2624 2315 2316 2626 2962 2963 +6 2625 2316 2317 2627 2963 2964 +6 2626 2317 2318 2628 2967 2964 +6 2627 2318 2319 2629 2967 2968 +6 2628 2319 2320 2630 2968 2969 +6 2629 2320 2321 2631 2969 2970 +6 2630 2321 2322 2632 2970 2971 +6 2631 2322 2323 2633 2971 2972 +6 2632 2323 2324 2634 2972 2973 +6 2633 2324 2325 2635 2973 2974 +6 2634 2325 2326 2636 2974 2975 +6 2635 2326 2327 2637 2975 2976 +6 2636 2327 2328 2329 2638 2976 +6 2637 2329 2639 2640 2976 2977 +6 2638 2329 2640 2641 2642 2330 +6 2638 2639 2641 2977 2978 2979 +6 2640 2639 2642 2643 2979 2980 +6 2641 2639 2643 2332 2331 2330 +6 2641 2642 2332 2644 2980 2981 +6 2643 2332 2333 2645 2981 2982 +6 2644 2333 2334 2646 2982 2983 +6 2645 2334 2335 2647 2983 2984 +6 2646 2335 2336 2648 2984 2985 +6 2647 2336 2337 2649 2985 2986 +6 2648 2337 2338 2650 2986 2987 +6 2649 2338 2339 2651 2987 2988 +6 2650 2339 2340 2652 2988 2989 +6 2651 2340 2341 2653 2989 2990 +6 2652 2341 2342 2654 2990 2991 +6 2653 2342 2343 2655 2991 2992 +6 2654 2343 2656 2992 2993 2657 +6 2655 2343 2344 2345 2346 2657 +6 2656 2346 2658 2993 2655 2994 +6 2657 2346 2347 2659 2994 2995 +6 2658 2347 2348 2660 2995 2996 +6 2659 2348 2661 2996 2997 2998 +6 2660 2348 2349 2662 2998 2999 +6 2661 2349 2350 2351 2663 2999 +6 2662 2351 2352 2664 2999 3000 +6 2663 2352 2353 2665 3000 3001 +6 2664 2353 2354 2666 3001 3002 +6 2665 2354 2355 2667 3002 3003 +6 2666 2355 2356 2668 3003 3566 +6 2667 2356 2357 2669 3566 3567 +6 2668 2357 2358 2670 3567 3568 +6 2669 2358 2359 2671 3568 3569 +6 2670 2359 2360 2672 3569 3570 +6 2671 2360 2361 2673 3570 3571 +6 2672 2361 2362 2363 2674 3571 +6 2673 2363 2675 3571 3572 3573 +6 2674 2363 2364 2676 3573 3574 +6 2675 2364 2365 2677 3392 3574 +6 2676 2365 2366 2678 3392 3393 +6 2677 2366 2367 2679 3393 3394 +6 2678 2367 2368 2680 3394 3395 +6 2679 2368 2369 2681 3395 3580 +6 2680 2369 2370 2682 3580 3581 +6 2681 2370 2371 2683 3581 3582 +6 2682 2371 2372 2684 3582 3583 +6 2683 2372 2373 2685 3583 3584 +6 2684 2373 2374 2686 3584 3585 +6 2685 2374 2375 2687 3585 3586 +6 2686 2375 2376 2688 3586 3587 +6 2687 2376 2377 2689 3587 3588 +6 2688 2377 2378 2690 3588 3589 +6 2689 2378 2379 2691 3279 3589 +6 2690 2379 2380 2692 3279 3280 +6 2691 2380 2381 2693 3280 3281 +6 2692 2381 2382 2694 3281 3282 +6 2693 2382 2383 2695 3282 3283 +6 2694 2383 2384 2696 3283 3284 +6 2695 2384 2385 2697 3284 3285 +6 2696 2385 2386 2698 3285 3286 +6 2697 2386 2387 2699 3286 3287 +6 2698 2387 2388 2700 3287 3288 +6 2699 2388 2389 2701 3288 3289 +6 2700 2389 2390 2702 3289 3290 +6 2701 2390 2391 2703 3290 3291 +6 2702 2391 2392 2704 3004 3291 +6 2703 2392 2393 2705 3004 3005 +6 2704 2393 2394 2706 3005 3006 +6 2705 2394 2395 2707 3006 3007 +6 2706 2395 2396 2708 3007 3008 +6 2707 2396 2397 2709 3008 3009 +6 2708 2397 2398 2710 3009 3010 +6 2709 2398 2399 2514 2711 3010 +6 2710 2514 2712 3010 3011 3012 +6 2711 2514 2515 2713 3012 3013 +6 2712 2515 2516 2714 3013 3014 +6 2713 2516 2517 2715 3014 3015 +6 2714 2517 2518 2716 3015 3016 +6 2715 2518 2519 2717 3016 3017 +6 2716 2519 2520 2718 3017 3018 +6 2717 2520 2521 2719 3018 3019 +6 2718 2521 2522 2720 3019 3020 +6 2719 2522 2523 2721 3020 3021 +6 2720 2523 2524 2722 3021 3022 +6 2721 2524 2525 2723 3022 3023 +6 2722 2525 2526 2724 3023 3024 +6 2723 2526 2527 2725 3024 3025 +6 2724 2527 2528 2726 3025 3026 +6 2725 2528 2529 2727 3026 3027 +6 2726 2529 2530 2728 3027 3028 +6 2727 2530 2531 2729 3028 3029 +6 2728 2531 2532 2730 3029 3030 +6 2729 2532 2533 2731 3030 3031 +6 2730 2533 2534 2732 3031 3032 +6 2731 2534 2535 2733 3032 3033 +6 2732 2535 2536 2734 3033 3034 +6 2733 2536 2537 2735 3034 3035 +6 2734 2537 2538 2736 3035 3036 +6 2735 2538 2539 2737 3036 3037 +6 2736 2539 2540 2738 3037 3038 +6 2737 2540 2541 2553 2739 3038 +6 2738 2553 2740 3038 3039 3040 +6 2739 2553 2554 2741 3040 3041 +6 2740 2554 2555 2571 2742 3041 +6 2741 2571 2743 3041 3042 2744 +6 2742 2571 2558 2559 2560 2744 +6 2743 2560 2745 3042 2742 3050 +5 2744 2560 2746 3050 3051 +6 2745 2560 2438 2439 2747 3051 +6 2746 2439 2440 2748 3051 3052 +6 2747 2440 2749 3052 3053 2750 +5 2748 2440 2441 2442 2750 +6 2749 2442 2751 3053 2748 3059 +7 2750 2442 2443 2446 3059 3060 3061 +6 1747 1748 1749 2753 2894 2895 +6 2752 1749 2234 2243 2754 2895 +6 2753 2243 2755 2895 2896 2897 +6 2754 2243 2244 2756 2897 2898 +6 2755 2244 2757 2898 2899 2900 +6 2756 2244 2245 2758 2900 2901 +6 2757 2245 2246 2759 2901 2902 +6 2758 2246 2760 2902 2903 2904 +6 2759 2246 2247 2761 2904 2905 +6 2760 2247 2248 2254 2762 2905 +6 2761 2254 2255 2763 2905 2906 +6 2762 2255 2256 2764 2906 2907 +6 2763 2256 2257 2258 2765 2907 +6 2764 2258 2766 2907 2908 2909 +6 2765 2258 2259 2767 2909 2910 +6 2766 2259 2260 2768 2910 2911 +6 2767 2260 2261 2769 2911 2912 +6 2768 2261 2262 2770 2912 2913 +6 2769 2262 2263 2572 2771 2913 +6 2770 2572 2772 2913 2914 2915 +6 2771 2572 2573 2773 2915 2916 +6 2772 2573 2574 2774 2916 2917 +6 2773 2574 2575 2775 2917 2918 +6 2774 2575 2576 2776 2918 2919 +6 2775 2576 2577 2777 2919 2920 +6 2776 2577 2578 2778 2920 2921 +6 2777 2578 2579 2779 2921 2922 +6 2778 2579 2580 2780 2922 2923 +6 2779 2580 2581 2781 2923 2924 +6 2780 2581 2582 2782 2924 2925 +6 2781 2582 2583 2783 2925 2926 +6 2782 2583 2584 2784 2926 2927 +6 2783 2584 2585 2785 2927 2928 +6 2784 2585 2586 2786 2928 2929 +6 2785 2586 2587 2787 2929 2930 +6 2786 2587 2588 2788 2930 2931 +6 2787 2588 2589 2789 2931 2932 +6 2788 2589 2590 2790 2932 2933 +6 2789 2590 2591 2791 2933 2934 +6 2790 2591 2592 2792 2934 2935 +6 2791 2592 2593 2793 2935 2936 +6 2792 2593 2594 2794 2936 2937 +6 2793 2594 2595 2795 2937 2938 +6 2794 2595 2596 2796 2938 2939 +6 2795 2596 2597 2797 2939 2940 +6 2796 2597 2598 2798 2940 2941 +6 2797 2598 2599 2799 2941 2942 +6 2798 2599 2600 2800 2942 2943 +6 2799 2600 2601 2801 2943 2944 +6 2800 2601 2602 2802 2944 2945 +6 2801 2602 2603 2803 2945 2825 +6 2802 2603 2604 2605 2804 2825 +6 2803 2605 2607 2825 2826 2827 +6 2174 2175 2176 2178 2806 3396 +6 2805 2178 2807 3396 3397 3401 +6 2806 2178 2179 2808 3401 3402 +6 2807 2179 2809 3402 3403 3404 +6 2808 2179 1732 3404 3405 1733 +6 2500 2501 2811 4096 4094 4389 +6 2810 2501 2502 2812 4389 2814 +6 2811 2502 2813 1665 1667 2814 +6 2812 2502 1657 1659 1662 1665 +6 2812 1667 2815 3140 4389 2811 +6 2814 1667 1668 2816 2818 3140 +6 2815 1668 2817 2818 2819 2820 +6 2816 1668 1669 2820 2821 2822 +6 2815 2816 2819 3140 3141 3142 +6 2818 2816 2820 3142 3143 3144 +6 2819 2816 2817 2821 3144 3145 +6 2820 2817 2822 3145 3146 3147 +6 2821 2817 1669 2823 2824 3147 +6 2822 1669 2824 1673 1672 1670 +6 2822 2823 1673 3147 3148 1674 +6 2803 2804 2826 2945 2802 2946 +6 2825 2804 2827 2946 2947 2828 +6 2826 2804 2607 2608 2609 2828 +6 2827 2609 2829 2947 2826 2948 +5 2828 2609 2610 2830 2948 +6 2829 2610 2611 2831 2948 2949 +6 2830 2611 2612 2832 2949 2950 +6 2831 2612 2613 2833 2950 2951 +6 2832 2613 2614 2834 2951 2952 +6 2833 2614 2615 2835 2952 2953 +7 2834 2615 2616 2618 2836 2953 2954 +5 2835 2618 2837 2954 2955 +6 2836 2618 2619 2838 2955 2956 +6 2837 2619 2839 2840 2956 2957 +6 2838 2619 2840 2841 2621 2620 +6 2838 2839 2841 2957 2958 2959 +6 2840 2839 2621 2959 2960 2622 +6 409 2546 2843 2844 9691 430 +6 2842 2546 2844 2845 2548 2846 +6 2842 2843 2845 3169 9689 9691 +6 2844 2843 3169 3166 3163 2846 +6 2843 2548 2847 2848 3163 2845 +6 2846 2548 2848 2849 2549 2858 +6 2846 2847 2849 2850 3163 3164 +6 2848 2847 2850 2851 2852 2858 +6 2848 2849 2851 2853 2859 3164 +6 2850 2849 2852 2853 2854 2855 +6 2851 2849 2855 2856 2857 2858 +6 2850 2851 2854 2859 2860 2861 +5 2853 2851 2855 2861 6677 +7 2854 2851 2852 2856 6677 6678 6679 +7 2855 2852 2857 6690 6687 6681 6679 +6 2856 2852 2858 6692 6690 2551 +6 2857 2852 2849 2551 2549 2847 +6 2850 2853 2860 3181 3164 6662 +7 2859 2853 2861 6662 6675 6667 6663 +6 2860 2853 2854 6676 6675 6677 +5 1632 1634 1629 1630 1631 +6 1629 1634 1637 2864 1628 7216 +7 2863 1637 1638 2865 7217 7216 7218 +5 2864 1638 1639 2866 7218 +7 2865 1639 1640 2867 7218 7219 7220 +7 2866 1640 1641 2868 3190 3215 7220 +6 2867 1641 1642 2491 2869 3190 +6 2868 2491 2870 3190 3191 3182 +6 2869 2491 2481 2495 2871 3182 +6 2870 2495 2872 2874 2885 3182 +6 2871 2495 2496 2497 2873 2874 +6 2872 2497 2874 2875 2882 2883 +6 2872 2873 2875 2876 2871 2885 +6 2874 2873 2876 2877 2881 2882 +6 2874 2875 2877 2878 2885 2886 +6 2876 2875 2878 2879 2880 2881 +6 2876 2877 2879 2886 2887 2888 +6 2878 2877 2880 2888 2889 2890 +6 2879 2877 2881 2893 2890 7601 +6 2880 2877 2875 2882 4087 7601 +6 2881 2875 2873 2883 4087 4088 +6 2882 2873 2497 2498 2884 4088 +6 2883 2498 2499 4088 4089 4093 +6 2871 2874 2876 2886 3182 3183 +6 2885 2876 2878 2887 3183 3184 +6 2886 2878 2888 3184 3185 3186 +6 2887 2878 2879 2889 3189 3186 +6 2888 2879 2890 2891 3960 3189 +6 2889 2879 2891 2892 2893 2880 +6 2889 2890 2892 3962 3960 7593 +6 2891 2890 2893 7593 7594 7595 +6 2892 2890 2880 7601 7598 7595 +6 1746 1747 2752 2895 3200 3199 +6 2894 2752 2753 2754 2896 3199 +6 2895 2754 2897 3199 3201 3202 +6 2896 2754 2755 2898 3202 3203 +6 2897 2755 2756 2899 3203 3204 +6 2898 2756 2900 3204 3205 3206 +6 2899 2756 2757 2901 3206 3207 +6 2900 2757 2758 2902 3207 3208 +6 2901 2758 2759 2903 3208 3209 +6 2902 2759 2904 3209 3210 3211 +6 2903 2759 2760 2905 3214 3211 +6 2904 2760 2761 2762 2906 3214 +6 2905 2762 2763 2907 3484 3214 +6 2906 2763 2764 2765 2908 3484 +6 2907 2765 2909 3483 3213 3484 +7 2908 2765 2766 2910 3501 3483 3698 +6 2909 2766 2767 2911 3698 3699 +6 2910 2767 2768 2912 3699 3700 +6 2911 2768 2769 2913 3700 3701 +6 2912 2769 2770 2771 2914 3701 +6 2913 2771 2915 3701 3702 3703 +6 2914 2771 2772 2916 3703 3704 +6 2915 2772 2773 2917 3704 3705 +6 2916 2773 2774 2918 3705 3706 +6 2917 2774 2775 2919 3706 3707 +6 2918 2775 2776 2920 3707 3708 +6 2919 2776 2777 2921 3708 3709 +6 2920 2777 2778 2922 3709 3710 +6 2921 2778 2779 2923 3710 3711 +6 2922 2779 2780 2924 3711 3712 +6 2923 2780 2781 2925 3712 3713 +6 2924 2781 2782 2926 3713 3714 +6 2925 2782 2783 2927 3714 3715 +6 2926 2783 2784 2928 3715 3716 +6 2927 2784 2785 2929 3716 3717 +6 2928 2785 2786 2930 3717 3718 +6 2929 2786 2787 2931 3718 3719 +6 2930 2787 2788 2932 3719 3720 +6 2931 2788 2789 2933 3720 3721 +6 2932 2789 2790 2934 3721 3722 +6 2933 2790 2791 2935 3722 3723 +6 2934 2791 2792 2936 3723 3724 +6 2935 2792 2793 2937 3724 3725 +6 2936 2793 2794 2938 3725 3726 +6 2937 2794 2795 2939 3726 3727 +6 2938 2795 2796 2940 3727 3728 +6 2939 2796 2797 2941 3728 3729 +6 2940 2797 2798 2942 3729 3730 +6 2941 2798 2799 2943 3730 3731 +6 2942 2799 2800 2944 3731 3732 +6 2943 2800 2801 2945 3732 3733 +6 2944 2801 2802 2825 2946 3733 +6 2945 2825 2826 2947 3733 3734 +6 2946 2826 2828 2948 3734 3735 +6 2947 2828 2829 2830 2949 3735 +7 2948 2830 2831 2950 3735 3736 3737 +6 2949 2831 2832 2951 3243 3737 +6 2950 2832 2833 2952 3243 3244 +6 2951 2833 2834 2953 3244 3245 +6 2952 2834 2835 2954 3245 3246 +5 2953 2835 2836 2955 3246 +7 2954 2836 2837 2956 3246 3247 3248 +6 2955 2837 2838 2957 3248 3249 +6 2956 2838 2840 2958 3249 3250 +6 2957 2840 2959 3250 3251 3252 +6 2958 2840 2841 2960 3252 3253 +6 2959 2841 2622 2623 2961 3253 +6 2960 2623 2624 2962 3255 3253 +6 2961 2624 2625 2963 3255 3256 +6 2962 2625 2626 2964 2965 3256 +6 2963 2626 2965 2966 2967 2627 +6 2963 2964 2966 3256 3257 3258 +6 2965 2964 2967 3258 3259 3260 +6 2966 2964 2627 2628 2968 3260 +6 2967 2628 2629 2969 3260 3261 +6 2968 2629 2630 2970 3261 3262 +6 2969 2630 2631 2971 3262 3263 +6 2970 2631 2632 2972 3263 3264 +6 2971 2632 2633 2973 3264 3265 +6 2972 2633 2634 2974 3265 3266 +6 2973 2634 2635 2975 3266 3267 +6 2974 2635 2636 2976 3267 3268 +6 2975 2636 2637 2638 2977 3268 +6 2976 2638 2640 2978 3268 3269 +6 2977 2640 2979 3269 3270 3271 +6 2978 2640 2641 2980 3271 3272 +6 2979 2641 2643 2981 3272 3273 +6 2980 2643 2644 2982 3273 3274 +6 2981 2644 2645 2983 3274 3275 +6 2982 2645 2646 2984 3275 3276 +6 2983 2646 2647 2985 3276 3277 +6 2984 2647 2648 2986 3277 3278 +6 2985 2648 2649 2987 3278 3825 +6 2986 2649 2650 2988 3546 3825 +6 2987 2650 2651 2989 3546 3547 +6 2988 2651 2652 2990 3547 3548 +6 2989 2652 2653 2991 3548 3549 +6 2990 2653 2654 2992 3549 3550 +6 2991 2654 2655 2993 3550 3551 +6 2992 2655 2657 2994 3551 3552 +6 2993 2657 2658 2995 3552 3553 +6 2994 2658 2659 2996 3553 3554 +6 2995 2659 2660 2997 3554 3555 +6 2996 2660 2998 3555 3556 3557 +6 2997 2660 2661 2999 3557 3558 +6 2998 2661 2662 2663 3000 3558 +6 2999 2663 2664 3001 3558 3559 +6 3000 2664 2665 3002 3559 3560 +6 3001 2665 2666 3003 3560 3561 +6 3002 2666 2667 3561 3562 3566 +6 2703 2704 3005 3291 3292 3293 +6 3004 2704 2705 3006 3293 3294 +6 3005 2705 2706 3007 3294 3295 +6 3006 2706 2707 3008 3295 3296 +6 3007 2707 2708 3009 3296 3297 +6 3008 2708 2709 3010 3297 3298 +6 3009 2709 2710 2711 3011 3298 +6 3010 2711 3012 3298 3299 3300 +6 3011 2711 2712 3013 3300 3301 +6 3012 2712 2713 3014 3301 3302 +6 3013 2713 2714 3015 3302 3303 +6 3014 2714 2715 3016 3303 3304 +6 3015 2715 2716 3017 3304 3305 +6 3016 2716 2717 3018 3305 3306 +6 3017 2717 2718 3019 3306 3307 +6 3018 2718 2719 3020 3307 3308 +6 3019 2719 2720 3021 3308 3309 +6 3020 2720 2721 3022 3309 3310 +6 3021 2721 2722 3023 3310 3311 +6 3022 2722 2723 3024 3311 3312 +6 3023 2723 2724 3025 3312 3313 +6 3024 2724 2725 3026 3313 3314 +6 3025 2725 2726 3027 3314 3315 +6 3026 2726 2727 3028 3315 3316 +6 3027 2727 2728 3029 3316 3317 +6 3028 2728 2729 3030 3317 3318 +6 3029 2729 2730 3031 3318 3319 +6 3030 2730 2731 3032 3319 3320 +6 3031 2731 2732 3033 3320 3321 +6 3032 2732 2733 3034 3321 3322 +6 3033 2733 2734 3035 3322 3323 +6 3034 2734 2735 3036 3043 3323 +6 3035 2735 2736 3037 3043 3044 +6 3036 2736 2737 3038 3044 3045 +6 3037 2737 2738 2739 3039 3045 +6 3038 2739 3040 3045 3046 3047 +6 3039 2739 2740 3041 3047 3048 +6 3040 2740 2741 2742 3042 3048 +6 3041 2742 2744 3048 3049 3050 +6 3035 3036 3044 3323 3324 3325 +6 3043 3036 3037 3045 3325 3326 +6 3044 3037 3038 3039 3046 3326 +6 3045 3039 3047 3326 3327 3328 +6 3046 3039 3040 3048 3054 3328 +6 3047 3040 3041 3042 3049 3054 +6 3048 3042 3050 3054 3055 3056 +6 3049 3042 2744 2745 3051 3056 +6 3050 2745 2746 2747 3052 3056 +6 3051 2747 2748 3053 3056 3057 +6 3052 2748 2750 3057 3058 3059 +6 3047 3048 3049 3055 3328 3329 +6 3054 3049 3056 3329 3330 3057 +6 3055 3049 3050 3051 3052 3057 +7 3056 3052 3053 3058 3330 3055 3642 +5 3057 3053 3059 3642 3643 +7 3058 3053 2750 2751 3060 3643 3644 +6 3059 2751 3061 3644 3645 3062 +5 3060 2751 2446 2447 3062 +6 3061 2447 3063 3645 3060 3911 +6 3062 2447 2448 3064 3911 3912 +6 3063 2448 3065 3070 3912 3913 +6 3064 2448 2449 2450 3066 3070 +6 3065 2450 2451 3067 3070 3071 +6 3066 2451 2452 3068 3071 3072 +6 3067 2452 2453 3069 3072 3073 +6 3068 2453 2455 3073 3074 3075 +6 3064 3065 3066 3071 3913 3914 +6 3070 3066 3067 3072 3914 3915 +6 3071 3067 3068 3073 3915 3916 +6 3072 3068 3069 3074 3916 3917 +6 3073 3069 3075 3917 3918 3919 +6 3074 3069 2455 2456 3076 3919 +6 3075 2456 2457 2458 3077 3919 +6 3076 2458 2459 3078 3350 3919 +6 3077 2459 2460 3079 3350 3351 +6 3078 2460 2461 3080 3108 3351 +6 3079 2461 2462 3081 3108 3109 +6 3080 2462 3082 3092 3109 3110 +6 3081 2462 2463 3083 3092 3093 +6 3082 2463 2464 3084 3085 3093 +6 3083 2464 3085 3086 2483 2465 +6 3083 3084 3086 3093 3113 3360 +6 3085 3084 2483 3927 3153 3360 +6 17 18 3088 3089 3090 3091 +6 3087 18 19 3096 3127 3091 +6 17 3087 3090 3099 418 16 +6 3089 3087 3091 3099 3104 3105 +6 3090 3087 3105 3106 3088 3127 +6 3081 3082 3093 3110 3111 3112 +6 3092 3082 3083 3085 3112 3113 +5 1616 1617 3095 4100 3545 +6 3094 1617 1618 4368 4100 1625 +6 3088 19 20 3097 3126 3127 +6 3096 20 21 3126 3129 415 +6 2242 1658 1656 1648 1183 1185 +6 3089 3090 418 3100 3103 3104 +6 418 3099 419 3101 3102 3103 +6 419 3100 3102 3229 3230 3685 +6 3101 3100 3103 3227 3229 3499 +7 3102 3100 3099 3104 3114 3499 3498 +6 3103 3099 3090 3105 3114 3115 +6 3104 3090 3091 3106 3107 3115 +6 3105 3091 3107 3127 3125 3119 +6 3105 3106 3117 3115 3118 3119 +6 3079 3080 3109 3351 3352 3353 +6 3108 3080 3081 3110 3353 3354 +6 3109 3081 3092 3111 3354 3355 +6 3110 3092 3112 3355 3356 3357 +6 3111 3092 3093 3113 3357 3358 +6 3112 3093 3085 3358 3359 3360 +5 3103 3104 3115 3116 3498 +6 3114 3104 3116 3117 3107 3105 +7 3114 3115 3117 3498 3505 3502 3496 +6 3116 3115 3107 3118 6713 3505 +6 3117 3107 3119 3120 6713 6712 +6 3118 3107 3120 3121 3125 3106 +6 3118 3119 3121 3122 6712 6714 +6 3120 3119 3122 3123 3124 3125 +6 3120 3121 3123 3885 3888 6714 +6 3122 3121 3124 3128 3884 3885 +6 3123 3121 3125 3126 3128 3129 +6 3124 3121 3119 3126 3127 3106 +6 3124 3125 3127 3129 3096 3097 +6 3126 3125 3106 3096 3088 3091 +6 3123 3124 3129 3883 3340 3884 +6 3128 3124 3126 415 3883 3097 +6 2202 2204 3131 3852 3853 9782 +6 3130 2204 2206 1526 1527 9782 +6 2095 2096 3133 3134 9777 3139 +6 2095 3132 3134 3135 3136 2094 +6 3133 3132 3135 3137 3138 3139 +6 3133 3134 3136 3137 5947 5946 +6 3133 3135 5946 5944 5948 2094 +6 3135 3134 3138 6091 6092 5947 +6 3137 3134 3139 6091 6090 6093 +6 3138 3134 6093 6094 9777 3132 +6 2814 2815 2818 3141 4389 4387 +6 3140 2818 3142 4386 4385 4387 +6 3141 2818 2819 3143 4391 4386 +6 3142 2819 3144 7768 4391 7769 +6 3143 2819 2820 3145 7775 7769 +6 3144 2820 2821 3146 7775 7776 +6 3145 2821 3147 4232 7776 9792 +6 3146 2821 2822 2824 3148 4232 +6 3147 2824 1674 1675 3413 4232 +6 2487 2488 3150 3157 3158 3162 +6 2487 3149 3151 3152 3156 3157 +6 2487 3150 3152 3153 3927 2485 +6 3151 3150 3153 3154 3155 3156 +6 3151 3152 3154 3927 3086 3360 +6 3153 3152 3155 3359 3360 3361 +6 3154 3152 3156 3361 3362 3363 +6 3155 3152 3150 3157 3678 3363 +6 3156 3150 3149 3158 3159 3678 +6 3157 3149 3159 3160 3161 3162 +6 3157 3158 3160 3677 3678 3946 +6 3159 3158 3161 3946 3947 3963 +6 3160 3158 3162 3963 3964 3965 +6 3161 3158 3149 3968 3965 2488 +6 2846 2848 3164 3165 3166 2845 +6 3163 2848 3165 3181 2859 2850 +6 3163 3164 3166 3167 3178 3181 +6 3163 3165 3167 3168 3169 2845 +6 3166 3165 3168 3178 3175 3172 +6 3166 3167 3169 3170 3171 3172 +6 3166 3168 3170 2844 2845 9689 +6 3169 3168 3171 9688 9687 9689 +5 3170 3168 3172 3173 9688 +6 3171 3168 3173 3174 3175 3167 +6 3171 3172 3174 9692 9688 6654 +7 3173 3172 3175 3176 6655 6653 6654 +6 3174 3172 3176 3177 3178 3167 +5 3174 3175 3177 3451 6655 +6 3176 3175 3178 3179 3180 3451 +6 3177 3175 3179 3167 3165 3181 +6 3177 3178 3180 3181 6661 6662 +6 3177 3179 3451 6658 6660 6661 +6 3178 3165 3179 3164 2859 6662 +6 2870 2871 2885 3183 3191 2869 +6 3182 2885 2886 3184 3217 3191 +6 3183 2886 2887 3185 3194 3217 +6 3184 2887 3186 3187 3193 3194 +6 3185 2887 3187 3188 3189 2888 +6 3185 3186 3188 3193 3197 7585 +6 3187 3186 3189 3959 7587 7585 +6 3188 3186 2888 3959 3960 2889 +6 2868 2869 3191 2867 3215 3216 +6 3190 2869 3182 3216 3217 3183 +6 1742 1743 1745 3198 3199 3200 +6 3185 3187 3194 3195 3196 3197 +6 3185 3193 3195 7223 3217 3184 +7 3194 3193 3196 7223 7222 7205 7204 +6 3195 3193 3197 7197 7198 7204 +6 3196 3193 3187 7584 7197 7585 +6 1741 1742 3192 3199 3412 3201 +7 3198 3192 3200 2894 2895 2896 3201 +5 3199 3192 1745 1746 2894 +6 3199 2896 3202 3412 3198 9752 +6 3201 2896 2897 3203 3471 9752 +6 3202 2897 2898 3204 3471 3472 +6 3203 2898 2899 3205 3472 3473 +6 3204 2899 3206 3473 3474 3475 +6 3205 2899 2900 3207 3475 3476 +6 3206 2900 2901 3208 3476 3477 +6 3207 2901 2902 3209 3477 3478 +6 3208 2902 2903 3210 3478 3479 +6 3209 2903 3211 3212 3479 3480 +6 3210 2903 3212 3213 3214 2904 +6 3210 3211 3213 3480 3481 3482 +7 3212 3211 3214 3482 3483 2908 3484 +6 3213 3211 2904 3484 2906 2905 +6 2867 3190 3216 7221 7220 7222 +6 3215 3190 3191 3217 7222 7223 +6 3216 3191 3183 7223 3194 3184 +6 636 637 3219 4041 3764 3763 +6 3218 637 639 3220 3485 4041 +6 3219 639 3221 3222 3223 3485 +6 3220 639 640 3222 3241 3242 +6 3220 3221 3223 3224 3225 3242 +6 3220 3222 3224 3485 3486 3487 +6 3223 3222 3225 3226 3487 3488 +6 3224 3222 3226 3227 3228 3242 +6 3224 3225 3227 3494 3488 3495 +7 3226 3225 3228 3229 3102 3495 3499 +6 3227 3225 3229 3230 3231 3242 +5 3227 3228 3102 3101 3230 +6 3101 3229 3228 3231 3232 3685 +6 3230 3228 3232 3233 3242 3241 +6 3230 3231 3233 3234 3235 3685 +6 3232 3231 3234 3241 3240 3237 +7 3232 3233 3235 12 11 3236 3237 +5 3232 3234 12 3685 13 +6 11 3234 3237 3238 3239 10 +6 3236 3234 3238 644 3240 3233 +6 3236 3237 3239 648 645 644 +5 3236 3238 10 9 648 +6 644 3237 641 640 3241 3233 +6 640 3240 3221 3242 3231 3233 +6 3221 3241 3222 3225 3228 3231 +6 2950 2951 3244 3737 3738 3739 +6 3243 2951 2952 3245 3739 3740 +6 3244 2952 2953 3246 3740 3741 +7 3245 2953 2954 2955 3247 3741 3742 +5 3246 2955 3248 3742 3743 +6 3247 2955 2956 3249 3743 3744 +6 3248 2956 2957 3250 3744 3745 +6 3249 2957 2958 3251 3745 3746 +6 3250 2958 3252 3746 3747 3748 +6 3251 2958 2959 3253 3254 3748 +6 3252 2959 3254 3255 2961 2960 +6 3252 3253 3255 3748 3749 3750 +6 3254 3253 2961 2962 3256 3750 +6 3255 2962 2963 2965 3257 3750 +6 3256 2965 3258 3750 3751 3752 +6 3257 2965 2966 3259 3752 3753 +6 3258 2966 3260 3753 3754 3755 +6 3259 2966 2967 2968 3261 3755 +6 3260 2968 2969 3262 3755 3756 +6 3261 2969 2970 3263 3756 3757 +6 3262 2970 2971 3264 3757 3758 +6 3263 2971 2972 3265 3758 3759 +6 3264 2972 2973 3266 3759 3760 +7 3265 2973 2974 3267 3760 4055 4052 +5 3266 2974 2975 3268 4055 +6 3267 2975 2976 2977 3269 4055 +7 3268 2977 2978 3270 4055 4054 4056 +5 3269 2978 3271 4056 4057 +6 3270 2978 2979 3272 4057 4058 +6 3271 2979 2980 3273 4058 4059 +6 3272 2980 2981 3274 4059 4060 +6 3273 2981 2982 3275 4060 4061 +6 3274 2982 2983 3276 4061 4062 +6 3275 2983 2984 3277 4065 4062 +6 3276 2984 2985 3278 4065 4066 +6 3277 2985 2986 3827 4066 3825 +6 2690 2691 3280 3589 3590 3591 +6 3279 2691 2692 3281 3591 3592 +6 3280 2692 2693 3282 3592 3593 +6 3281 2693 2694 3283 3593 3594 +6 3282 2694 2695 3284 3594 3595 +6 3283 2695 2696 3285 3595 3596 +6 3284 2696 2697 3286 3596 3597 +6 3285 2697 2698 3287 3597 3598 +6 3286 2698 2699 3288 3598 3599 +6 3287 2699 2700 3289 3599 3600 +6 3288 2700 2701 3290 3600 3601 +6 3289 2701 2702 3291 3601 3602 +6 3290 2702 2703 3004 3292 3602 +6 3291 3004 3293 3602 3603 3604 +6 3292 3004 3005 3294 3604 3605 +6 3293 3005 3006 3295 3605 3606 +6 3294 3006 3007 3296 3606 3607 +6 3295 3007 3008 3297 3607 3608 +6 3296 3008 3009 3298 3608 3609 +6 3297 3009 3010 3011 3299 3609 +6 3298 3011 3300 3609 3610 3611 +6 3299 3011 3012 3301 3611 3612 +6 3300 3012 3013 3302 3612 3613 +6 3301 3013 3014 3303 3613 3614 +6 3302 3014 3015 3304 3614 3615 +6 3303 3015 3016 3305 3615 3616 +6 3304 3016 3017 3306 3616 3617 +6 3305 3017 3018 3307 3617 3618 +6 3306 3018 3019 3308 3618 3619 +6 3307 3019 3020 3309 3619 3620 +6 3308 3020 3021 3310 3620 3621 +6 3309 3021 3022 3311 3621 3622 +6 3310 3022 3023 3312 3622 3623 +6 3311 3023 3024 3313 3623 3624 +6 3312 3024 3025 3314 3624 3625 +6 3313 3025 3026 3315 3625 3626 +6 3314 3026 3027 3316 3626 3627 +6 3315 3027 3028 3317 3627 3628 +6 3316 3028 3029 3318 3628 3629 +6 3317 3029 3030 3319 3629 3630 +6 3318 3030 3031 3320 3630 3631 +6 3319 3031 3032 3321 3631 3632 +6 3320 3032 3033 3322 3632 3633 +6 3321 3033 3034 3323 3633 3634 +6 3322 3034 3035 3043 3324 3634 +6 3323 3043 3325 3634 3635 3636 +6 3324 3043 3044 3326 3636 3637 +6 3325 3044 3045 3046 3327 3637 +6 3326 3046 3328 3637 3638 3639 +6 3327 3046 3047 3054 3329 3639 +6 3328 3054 3055 3330 3639 3640 +6 3329 3055 3057 3640 3641 3642 +6 2508 2509 33 34 3332 3881 +6 3331 34 35 2249 3333 3881 +6 3332 2249 3334 3335 3881 3882 +6 3333 2249 3335 3336 3337 2250 +6 3333 3334 3336 9708 6500 3882 +6 3335 3334 3337 9707 6493 9708 +6 3336 3334 2250 2251 2252 9707 +6 1172 1173 1525 3339 3340 3883 +6 3338 1525 3340 3341 3342 4251 +6 3338 3339 3341 3883 3128 3884 +6 3340 3339 3342 3343 3886 3884 +6 3341 3339 3343 3344 2207 4251 +6 3341 3342 3344 3862 6718 3886 +6 3343 3342 2207 2208 3345 3862 +6 3344 2208 2210 3346 3347 3862 +6 3345 2210 3347 3348 3349 2212 +6 3345 3346 3348 3862 3863 3864 +6 3347 3346 3349 6533 3864 6525 +6 3348 3346 2212 2214 6524 6525 +6 3077 3078 3351 3919 3918 3920 +6 3350 3078 3079 3108 3352 3920 +6 3351 3108 3353 3920 3921 3922 +6 3352 3108 3109 3354 3922 3923 +6 3353 3109 3110 3355 3923 3924 +6 3354 3110 3111 3356 3924 3925 +6 3355 3111 3357 3925 3926 3375 +6 3356 3111 3112 3358 3369 3375 +6 3357 3112 3113 3359 3368 3369 +6 3358 3113 3360 3154 3361 3368 +6 3359 3113 3154 3086 3153 3085 +6 3359 3154 3155 3362 3364 3368 +6 3361 3155 3363 3364 3365 3679 +6 3362 3155 3156 3678 3676 3679 +6 3361 3362 3365 3366 3367 3368 +6 3364 3362 3366 3679 3668 3669 +6 3364 3365 3367 3374 3371 3669 +6 3364 3366 3368 3369 3370 3371 +6 3364 3367 3369 3361 3359 3358 +6 3368 3367 3370 3358 3357 3375 +6 3369 3367 3371 3372 3375 3376 +6 3370 3367 3372 3373 3374 3366 +6 3370 3371 3373 3376 3377 3378 +6 3372 3371 3374 3378 3379 3380 +6 3373 3371 3366 3380 3381 3669 +6 3357 3369 3370 3376 3926 3356 +7 3375 3370 3372 3377 3944 3926 4343 +5 3376 3372 3378 4343 4344 +6 3377 3372 3373 3379 4344 4345 +6 3378 3373 3380 3646 4348 4345 +6 3379 3373 3374 3381 3382 3646 +6 3380 3374 3382 3383 3669 3657 +6 3380 3381 3383 3384 3385 3646 +6 3382 3381 3384 3391 3388 3657 +6 3382 3383 3385 3386 3387 3388 +6 3382 3384 3386 3646 3647 3648 +6 3385 3384 3387 3648 3649 3650 +6 3386 3384 3388 3389 3650 3651 +6 3387 3384 3389 3390 3391 3383 +6 3387 3388 3390 3651 3652 3653 +6 3389 3388 3391 3653 3654 3655 +6 3390 3388 3383 3655 3656 3657 +6 2676 2677 3393 3574 3575 3576 +6 3392 2677 2678 3394 3576 3577 +6 3393 2678 2679 3395 3577 3578 +6 3394 2679 2680 3578 3579 3580 +6 2174 2805 2806 3397 3398 4748 +6 3396 2806 3398 3399 3400 3401 +6 3396 3397 3399 3893 4748 4747 +6 3398 3397 3400 3893 3894 3895 +6 3399 3397 3401 3895 3896 3897 +6 3400 3397 2806 2807 3402 3897 +6 3401 2807 2808 3403 3897 3898 +6 3402 2808 3404 3898 3899 3900 +6 3403 2808 2809 3405 3900 3901 +6 3404 2809 1733 3406 3680 3901 +6 3405 1733 1734 1735 3407 3680 +6 3406 1735 1736 3408 3680 3681 +6 3407 1736 1737 3409 3681 3682 +6 3408 1737 1738 3410 3684 3682 +6 3409 1738 1739 3411 3471 3684 +6 3410 1739 1740 3412 9752 3471 +6 3411 1740 1741 3198 3201 9752 +6 3148 1675 1676 1677 3414 4232 +6 3413 1677 1678 3415 9792 4232 +6 3414 1678 3416 7779 7777 9792 +6 3415 1678 1679 7779 7780 5383 +6 1696 1697 3418 3787 1695 3788 +6 3417 1697 1698 3419 3788 3790 +6 3418 1698 1699 2224 3420 3790 +6 3419 2224 3421 3790 3791 3792 +6 3420 2224 2225 3422 3792 3793 +6 3421 2225 2226 3423 3424 3793 +6 3422 2226 3424 3425 3426 3427 +6 3422 3423 3425 3795 3793 3796 +6 3424 3423 3426 3796 3797 3798 +6 3425 3423 3427 3798 3799 3800 +6 3426 3423 2226 2227 3428 3800 +6 3427 2227 2228 3429 3800 3801 +6 3428 2228 2229 3430 3801 3802 +6 3429 2229 3431 3802 3803 3433 +6 3430 2229 2230 2239 3432 3433 +6 3431 2239 3433 3434 3435 3436 +6 3431 3432 3434 3443 3803 3430 +6 3433 3432 3435 3443 3444 3445 +6 3434 3432 3436 3445 3446 3447 +6 3435 3432 2239 2240 2562 3447 +6 2492 2493 3438 3439 3516 2494 +6 2492 3437 3439 3440 3441 3442 +6 3438 3437 3440 3514 3515 3516 +6 3438 3439 3441 3509 3510 3514 +6 3438 3440 3442 3452 3454 3509 +6 3438 3441 2492 71 3452 70 +6 3433 3434 3444 3803 3804 3805 +6 3443 3434 3445 3805 3806 3807 +6 3444 3434 3435 3446 3807 3808 +6 3445 3435 3447 3808 3809 3448 +6 3446 3435 3436 2562 2563 3448 +6 3447 2563 3449 3809 3446 4108 +6 3448 2563 2564 3450 3455 4108 +6 3449 2564 2568 3455 3456 2569 +7 3176 3177 3180 6656 6655 6657 6658 +6 3442 3441 70 69 3453 3454 +6 69 3452 3454 68 3506 3507 +6 3453 3452 3441 3507 3508 3509 +6 3449 3450 3456 3457 4108 4109 +6 3455 3450 3457 3458 3459 2569 +6 3455 3456 3458 3465 4111 4109 +6 3457 3456 3459 3460 3461 3465 +6 3458 3456 3460 3464 2570 2569 +6 3458 3459 3461 3462 3463 3464 +6 3458 3460 3462 3465 3466 3467 +6 3461 3460 3463 3467 3468 3470 +6 3462 3460 3464 1722 3470 1721 +6 3463 3460 3459 2570 1721 1720 +6 3457 3458 3461 3466 4395 4111 +6 3465 3461 3467 4405 4395 4746 +6 3466 3461 3462 3468 3469 4746 +6 3467 3462 3469 2173 1725 3470 +6 3467 3468 2173 4746 4747 4748 +6 1725 3468 1723 1722 3463 3462 +7 3202 3203 3472 9752 3411 3410 3684 +6 3471 3203 3204 3473 3682 3684 +6 3472 3204 3205 3474 3683 3682 +6 3473 3205 3475 3686 3903 3683 +6 3474 3205 3206 3476 3686 3687 +6 3475 3206 3207 3477 3687 3688 +6 3476 3207 3208 3478 3688 3689 +6 3477 3208 3209 3479 3689 3690 +6 3478 3209 3210 3480 3690 3691 +6 3479 3210 3212 3481 3691 3692 +6 3480 3212 3482 3500 3695 3692 +6 3481 3212 3213 3483 3500 3501 +5 3482 3213 2908 3501 2909 +5 2908 3213 3214 2906 2907 +6 3219 3220 3223 3486 4040 4041 +6 3485 3223 3487 3490 3969 4040 +6 3486 3223 3224 3488 3489 3490 +6 3487 3224 3489 3493 3494 3226 +6 3487 3488 3490 3491 3492 3493 +6 3487 3489 3491 3486 3969 3970 +6 3490 3489 3492 3970 3971 3972 +6 3491 3489 3493 3972 9748 6556 +6 3492 3489 3488 3494 3497 9748 +6 3493 3488 3226 3495 3496 3497 +6 3494 3226 3227 3496 3498 3499 +6 3494 3495 3497 3498 3502 3116 +6 3494 3496 3493 3502 3503 9748 +6 3496 3495 3499 3103 3114 3116 +5 3498 3495 3227 3102 3103 +6 3481 3482 3501 3695 3696 3697 +6 3500 3482 3483 2909 3697 3698 +6 3497 3496 3503 3504 3505 3116 +6 3497 3502 3504 9748 6707 9749 +6 3503 3502 3505 6713 6711 9749 +5 3504 3502 3116 6713 3117 +6 68 3453 3507 6698 6704 67 +6 3506 3453 3454 3508 6698 6705 +6 3507 3454 3509 3511 4523 6705 +6 3508 3454 3441 3440 3510 3511 +6 3509 3440 3511 3512 3513 3514 +6 3509 3510 3512 3771 3508 4523 +6 3511 3510 3513 3771 3772 3773 +6 3512 3510 3514 3773 3774 3521 +6 3513 3510 3440 3439 3515 3521 +6 3514 3439 3516 3521 3522 3518 +6 3515 3439 3437 2494 3517 3518 +6 3516 2494 3518 3519 1608 1607 +6 3516 3517 3519 3522 3515 3523 +6 3518 3517 1608 1614 3523 3524 +5 1614 1608 1606 1609 1611 +6 3514 3515 3522 3774 3513 4532 +6 3521 3515 3518 3523 4117 4532 +6 3522 3518 3519 3524 3526 4117 +6 3523 3519 1614 1615 3525 3526 +6 3524 1615 3526 3527 3528 3529 +6 3524 3525 3527 3523 4117 4118 +6 3526 3525 3528 3530 4118 4119 +6 3527 3525 3529 3530 3531 3544 +6 3528 3525 1615 3544 3545 1616 +6 3527 3528 3531 3532 4119 9787 +6 3530 3528 3532 3533 3543 3544 +6 3530 3531 3533 3534 9787 9788 +6 3532 3531 3534 3535 3542 3543 +6 3532 3533 3535 3536 9788 9789 +6 3534 3533 3536 3537 3541 3542 +6 3534 3535 3537 3538 9789 7179 +6 3536 3535 3538 3539 3540 3541 +6 3536 3537 3539 7183 7180 7179 +6 3538 3537 3540 7183 7184 7185 +6 3539 3537 3541 7185 7186 7213 +6 3540 3537 3535 3542 7213 4373 +6 3541 3535 3533 3543 4373 4098 +6 3542 3533 3531 3544 4097 4098 +6 3543 3531 3528 3529 3545 4097 +6 3544 3529 1616 4100 4097 3094 +6 2987 2988 3547 3825 3826 3830 +6 3546 2988 2989 3548 3830 3831 +6 3547 2989 2990 3549 3831 3832 +6 3548 2990 2991 3550 3832 3833 +6 3549 2991 2992 3551 3833 3834 +6 3550 2992 2993 3552 3810 3834 +6 3551 2993 2994 3553 3810 3811 +6 3552 2994 2995 3554 3811 3812 +6 3553 2995 2996 3555 3812 3813 +6 3554 2996 2997 3556 3813 3814 +6 3555 2997 3557 3814 3815 3816 +6 3556 2997 2998 3558 3816 3817 +6 3557 2998 2999 3000 3559 3817 +6 3558 3000 3001 3560 3817 3818 +6 3559 3001 3002 3561 3818 3819 +6 3560 3002 3003 3562 3563 3819 +6 3561 3003 3563 3564 3565 3566 +6 3561 3562 3564 3819 3820 3821 +6 3563 3562 3565 3821 3822 3823 +6 3564 3562 3566 3823 3824 3567 +6 3565 3562 3003 2667 2668 3567 +6 3566 2668 2669 3568 3824 3565 +6 3567 2669 2670 3569 3851 3824 +6 3568 2670 2671 3570 3880 3851 +6 3569 2671 2672 3571 3892 3880 +6 3570 2672 2673 2674 3572 3892 +6 3571 2674 3573 4238 3892 4258 +6 3572 2674 2675 3574 4258 4259 +6 3573 2675 2676 3392 3575 4259 +6 3574 3392 3576 4259 4260 4264 +6 3575 3392 3393 3577 4264 4265 +6 3576 3393 3394 3578 4265 4266 +6 3577 3394 3395 3579 4266 4267 +6 3578 3395 3580 4267 4268 4269 +6 3579 3395 2680 2681 3581 4269 +6 3580 2681 2682 3582 4142 4269 +6 3581 2682 2683 3583 4142 4143 +6 3582 2683 2684 3584 4143 4144 +6 3583 2684 2685 3585 4144 4145 +6 3584 2685 2686 3586 4145 4146 +6 3585 2686 2687 3587 4146 4147 +6 3586 2687 2688 3588 4147 4148 +6 3587 2688 2689 3589 4148 4149 +6 3588 2689 2690 3279 3590 4149 +6 3589 3279 3591 4149 4150 4151 +6 3590 3279 3280 3592 4151 4152 +6 3591 3280 3281 3593 4152 4153 +6 3592 3281 3282 3594 4153 4154 +6 3593 3282 3283 3595 4154 4155 +6 3594 3283 3284 3596 4155 4156 +6 3595 3284 3285 3597 4156 4157 +6 3596 3285 3286 3598 4157 4158 +6 3597 3286 3287 3599 4158 4159 +6 3598 3287 3288 3600 4159 4160 +6 3599 3288 3289 3601 4160 4161 +6 3600 3289 3290 3602 4161 4162 +6 3601 3290 3291 3292 3603 4162 +6 3602 3292 3604 4162 4163 4164 +6 3603 3292 3293 3605 4164 4165 +6 3604 3293 3294 3606 4165 4166 +6 3605 3294 3295 3607 4166 4167 +6 3606 3295 3296 3608 4167 4168 +6 3607 3296 3297 3609 4168 4169 +6 3608 3297 3298 3299 3610 4169 +6 3609 3299 3611 4169 4170 4171 +6 3610 3299 3300 3612 4171 4172 +6 3611 3300 3301 3613 4172 4173 +6 3612 3301 3302 3614 4173 4174 +6 3613 3302 3303 3615 4174 4175 +6 3614 3303 3304 3616 4175 4176 +6 3615 3304 3305 3617 4176 4177 +6 3616 3305 3306 3618 4177 4178 +6 3617 3306 3307 3619 4178 4179 +6 3618 3307 3308 3620 4179 4180 +6 3619 3308 3309 3621 4180 4181 +6 3620 3309 3310 3622 4181 4182 +6 3621 3310 3311 3623 4182 4183 +6 3622 3311 3312 3624 4183 4184 +6 3623 3312 3313 3625 4184 4185 +6 3624 3313 3314 3626 4185 4186 +6 3625 3314 3315 3627 4186 4187 +6 3626 3315 3316 3628 4187 4188 +6 3627 3316 3317 3629 4188 4189 +6 3628 3317 3318 3630 4189 4190 +6 3629 3318 3319 3631 4190 4191 +6 3630 3319 3320 3632 4191 4192 +6 3631 3320 3321 3633 4192 4193 +6 3632 3321 3322 3634 4193 4194 +6 3633 3322 3323 3324 3635 4194 +6 3634 3324 3636 3904 4194 4195 +6 3635 3324 3325 3637 3904 3905 +6 3636 3325 3326 3327 3638 3905 +6 3637 3327 3639 3905 3906 3907 +6 3638 3327 3328 3329 3640 3907 +6 3639 3329 3330 3641 3907 3908 +6 3640 3330 3642 3908 3909 3643 +5 3641 3330 3057 3058 3643 +7 3642 3058 3059 3644 3909 3641 3928 +6 3643 3059 3060 3645 3910 3928 +5 3644 3060 3062 3910 3911 +6 3382 3385 3647 3380 3379 4348 +6 3646 3385 3648 4348 4349 4350 +6 3647 3385 3386 3649 4353 4350 +6 3648 3386 3650 3658 4353 4354 +6 3649 3386 3387 3651 3658 3659 +6 3650 3387 3389 3652 3659 3660 +6 3651 3389 3653 3660 3661 3662 +6 3652 3389 3390 3654 3662 3663 +6 3653 3390 3655 3663 3664 3665 +6 3654 3390 3391 3656 3665 3666 +6 3655 3391 3657 3666 3667 3668 +6 3656 3391 3383 3668 3669 3381 +6 3649 3650 3659 4354 4355 4359 +6 3658 3650 3651 3660 4372 4359 +6 3659 3651 3652 3661 9794 4372 +6 3660 3652 3662 4907 4909 9794 +6 3661 3652 3653 3663 3670 4907 +6 3662 3653 3654 3664 3670 3671 +6 3663 3654 3665 3671 3672 3673 +6 3664 3654 3655 3666 3673 3674 +6 3665 3655 3656 3667 3674 3675 +6 3666 3656 3668 3675 3676 3679 +6 3667 3656 3657 3669 3365 3679 +6 3668 3657 3381 3365 3366 3374 +6 3662 3663 3671 4904 4906 4907 +6 3670 3663 3664 3672 4903 4904 +6 3671 3664 3673 5919 4903 3952 +6 3672 3664 3665 3674 3951 3952 +6 3673 3665 3666 3675 3945 3951 +6 3674 3666 3667 3676 3677 3945 +6 3675 3667 3677 3678 3363 3679 +6 3675 3676 3678 3159 3945 3946 +6 3677 3676 3159 3157 3156 3363 +6 3363 3676 3362 3365 3668 3667 +6 3405 3406 3407 3681 3901 3902 +6 3680 3407 3408 3682 3683 3902 +7 3681 3408 3683 3473 3472 3684 3409 +6 3681 3682 3473 3902 3903 3474 +5 3472 3682 3409 3410 3471 +7 419 3101 3230 3232 3235 13 14 +7 3474 3475 3687 3903 4666 4665 4689 +5 3686 3475 3476 3688 4689 +7 3687 3476 3477 3689 4689 4690 4691 +6 3688 3477 3478 3690 4691 4692 +6 3689 3478 3479 3691 4692 4693 +6 3690 3479 3480 3692 3693 4693 +6 3691 3480 3693 3694 3695 3481 +6 3691 3692 3694 4693 4694 4695 +6 3693 3692 3695 4695 4696 4697 +6 3694 3692 3481 3500 3696 4697 +6 3695 3500 3697 4697 4698 4699 +6 3696 3500 3501 3698 4699 4700 +6 3697 3501 2909 2910 3699 4700 +6 3698 2910 2911 3700 3973 4700 +6 3699 2911 2912 3701 3973 3974 +6 3700 2912 2913 2914 3702 3974 +6 3701 2914 3703 3974 3975 3976 +6 3702 2914 2915 3704 3976 3977 +6 3703 2915 2916 3705 3977 3978 +6 3704 2916 2917 3706 3978 3979 +6 3705 2917 2918 3707 3979 3980 +6 3706 2918 2919 3708 3980 3981 +6 3707 2919 2920 3709 3981 3982 +6 3708 2920 2921 3710 3982 3983 +6 3709 2921 2922 3711 3983 3984 +6 3710 2922 2923 3712 3984 3985 +6 3711 2923 2924 3713 3985 3986 +6 3712 2924 2925 3714 3986 3987 +6 3713 2925 2926 3715 3987 3988 +6 3714 2926 2927 3716 3988 3989 +6 3715 2927 2928 3717 3989 3990 +6 3716 2928 2929 3718 3990 3991 +6 3717 2929 2930 3719 3991 3992 +6 3718 2930 2931 3720 3992 3993 +6 3719 2931 2932 3721 3993 3994 +6 3720 2932 2933 3722 3994 3995 +6 3721 2933 2934 3723 3995 3996 +6 3722 2934 2935 3724 3996 3997 +6 3723 2935 2936 3725 3997 3998 +6 3724 2936 2937 3726 3998 3999 +6 3725 2937 2938 3727 3999 4000 +6 3726 2938 2939 3728 4000 4001 +6 3727 2939 2940 3729 4001 4002 +6 3728 2940 2941 3730 4002 4003 +6 3729 2941 2942 3731 4003 4004 +6 3730 2942 2943 3732 4004 4005 +6 3731 2943 2944 3733 4005 4006 +6 3732 2944 2945 2946 3734 4006 +6 3733 2946 2947 3735 4006 4007 +6 3734 2947 2948 2949 3736 4007 +6 3735 2949 3737 4007 4008 3738 +5 3736 2949 2950 3243 3738 +6 3737 3243 3739 4008 3736 4013 +6 3738 3243 3244 3740 4013 4014 +6 3739 3244 3245 3741 4014 4015 +6 3740 3245 3246 3742 4015 4016 +6 3741 3246 3247 3743 4016 4017 +6 3742 3247 3248 3744 4017 4018 +6 3743 3248 3249 3745 4018 4019 +6 3744 3249 3250 3746 4019 4020 +6 3745 3250 3251 3747 4020 4021 +6 3746 3251 3748 4021 4022 4023 +6 3747 3251 3252 3254 3749 4023 +6 3748 3254 3750 4023 4024 4025 +7 3749 3254 3255 3256 3257 3751 4025 +5 3750 3257 3752 4025 4026 +6 3751 3257 3258 3753 4026 4027 +6 3752 3258 3259 3754 4030 4027 +7 3753 3259 3755 4038 4030 4047 3756 +5 3754 3259 3260 3261 3756 +6 3755 3261 3262 3757 4047 3754 +6 3756 3262 3263 3758 4047 4048 +6 3757 3263 3264 3759 4048 4049 +6 3758 3264 3265 3760 4049 4050 +6 3759 3265 3266 4050 4051 4052 +6 616 618 3762 3765 3766 3764 +6 3761 618 626 628 3763 3764 +6 3762 628 3764 3218 636 630 +6 3762 3763 3766 3761 4041 3218 +6 616 3761 3766 4039 6558 613 +6 3765 3761 3764 4039 4040 4041 +5 2086 1568 3768 3769 6094 +6 3767 1568 3769 3770 1572 1569 +6 3767 3768 3770 6093 6094 6095 +7 3769 3768 1572 6095 6089 6318 6319 +6 3511 3512 3772 4523 4524 4525 +6 3771 3512 3773 4525 4526 4529 +6 3772 3512 3513 3774 4529 4530 +6 3773 3513 3521 4530 4531 4532 +6 1683 1684 3776 5392 5386 5384 +6 3775 1684 3777 5621 5392 3779 +6 3776 1684 1685 1687 3778 3779 +6 3777 1687 3779 3780 3781 3782 +6 3777 3778 3780 7792 5621 3776 +6 3779 3778 3781 7799 7793 7792 +6 3780 3778 3782 7799 3784 3783 +6 3781 3778 1687 1688 1689 3783 +6 3782 1689 1690 1692 3784 3781 +6 3783 1692 3785 7799 3781 7800 +6 3784 1692 1693 3786 7800 7801 +6 3785 1693 3787 3788 3789 7801 +6 3786 1693 1694 1695 3417 3788 +6 3787 3417 3418 3786 3789 3790 +6 3786 3788 3790 7801 7802 3791 +6 3789 3788 3418 3419 3420 3791 +6 3790 3420 3792 7802 3789 7803 +6 3791 3420 3421 3793 3794 7803 +6 3792 3421 3794 3795 3424 3422 +6 3792 3793 3795 7803 7804 7805 +6 3794 3793 3424 3796 7805 7806 +6 3795 3424 3425 3797 7810 7806 +6 3796 3425 3798 3953 7810 7811 +6 3797 3425 3426 3799 3953 3954 +6 3798 3426 3800 3954 3955 3956 +6 3799 3426 3427 3428 3801 3956 +6 3800 3428 3429 3802 3956 3957 +6 3801 3429 3430 3803 3957 3958 +6 3802 3430 3433 3443 3804 3958 +6 3803 3443 3805 3958 4101 4240 +6 3804 3443 3444 3806 4101 4102 +6 3805 3444 3807 4102 4103 4104 +6 3806 3444 3445 3808 4104 4105 +6 3807 3445 3446 3809 4105 4106 +6 3808 3446 3448 4106 4107 4108 +6 3551 3552 3811 3834 3835 3836 +6 3810 3552 3553 3812 3836 3837 +6 3811 3553 3554 3813 3837 3838 +6 3812 3554 3555 3814 3838 3839 +6 3813 3555 3556 3815 3839 3840 +6 3814 3556 3816 3840 3841 3842 +6 3815 3556 3557 3817 3842 3843 +6 3816 3557 3558 3559 3818 3843 +6 3817 3559 3560 3819 3843 3844 +6 3818 3560 3561 3563 3820 3844 +6 3819 3563 3821 3844 3845 3846 +6 3820 3563 3564 3822 3846 3847 +6 3821 3564 3823 3847 3848 3849 +6 3822 3564 3565 3824 3849 3850 +6 3823 3565 3567 3850 3851 3568 +6 2987 3546 3826 3827 3278 2986 +6 3825 3546 3827 3828 3829 3830 +6 3825 3826 3828 4070 4066 3278 +6 3827 3826 3829 4757 4070 4764 +6 3828 3826 3830 4764 4765 4766 +6 3829 3826 3546 3547 3831 4766 +6 3830 3547 3548 3832 4766 4767 +6 3831 3548 3549 3833 4767 4768 +6 3832 3549 3550 3834 4771 4768 +6 3833 3550 3551 3810 3835 4771 +6 3834 3810 3836 5017 4771 5025 +6 3835 3810 3811 3837 5025 5026 +6 3836 3811 3812 3838 5026 5027 +6 3837 3812 3813 3839 4406 5027 +6 3838 3813 3814 3840 3865 4406 +6 3839 3814 3815 3841 3865 3866 +6 3840 3815 3842 3866 3867 3868 +6 3841 3815 3816 3843 3854 3868 +6 3842 3816 3817 3818 3844 3854 +6 3843 3818 3819 3820 3845 3854 +6 3844 3820 3846 3854 3855 3856 +6 3845 3820 3821 3847 3856 3857 +6 3846 3821 3822 3848 3857 3858 +6 3847 3822 3849 3861 3858 3877 +6 3848 3822 3823 3850 3877 3878 +6 3849 3823 3824 3851 3878 3879 +6 3850 3824 3568 3879 3880 3569 +6 2182 2200 2180 3853 2202 3130 +6 2180 3852 28 27 3130 9782 +6 3842 3843 3844 3845 3855 3868 +6 3854 3845 3856 3868 3869 3870 +6 3855 3845 3846 3857 3870 3871 +6 3856 3846 3847 3858 3859 3871 +6 3857 3847 3859 3860 3861 3848 +6 3857 3858 3860 3871 3872 3873 +6 3859 3858 3861 3873 3874 3875 +6 3860 3858 3848 3875 3876 3877 +6 3344 3345 3347 3863 6718 3343 +6 3862 3347 3864 6717 6716 6718 +7 3863 3347 6533 6532 3348 6534 6717 +6 3839 3840 3866 4406 4407 4408 +6 3865 3840 3841 3867 4408 4409 +6 3866 3841 3868 4409 4410 3869 +6 3867 3841 3842 3854 3855 3869 +6 3868 3855 3870 4410 3867 4421 +6 3869 3855 3856 3871 4421 4422 +6 3870 3856 3857 3859 3872 4422 +6 3871 3859 3873 4422 4423 4424 +6 3872 3859 3860 3874 4424 4425 +6 3873 3860 3875 4425 4426 4427 +6 3874 3860 3861 3876 4427 4428 +6 3875 3861 3877 4428 4429 3889 +6 3876 3861 3848 3849 3878 3889 +6 3877 3849 3850 3879 3889 3890 +6 3878 3850 3851 3880 3890 3891 +6 3879 3851 3569 3891 3892 3570 +6 2508 3331 2510 3882 3332 3333 +6 2510 3881 3335 6500 2512 3333 +6 3338 3340 3128 1172 415 3129 +6 3128 3340 3123 3885 3886 3341 +6 3123 3884 3886 3887 3888 3122 +6 3885 3884 3887 3343 6718 3341 +6 3885 3886 3888 6539 6716 6718 +6 3885 3887 3122 6714 6715 6539 +6 3877 3878 3890 4429 3876 4252 +6 3889 3878 3879 3891 4237 4252 +6 3890 3879 3880 3892 4237 4238 +6 3891 3880 3570 4238 3572 3571 +6 3398 3399 3894 4747 4745 4744 +6 3893 3399 3895 4744 4749 4750 +6 3894 3399 3400 3896 4753 4750 +6 3895 3400 3897 4662 4759 4753 +6 3896 3400 3401 3402 3898 4662 +6 3897 3402 3403 3899 4662 4663 +6 3898 3403 3900 4663 4664 4665 +6 3899 3403 3404 3901 4665 4666 +6 3900 3404 3405 3680 3902 4666 +6 3901 3680 3681 3683 3903 4666 +5 3902 3683 3474 4666 3686 +6 3635 3636 3905 4195 4196 4197 +6 3904 3636 3637 3638 3906 4197 +6 3905 3638 3907 4197 4198 4199 +6 3906 3638 3639 3640 3908 4199 +6 3907 3640 3641 3909 4199 4200 +6 3908 3641 3643 3928 4200 4201 +5 3644 3645 3911 3928 3929 +7 3910 3645 3062 3063 3912 3929 3930 +7 3911 3063 3064 3913 3930 3931 3932 +6 3912 3064 3070 3914 3932 3933 +6 3913 3070 3071 3915 3933 3934 +6 3914 3071 3072 3916 3934 3935 +6 3915 3072 3073 3917 3935 3936 +6 3916 3073 3074 3918 3936 3937 +6 3917 3074 3919 3350 3920 3937 +6 3918 3074 3075 3076 3077 3350 +6 3918 3350 3351 3352 3921 3937 +6 3920 3352 3922 3937 3938 3939 +6 3921 3352 3353 3923 3939 3940 +6 3922 3353 3354 3924 3940 3941 +6 3923 3354 3355 3925 3941 3942 +6 3924 3355 3356 3926 3942 3943 +6 3925 3356 3375 3943 3944 3376 +6 3086 2483 2484 2485 3151 3153 +6 3909 3643 3644 3910 3929 4201 +6 3928 3910 3911 3930 4201 4202 +6 3929 3911 3912 3931 4202 4203 +6 3930 3912 3932 4203 4204 4205 +5 3931 3912 3913 3933 4205 +6 3932 3913 3914 3934 4205 4206 +6 3933 3914 3915 3935 4206 4207 +6 3934 3915 3916 3936 4207 4208 +6 3935 3916 3917 3937 4208 3938 +6 3936 3917 3918 3920 3921 3938 +6 3937 3921 3939 4208 3936 4336 +6 3938 3921 3922 3940 4336 4337 +6 3939 3922 3923 3941 4337 4338 +6 3940 3923 3924 3942 4338 4339 +6 3941 3924 3925 3943 4339 4340 +6 3942 3925 3926 3944 4340 4341 +6 3943 3926 3376 4341 4342 4343 +6 3674 3675 3677 3946 3951 3948 +6 3945 3677 3159 3160 3947 3948 +6 3946 3160 3948 3949 5923 3963 +6 3946 3947 3949 3950 3951 3945 +6 3948 3947 3950 5921 5922 5923 +6 3948 3949 3951 3952 5920 5921 +6 3948 3950 3952 3673 3674 3945 +6 3951 3950 3673 5919 3672 5920 +6 3797 3798 3954 7811 7812 7813 +6 3953 3798 3799 3955 7813 7814 +6 3954 3799 3956 7814 7815 7816 +6 3955 3799 3800 3801 3957 7816 +6 3956 3801 3802 3958 4239 7816 +6 3957 3802 3803 3804 4239 4240 +6 3188 3189 3960 3961 7589 7587 +6 3959 3189 3961 3962 2891 2889 +6 3959 3960 3962 7589 7590 7591 +6 3961 3960 2891 7591 7592 7593 +6 3160 3161 3964 5923 3947 5924 +6 3963 3161 3965 3966 5924 5925 +6 3964 3161 3966 3967 3968 3162 +6 3964 3965 3967 5925 5943 5944 +6 3966 3965 3968 5944 5949 5948 +6 3967 3965 3162 5949 2489 2488 +6 3486 3490 3970 6557 4039 4040 +6 3969 3490 3491 3971 1598 6557 +6 3970 3491 3972 6359 1596 1598 +6 3971 3491 3492 6556 6358 6359 +6 3699 3700 3974 4700 4701 4702 +6 3973 3700 3701 3702 3975 4702 +6 3974 3702 3976 4702 4703 4704 +6 3975 3702 3703 3977 4704 4705 +6 3976 3703 3704 3978 4705 4706 +6 3977 3704 3705 3979 4706 4707 +6 3978 3705 3706 3980 4707 4708 +6 3979 3706 3707 3981 4708 4709 +6 3980 3707 3708 3982 4709 4710 +6 3981 3708 3709 3983 4710 4711 +6 3982 3709 3710 3984 4711 4712 +6 3983 3710 3711 3985 4712 4713 +6 3984 3711 3712 3986 4713 4714 +6 3985 3712 3713 3987 4714 4715 +6 3986 3713 3714 3988 4715 4716 +6 3987 3714 3715 3989 4716 4717 +6 3988 3715 3716 3990 4717 4718 +6 3989 3716 3717 3991 4718 4719 +6 3990 3717 3718 3992 4719 4720 +6 3991 3718 3719 3993 4720 4721 +6 3992 3719 3720 3994 4721 4722 +6 3993 3720 3721 3995 4440 4722 +6 3994 3721 3722 3996 4440 4441 +6 3995 3722 3723 3997 4441 4442 +6 3996 3723 3724 3998 4442 4443 +6 3997 3724 3725 3999 4443 4444 +6 3998 3725 3726 4000 4444 4445 +6 3999 3726 3727 4001 4445 4446 +6 4000 3727 3728 4002 4446 4447 +6 4001 3728 3729 4003 4071 4447 +6 4002 3729 3730 4004 4009 4071 +6 4003 3730 3731 4005 4009 4010 +6 4004 3731 3732 4006 4010 4011 +6 4005 3732 3733 3734 4007 4011 +6 4006 3734 3735 3736 4008 4011 +6 4007 3736 3738 4011 4012 4013 +6 4003 4004 4010 4071 4072 4073 +6 4009 4004 4005 4011 4073 4012 +6 4010 4005 4006 4007 4008 4012 +6 4011 4008 4013 4073 4010 4074 +6 4012 4008 3738 3739 4014 4074 +6 4013 3739 3740 4015 4074 4075 +7 4014 3740 3741 4016 4075 4076 4077 +6 4015 3741 3742 4017 4077 4078 +6 4016 3742 3743 4018 4078 4079 +6 4017 3743 3744 4019 4079 4080 +6 4018 3744 3745 4020 4080 4081 +6 4019 3745 3746 4021 4081 4082 +6 4020 3746 3747 4022 4082 4083 +6 4021 3747 4023 4031 4083 4084 +6 4022 3747 3748 3749 4024 4031 +6 4023 3749 4025 4031 4032 4033 +6 4024 3749 3750 3751 4026 4033 +6 4025 3751 3752 4027 4028 4033 +6 4026 3752 4028 4029 4030 3753 +6 4026 4027 4029 4033 4034 4035 +6 4028 4027 4030 4035 4036 4037 +6 4029 4027 3753 4037 4038 3754 +6 4022 4023 4024 4032 4084 4085 +6 4031 4024 4033 4085 4086 4034 +6 4032 4024 4025 4026 4028 4034 +6 4033 4028 4035 4086 4032 4463 +6 4034 4028 4029 4036 4042 4463 +6 4035 4029 4037 4042 4043 4044 +6 4036 4029 4030 4038 4044 4045 +6 4037 4030 3754 4045 4046 4047 +6 3765 3766 4040 6557 6558 3969 +6 4039 3766 4041 3969 3486 3485 +6 4040 3766 3764 3218 3485 3219 +6 4035 4036 4043 4463 4464 4465 +6 4042 4036 4044 4465 4466 4467 +6 4043 4036 4037 4045 4467 4468 +6 4044 4037 4038 4046 4468 4469 +6 4045 4038 4047 4469 4470 4048 +6 4046 4038 3754 3756 3757 4048 +6 4047 3757 3758 4049 4470 4046 +6 4048 3758 3759 4050 4470 4471 +6 4049 3759 3760 4051 4471 4210 +6 4050 3760 4052 4053 4209 4210 +6 4051 3760 4053 4054 4055 3266 +6 4051 4052 4054 4209 4222 4223 +6 4053 4052 4055 3269 4056 4223 +6 4054 4052 3266 3267 3268 3269 +5 4054 3269 3270 4057 4223 +7 4056 3270 3271 4058 4223 4224 4225 +7 4057 3271 3272 4059 4225 4226 4227 +6 4058 3272 3273 4060 4227 4228 +6 4059 3273 3274 4061 4228 4229 +6 4060 3274 3275 4062 4063 4229 +6 4061 3275 4063 4064 4065 3276 +6 4061 4062 4064 4231 4229 4503 +6 4063 4062 4065 4067 4068 4503 +6 4064 4062 3276 3277 4066 4067 +6 4065 3277 4067 4070 3827 3278 +6 4065 4066 4064 4068 4069 4070 +6 4064 4067 4069 4514 4503 4755 +6 4068 4067 4070 4755 4756 4757 +6 4069 4067 4066 3827 4757 3828 +6 4002 4003 4009 4072 4447 4448 +6 4071 4009 4073 4448 4449 4450 +6 4072 4009 4010 4012 4074 4450 +6 4073 4012 4013 4014 4075 4450 +6 4074 4014 4015 4076 4450 4451 +6 4075 4015 4077 4451 4452 4453 +5 4076 4015 4016 4078 4453 +6 4077 4016 4017 4079 4453 4454 +6 4078 4017 4018 4080 4454 4455 +6 4079 4018 4019 4081 4455 4456 +6 4080 4019 4020 4082 4456 4457 +6 4081 4020 4021 4083 4457 4458 +6 4082 4021 4022 4084 4458 4459 +6 4083 4022 4031 4085 4459 4460 +6 4084 4031 4032 4086 4460 4461 +6 4085 4032 4034 4461 4462 4463 +6 2881 2882 4088 4090 7600 7601 +6 4087 2882 2883 2884 4089 4090 +6 4088 2884 4090 4091 4092 4093 +7 4088 4089 4091 7599 7600 4087 7752 +6 4090 4089 4092 7752 7754 4380 +6 4091 4089 4093 4095 4379 4380 +6 4092 4089 2884 2499 4094 4095 +6 4093 2499 4095 4096 2810 2500 +6 4093 4094 4096 4092 4379 4388 +6 4095 4094 2810 4388 4387 4389 +6 3543 3544 4098 4099 4100 3545 +6 3543 4097 4099 4366 4373 3542 +6 4098 4097 4100 4366 4367 4368 +6 4099 4097 3545 4368 3095 3094 +6 3804 3805 4102 4240 4241 4242 +6 4101 3805 3806 4103 4242 4243 +6 4102 3806 4104 4243 4244 4245 +6 4103 3806 3807 4105 4112 4245 +6 4104 3807 3808 4106 4112 4113 +6 4105 3808 3809 4107 4113 4114 +6 4106 3809 4108 4109 4110 4114 +6 4107 3809 3448 3449 3455 4109 +6 4108 3455 4107 4110 4111 3457 +6 4107 4109 4111 4114 4115 4116 +6 4110 4109 3457 4116 4395 3465 +6 4104 4105 4113 4245 4246 4247 +6 4112 4105 4106 4114 4250 4247 +6 4113 4106 4107 4110 4115 4250 +6 4114 4110 4116 4250 4392 4393 +6 4115 4110 4111 4393 4394 4395 +7 3523 3526 4118 4531 4532 3522 4120 +5 4117 3526 3527 4119 4120 +6 4118 3527 4120 4121 3530 9787 +7 4118 4119 4121 4122 9785 4531 4117 +6 4120 4119 4122 4123 9787 9790 +6 4120 4121 4123 4124 4396 9785 +6 4122 4121 4124 4125 9790 7173 +6 4122 4123 4125 4126 4127 4396 +6 4124 4123 4126 7172 4141 7173 +6 4124 4125 4127 4128 4129 4141 +6 4124 4126 4128 4396 4397 4398 +6 4127 4126 4129 4130 4131 4398 +6 4128 4126 4130 4137 4140 4141 +6 4128 4129 4131 4132 4136 4137 +6 4128 4130 4132 4133 4398 4399 +6 4131 4130 4133 4134 4135 4136 +6 4131 4132 4134 4402 4399 4411 +6 4133 4132 4135 4411 4412 4413 +6 4134 4132 4136 4413 4414 7165 +6 4135 4132 4130 4137 4138 7165 +6 4136 4130 4129 4138 4139 4140 +6 4136 4137 4139 7164 7162 7165 +6 4138 4137 4140 7169 7164 7170 +6 4139 4137 4129 4141 7170 7171 +6 4140 4129 4126 7171 7172 4125 +6 3581 3582 4143 4269 4270 4271 +6 4142 3582 3583 4144 4271 4272 +6 4143 3583 3584 4145 4272 4273 +6 4144 3584 3585 4146 4273 4274 +6 4145 3585 3586 4147 4274 4275 +6 4146 3586 3587 4148 4275 4276 +6 4147 3587 3588 4149 4276 4277 +6 4148 3588 3589 3590 4150 4277 +6 4149 3590 4151 4277 4278 4279 +6 4150 3590 3591 4152 4279 4280 +6 4151 3591 3592 4153 4280 4281 +6 4152 3592 3593 4154 4281 4282 +6 4153 3593 3594 4155 4282 4283 +6 4154 3594 3595 4156 4283 4284 +6 4155 3595 3596 4157 4284 4285 +6 4156 3596 3597 4158 4285 4286 +6 4157 3597 3598 4159 4286 4287 +6 4158 3598 3599 4160 4287 4288 +6 4159 3599 3600 4161 4288 4289 +6 4160 3600 3601 4162 4289 4290 +6 4161 3601 3602 3603 4163 4290 +6 4162 3603 4164 4290 4291 4292 +6 4163 3603 3604 4165 4292 4293 +6 4164 3604 3605 4166 4293 4294 +6 4165 3605 3606 4167 4294 4295 +6 4166 3606 3607 4168 4295 4296 +6 4167 3607 3608 4169 4296 4297 +6 4168 3608 3609 3610 4170 4297 +6 4169 3610 4171 4297 4298 4299 +6 4170 3610 3611 4172 4299 4300 +6 4171 3611 3612 4173 4300 4301 +6 4172 3612 3613 4174 4301 4302 +6 4173 3613 3614 4175 4302 4303 +6 4174 3614 3615 4176 4303 4304 +6 4175 3615 3616 4177 4304 4305 +6 4176 3616 3617 4178 4305 4306 +6 4177 3617 3618 4179 4306 4307 +6 4178 3618 3619 4180 4307 4308 +6 4179 3619 3620 4181 4308 4309 +6 4180 3620 3621 4182 4309 4310 +6 4181 3621 3622 4183 4310 4311 +6 4182 3622 3623 4184 4311 4312 +6 4183 3623 3624 4185 4312 4313 +6 4184 3624 3625 4186 4313 4314 +6 4185 3625 3626 4187 4314 4315 +6 4186 3626 3627 4188 4315 4316 +6 4187 3627 3628 4189 4316 4317 +6 4188 3628 3629 4190 4317 4318 +6 4189 3629 3630 4191 4318 4319 +6 4190 3630 3631 4192 4319 4320 +6 4191 3631 3632 4193 4320 4321 +6 4192 3632 3633 4194 4321 4322 +6 4193 3633 3634 3635 4195 4322 +6 4194 3635 3904 4196 4322 4323 +6 4195 3904 4197 4323 4324 4325 +6 4196 3904 3905 3906 4198 4325 +6 4197 3906 4199 4325 4326 4327 +6 4198 3906 3907 3908 4200 4327 +6 4199 3908 3909 4201 4327 4328 +6 4200 3909 3928 3929 4202 4328 +6 4201 3929 3930 4203 4328 4329 +6 4202 3930 3931 4204 4329 4330 +6 4203 3931 4205 4330 4331 4332 +6 4204 3931 3932 3933 4206 4332 +6 4205 3933 3934 4207 4332 4333 +6 4206 3934 3935 4208 4333 4334 +7 4207 3935 3936 3938 4334 4335 4336 +6 4051 4053 4210 4211 4212 4222 +6 4051 4209 4211 4471 4050 4478 +6 4210 4209 4212 4213 4478 4479 +6 4211 4209 4213 4214 4221 4222 +6 4211 4212 4214 4215 4479 4480 +6 4213 4212 4215 4216 4217 4221 +6 4213 4214 4216 4480 4481 4482 +6 4215 4214 4217 4218 4482 4483 +6 4216 4214 4218 4219 4220 4221 +6 4216 4217 4219 4233 4483 4484 +6 4218 4217 4220 4233 4234 4235 +6 4219 4217 4221 4225 4235 4224 +6 4220 4217 4214 4212 4222 4224 +6 4221 4212 4209 4053 4223 4224 +6 4222 4053 4054 4056 4057 4224 +6 4223 4057 4225 4222 4221 4220 +6 4224 4057 4058 4226 4235 4220 +6 4225 4058 4227 4236 4235 4489 +5 4226 4058 4059 4228 4489 +7 4227 4059 4060 4229 4230 4488 4489 +6 4228 4060 4230 4231 4063 4061 +6 4228 4229 4231 4490 4488 4501 +6 4230 4229 4063 4501 4502 4503 +6 3148 3413 3147 3146 9792 3414 +6 4218 4219 4234 4484 4485 4486 +6 4233 4219 4235 4236 4486 4487 +6 4234 4219 4236 4226 4225 4220 +6 4234 4235 4226 4487 4488 4489 +6 3890 3891 4238 4252 4253 4257 +6 4237 3891 3892 3572 4257 4258 +6 3957 3958 4240 7816 7817 4504 +6 4239 3958 3804 4101 4241 4504 +6 4240 4101 4242 4504 4505 4506 +6 4241 4101 4102 4243 4506 4507 +6 4242 4102 4103 4244 4417 4507 +6 4243 4103 4245 4417 4418 4419 +6 4244 4103 4104 4112 4246 4419 +6 4245 4112 4247 4248 4419 4420 +6 4246 4112 4248 4249 4250 4113 +6 4246 4247 4249 4420 7830 7831 +6 4248 4247 4250 4392 4740 7831 +6 4249 4247 4113 4114 4115 4392 +6 3342 3339 1525 1526 2206 2207 +6 3890 4237 4253 4254 4429 3889 +6 4252 4237 4254 4255 4256 4257 +6 4252 4253 4255 4648 4429 6893 +6 4254 4253 4256 4730 4731 6893 +6 4255 4253 4257 4730 4262 4261 +6 4256 4253 4237 4238 4258 4261 +6 4257 4238 3572 3573 4259 4261 +6 4258 3573 3574 3575 4260 4261 +6 4259 3575 4261 4262 4263 4264 +6 4259 4260 4262 4257 4258 4256 +6 4261 4260 4263 4733 4730 4256 +6 4262 4260 4264 6902 4733 6903 +6 4263 4260 3575 3576 4265 6903 +6 4264 3576 3577 4266 5232 6903 +6 4265 3577 3578 4267 5232 5233 +6 4266 3578 3579 4268 5233 5234 +6 4267 3579 4269 5234 5235 4270 +6 4268 3579 3580 3581 4142 4270 +6 4269 4142 4271 5235 4268 5452 +6 4270 4142 4143 4272 5452 5453 +6 4271 4143 4144 4273 5453 5454 +6 4272 4144 4145 4274 5454 5455 +6 4273 4145 4146 4275 5458 5455 +6 4274 4146 4147 4276 5470 5458 +6 4275 4147 4148 4277 5470 5471 +6 4276 4148 4149 4150 4278 5471 +6 4277 4150 4279 5471 5472 5473 +6 4278 4150 4151 4280 5473 5474 +6 4279 4151 4152 4281 5474 5475 +6 4280 4152 4153 4282 5047 5475 +6 4281 4153 4154 4283 5047 5048 +6 4282 4154 4155 4284 5048 5049 +6 4283 4155 4156 4285 5049 5050 +6 4284 4156 4157 4286 5050 5051 +6 4285 4157 4158 4287 5051 5052 +6 4286 4158 4159 4288 5052 5053 +6 4287 4159 4160 4289 4924 5053 +6 4288 4160 4161 4290 4924 4925 +6 4289 4161 4162 4163 4291 4925 +6 4290 4163 4292 4925 4926 4927 +6 4291 4163 4164 4293 4927 4928 +6 4292 4164 4165 4294 4928 4929 +6 4293 4165 4166 4295 4929 4930 +6 4294 4166 4167 4296 4930 4931 +6 4295 4167 4168 4297 4931 4932 +6 4296 4168 4169 4170 4298 4932 +6 4297 4170 4299 4772 4932 4933 +6 4298 4170 4171 4300 4772 4773 +6 4299 4171 4172 4301 4773 4774 +6 4300 4172 4173 4302 4774 4775 +6 4301 4173 4174 4303 4775 4776 +6 4302 4174 4175 4304 4776 4777 +6 4303 4175 4176 4305 4777 4778 +6 4304 4176 4177 4306 4778 4779 +6 4305 4177 4178 4307 4779 4780 +6 4306 4178 4179 4308 4780 4781 +6 4307 4179 4180 4309 4781 4782 +6 4308 4180 4181 4310 4782 4783 +6 4309 4181 4182 4311 4567 4783 +6 4310 4182 4183 4312 4567 4568 +6 4311 4183 4184 4313 4568 4569 +6 4312 4184 4185 4314 4569 4570 +6 4313 4185 4186 4315 4570 4571 +6 4314 4186 4187 4316 4571 4572 +6 4315 4187 4188 4317 4572 4573 +6 4316 4188 4189 4318 4573 4574 +6 4317 4189 4190 4319 4574 4575 +6 4318 4190 4191 4320 4575 4576 +6 4319 4191 4192 4321 4576 4577 +6 4320 4192 4193 4322 4577 4578 +6 4321 4193 4194 4195 4323 4578 +6 4322 4195 4196 4324 4578 4579 +6 4323 4196 4325 4579 4580 4581 +6 4324 4196 4197 4198 4326 4581 +6 4325 4198 4327 4581 4582 4583 +6 4326 4198 4199 4200 4328 4583 +6 4327 4200 4201 4202 4329 4583 +6 4328 4202 4203 4330 4583 4584 +6 4329 4203 4204 4331 4584 4585 +6 4330 4204 4332 4585 4586 4590 +7 4331 4204 4205 4206 4333 4590 4591 +6 4332 4206 4207 4334 4591 4592 +6 4333 4207 4208 4335 4592 4593 +6 4334 4208 4336 4337 4430 4593 +5 4335 4208 3938 3939 4337 +6 4336 3939 3940 4338 4335 4430 +6 4337 3940 3941 4339 4430 4431 +6 4338 3941 3942 4340 4431 4432 +6 4339 3942 3943 4341 4432 4433 +6 4340 3943 3944 4342 4433 4434 +6 4341 3944 4343 4434 4435 4436 +6 4342 3944 3376 3377 4344 4436 +6 4343 3377 3378 4345 4346 4436 +6 4344 3378 4346 4347 4348 3379 +6 4344 4345 4347 4436 4437 4438 +6 4346 4345 4348 4438 4439 4349 +6 4347 4345 3379 3646 3647 4349 +6 4348 3647 4350 4351 4439 4347 +6 4349 3647 4351 4352 4353 3648 +6 4349 4350 4352 4602 4439 4603 +6 4351 4350 4353 4603 4604 4605 +6 4352 4350 3648 3649 4354 4605 +6 4353 3649 3658 4355 4356 4605 +6 4354 3658 4356 4357 4358 4359 +6 4354 4355 4357 4605 4606 4607 +6 4356 4355 4358 4362 4363 4607 +6 4357 4355 4359 4360 4361 4362 +6 4358 4355 4360 4372 3659 3658 +6 4358 4359 4361 4369 4370 4372 +6 4358 4360 4362 4365 4369 4615 +6 4358 4361 4357 4363 4364 4365 +6 4357 4362 4364 4607 4608 4609 +6 4363 4362 4365 4612 4609 4613 +6 4364 4362 4361 4613 4614 4615 +6 4098 4099 4367 4373 4374 4375 +6 4366 4099 4368 4375 4376 4377 +7 4367 4099 4100 3095 4377 1627 1625 +6 4361 4360 4370 4371 4615 4616 +6 4369 4360 4371 4372 9795 9794 +6 4369 4370 9795 4643 4638 4616 +6 4370 4360 4359 3659 9794 3660 +6 4098 4366 4374 7213 3541 3542 +6 4373 4366 4375 7213 7211 7210 +6 4374 4366 4367 4376 7210 7214 +6 4375 4367 4377 4378 7214 7215 +6 4376 4367 4368 4378 1628 1627 +5 4376 4377 1628 7215 7216 +6 4092 4095 4380 4381 4382 4388 +7 4092 4379 4381 7754 4091 7753 7755 +6 4380 4379 4382 4383 7755 7756 +6 4381 4379 4383 4384 4385 4388 +6 4381 4382 4384 7756 7757 7765 +6 4383 4382 4385 4386 4390 7765 +6 4384 4382 4386 3141 4387 4388 +6 4384 4385 3141 4390 4391 3142 +6 3141 4385 4388 4096 4389 3140 +6 4387 4385 4382 4379 4095 4096 +6 4387 4096 2810 2811 2814 3140 +6 4384 4386 4391 7765 7766 7767 +6 4390 4386 3142 7767 7768 3143 +6 4250 4115 4393 4249 4740 4741 +6 4392 4115 4116 4394 4403 4741 +6 4393 4116 4395 4403 4404 4405 +6 4394 4116 4111 3465 4405 3466 +5 4122 4124 4127 4397 9785 +7 4396 4127 4398 4400 4529 4530 9785 +6 4397 4127 4128 4131 4399 4400 +6 4398 4131 4400 4401 4402 4133 +6 4398 4399 4401 4526 4529 4397 +5 4400 4399 4402 4528 4526 +7 4401 4399 4133 4411 4535 4528 4536 +6 4393 4394 4404 4741 4742 4743 +6 4403 4394 4405 4743 4744 4745 +6 4404 4394 4395 3466 4745 4746 +6 3838 3839 3865 4407 5027 5028 +6 4406 3865 4408 5028 5029 5030 +6 4407 3865 3866 4409 5030 5031 +6 4408 3866 3867 4410 5031 5032 +6 4409 3867 3869 4421 5032 5033 +6 4402 4133 4134 4412 4536 4537 +6 4411 4134 4413 4546 4540 4537 +6 4412 4134 4135 4414 4415 4546 +6 4413 4135 4415 4416 7165 7166 +6 4413 4414 4416 4546 4545 4649 +6 4415 4414 4650 4649 7166 7167 +6 4243 4244 4418 4507 4508 4509 +6 4417 4244 4419 4509 4510 4511 +6 4418 4244 4245 4246 4420 4511 +6 4419 4246 4248 7829 4511 7830 +6 4410 3869 3870 4422 5033 5034 +6 4421 3870 3871 3872 4423 5034 +6 4422 3872 4424 5034 5035 5036 +6 4423 3872 3873 4425 5036 5037 +6 4424 3873 3874 4426 4644 5037 +6 4425 3874 4427 4644 4645 4646 +6 4426 3874 3875 4428 4646 4647 +6 4427 3875 3876 4429 4647 4648 +6 4428 3876 3889 4648 4254 4252 +6 4335 4337 4338 4431 4593 4594 +6 4430 4338 4339 4432 4594 4595 +6 4431 4339 4340 4433 4595 4596 +6 4432 4340 4341 4434 4596 4597 +6 4433 4341 4342 4435 4597 4598 +6 4434 4342 4436 4598 4599 4437 +6 4435 4342 4343 4344 4346 4437 +6 4436 4346 4438 4599 4435 4600 +6 4437 4346 4347 4439 4600 4601 +6 4438 4347 4349 4601 4602 4351 +6 3994 3995 4441 4722 4723 4724 +6 4440 3995 3996 4442 4724 4725 +6 4441 3996 3997 4443 4725 4726 +6 4442 3997 3998 4444 4726 4727 +6 4443 3998 3999 4445 4727 4728 +6 4444 3999 4000 4446 4728 4729 +6 4445 4000 4001 4447 4729 4659 +6 4446 4001 4002 4071 4448 4659 +6 4447 4071 4072 4449 4659 4660 +6 4448 4072 4450 4660 4661 4451 +6 4449 4072 4073 4074 4075 4451 +6 4450 4075 4076 4452 4661 4449 +6 4451 4076 4453 4670 4739 4661 +6 4452 4076 4077 4078 4454 4670 +6 4453 4078 4079 4455 4670 4671 +6 4454 4079 4080 4456 4671 4672 +6 4455 4080 4081 4457 4672 4673 +6 4456 4081 4082 4458 4673 4674 +6 4457 4082 4083 4459 4674 4675 +6 4458 4083 4084 4460 4675 4676 +6 4459 4084 4085 4461 4676 4677 +6 4460 4085 4086 4462 4677 4678 +6 4461 4086 4463 4678 4679 4680 +7 4462 4086 4034 4035 4042 4464 4680 +5 4463 4042 4465 4680 4681 +6 4464 4042 4043 4466 4472 4681 +6 4465 4043 4467 4472 4473 4474 +6 4466 4043 4044 4468 4474 4475 +6 4467 4044 4045 4469 4475 4476 +6 4468 4045 4046 4470 4476 4477 +6 4469 4046 4048 4049 4471 4477 +6 4470 4049 4050 4210 4477 4478 +6 4465 4466 4473 4681 4682 4683 +6 4472 4466 4474 4683 4684 4685 +6 4473 4466 4467 4475 4685 4686 +6 4474 4467 4468 4476 4686 4687 +6 4475 4468 4469 4477 4687 4688 +6 4476 4469 4470 4471 4478 4688 +6 4477 4471 4210 4211 4479 4688 +6 4478 4211 4213 4480 4688 5214 +6 4479 4213 4215 4481 5214 5215 +6 4480 4215 4482 5215 5216 5217 +6 4481 4215 4216 4483 4491 5217 +6 4482 4216 4218 4484 4491 4492 +6 4483 4218 4233 4485 4492 4493 +6 4484 4233 4486 4493 4494 4495 +6 4485 4233 4234 4487 4495 4496 +6 4486 4234 4236 4488 4490 4496 +6 4487 4236 4489 4228 4490 4230 +5 4488 4236 4228 4227 4226 +6 4487 4488 4230 4496 4497 4501 +6 4482 4483 4492 4982 4990 5217 +6 4491 4483 4484 4493 4982 4983 +6 4492 4484 4485 4494 4983 4984 +6 4493 4485 4495 4984 4985 4986 +6 4494 4485 4486 4496 4986 4498 +6 4495 4486 4487 4490 4497 4498 +6 4496 4490 4498 4499 4500 4501 +6 4496 4497 4499 4986 4495 4987 +6 4498 4497 4500 4987 4988 4989 +5 4499 4497 4501 4989 4512 +7 4500 4497 4490 4230 4231 4502 4512 +6 4501 4231 4503 4512 4513 4514 +6 4502 4231 4063 4514 4068 4064 +6 4240 4241 4505 7817 4239 7818 +6 4504 4241 4506 7818 7819 7820 +6 4505 4241 4242 4507 7820 7821 +6 4506 4242 4243 4417 4508 7821 +6 4507 4417 4509 7821 7822 7823 +6 4508 4417 4418 4510 7823 7824 +6 4509 4418 4511 7824 7825 7826 +6 4510 4418 4419 7826 7829 4420 +7 4501 4502 4513 4989 4500 5003 5000 +6 4512 4502 4514 4755 4760 5003 +5 4513 4502 4503 4068 4755 +6 427 412 4516 4517 5612 5613 +6 4515 412 4517 4518 4522 411 +6 4515 4516 4518 4519 5612 5616 +6 4517 4516 4519 4520 4521 4522 +6 4517 4518 4520 9735 7509 5616 +6 4519 4518 4521 5236 9735 9679 +6 4520 4518 4522 5236 5237 5238 +6 4521 4518 4516 411 5238 422 +7 3508 3511 3771 4524 6694 6696 6705 +6 4523 3771 4525 6695 6694 4533 +6 4524 3771 3772 4526 4527 4533 +7 4525 3772 4527 4528 4401 4400 4529 +6 4525 4526 4528 4533 4534 4535 +5 4527 4526 4401 4535 4402 +6 4400 4526 3772 3773 4530 4397 +6 4529 3773 3774 4531 4397 9785 +6 4530 3774 4532 4117 4120 9785 +5 4531 3774 4117 3522 3521 +6 4525 4527 4534 5157 4524 6695 +6 4533 4527 4535 5157 5158 4667 +6 4534 4527 4528 4402 4536 4667 +6 4535 4402 4411 4537 4538 4667 +6 4536 4411 4538 4539 4540 4412 +6 4536 4537 4539 4667 4668 4669 +6 4538 4537 4540 4541 4547 4669 +6 4539 4537 4541 4542 4546 4412 +6 4539 4540 4542 4543 4547 4548 +6 4541 4540 4543 4544 4545 4546 +6 4541 4542 4544 4551 4548 4552 +6 4543 4542 4545 4552 4553 4554 +6 4544 4542 4546 4415 4649 4554 +6 4545 4542 4540 4412 4413 4415 +6 4539 4541 4548 4549 9763 4669 +6 4547 4541 4549 4550 4551 4543 +6 4547 4548 4550 4558 4561 9763 +6 4549 4548 4551 4558 4559 4560 +6 4550 4548 4543 4552 6764 4560 +6 4551 4543 4544 4553 7145 6764 +6 4552 4544 4554 4555 7146 7145 +6 4553 4544 4555 4556 4545 4649 +6 4553 4554 4556 4557 7146 7147 +6 4555 4554 4557 4649 4650 7154 +6 4555 4556 7147 7149 7150 7154 +6 4549 4550 4559 4561 4562 4563 +6 4558 4550 4560 4566 4563 6765 +6 4559 4550 6764 6763 6765 4551 +7 4549 4558 4562 9763 9762 6676 9793 +6 4561 4558 4563 4564 6675 6676 +6 4562 4558 4564 4565 4566 4559 +6 4562 4563 4565 6666 6667 6675 +6 4564 4563 4566 6674 6666 6791 +6 4565 4563 4559 6765 6766 6791 +6 4310 4311 4568 4783 4784 4785 +6 4567 4311 4312 4569 4785 4786 +6 4568 4312 4313 4570 4786 4787 +6 4569 4313 4314 4571 4787 4788 +6 4570 4314 4315 4572 4788 4789 +6 4571 4315 4316 4573 4789 4790 +6 4572 4316 4317 4574 4790 4791 +6 4573 4317 4318 4575 4791 4792 +6 4574 4318 4319 4576 4792 4793 +6 4575 4319 4320 4577 4793 4794 +6 4576 4320 4321 4578 4794 4795 +6 4577 4321 4322 4323 4579 4795 +6 4578 4323 4324 4580 4795 4796 +6 4579 4324 4581 4796 4797 4798 +6 4580 4324 4325 4326 4582 4798 +6 4581 4326 4583 4798 4799 4584 +6 4582 4326 4327 4328 4329 4584 +6 4583 4329 4330 4585 4799 4582 +7 4584 4330 4331 4586 4587 4805 4799 +6 4585 4331 4587 4588 4589 4590 +5 4585 4586 4588 4805 4806 +6 4587 4586 4589 4806 4807 4808 +6 4588 4586 4590 4808 4809 4810 +6 4589 4586 4331 4332 4591 4810 +5 4590 4332 4333 4592 4810 +6 4591 4333 4334 4593 4810 4811 +6 4592 4334 4335 4430 4594 4811 +6 4593 4430 4431 4595 4811 4812 +6 4594 4431 4432 4596 4812 4813 +6 4595 4432 4433 4597 4813 4814 +6 4596 4433 4434 4598 4814 4815 +6 4597 4434 4435 4599 4815 4816 +6 4598 4435 4437 4600 4816 4817 +6 4599 4437 4438 4601 4817 4818 +6 4600 4438 4439 4602 4818 4819 +6 4601 4439 4351 4603 4822 4819 +6 4602 4351 4352 4604 4822 4823 +6 4603 4352 4605 4826 4823 4827 +7 4604 4352 4353 4354 4356 4606 4827 +5 4605 4356 4607 4827 4828 +6 4606 4356 4357 4363 4608 4828 +5 4607 4363 4609 4610 4828 +6 4608 4363 4610 4611 4612 4364 +7 4608 4609 4611 4828 4829 4830 4831 +6 4610 4609 4612 4831 4832 4833 +6 4611 4609 4364 4613 4833 4835 +6 4612 4364 4365 4614 4838 4835 +6 4613 4365 4615 4617 4618 4838 +6 4614 4365 4361 4369 4616 4617 +7 4615 4369 4617 4638 4635 4620 4371 +6 4615 4616 4614 4618 4619 4620 +6 4614 4617 4619 4838 4623 4839 +6 4618 4617 4620 4621 4622 4623 +6 4619 4617 4621 4634 4635 4616 +6 4619 4620 4622 4629 4630 4634 +6 4619 4621 4623 4624 4625 4629 +6 4619 4622 4624 4841 4839 4618 +6 4623 4622 4625 4626 4841 4842 +6 4624 4622 4626 4627 4628 4629 +6 4624 4625 4627 4842 4861 4854 +6 4626 4625 4628 4861 4862 4863 +6 4627 4625 4629 4863 4864 4631 +6 4628 4625 4622 4621 4630 4631 +6 4629 4621 4631 4632 4633 4634 +6 4629 4630 4632 4864 4628 4865 +6 4631 4630 4633 4639 4869 4865 +6 4632 4630 4634 4639 4640 4636 +6 4633 4630 4621 4620 4635 4636 +6 4634 4620 4636 4637 4638 4616 +6 4634 4635 4637 4640 4633 4641 +6 4636 4635 4638 4641 4642 4643 +5 4637 4635 4616 4643 4371 +6 4632 4633 4640 4869 4913 9761 +6 4639 4633 4636 4641 4913 4914 +6 4640 4636 4637 4642 4917 4914 +6 4641 4637 4643 4911 4917 4910 +7 4642 4637 4638 4909 4910 9795 4371 +6 4425 4426 4645 5037 5038 5045 +6 4644 4426 4646 5046 5045 6890 +6 4645 4426 4427 4647 6891 6890 +6 4646 4427 4428 4648 6891 6892 +6 4647 4428 4429 4254 6892 6893 +6 4545 4415 4554 4556 4650 4416 +6 4556 4649 4416 7167 7155 7154 +6 423 53 54 4652 4653 9685 +6 4651 54 4653 4654 4658 55 +6 4651 4652 4654 4655 9684 9685 +6 4653 4652 4655 4656 4657 4658 +6 4653 4654 4656 9683 9681 9684 +6 4655 4654 4657 9683 9686 9687 +7 4656 4654 4658 5381 9689 9687 9690 +6 4657 4654 4652 55 5381 56 +6 4447 4448 4660 4729 4446 4737 +6 4659 4448 4449 4661 4737 4738 +6 4660 4449 4451 4738 4739 4452 +6 3896 3897 3898 4663 7842 4759 +6 4662 3898 3899 4664 7842 7843 +6 4663 3899 4665 7843 4690 4689 +6 4664 3899 3900 4666 3686 4689 +6 4665 3900 3901 3902 3903 3686 +6 4535 4536 4538 4668 5158 4534 +6 4667 4538 4669 9751 5158 9762 +6 4668 4538 4539 9762 9763 4547 +7 4452 4453 4454 4671 4981 4739 5195 +6 4670 4454 4455 4672 5195 5196 +6 4671 4455 4456 4673 5196 5197 +6 4672 4456 4457 4674 5197 5198 +6 4673 4457 4458 4675 5198 5199 +6 4674 4458 4459 4676 5199 5200 +6 4675 4459 4460 4677 5200 5201 +6 4676 4460 4461 4678 5201 5202 +6 4677 4461 4462 4679 5202 5203 +6 4678 4462 4680 5203 5204 5205 +6 4679 4462 4463 4464 4681 5205 +7 4680 4464 4465 4472 4682 5205 5206 +5 4681 4472 4683 5206 5207 +7 4682 4472 4473 4684 5207 5208 5209 +5 4683 4473 4685 5209 5210 +7 4684 4473 4474 4686 5210 5211 5212 +6 4685 4474 4475 4687 5212 5213 +6 4686 4475 4476 4688 5213 5214 +6 4687 4476 4477 4478 4479 5214 +6 4665 3686 3687 3688 4690 4664 +6 4689 3688 4691 7843 4664 7844 +6 4690 3688 3689 4692 7844 7845 +6 4691 3689 3690 4693 5159 7845 +6 4692 3690 3691 3693 4694 5159 +6 4693 3693 4695 5159 5160 5161 +6 4694 3693 3694 4696 5161 5162 +6 4695 3694 4697 5162 5163 5164 +6 4696 3694 3695 3696 4698 5164 +6 4697 3696 4699 5164 5165 5166 +6 4698 3696 3697 4700 5166 4701 +6 4699 3697 3698 3699 3973 4701 +6 4700 3973 4702 5166 4699 7855 +6 4701 3973 3974 3975 4703 7855 +6 4702 3975 4704 7309 7855 7856 +6 4703 3975 3976 4705 7309 7310 +6 4704 3976 3977 4706 7310 7311 +6 4705 3977 3978 4707 7311 7312 +6 4706 3978 3979 4708 7312 7313 +6 4707 3979 3980 4709 5171 7313 +6 4708 3980 3981 4710 5171 5172 +6 4709 3981 3982 4711 5172 5173 +6 4710 3982 3983 4712 5173 5174 +6 4711 3983 3984 4713 5174 5175 +6 4712 3984 3985 4714 5175 5176 +6 4713 3985 3986 4715 5176 5177 +6 4714 3986 3987 4716 5177 5178 +6 4715 3987 3988 4717 4966 5178 +6 4716 3988 3989 4718 4966 4967 +6 4717 3989 3990 4719 4967 4968 +6 4718 3990 3991 4720 4968 4969 +6 4719 3991 3992 4721 4969 4970 +6 4720 3992 3993 4722 4970 4971 +6 4721 3993 3994 4440 4723 4971 +6 4722 4440 4724 4971 4972 4973 +6 4723 4440 4441 4725 4973 4974 +6 4724 4441 4442 4726 4974 4975 +6 4725 4442 4443 4727 4734 4975 +6 4726 4443 4444 4728 4734 4735 +6 4727 4444 4445 4729 4735 4736 +6 4728 4445 4446 4659 4736 4737 +6 4255 4256 4731 4732 4733 4262 +6 4255 4730 4732 6893 6894 6895 +6 4731 4730 4733 6895 6896 6897 +6 4732 4730 4262 6897 6902 4263 +6 4726 4727 4735 4975 4976 4977 +6 4734 4727 4728 4736 4977 4978 +6 4735 4728 4729 4737 4978 4979 +6 4736 4729 4659 4660 4738 4979 +6 4737 4660 4661 4739 4979 4980 +6 4738 4661 4452 4980 4981 4670 +6 4249 4392 4741 5004 7831 7832 +6 4740 4392 4393 4403 4742 5004 +6 4741 4403 4743 4754 5004 5005 +6 4742 4403 4404 4744 4754 4749 +6 4743 4404 4745 3893 3894 4749 +6 4744 4404 4405 4746 4747 3893 +6 4745 4405 3466 3467 3469 4747 +6 4746 3469 4748 3398 3893 4745 +6 4747 3469 2173 2174 3396 3398 +6 4744 3894 4750 4751 4754 4743 +6 4749 3894 4751 4752 4753 3895 +6 4749 4750 4752 5006 4754 7838 +6 4751 4750 4753 4758 7838 7839 +6 4752 4750 3895 4758 4759 3896 +6 4742 4743 4749 5005 5006 4751 +7 4514 4068 4069 4756 4513 4760 4761 +5 4755 4069 4757 4761 4762 +7 4756 4069 4070 3828 4762 4763 4764 +6 4752 4753 4759 7839 7840 7841 +6 4758 4753 3896 7841 7842 4662 +6 4513 4755 4761 5007 5003 5002 +5 4760 4755 4756 4762 5007 +7 4761 4756 4757 4763 5007 5008 5009 +6 4762 4757 4764 5009 5010 5011 +6 4763 4757 3828 3829 4765 5011 +6 4764 3829 4766 5011 5012 5013 +6 4765 3829 3830 3831 4767 5013 +6 4766 3831 3832 4768 4769 5013 +6 4767 3832 4769 4770 4771 3833 +7 4767 4768 4770 5013 5012 5014 5015 +6 4769 4768 4771 5015 5016 5017 +6 4770 4768 3833 5017 3835 3834 +6 4298 4299 4773 4933 4934 4935 +6 4772 4299 4300 4774 4935 4936 +6 4773 4300 4301 4775 4936 4937 +6 4774 4301 4302 4776 4937 4938 +6 4775 4302 4303 4777 4938 4939 +6 4776 4303 4304 4778 4939 4940 +6 4777 4304 4305 4779 4940 4941 +6 4778 4305 4306 4780 4941 4942 +6 4779 4306 4307 4781 4942 4943 +6 4780 4307 4308 4782 4943 4944 +6 4781 4308 4309 4783 4944 4945 +6 4782 4309 4310 4567 4784 4945 +6 4783 4567 4785 4945 4946 4947 +6 4784 4567 4568 4786 4947 4948 +6 4785 4568 4569 4787 4948 4949 +6 4786 4569 4570 4788 4949 4950 +6 4787 4570 4571 4789 4950 4951 +6 4788 4571 4572 4790 4951 4952 +6 4789 4572 4573 4791 4952 4953 +6 4790 4573 4574 4792 4953 4954 +6 4791 4574 4575 4793 4954 4955 +6 4792 4575 4576 4794 4800 4955 +6 4793 4576 4577 4795 4800 4801 +6 4794 4577 4578 4579 4796 4801 +6 4795 4579 4580 4797 4801 4802 +6 4796 4580 4798 4802 4803 4804 +6 4797 4580 4581 4582 4799 4804 +6 4798 4582 4584 4804 4805 4585 +6 4793 4794 4801 4955 4956 4957 +6 4800 4794 4795 4796 4802 4957 +6 4801 4796 4797 4803 4957 4958 +6 4802 4797 4804 4958 4959 4960 +6 4803 4797 4798 4799 4805 4960 +6 4804 4799 4585 4587 4806 4960 +6 4805 4587 4588 4807 4919 4960 +6 4806 4588 4808 4919 4920 4921 +6 4807 4588 4589 4809 4921 4922 +6 4808 4589 4810 4922 4923 4811 +6 4809 4589 4590 4591 4592 4811 +7 4810 4592 4593 4594 4812 4923 4809 +5 4811 4594 4595 4813 4923 +6 4812 4595 4596 4814 4965 4923 +6 4813 4596 4597 4815 5094 4965 +6 4814 4597 4598 4816 5094 5095 +6 4815 4598 4599 4817 5095 5096 +6 4816 4599 4600 4818 5096 5097 +6 4817 4600 4601 4819 4820 5097 +6 4818 4601 4820 4821 4822 4602 +6 4818 4819 4821 5097 5098 5099 +6 4820 4819 4822 5099 5100 4824 +6 4821 4819 4602 4603 4823 4824 +6 4822 4603 4824 4825 4826 4604 +6 4822 4823 4825 5100 4821 5101 +6 4824 4823 4826 5101 5102 5103 +6 4825 4823 4604 4827 5103 5104 +6 4826 4604 4605 4606 4828 5104 +7 4827 4606 4607 4608 4610 4829 5104 +6 4828 4610 4830 5104 5103 5105 +6 4829 4610 4831 5105 5106 5107 +6 4830 4610 4611 4832 5107 5108 +6 4831 4611 4833 4834 5114 5108 +5 4832 4611 4612 4834 4835 +6 4832 4833 4835 4836 5114 5115 +7 4834 4833 4612 4836 4837 4838 4613 +6 4834 4835 4837 5115 4846 4845 +6 4836 4835 4838 4839 4840 4845 +6 4837 4835 4613 4614 4618 4839 +6 4837 4838 4840 4841 4623 4618 +6 4837 4839 4841 4843 4844 4845 +6 4840 4839 4623 4624 4842 4843 +6 4841 4624 4843 4626 4853 4854 +6 4841 4842 4840 4844 4853 4851 +6 4840 4843 4845 4846 4847 4851 +5 4840 4844 4846 4836 4837 +7 4845 4844 4847 4848 5115 4836 5116 +6 4846 4844 4848 4849 4850 4851 +6 4846 4847 4849 5118 5116 5119 +6 4848 4847 4850 5119 5120 5121 +6 4849 4847 4851 4852 5121 5122 +6 4850 4847 4852 4853 4843 4844 +6 4850 4851 4853 4855 4856 5122 +6 4852 4851 4843 4842 4854 4855 +6 4853 4842 4855 4858 4861 4626 +6 4852 4853 4854 4856 4857 4858 +6 4852 4855 4857 5122 5123 5124 +6 4856 4855 4858 4859 5124 5125 +6 4857 4855 4854 4859 4860 4861 +6 4857 4858 4860 5125 5126 5130 +6 4859 4858 4861 5130 5131 4862 +6 4860 4858 4854 4626 4627 4862 +6 4861 4627 4863 5131 4860 5132 +6 4862 4627 4628 4864 4866 5132 +6 4863 4628 4631 4865 4866 4867 +6 4864 4631 4867 4868 4869 4632 +6 4863 4864 4867 5132 5133 5137 +6 4866 4864 4865 4868 5137 5138 +6 4867 4865 4869 4870 4871 5138 +6 4868 4865 4632 4639 4870 9761 +6 4868 4869 4871 4872 4873 9761 +6 4868 4870 4872 5138 5139 5140 +6 4871 4870 4873 4874 5151 5140 +6 4872 4870 4874 4875 4876 9761 +6 4872 4873 4875 5150 5148 5151 +6 4874 4873 4876 4877 4878 5150 +6 4875 4873 4877 9761 4913 4915 +6 4875 4876 4878 4879 4880 4915 +6 4875 4877 4879 5156 5150 4883 +6 4878 4877 4880 4881 4882 4883 +6 4879 4877 4881 4915 4916 9754 +7 4879 4880 4882 9754 9755 9757 9758 +6 4879 4881 4883 4884 4885 9758 +6 4879 4882 4884 5156 4878 5370 +6 4883 4882 4885 4886 5370 5371 +6 4884 4882 4886 4887 9758 4896 +6 4884 4885 4887 4888 4889 5371 +6 4886 4885 4888 4895 4892 4896 +6 4886 4887 4889 4890 4891 4892 +6 4886 4888 4890 5373 5371 5900 +6 4889 4888 4891 5899 5897 5900 +6 4890 4888 4892 4893 5899 5902 +6 4891 4888 4893 4894 4895 4887 +6 4891 4892 4894 5902 5903 5904 +6 4893 4892 4895 5913 5904 5914 +6 4894 4892 4887 4896 4897 5914 +7 4895 4887 4897 4898 9758 9757 4885 +6 4895 4896 4898 4899 4900 5914 +5 4897 4896 4899 9757 9760 +6 4897 4898 4900 4901 4902 9760 +6 4897 4899 4901 5914 5915 5918 +6 4900 4899 4902 4903 5918 5919 +6 4901 4899 4903 4904 4905 9760 +6 4901 4902 4904 5919 3672 3671 +6 4903 4902 4905 4906 3670 3671 +6 4904 4902 4906 9755 4912 9760 +6 4904 4905 3670 4907 4908 4912 +6 3670 4906 4908 4909 3662 3661 +6 4907 4906 4909 4910 4911 4912 +7 4907 4908 4910 4643 3661 9794 9795 +5 4909 4908 4911 4643 4642 +6 4910 4908 4912 4918 4917 4642 +6 4911 4908 4906 9755 4918 4905 +6 4639 4640 4914 4915 9761 4876 +6 4913 4640 4915 4916 4917 4641 +6 4913 4914 4916 4876 4877 4880 +6 4915 4914 4917 4918 9754 4880 +6 4916 4914 4918 4911 4642 4641 +6 4916 4917 4911 9754 9755 4912 +6 4806 4807 4920 4960 4959 4961 +6 4919 4807 4921 4961 4962 4963 +6 4920 4807 4808 4922 4963 4964 +6 4921 4808 4809 4923 4964 4965 +6 4922 4809 4811 4965 4813 4812 +6 4288 4289 4925 5053 5054 5055 +6 4924 4289 4290 4291 4926 5055 +6 4925 4291 4927 5055 5056 5057 +6 4926 4291 4292 4928 5057 5058 +6 4927 4292 4293 4929 5058 5059 +6 4928 4293 4294 4930 5059 5060 +6 4929 4294 4295 4931 5060 5061 +6 4930 4295 4296 4932 5061 5062 +6 4931 4296 4297 4298 4933 5062 +6 4932 4298 4772 4934 5062 5063 +6 4933 4772 4935 5063 5064 5065 +6 4934 4772 4773 4936 5065 5066 +6 4935 4773 4774 4937 5066 5067 +6 4936 4774 4775 4938 5067 5068 +6 4937 4775 4776 4939 5068 5069 +6 4938 4776 4777 4940 5069 5070 +6 4939 4777 4778 4941 5070 5071 +6 4940 4778 4779 4942 5071 5072 +6 4941 4779 4780 4943 5072 5073 +6 4942 4780 4781 4944 5073 5074 +6 4943 4781 4782 4945 5074 5075 +6 4944 4782 4783 4784 4946 5075 +6 4945 4784 4947 5075 5076 5077 +6 4946 4784 4785 4948 5077 5078 +6 4947 4785 4786 4949 5078 5079 +6 4948 4786 4787 4950 5079 5080 +6 4949 4787 4788 4951 5080 5081 +6 4950 4788 4789 4952 5081 5082 +6 4951 4789 4790 4953 5082 5083 +6 4952 4790 4791 4954 5083 5084 +6 4953 4791 4792 4955 5084 5085 +6 4954 4792 4793 4800 4956 5085 +6 4955 4800 4957 5085 5086 5087 +6 4956 4800 4801 4802 4958 5087 +6 4957 4802 4803 4959 5089 5087 +6 4958 4803 4960 4919 4961 5089 +6 4959 4803 4804 4805 4806 4919 +6 4959 4919 4920 4962 5089 5090 +6 4961 4920 4963 5090 5091 5092 +6 4962 4920 4921 4964 5092 5093 +6 4963 4921 4922 4965 5093 5094 +6 4964 4922 4923 4813 5094 4814 +6 4716 4717 4967 5178 5179 5180 +6 4966 4717 4718 4968 5180 5181 +6 4967 4718 4719 4969 5181 5182 +6 4968 4719 4720 4970 5182 5183 +6 4969 4720 4721 4971 5183 5184 +6 4970 4721 4722 4723 4972 5184 +6 4971 4723 4973 5184 5185 5186 +6 4972 4723 4724 4974 5186 5187 +6 4973 4724 4725 4975 5187 5188 +6 4974 4725 4726 4734 4976 5188 +6 4975 4734 4977 5188 5189 5190 +6 4976 4734 4735 4978 5190 5191 +6 4977 4735 4736 4979 5191 5192 +6 4978 4736 4737 4738 4980 5192 +6 4979 4738 4739 4981 5192 5193 +6 4980 4739 4670 5193 5194 5195 +6 4491 4492 4983 4990 4991 4992 +6 4982 4492 4493 4984 4992 4993 +6 4983 4493 4494 4985 4993 4994 +6 4984 4494 4986 4994 4995 4996 +6 4985 4494 4495 4498 4987 4996 +6 4986 4498 4499 4988 4996 4997 +6 4987 4499 4989 4997 4998 4999 +6 4988 4499 4500 4512 4999 5000 +6 4491 4982 4991 5217 5218 5219 +6 4990 4982 4992 5219 5220 5221 +6 4991 4982 4983 4993 5221 5222 +6 4992 4983 4984 4994 5222 5223 +6 4993 4984 4985 4995 5223 5224 +6 4994 4985 4996 5224 5225 5226 +6 4995 4985 4986 4987 4997 5226 +6 4996 4987 4988 4998 5226 5227 +6 4997 4988 4999 5227 5228 5229 +6 4998 4988 4989 5000 5001 5229 +6 4999 4989 5001 5002 5003 4512 +6 4999 5000 5002 5229 5230 5231 +7 5001 5000 5003 4760 5007 5167 5231 +5 5002 5000 4512 4513 4760 +6 4740 4741 4742 5005 7832 7835 +6 5004 4742 4754 5006 7835 7836 +6 5005 4754 4751 7836 7837 7838 +7 4760 4761 4762 5008 5022 5002 5167 +6 5007 4762 5009 5022 5023 5024 +6 5008 4762 4763 5010 5024 5019 +6 5009 4763 5011 5012 5018 5019 +5 5010 4763 4764 4765 5012 +7 5011 4765 5013 4769 5014 5010 5018 +5 5012 4765 4766 4767 4769 +6 5012 4769 5015 5021 5018 5242 +6 5014 4769 4770 5016 5242 5243 +6 5015 4770 5017 5243 5244 5025 +5 5016 4770 4771 3835 5025 +6 5010 5012 5019 5020 5021 5014 +7 5010 5018 5020 5024 5009 5239 6834 +6 5019 5018 5021 5239 5240 5241 +5 5020 5018 5014 5241 5242 +5 5007 5008 5023 5167 5168 +6 5022 5008 5024 5168 5169 5170 +6 5023 5008 5009 5019 5170 6834 +7 5017 3835 3836 5026 5244 5016 5245 +6 5025 3836 3837 5027 5245 5246 +6 5026 3837 3838 4406 5028 5246 +6 5027 4406 4407 5029 5246 5247 +6 5028 4407 5030 5250 5247 6845 +6 5029 4407 4408 5031 6845 6846 +6 5030 4408 4409 5032 6846 6847 +6 5031 4409 4410 5033 6850 6847 +6 5032 4410 4421 5034 6850 6851 +6 5033 4421 4422 4423 5035 6851 +6 5034 4423 5036 6851 6852 6853 +6 5035 4423 4424 5037 6853 5039 +6 5036 4424 4425 4644 5038 5039 +6 5037 4644 5039 5040 5041 5045 +6 5037 5038 5040 6853 5036 6854 +6 5039 5038 5041 5042 6857 6854 +6 5040 5038 5042 5043 5044 5045 +6 5040 5041 5043 6859 6857 6864 +6 5042 5041 5044 6879 6880 6864 +6 5043 5041 5045 5046 6881 6879 +6 5044 5041 5046 4645 4644 5038 +6 5044 5045 4645 6881 6882 6890 +6 4281 4282 5048 5475 5476 5477 +6 5047 4282 4283 5049 5477 5478 +6 5048 4283 4284 5050 5478 5479 +6 5049 4284 4285 5051 5479 5480 +6 5050 4285 4286 5052 5480 5481 +6 5051 4286 4287 5053 5481 5482 +6 5052 4287 4288 4924 5054 5482 +6 5053 4924 5055 5482 5483 5484 +6 5054 4924 4925 4926 5056 5484 +6 5055 4926 5057 5484 5485 5486 +6 5056 4926 4927 5058 5486 5487 +6 5057 4927 4928 5059 5487 5488 +6 5058 4928 4929 5060 5488 5489 +6 5059 4929 4930 5061 5489 5490 +6 5060 4930 4931 5062 5490 5491 +6 5061 4931 4932 4933 5063 5491 +6 5062 4933 4934 5064 5491 5492 +6 5063 4934 5065 5251 5492 5493 +6 5064 4934 4935 5066 5251 5252 +6 5065 4935 4936 5067 5252 5253 +6 5066 4936 4937 5068 5253 5254 +6 5067 4937 4938 5069 5254 5255 +6 5068 4938 4939 5070 5255 5256 +6 5069 4939 4940 5071 5256 5257 +6 5070 4940 4941 5072 5257 5258 +6 5071 4941 4942 5073 5258 5259 +6 5072 4942 4943 5074 5259 5260 +6 5073 4943 4944 5075 5260 5261 +6 5074 4944 4945 4946 5076 5261 +6 5075 4946 5077 5261 5262 5263 +6 5076 4946 4947 5078 5263 5264 +6 5077 4947 4948 5079 5264 5265 +6 5078 4948 4949 5080 5265 5266 +6 5079 4949 4950 5081 5266 5267 +6 5080 4950 4951 5082 5267 5268 +6 5081 4951 4952 5083 5268 5269 +6 5082 4952 4953 5084 5269 5270 +6 5083 4953 4954 5085 5270 5271 +6 5084 4954 4955 4956 5086 5271 +6 5085 4956 5087 5088 5271 5272 +6 5086 4956 4957 5088 5089 4958 +6 5086 5087 5089 5272 5273 5090 +6 5088 5087 4958 4959 4961 5090 +6 5089 4961 4962 5091 5273 5088 +6 5090 4962 5092 5273 5274 5275 +6 5091 4962 4963 5093 5275 5276 +6 5092 4963 4964 5094 5276 5277 +7 5093 4964 4965 4814 4815 5095 5277 +6 5094 4815 4816 5096 5277 5278 +6 5095 4816 4817 5097 5278 5279 +6 5096 4817 4818 4820 5098 5279 +6 5097 4820 5099 5279 5280 5281 +6 5098 4820 4821 5100 5281 5282 +6 5099 4821 4824 5101 5282 5283 +6 5100 4824 4825 5102 5283 5153 +6 5101 4825 5103 5105 5152 5153 +6 5102 4825 4826 5104 4829 5105 +5 5103 4826 4827 4828 4829 +6 5103 4829 4830 5106 5102 5152 +7 5105 4830 5107 5155 5152 5288 5289 +6 5106 4830 4831 5108 5109 5289 +6 5107 4831 5109 5110 5114 4832 +6 5107 5108 5110 5111 5289 5290 +6 5109 5108 5111 5112 5113 5114 +6 5109 5110 5112 5290 5291 5295 +6 5111 5110 5113 5295 5296 5117 +6 5112 5110 5114 5115 5116 5117 +6 5113 5110 5108 4832 4834 5115 +6 5114 4834 4836 4846 5116 5113 +6 5115 4846 5113 5117 5118 4848 +6 5113 5116 5118 5296 5112 5297 +6 5117 5116 4848 5119 5300 5297 +6 5118 4848 4849 5120 5300 5301 +6 5119 4849 5121 5301 5302 5303 +5 5120 4849 4850 5122 5303 +6 5121 4850 4852 4856 5123 5303 +6 5122 4856 5124 5319 5303 5320 +6 5123 4856 4857 5125 5322 5320 +6 5124 4857 4859 5126 5127 5322 +6 5125 4859 5127 5128 5129 5130 +6 5125 5126 5128 5323 5322 5324 +6 5127 5126 5129 5324 5325 5329 +6 5128 5126 5130 5337 5329 5338 +6 5129 5126 4859 4860 5131 5338 +6 5130 4860 4862 5132 5338 5339 +7 5131 4862 4863 4866 5133 5134 5339 +6 5132 4866 5134 5135 5136 5137 +5 5132 5133 5135 5339 5340 +6 5134 5133 5136 5340 5341 5342 +6 5135 5133 5137 5347 5345 5342 +6 5136 5133 4866 4867 5138 5347 +6 5137 4867 4868 4871 5139 5347 +6 5138 4871 5140 5141 5345 5347 +6 5139 4871 5141 5142 4872 5151 +6 5139 5140 5142 5143 5346 5345 +6 5141 5140 5143 5144 5145 5151 +6 5141 5142 5144 5346 5361 5360 +7 5143 5142 5145 5146 5361 5358 5362 +6 5144 5142 5146 5147 5148 5151 +6 5144 5145 5147 5362 5363 5367 +5 5146 5145 5148 5149 5367 +6 5147 5145 5149 5150 4874 5151 +7 5147 5148 5150 5156 5367 5368 5369 +6 5149 5148 4874 5156 4878 4875 +6 4874 5148 4872 5140 5142 5145 +6 5102 5105 5153 5154 5155 5106 +6 5102 5152 5154 5283 5101 5284 +6 5153 5152 5155 5284 5285 5286 +6 5154 5152 5106 5286 5287 5288 +6 5149 5150 4878 4883 5369 5370 +7 4533 4534 5158 6683 6684 6685 6695 +6 5157 4534 4667 6683 9751 4668 +5 4692 4693 4694 5160 7845 +7 5159 4694 5161 7845 7846 7847 7848 +6 5160 4694 4695 5162 7848 7849 +6 5161 4695 4696 5163 7849 7850 +6 5162 4696 5164 7850 7851 7852 +6 5163 4696 4697 4698 5165 7852 +6 5164 4698 5166 7852 7853 7854 +6 5165 4698 4699 4701 7854 7855 +5 5002 5007 5022 5168 5231 +8 5167 5022 5023 5169 5230 5231 6827 6825 +6 5168 5023 5170 6827 6828 6831 +7 5169 5023 5024 6831 6832 6833 6834 +6 4708 4709 5172 7313 7314 7315 +6 5171 4709 4710 5173 7315 7316 +6 5172 4710 4711 5174 7316 7317 +6 5173 4711 4712 5175 7317 7318 +6 5174 4712 4713 5176 7318 7319 +6 5175 4713 4714 5177 7319 7320 +6 5176 4714 4715 5178 7320 7321 +6 5177 4715 4716 4966 5179 7321 +6 5178 4966 5180 7321 7322 7323 +6 5179 4966 4967 5181 7323 7324 +6 5180 4967 4968 5182 5412 7324 +6 5181 4968 4969 5183 5412 5413 +6 5182 4969 4970 5184 5413 5414 +6 5183 4970 4971 4972 5185 5414 +6 5184 4972 5186 5414 5415 5416 +6 5185 4972 4973 5187 5404 5416 +6 5186 4973 4974 5188 5404 5405 +6 5187 4974 4975 4976 5189 5405 +6 5188 4976 5190 5405 5406 5407 +6 5189 4976 4977 5191 5407 5408 +6 5190 4977 4978 5192 5408 5409 +6 5191 4978 4979 4980 5193 5409 +6 5192 4980 4981 5194 5409 5410 +6 5193 4981 5195 5410 5411 5196 +5 5194 4981 4670 4671 5196 +6 5195 4671 4672 5197 5411 5194 +7 5196 4672 4673 5198 5424 5411 5432 +5 5197 4673 4674 5199 5432 +7 5198 4674 4675 5200 5432 5433 5434 +6 5199 4675 4676 5201 5434 5435 +6 5200 4676 4677 5202 5435 5436 +6 5201 4677 4678 5203 5436 5437 +6 5202 4678 4679 5204 5437 5438 +6 5203 4679 5205 5438 5439 5440 +6 5204 4679 4680 4681 5206 5440 +5 5205 4681 4682 5207 5440 +7 5206 4682 4683 5208 5440 5441 5442 +6 5207 4683 5209 5442 5443 5444 +6 5208 4683 4684 5210 5425 5444 +7 5209 4684 4685 5211 5425 5426 5427 +5 5210 4685 5212 5427 5428 +7 5211 4685 4686 5213 5428 5216 5215 +5 5212 4686 4687 5214 5215 +6 5213 4687 4688 4479 4480 5215 +6 5214 4480 4481 5216 5212 5213 +6 5215 4481 5217 5428 5212 5218 +6 5216 4481 4482 4491 4990 5218 +7 5217 4990 5219 5448 5428 5216 6811 +6 5218 4990 4991 5220 6811 6812 +6 5219 4991 5221 6812 6813 6814 +6 5220 4991 4992 5222 6814 6815 +5 5221 4992 4993 5223 6815 +7 5222 4993 4994 5224 6815 6816 6817 +5 5223 4994 4995 5225 6817 +7 5224 4995 5226 6817 6818 6819 6820 +6 5225 4995 4996 4997 5227 6820 +6 5226 4997 4998 5228 6820 6821 +6 5227 4998 5229 6821 6822 6823 +6 5228 4998 4999 5001 5230 6823 +7 5229 5001 5231 5168 6823 6824 6825 +5 5230 5001 5168 5167 5002 +6 4265 4266 5233 6903 6904 5459 +6 5232 4266 4267 5234 5449 5459 +6 5233 4267 4268 5235 5449 5450 +6 5234 4268 4270 5450 5451 5452 +6 4520 4521 5237 9678 9679 9680 +6 5236 4521 5238 9680 9684 9685 +6 5237 4521 4522 423 9685 422 +6 5019 5020 5240 6833 6834 6835 +6 5239 5020 5241 5649 6835 6836 +6 5240 5020 5021 5242 5649 5650 +7 5241 5021 5014 5015 5243 5650 5651 +5 5242 5015 5016 5244 5651 +7 5243 5016 5025 5245 5653 5651 5654 +6 5244 5025 5026 5246 5654 5248 +6 5245 5026 5027 5028 5247 5248 +6 5246 5028 5248 5249 5250 5029 +6 5246 5247 5249 5654 5245 6841 +6 5248 5247 5250 6842 6841 6843 +6 5249 5247 5029 6843 6844 6845 +6 5064 5065 5252 5493 5494 5495 +6 5251 5065 5066 5253 5495 5496 +6 5252 5066 5067 5254 5496 5497 +6 5253 5067 5068 5255 5497 5498 +6 5254 5068 5069 5256 5498 5499 +6 5255 5069 5070 5257 5499 5500 +6 5256 5070 5071 5258 5500 5501 +6 5257 5071 5072 5259 5501 5502 +6 5258 5072 5073 5260 5502 5503 +6 5259 5073 5074 5261 5503 5504 +6 5260 5074 5075 5076 5262 5504 +6 5261 5076 5263 5504 5505 5506 +6 5262 5076 5077 5264 5506 5507 +6 5263 5077 5078 5265 5507 5508 +6 5264 5078 5079 5266 5508 5509 +6 5265 5079 5080 5267 5509 5510 +6 5266 5080 5081 5268 5510 5511 +6 5267 5081 5082 5269 5511 5512 +6 5268 5082 5083 5270 5512 5513 +6 5269 5083 5084 5271 5513 5514 +6 5270 5084 5085 5086 5272 5514 +6 5271 5086 5088 5273 5514 5515 +6 5272 5088 5090 5091 5274 5515 +6 5273 5091 5275 5515 5516 5517 +6 5274 5091 5092 5276 5520 5517 +6 5275 5092 5093 5277 5520 5278 +5 5276 5093 5094 5095 5278 +6 5277 5095 5096 5279 5520 5276 +6 5278 5096 5097 5098 5280 5520 +6 5279 5098 5281 5520 5519 5521 +6 5280 5098 5099 5282 5521 5378 +6 5281 5099 5100 5283 5377 5378 +6 5282 5100 5101 5153 5284 5377 +6 5283 5153 5154 5285 5380 5377 +6 5284 5154 5286 5525 5380 5526 +6 5285 5154 5155 5287 5526 5527 +6 5286 5155 5288 5527 5528 5292 +6 5287 5155 5106 5289 5292 5290 +5 5288 5106 5107 5109 5290 +6 5289 5109 5111 5291 5292 5288 +6 5290 5111 5292 5293 5294 5295 +7 5290 5291 5293 5528 5287 5288 5529 +6 5292 5291 5294 5529 5530 5534 +5 5293 5291 5295 5534 5535 +6 5294 5291 5111 5112 5296 5535 +6 5295 5112 5117 5297 5298 5535 +6 5296 5117 5298 5299 5300 5118 +6 5296 5297 5299 5535 5536 5543 +6 5298 5297 5300 5543 5544 5545 +6 5299 5297 5118 5119 5301 5545 +6 5300 5119 5120 5302 5305 5545 +6 5301 5120 5303 5304 5305 5306 +7 5302 5120 5304 5319 5123 5121 5122 +6 5302 5303 5309 5306 5310 5319 +6 5301 5302 5306 5307 5544 5545 +6 5305 5302 5307 5308 5309 5304 +6 5305 5306 5308 5544 5546 5547 +6 5307 5306 5309 5312 5313 5547 +6 5308 5306 5304 5310 5311 5312 +6 5309 5304 5311 5317 5318 5319 +6 5309 5310 5312 5315 5316 5317 +6 5309 5311 5308 5313 5314 5315 +6 5308 5312 5314 5547 5548 5549 +6 5313 5312 5315 5549 5550 5551 +6 5314 5312 5311 5316 5554 5551 +6 5315 5311 5317 5556 5554 5559 +6 5316 5311 5310 5318 5559 5560 +6 5317 5310 5319 5320 5321 5560 +6 5318 5310 5304 5303 5123 5320 +6 5319 5123 5318 5321 5322 5124 +6 5318 5320 5322 5323 5560 5561 +6 5321 5320 5323 5127 5125 5124 +6 5321 5322 5127 5324 5561 5562 +6 5323 5127 5128 5325 5326 5562 +6 5324 5128 5326 5327 5328 5329 +6 5324 5325 5327 5562 5563 5564 +6 5326 5325 5328 5573 5564 5574 +6 5327 5325 5329 5330 5331 5574 +6 5328 5325 5330 5337 5129 5128 +6 5328 5329 5331 5332 5333 5337 +6 5328 5330 5332 5574 5575 5576 +6 5331 5330 5333 5334 5576 5577 +6 5332 5330 5334 5335 5336 5337 +6 5332 5333 5335 5577 5578 5579 +6 5334 5333 5336 5579 5341 5340 +6 5335 5333 5337 5338 5339 5340 +6 5336 5333 5330 5329 5129 5338 +6 5337 5129 5130 5131 5336 5339 +6 5336 5338 5131 5132 5134 5340 +6 5339 5134 5135 5341 5335 5336 +6 5340 5135 5342 5343 5579 5335 +6 5341 5135 5343 5344 5345 5136 +6 5341 5342 5344 5349 5350 5579 +6 5343 5342 5345 5346 5348 5349 +7 5344 5342 5346 5141 5139 5347 5136 +6 5344 5345 5141 5143 5348 5360 +5 5139 5345 5136 5137 5138 +6 5344 5346 5349 5352 5353 5360 +6 5344 5348 5343 5350 5351 5352 +6 5343 5349 5351 5579 5578 5580 +6 5350 5349 5352 5580 5581 5585 +6 5351 5349 5348 5353 5354 5585 +6 5352 5348 5354 5355 5356 5360 +6 5352 5353 5355 5609 5585 5610 +6 5354 5353 5356 5357 5808 5610 +6 5355 5353 5357 5358 5360 5361 +6 5355 5356 5358 5359 5808 5809 +6 5357 5356 5359 5361 5144 5362 +7 5357 5358 5809 5810 5811 5364 5362 +6 5356 5353 5348 5361 5143 5346 +5 5356 5360 5143 5144 5358 +6 5358 5144 5146 5363 5364 5359 +6 5362 5146 5364 5365 5366 5367 +5 5362 5363 5365 5811 5359 +6 5364 5363 5366 5811 5812 5403 +7 5365 5363 5367 5403 5402 5368 5376 +6 5366 5363 5146 5147 5149 5368 +6 5367 5149 5369 5375 5366 5376 +6 5368 5149 5156 5370 5372 5375 +6 5369 5156 4883 4884 5371 5372 +6 5370 4884 5372 5373 4889 4886 +6 5370 5371 5373 5374 5375 5369 +6 5372 5371 5374 4889 5394 5900 +6 5372 5373 5375 5376 5393 5394 +5 5372 5374 5376 5369 5368 +6 5375 5374 5393 5366 5368 5402 +6 5282 5283 5378 5379 5380 5284 +6 5282 5377 5379 5521 5281 5522 +6 5378 5377 5380 5522 5523 5524 +6 5379 5377 5284 5524 5525 5285 +6 4657 4658 56 9690 431 57 +6 1680 1681 1679 5383 5384 1683 +6 1679 5382 5384 5385 7780 3416 +6 5383 5382 5385 5386 3775 1683 +6 5383 5384 5386 5387 7780 7781 +6 5385 5384 5387 5388 5392 3775 +6 5385 5386 5388 5389 7781 7782 +6 5387 5386 5389 5390 5391 5392 +6 5387 5388 5390 5617 7782 7783 +6 5389 5388 5391 5617 5618 5619 +6 5390 5388 5392 5619 5620 5621 +6 5391 5388 5386 3775 5621 3776 +6 5376 5374 5394 5395 5402 5399 +6 5393 5374 5395 5373 5396 5900 +6 5393 5394 5396 5397 5398 5399 +5 5395 5394 5397 5900 5895 +6 5395 5396 5398 5894 5891 5895 +6 5395 5397 5399 5400 5890 5891 +6 5395 5398 5400 5401 5402 5393 +6 5399 5398 5401 5881 5889 5890 +7 5399 5400 5402 5403 5888 5882 5881 +6 5399 5401 5403 5366 5376 5393 +6 5402 5401 5888 5812 5365 5366 +6 5186 5187 5405 5416 5417 5418 +6 5404 5187 5188 5189 5406 5418 +6 5405 5189 5407 5418 5419 5420 +6 5406 5189 5190 5408 5420 5421 +6 5407 5190 5191 5409 5421 5422 +6 5408 5191 5192 5193 5410 5422 +6 5409 5193 5194 5411 5422 5423 +6 5410 5194 5196 5423 5424 5197 +6 5181 5182 5413 7324 7325 7326 +6 5412 5182 5183 5414 7326 7327 +6 5413 5183 5184 5185 5415 7327 +6 5414 5185 5416 7327 7328 7329 +6 5415 5185 5186 5404 5417 7329 +6 5416 5404 5418 7329 7330 7331 +6 5417 5404 5405 5406 5419 7331 +6 5418 5406 5420 6792 7331 7332 +6 5419 5406 5407 5421 6792 6793 +6 5420 5407 5408 5422 5429 6793 +6 5421 5408 5409 5410 5423 5429 +6 5422 5410 5411 5424 5429 5430 +6 5423 5411 5197 5430 5431 5432 +6 5209 5210 5426 5444 5445 5446 +6 5425 5210 5427 5446 5447 5448 +5 5426 5210 5211 5428 5448 +6 5427 5211 5212 5216 5448 5218 +6 5421 5422 5423 5430 6793 6794 +6 5429 5423 5424 5431 6794 6795 +6 5430 5424 5432 6795 6796 5433 +6 5431 5424 5197 5198 5199 5433 +5 5432 5199 5434 6796 5431 +6 5433 5199 5200 5435 6796 6797 +6 5434 5200 5201 5436 6797 6798 +6 5435 5201 5202 5437 6798 6799 +6 5436 5202 5203 5438 6799 6800 +6 5437 5203 5204 5439 6800 6801 +6 5438 5204 5440 6801 6802 6803 +7 5439 5204 5205 5206 5207 5441 6803 +5 5440 5207 5442 6803 6804 +6 5441 5207 5208 5443 6804 6805 +6 5442 5208 5444 6805 6806 5445 +5 5443 5208 5209 5425 5445 +6 5444 5425 5446 6806 5443 6807 +6 5445 5425 5426 5447 6807 6808 +6 5446 5426 5448 6808 6809 6810 +7 5447 5426 5427 5428 5218 6810 6811 +6 5233 5234 5450 5459 5460 5461 +6 5449 5234 5235 5451 5461 5462 +6 5450 5235 5452 5462 5463 5464 +6 5451 5235 4270 4271 5453 5464 +6 5452 4271 4272 5454 5464 5465 +6 5453 4272 4273 5455 5456 5465 +6 5454 4273 5456 5457 5458 4274 +6 5454 5455 5457 5465 5466 5467 +6 5456 5455 5458 5467 5468 5469 +6 5457 5455 4274 5469 5470 4275 +6 5233 5449 5460 6904 5232 6905 +6 5459 5449 5461 6905 6906 6907 +6 5460 5449 5450 5462 6907 6908 +6 5461 5450 5451 5463 6908 6909 +6 5462 5451 5464 6909 6910 6911 +6 5463 5451 5452 5453 5465 6911 +6 5464 5453 5454 5456 5466 6911 +6 5465 5456 5467 6911 6912 6913 +6 5466 5456 5457 5468 6913 6914 +6 5467 5457 5469 6914 6915 6916 +6 5468 5457 5458 5470 6916 6917 +6 5469 5458 4275 4276 5471 6917 +6 5470 4276 4277 4278 5472 6917 +6 5471 4278 5473 6917 6918 6919 +6 5472 4278 4279 5474 6919 6920 +6 5473 4279 4280 5475 6920 6921 +6 5474 4280 4281 5047 5476 6921 +6 5475 5047 5477 6921 6922 6923 +6 5476 5047 5048 5478 6923 6924 +6 5477 5048 5049 5479 6924 6925 +6 5478 5049 5050 5480 6925 6926 +6 5479 5050 5051 5481 6926 6927 +6 5480 5051 5052 5482 5655 6927 +6 5481 5052 5053 5054 5483 5655 +6 5482 5054 5484 5655 5656 5657 +6 5483 5054 5055 5056 5485 5657 +6 5484 5056 5486 5657 5658 5659 +6 5485 5056 5057 5487 5659 5660 +6 5486 5057 5058 5488 5660 5661 +6 5487 5058 5059 5489 5661 5662 +6 5488 5059 5060 5490 5622 5662 +6 5489 5060 5061 5491 5622 5623 +6 5490 5061 5062 5063 5492 5623 +6 5491 5063 5064 5493 5623 5624 +6 5492 5064 5251 5494 5624 5625 +6 5493 5251 5495 5625 5626 5627 +6 5494 5251 5252 5496 5627 5628 +6 5495 5252 5253 5497 5628 5629 +6 5496 5253 5254 5498 5629 5630 +6 5497 5254 5255 5499 5630 5631 +6 5498 5255 5256 5500 5631 5632 +6 5499 5256 5257 5501 5632 5633 +6 5500 5257 5258 5502 5633 5634 +6 5501 5258 5259 5503 5634 5635 +6 5502 5259 5260 5504 5635 5636 +6 5503 5260 5261 5262 5505 5636 +6 5504 5262 5506 5636 5637 5638 +6 5505 5262 5263 5507 5638 5639 +6 5506 5263 5264 5508 5639 5640 +6 5507 5264 5265 5509 5640 5641 +6 5508 5265 5266 5510 5641 5642 +6 5509 5266 5267 5511 5642 5643 +6 5510 5267 5268 5512 5643 5644 +6 5511 5268 5269 5513 5644 5645 +6 5512 5269 5270 5514 5645 5646 +6 5513 5270 5271 5272 5515 5646 +6 5514 5272 5273 5274 5516 5646 +6 5515 5274 5517 5518 5646 5647 +6 5516 5274 5518 5519 5520 5275 +6 5516 5517 5519 5647 5648 5521 +5 5518 5517 5520 5280 5521 +7 5519 5517 5275 5276 5278 5279 5280 +7 5519 5280 5281 5378 5522 5648 5518 +5 5521 5378 5379 5523 5648 +7 5522 5379 5524 5686 5648 5685 5687 +6 5523 5379 5380 5525 5688 5687 +6 5524 5380 5285 5526 5688 5689 +6 5525 5285 5286 5527 5689 5690 +6 5526 5286 5287 5528 5690 5691 +6 5527 5287 5292 5529 5691 5692 +6 5528 5292 5293 5530 5531 5692 +6 5529 5293 5531 5532 5533 5534 +5 5529 5530 5532 5692 5693 +6 5531 5530 5533 5693 5694 5695 +7 5532 5530 5534 5695 5696 5539 5537 +6 5533 5530 5293 5294 5535 5537 +7 5534 5294 5295 5296 5298 5536 5537 +6 5535 5298 5537 5538 5542 5543 +6 5535 5536 5538 5539 5533 5534 +6 5537 5536 5539 5540 5541 5542 +6 5537 5538 5540 5696 5533 5697 +6 5539 5538 5541 5697 5698 5699 +7 5540 5538 5542 5699 5700 5701 9796 +5 5541 5538 5536 5543 9796 +6 5542 5536 5298 5299 5544 9796 +7 5543 5299 5545 5305 5307 5546 9796 +5 5544 5299 5305 5301 5300 +6 5544 5307 5547 5702 5701 9796 +6 5546 5307 5308 5313 5548 5702 +6 5547 5313 5549 5702 5703 5704 +6 5548 5313 5314 5550 5704 5705 +6 5549 5314 5551 5552 5705 5706 +6 5550 5314 5552 5553 5554 5315 +6 5550 5551 5553 5706 5707 5708 +6 5552 5551 5554 5555 5708 5709 +6 5553 5551 5315 5555 5556 5316 +6 5553 5554 5556 5557 5709 5710 +6 5555 5554 5316 5557 5558 5559 +6 5555 5556 5558 5710 5711 5712 +6 5557 5556 5559 5715 5712 5716 +6 5558 5556 5316 5317 5560 5716 +6 5559 5317 5318 5321 5561 5716 +6 5560 5321 5323 5562 5717 5716 +6 5561 5323 5324 5326 5563 5717 +6 5562 5326 5564 5565 5718 5717 +6 5563 5326 5565 5566 5573 5327 +6 5563 5564 5566 5567 5718 5714 +6 5565 5564 5567 5568 5572 5573 +6 5565 5566 5568 5569 5754 5714 +6 5567 5566 5569 5570 5571 5572 +6 5567 5568 5570 5753 5754 5755 +6 5569 5568 5571 5755 5756 5771 +6 5570 5568 5572 5770 5768 5771 +6 5571 5568 5566 5573 5770 5772 +6 5572 5566 5564 5327 5574 5772 +6 5573 5327 5328 5331 5575 5772 +6 5574 5331 5576 5772 5773 5774 +6 5575 5331 5332 5577 5774 5595 +7 5576 5332 5334 5578 5595 5590 5775 +6 5577 5334 5579 5350 5580 5775 +6 5578 5334 5335 5341 5343 5350 +6 5578 5350 5351 5581 5582 5775 +6 5580 5351 5582 5583 5584 5585 +6 5580 5581 5583 5586 5587 5775 +6 5582 5581 5584 5586 5606 5607 +6 5583 5581 5585 5607 5608 5609 +6 5584 5581 5351 5352 5609 5354 +6 5582 5583 5587 5588 5606 5598 +6 5582 5586 5588 5589 5590 5775 +6 5587 5586 5589 5596 5597 5598 +6 5587 5588 5590 5591 5592 5596 +6 5587 5589 5591 5595 5577 5775 +6 5590 5589 5592 5593 5595 5774 +6 5591 5589 5593 5594 5596 5779 +6 5591 5592 5594 5774 5773 5776 +6 5593 5592 5776 5777 5778 5779 +5 5590 5591 5774 5576 5577 +6 5592 5589 5588 5597 5779 5780 +6 5596 5588 5598 5599 5600 5780 +6 5597 5588 5599 5603 5606 5586 +6 5597 5598 5600 5601 5602 5603 +6 5597 5599 5601 5780 5781 5782 +6 5600 5599 5602 5782 5790 5791 +6 5601 5599 5603 5604 5791 5792 +6 5602 5599 5604 5605 5598 5606 +6 5602 5603 5605 5795 5792 5796 +6 5604 5603 5796 5797 5607 5606 +6 5603 5598 5586 5583 5607 5605 +6 5606 5583 5584 5608 5797 5605 +6 5607 5584 5609 5611 5799 5797 +6 5608 5584 5585 5354 5610 5611 +7 5609 5354 5611 5801 5807 5808 5355 +5 5609 5610 5608 5801 5799 +6 4515 4517 5613 5614 5615 5616 +6 4515 5612 5614 428 427 7501 +6 5613 5612 5615 7501 7502 7506 +6 5614 5612 5616 7506 7507 7508 +6 5615 5612 4517 7508 7509 4519 +6 5389 5390 5618 7783 7784 7785 +6 5617 5390 5619 7785 7786 7787 +6 5618 5390 5391 5620 7787 7790 +6 5619 5391 5621 7790 7791 7792 +6 5620 5391 5392 3776 3779 7792 +6 5489 5490 5623 5662 5663 5664 +6 5622 5490 5491 5492 5624 5664 +6 5623 5492 5493 5625 5664 5665 +6 5624 5493 5494 5626 5665 5666 +6 5625 5494 5627 5666 5667 5668 +6 5626 5494 5495 5628 5668 5669 +6 5627 5495 5496 5629 5669 5670 +6 5628 5496 5497 5630 5670 5671 +6 5629 5497 5498 5631 5671 5672 +6 5630 5498 5499 5632 5672 5673 +6 5631 5499 5500 5633 5673 5674 +6 5632 5500 5501 5634 5674 5675 +6 5633 5501 5502 5635 5675 5676 +6 5634 5502 5503 5636 5676 5677 +6 5635 5503 5504 5505 5637 5677 +6 5636 5505 5638 5677 5678 5679 +6 5637 5505 5506 5639 5679 5680 +6 5638 5506 5507 5640 5680 5681 +6 5639 5507 5508 5641 5681 5682 +6 5640 5508 5509 5642 5682 5683 +6 5641 5509 5510 5643 5683 5684 +6 5642 5510 5511 5644 5684 5685 +6 5643 5511 5512 5645 5685 5686 +6 5644 5512 5513 5646 5686 5647 +6 5645 5513 5514 5515 5516 5647 +6 5646 5516 5518 5648 5686 5645 +6 5647 5518 5521 5686 5523 5522 +6 5240 5241 5650 6836 6837 6838 +6 5649 5241 5242 5651 5652 6838 +6 5650 5242 5652 5653 5244 5243 +6 5650 5651 5653 6838 6839 6840 +6 5652 5651 5244 5654 6840 6841 +5 5653 5244 5245 5248 6841 +6 5481 5482 5483 5656 6927 6928 +6 5655 5483 5657 6928 6929 6930 +6 5656 5483 5484 5485 5658 6930 +6 5657 5485 5659 6930 6931 6932 +6 5658 5485 5486 5660 5832 6932 +6 5659 5486 5487 5661 5832 5833 +6 5660 5487 5488 5662 5833 5834 +6 5661 5488 5489 5622 5663 5834 +6 5662 5622 5664 5834 5835 5836 +6 5663 5622 5623 5624 5665 5836 +6 5664 5624 5625 5666 5836 5814 +6 5665 5625 5626 5667 5813 5814 +6 5666 5626 5668 5813 5817 5818 +6 5667 5626 5627 5669 5860 5818 +6 5668 5627 5628 5670 5860 5861 +6 5669 5628 5629 5671 5861 5862 +6 5670 5629 5630 5672 5862 5863 +6 5671 5630 5631 5673 5863 5864 +6 5672 5631 5632 5674 5864 5865 +6 5673 5632 5633 5675 5865 5866 +6 5674 5633 5634 5676 5866 5867 +6 5675 5634 5635 5677 5867 5868 +6 5676 5635 5636 5637 5678 5868 +6 5677 5637 5679 5868 5869 5694 +6 5678 5637 5638 5680 5694 5870 +6 5679 5638 5639 5681 5870 5871 +6 5680 5639 5640 5682 5871 5872 +6 5681 5640 5641 5683 5872 5689 +6 5682 5641 5642 5684 5689 5688 +6 5683 5642 5643 5685 5687 5688 +6 5684 5643 5644 5686 5523 5687 +6 5685 5644 5645 5647 5648 5523 +5 5685 5523 5684 5688 5524 +6 5684 5687 5524 5525 5689 5683 +7 5688 5525 5526 5690 5872 5682 5683 +5 5689 5526 5527 5691 5872 +7 5690 5527 5528 5692 5872 5871 5693 +5 5691 5528 5529 5531 5693 +7 5692 5531 5532 5694 5871 5691 5870 +7 5693 5532 5695 5869 5678 5679 5870 +6 5694 5532 5533 5696 9699 5869 +6 5695 5533 5539 5697 9700 9699 +6 5696 5539 5540 5698 5719 9700 +6 5697 5540 5699 5719 5720 5721 +6 5698 5540 5541 5700 5721 5722 +6 5699 5541 5701 5702 5722 5723 +5 5700 5541 5702 5546 9796 +7 5700 5701 5546 5547 5548 5703 5723 +6 5702 5548 5704 5723 5724 5728 +6 5703 5548 5549 5705 5728 5729 +6 5704 5549 5550 5706 5729 5730 +6 5705 5550 5552 5707 5733 5730 +6 5706 5552 5708 5733 5734 5735 +6 5707 5552 5553 5709 5738 5735 +6 5708 5553 5555 5710 5738 5739 +6 5709 5555 5557 5711 5748 5739 +6 5710 5557 5712 5713 5748 5749 +6 5711 5557 5713 5714 5715 5558 +6 5711 5712 5714 5749 5750 5754 +7 5713 5712 5715 5718 5565 5754 5567 +6 5714 5712 5558 5716 5717 5718 +6 5715 5558 5717 5561 5560 5559 +6 5715 5716 5718 5563 5562 5561 +5 5715 5717 5563 5565 5714 +7 5697 5698 5720 9697 5866 9698 9700 +6 5719 5698 5721 9697 9696 9701 +6 5720 5698 5699 5722 9701 9702 +7 5721 5699 5700 5723 5724 5725 9702 +5 5722 5700 5702 5703 5724 +7 5723 5703 5722 5725 5726 5727 5728 +6 5722 5724 5726 6096 9702 9703 +6 5725 5724 5727 6096 6097 6098 +6 5726 5724 5728 6098 5731 5729 +5 5727 5724 5703 5704 5729 +6 5728 5704 5705 5730 5731 5727 +6 5729 5705 5731 5732 5733 5706 +7 5729 5730 5732 6098 5727 6099 6100 +6 5731 5730 5733 6100 6101 6102 +6 5732 5730 5706 5707 5734 6102 +6 5733 5707 5735 5736 6102 6103 +6 5734 5707 5736 5737 5738 5708 +6 5734 5735 5737 6106 6103 6107 +6 5736 5735 5738 6107 6108 5740 +6 5737 5735 5708 5709 5739 5740 +6 5738 5709 5740 5741 5748 5710 +6 5738 5739 5741 5742 6108 5737 +6 5740 5739 5742 5743 5747 5748 +6 5740 5741 5743 5744 6108 6109 +6 5742 5741 5744 5745 5746 5747 +6 5742 5743 5745 6112 6109 6113 +6 5744 5743 5746 6113 6114 6115 +6 5745 5743 5747 5751 6122 6115 +6 5746 5743 5741 5748 5749 5751 +6 5747 5741 5739 5710 5711 5749 +6 5748 5711 5713 5750 5747 5751 +6 5749 5713 5751 5752 5753 5754 +6 5747 5749 5746 5750 5752 6122 +5 5751 5750 5753 6122 5950 +6 5752 5750 5754 5569 5755 5950 +6 5753 5750 5713 5714 5569 5567 +6 5753 5569 5570 5756 5757 5950 +6 5755 5570 5757 5758 5759 5771 +6 5755 5756 5758 5950 5951 5952 +6 5757 5756 5759 5760 5952 5953 +6 5758 5756 5760 5761 5762 5771 +6 5758 5759 5761 5953 5954 5958 +6 5760 5759 5762 5763 5764 5958 +6 5761 5759 5763 5767 5768 5771 +6 5761 5762 5764 5765 5766 5767 +6 5761 5763 5765 5958 5959 5989 +6 5764 5763 5766 5990 5989 5991 +6 5765 5763 5767 5991 5992 5777 +6 5766 5763 5762 5768 5769 5777 +6 5767 5762 5769 5770 5571 5771 +6 5767 5768 5770 5773 5776 5777 +6 5769 5768 5571 5572 5772 5773 +6 5571 5768 5570 5762 5756 5759 +6 5770 5572 5573 5574 5575 5773 +7 5772 5575 5774 5593 5776 5770 5769 +6 5773 5575 5576 5595 5591 5593 +6 5590 5577 5587 5582 5580 5578 +5 5773 5593 5594 5777 5769 +7 5776 5594 5778 5992 5766 5769 5767 +6 5777 5594 5779 5993 5992 5783 +6 5778 5594 5592 5596 5780 5783 +6 5779 5596 5597 5600 5781 5783 +6 5780 5600 5782 5783 5784 5785 +6 5781 5600 5601 5785 5786 5790 +6 5780 5781 5784 5993 5778 5779 +6 5783 5781 5785 5994 5993 5997 +7 5784 5781 5782 5786 5787 5997 5998 +6 5785 5782 5787 5788 5789 5790 +6 5785 5786 5788 5998 5999 6000 +6 5787 5786 5789 6003 6000 6004 +6 5788 5786 5790 6010 6004 6200 +6 5789 5786 5782 5601 5791 6200 +6 5790 5601 5602 5792 5793 6200 +6 5791 5602 5793 5794 5795 5604 +6 5791 5792 5794 6199 6200 6198 +6 5793 5792 5795 6198 6201 6222 +6 5794 5792 5604 5796 6222 6220 +6 5795 5604 5605 5797 5798 6220 +6 5796 5605 5798 5799 5608 5607 +6 5796 5797 5799 5800 6219 6220 +6 5798 5797 5608 5800 5801 5611 +6 5798 5799 5801 5802 5803 6219 +7 5800 5799 5611 5610 5802 5806 5807 +6 5800 5801 5803 5804 5805 5806 +6 5800 5802 5804 6218 6210 6219 +6 5803 5802 5805 5824 5825 6218 +6 5804 5802 5806 5824 5831 5840 +6 5805 5802 5801 5807 5809 5840 +5 5806 5801 5610 5808 5809 +5 5807 5610 5355 5357 5809 +7 5808 5357 5359 5810 5840 5806 5807 +6 5809 5359 5811 5839 5840 5887 +7 5810 5359 5364 5365 5812 5886 5887 +6 5811 5365 5885 5886 5888 5403 +6 5666 5667 5814 5815 5816 5817 +6 5666 5813 5815 5836 5665 5843 +6 5814 5813 5816 5843 5844 5845 +6 5815 5813 5817 5820 5821 5845 +6 5816 5813 5667 5818 5819 5820 +6 5817 5667 5819 5860 5858 5668 +6 5817 5818 5820 5823 5858 5855 +6 5817 5819 5816 5821 5822 5823 +6 5816 5820 5822 5845 5846 5847 +6 5821 5820 5823 5853 5850 5847 +6 5822 5820 5819 5853 5854 5855 +6 5804 5805 5825 5826 5827 5831 +5 5804 5824 5826 6217 6218 +7 5825 5824 5827 5828 6217 6216 6022 +6 5826 5824 5828 5829 5830 5831 +6 5826 5827 5829 6020 6021 6022 +6 5828 5827 5830 5837 5873 6020 +6 5829 5827 5831 5837 5838 5839 +6 5830 5827 5824 5805 5839 5840 +6 5659 5660 5833 6932 6933 6934 +6 5832 5660 5661 5834 5841 6934 +6 5833 5661 5662 5663 5835 5841 +6 5834 5663 5836 5841 5842 5843 +6 5835 5663 5664 5665 5814 5843 +6 5829 5830 5838 5873 5874 5884 +6 5837 5830 5839 5886 5884 5887 +6 5838 5830 5831 5840 5810 5887 +6 5839 5831 5810 5809 5806 5805 +6 5833 5834 5835 5842 6934 6935 +6 5841 5835 5843 6935 6936 5844 +6 5842 5835 5836 5814 5815 5844 +6 5843 5815 5845 6019 6936 5842 +6 5844 5815 5816 5821 5846 6019 +6 5845 5821 5847 5848 6019 6941 +6 5846 5821 5848 5849 5850 5822 +6 5846 5847 5849 6941 6942 6943 +6 5848 5847 5850 5851 6946 6943 +6 5849 5847 5851 5852 5853 5822 +5 5849 5850 5852 6946 6386 +6 5851 5850 5853 6104 6105 6386 +6 5852 5850 5822 5823 5854 6104 +6 5853 5823 5855 5856 6101 6104 +6 5854 5823 5856 5857 5858 5819 +6 5854 5855 5857 6099 6100 6101 +6 5856 5855 5858 5859 6385 6099 +6 5857 5855 5859 5860 5818 5819 +6 5857 5858 5860 5861 6384 6385 +6 5859 5858 5818 5668 5669 5861 +6 5860 5669 5670 5862 6384 5859 +6 5861 5670 5671 5863 9704 6384 +6 5862 5671 5672 5864 9695 9704 +6 5863 5672 5673 5865 9695 9696 +6 5864 5673 5674 5866 9696 9697 +7 5865 5674 5675 5867 9697 5719 9698 +5 5866 5675 5676 5868 9698 +7 5867 5676 5677 5678 5869 9698 9699 +5 5868 5678 5694 5695 9699 +5 5694 5679 5680 5871 5693 +6 5870 5680 5681 5872 5691 5693 +6 5871 5681 5682 5689 5690 5691 +6 5829 5837 5874 5875 9737 6020 +6 5873 5837 5875 5876 5883 5884 +6 5873 5874 5876 5877 9737 6042 +6 5875 5874 5877 5878 5879 5883 +6 5875 5876 5878 6049 6042 6043 +6 5877 5876 5879 5880 6050 6049 +6 5878 5876 5880 5881 5882 5883 +6 5878 5879 5881 6050 6051 5889 +6 5880 5879 5882 5401 5400 5889 +6 5881 5879 5883 5885 5888 5401 +6 5882 5879 5876 5874 5884 5885 +6 5883 5874 5837 5885 5886 5838 +6 5883 5884 5886 5812 5882 5888 +6 5885 5884 5838 5812 5811 5887 +5 5811 5886 5838 5839 5810 +5 5882 5885 5812 5403 5401 +6 5881 5400 5890 6054 6051 5880 +6 5889 5400 5398 5891 5892 6054 +6 5890 5398 5892 5893 5894 5397 +6 5890 5891 5893 6057 6054 6058 +6 5892 5891 5894 6058 6059 6060 +6 5893 5891 5397 5895 5896 6060 +6 5894 5397 5896 5897 5900 5396 +6 5894 5895 5897 5898 6060 6062 +6 5896 5895 5898 5899 4890 5900 +6 5896 5897 5899 5901 6062 6063 +6 5898 5897 4890 4891 5901 5902 +7 4890 5897 5895 5396 5394 5373 4889 +6 5898 5899 5902 6066 6063 6067 +6 5901 5899 4891 4893 5903 6067 +6 5902 4893 5904 5905 5906 6067 +6 5903 4893 5905 5912 5913 4894 +6 5903 5904 5906 5907 5908 5912 +6 5903 5905 5907 6067 6071 6068 +7 5906 5905 5908 5909 6076 6073 6071 +6 5907 5905 5909 5910 5911 5912 +5 5907 5908 5910 5935 6076 +7 5909 5908 5911 5933 5930 5934 5935 +6 5910 5908 5912 5933 9753 5916 +6 5911 5908 5905 5904 5913 5916 +6 5912 5904 4894 5914 5915 5916 +6 5913 4894 4895 4897 4900 5915 +6 5914 4900 5913 5916 5917 5918 +6 5913 5915 5917 5912 9753 5911 +6 5916 5915 5918 9753 9756 9759 +6 5917 5915 4900 4901 5919 9759 +7 5918 4901 4903 3672 3952 5920 9759 +6 5919 3952 3950 5921 9756 9759 +5 5920 3950 3949 5922 9756 +6 5921 3949 5923 5931 5932 9756 +6 5922 3949 3947 3963 5924 5931 +6 5923 3963 3964 5925 5926 5931 +6 5924 3964 3966 5926 5927 5943 +6 5924 5925 5927 5928 5930 5931 +6 5926 5925 5928 5929 5942 5943 +5 5926 5927 5929 5930 5934 +7 5928 5927 5936 5934 5937 5941 5942 +7 5926 5928 5931 5932 5933 5910 5934 +6 5926 5930 5932 5924 5923 5922 +6 5931 5930 5922 5933 9753 9756 +5 5932 5930 5910 5911 9753 +6 5910 5930 5935 5936 5929 5928 +6 5910 5934 5936 6075 6076 5909 +6 5935 5934 5929 5937 5938 6075 +6 5936 5929 5938 5939 5940 5941 +5 5936 5937 5939 6075 6077 +6 5938 5937 5940 6077 6078 6087 +6 5939 5937 5941 6088 6087 6092 +7 5940 5937 5929 5942 5945 6092 5947 +5 5941 5929 5927 5943 5945 +6 5942 5927 5925 3966 5944 5945 +7 5943 3966 3967 5945 5946 3136 5948 +6 5943 5944 5942 5941 5946 5947 +5 5945 5944 5947 3135 3136 +6 5945 5946 3135 6092 5941 3137 +6 3136 5944 2094 2093 5949 3967 +6 2093 5948 3967 3968 2489 2490 +6 5755 5757 5951 5753 5752 6122 +6 5950 5757 5952 6167 6121 6122 +6 5951 5757 5758 5953 6167 6165 +6 5952 5758 5760 5954 5955 6165 +6 5953 5760 5955 5956 5957 5958 +6 5953 5954 5956 6163 6162 6165 +6 5955 5954 5957 5961 5968 6163 +6 5956 5954 5958 5959 5960 5961 +6 5957 5954 5760 5761 5764 5959 +6 5958 5764 5957 5960 5964 5989 +6 5957 5959 5961 5962 5963 5964 +6 5957 5960 5962 5965 5968 5956 +6 5961 5960 5963 5965 5966 5983 +6 5962 5960 5964 5984 5983 5985 +6 5963 5960 5959 5988 5985 5989 +6 5961 5962 5966 5967 5968 5969 +6 5965 5962 5967 5983 5981 5972 +6 5965 5966 5969 5970 5971 5972 +6 5961 5965 5956 5969 6164 6163 +7 5968 5965 5967 5970 6157 6158 6164 +6 5969 5967 5971 6448 6446 6157 +6 5970 5967 5972 5973 6448 6449 +6 5971 5967 5973 5974 5966 5981 +6 5971 5972 5974 5975 5976 6449 +6 5973 5972 5975 5979 5980 5981 +6 5973 5974 5976 5977 5978 5979 +6 5973 5975 5977 6449 6450 6451 +6 5976 5975 5978 6451 6609 6610 +6 5977 5975 5979 6610 6613 6614 +6 5978 5975 5974 5980 6614 6615 +6 5979 5974 5981 5982 6641 6615 +6 5980 5974 5982 5983 5966 5972 +6 5980 5981 5983 5984 6641 6642 +6 5982 5981 5984 5963 5962 5966 +6 5982 5983 5963 5985 5986 6642 +6 5984 5963 5986 5987 5988 5964 +6 5984 5985 5987 6644 6642 6169 +6 5986 5985 5988 5995 6168 6169 +6 5987 5985 5964 5989 5990 5995 +6 5988 5964 5959 5990 5765 5764 +6 5988 5989 5765 5991 5994 5995 +6 5990 5765 5766 5992 5993 5994 +5 5991 5766 5993 5778 5777 +6 5991 5992 5778 5994 5784 5783 +7 5991 5993 5784 5990 5995 5996 5997 +6 5990 5994 5996 5987 5988 6168 +6 5995 5994 5997 5998 5999 6168 +5 5996 5994 5784 5785 5998 +5 5996 5997 5999 5785 5787 +7 5996 5998 5787 6000 6001 6170 6168 +6 5999 5787 6001 6002 6003 5788 +5 5999 6000 6002 6170 6171 +6 6001 6000 6003 6171 6172 6006 +6 6002 6000 5788 6004 6005 6006 +6 6003 5788 6005 6009 6010 5789 +6 6003 6004 6006 6007 6008 6009 +6 6003 6005 6007 6172 6002 6173 +6 6006 6005 6008 6011 6173 6174 +6 6007 6005 6009 6011 6012 6016 +6 6008 6005 6004 6010 6018 6016 +6 6009 6004 5789 6199 6018 6200 +6 6007 6008 6012 6013 6180 6174 +6 6011 6008 6013 6014 6015 6016 +6 6011 6012 6014 6181 6180 6187 +6 6013 6012 6015 6191 6188 6187 +6 6014 6012 6016 6017 6191 6192 +6 6015 6012 6017 6018 6009 6008 +6 6015 6016 6018 6192 6195 6196 +6 6017 6016 6009 6199 6196 6010 +6 5844 5845 5846 6938 6936 6941 +6 5828 5829 6021 9737 6039 5873 +6 5828 6020 6022 6023 6024 6039 +6 5828 6021 6023 6216 5826 6223 +6 6022 6021 6024 6025 6026 6223 +6 6023 6021 6025 6038 6029 6039 +6 6023 6024 6026 6027 6028 6029 +6 6023 6025 6027 6223 6226 6224 +6 6026 6025 6028 6226 6227 6033 +6 6027 6025 6029 6030 6032 6033 +6 6028 6025 6030 6031 6038 6024 +6 6028 6029 6031 6032 6034 6035 +6 6030 6029 6035 6036 6037 6038 +6 6028 6030 6033 6034 6248 6240 +6 6028 6032 6227 6027 6228 6240 +6 6032 6030 6035 6248 6247 6249 +6 6034 6030 6031 6036 6249 6250 +6 6035 6031 6037 6250 6264 6265 +6 6036 6031 6038 6040 6041 6265 +6 6037 6031 6029 6024 6039 6040 +6 6038 6024 6040 9737 6020 6021 +6 6038 6039 6037 6041 6042 9737 +7 6037 6040 6042 6043 6044 6266 6265 +6 6041 6040 6043 9737 5875 5877 +6 6041 6042 6044 6045 6049 5877 +5 6041 6043 6045 6046 6266 +6 6044 6043 6046 6047 6048 6049 +7 6044 6045 6047 6263 6266 6262 6267 +6 6046 6045 6048 6270 6267 6281 +6 6047 6045 6049 6050 6052 6281 +6 6048 6045 6043 6050 5878 5877 +6 6048 6049 5878 5880 6051 6052 +6 6050 5880 6052 6053 6054 5889 +6 6050 6051 6053 6055 6281 6048 +6 6052 6051 6054 6055 6056 6057 +6 6053 6051 5889 5890 6057 5892 +7 6052 6053 6056 6280 6281 6279 6282 +6 6055 6053 6057 6284 6282 6285 +6 6056 6053 6054 5892 6058 6285 +6 6057 5892 5893 6059 6061 6285 +6 6058 5893 6060 6061 6288 6289 +6 6059 5893 5894 5896 6062 6289 +6 6058 6059 6285 6286 6287 6288 +6 6060 5896 5898 6063 6064 6289 +6 6062 5898 6064 6065 6066 5901 +7 6062 6063 6065 6289 6292 6290 6293 +5 6064 6063 6066 6293 6069 +6 6065 6063 5901 6067 6068 6069 +6 6066 5901 5902 5903 5906 6068 +6 6066 6067 6069 6070 6071 5906 +7 6066 6068 6070 6293 6065 6294 6295 +5 6069 6068 6071 6072 6295 +6 6070 6068 5906 6072 6073 5907 +7 6070 6071 6073 6074 6297 6295 6298 +6 6072 6071 6074 6075 6076 5907 +6 6072 6073 6075 6298 6079 6077 +7 6074 6073 6076 5935 5936 5938 6077 +5 6075 6073 5935 5909 5907 +6 6075 5938 5939 6078 6079 6074 +6 6077 5939 6079 6080 6087 6084 +6 6077 6078 6080 6081 6298 6074 +6 6079 6078 6081 6082 6083 6084 +6 6079 6080 6082 6298 6299 6302 +6 6081 6080 6083 6302 6303 6315 +6 6082 6080 6084 6085 6314 6315 +6 6083 6080 6085 6086 6087 6078 +7 6083 6084 6086 6089 6314 6316 6319 +6 6085 6084 6087 6088 6089 6090 +6 6086 6084 6088 5940 5939 6078 +6 6086 6087 5940 6090 6091 6092 +6 6085 6086 6090 6095 3770 6319 +7 6089 6086 6088 6091 3138 6093 6095 +5 6090 6088 6092 3137 3138 +6 6091 6088 5940 5941 5947 3137 +6 6090 3138 3139 6094 3769 6095 +7 6093 3139 3769 3767 2086 2085 9777 +5 6093 3769 3770 6089 6090 +6 5725 5726 6097 6384 9703 9704 +6 6096 5726 6098 6099 6384 6385 +5 6097 5726 5727 5731 6099 +7 6097 6098 5731 6100 6385 5857 5856 +5 6099 5731 5732 6101 5856 +7 6100 5732 6102 6103 6104 5856 5854 +5 6101 5732 5733 5734 6103 +7 6102 5734 6101 6104 6105 6106 5736 +6 6101 6103 6105 5854 5853 5852 +6 6104 6103 6106 5852 6386 6387 +5 6105 6103 5736 6107 6387 +7 6106 5736 5737 6108 6387 6388 6110 +6 6107 5737 5740 5742 6109 6110 +6 6108 5742 6110 6111 6112 5744 +6 6108 6109 6111 6388 6107 6389 +6 6110 6109 6112 6389 6390 6391 +6 6111 6109 5744 6113 6394 6391 +6 6112 5744 5745 6114 6116 6394 +6 6113 5745 6115 6116 6117 6118 +6 6114 5745 6121 6118 6122 5746 +6 6113 6114 6117 6394 9738 9739 +6 6116 6114 6118 6119 6123 9739 +6 6117 6114 6119 6120 6121 6115 +6 6117 6118 6120 6123 6124 6166 +5 6119 6118 6121 6167 6166 +6 6120 6118 6115 6122 6167 5951 +7 6121 6115 5746 5751 5752 5950 5951 +6 6117 6119 6124 6125 6132 9739 +6 6123 6119 6125 6126 6166 6161 +6 6123 6124 6126 6127 6128 6132 +6 6125 6124 6127 6153 6161 6159 +6 6125 6126 6128 6129 6152 6153 +6 6125 6127 6129 6130 6131 6132 +6 6128 6127 6130 6151 6150 6152 +6 6128 6129 6131 6151 6138 6135 +6 6128 6130 6132 6133 6134 6135 +6 6128 6131 6133 9739 6123 6125 +6 6132 6131 6134 6399 9738 9739 +6 6133 6131 6135 6136 6398 6399 +6 6134 6131 6136 6137 6138 6130 +6 6134 6135 6137 6398 6400 6401 +6 6136 6135 6138 6139 6401 6402 +6 6137 6135 6139 6140 6151 6130 +6 6137 6138 6140 6141 6402 6403 +6 6139 6138 6141 6142 6149 6151 +6 6139 6140 6142 6143 6403 6404 +6 6141 6140 6143 6144 6145 6149 +6 6141 6142 6144 6404 6405 6406 +6 6143 6142 6145 6146 6406 6437 +6 6144 6142 6146 6147 6148 6149 +6 6144 6145 6147 6438 6437 6439 +6 6146 6145 6148 6439 6440 6441 +6 6147 6145 6149 6150 6441 6442 +6 6148 6145 6142 6140 6150 6151 +6 6148 6149 6151 6129 6152 6442 +6 6150 6149 6140 6138 6130 6129 +6 6150 6129 6127 6153 6154 6442 +6 6152 6127 6126 6154 6155 6159 +6 6152 6153 6155 6156 6442 6443 +6 6154 6153 6156 6157 6158 6159 +6 6154 6155 6157 6445 6443 6446 +6 6156 6155 6158 5970 6446 5969 +6 6157 6155 6159 6160 5969 6164 +6 6158 6155 6153 6160 6161 6126 +6 6158 6159 6161 6162 6163 6164 +6 6160 6159 6126 6162 6124 6166 +6 6160 6161 6163 5955 6165 6166 +6 6160 6162 6164 5968 5956 5955 +5 6160 6163 5968 6158 5969 +6 5955 6162 6166 6167 5952 5953 +7 6165 6162 6167 6120 6119 6124 6161 +6 6165 6166 6120 6121 5951 5952 +6 5995 5996 5987 6169 6170 5999 +6 5987 6168 6170 6644 5986 9784 +6 6169 6168 5999 6001 6171 9784 +7 6170 6001 6002 6172 6790 9784 9783 +7 6171 6002 6006 6173 6789 6787 6790 +6 6172 6006 6007 6174 6175 6789 +6 6173 6007 6175 6176 6011 6180 +6 6173 6174 6176 6177 6785 6789 +6 6175 6174 6177 6178 6179 6180 +6 6175 6176 6178 6783 6782 6785 +6 6177 6176 6179 9797 6783 9798 +6 6178 6176 6180 6181 6182 9797 +6 6179 6176 6181 6013 6011 6174 +6 6179 6180 6182 6183 6187 6013 +6 6179 6181 6183 6184 9797 9800 +6 6182 6181 6184 6185 6186 6187 +6 6182 6183 6185 6363 6646 9800 +6 6184 6183 6186 6363 6364 6368 +6 6185 6183 6187 6188 6189 6368 +6 6186 6183 6181 6188 6013 6014 +6 6186 6187 6189 6190 6191 6014 +6 6186 6188 6190 6368 6369 6370 +6 6189 6188 6191 6370 6373 6193 +6 6190 6188 6014 6015 6192 6193 +6 6191 6015 6017 6193 6194 6195 +6 6191 6192 6194 6373 6190 6374 +6 6193 6192 6195 6383 6374 6204 +6 6194 6192 6017 6196 6197 6204 +6 6195 6017 6197 6198 6199 6018 +6 6195 6196 6198 6201 6202 6204 +6 6197 6196 6199 5793 5794 6201 +6 6198 6196 6018 6010 6200 5793 +6 6199 6010 5793 5791 5790 5789 +6 6198 5794 6197 6202 6203 6222 +6 6197 6201 6203 6204 6205 6206 +6 6202 6201 6206 6207 6221 6222 +6 6197 6202 6205 6383 6194 6195 +6 6204 6202 6206 6383 6460 6382 +6 6205 6202 6203 6207 6208 6460 +6 6206 6203 6208 6209 6210 6221 +6 6206 6207 6209 6211 6212 6460 +6 6208 6207 6210 6211 6215 6218 +6 6209 6207 5803 6218 6219 6221 +6 6208 6209 6212 6213 6214 6215 +6 6208 6211 6213 6457 6459 6460 +7 6212 6211 6214 6224 6225 6455 6457 +5 6213 6211 6215 6216 6224 +6 6214 6211 6209 6216 6217 6218 +7 6214 6215 6217 5826 6022 6223 6224 +5 6216 6215 6218 5825 5826 +7 6217 6215 5825 5804 5803 6210 6209 +6 5803 6210 5800 5798 6220 6221 +6 5798 6219 6221 6222 5795 5796 +6 6220 6219 6210 6207 6203 6222 +6 6220 6221 6203 6201 5794 5795 +5 6216 6022 6023 6026 6224 +7 6216 6223 6214 6213 6225 6226 6026 +7 6213 6224 6226 6455 6232 6227 6229 +5 6225 6224 6026 6027 6227 +6 6226 6027 6033 6228 6229 6225 +6 6227 6033 6229 6230 6239 6240 +6 6227 6228 6230 6231 6232 6225 +6 6229 6228 6231 6238 6235 6239 +6 6229 6230 6232 6233 6234 6235 +6 6229 6231 6233 6455 6225 6456 +6 6232 6231 6234 6456 6461 6462 +6 6233 6231 6235 6236 6462 6463 +6 6234 6231 6236 6237 6238 6230 +6 6234 6235 6237 6463 6464 6472 +6 6236 6235 6238 6474 6472 6477 +6 6237 6235 6230 6239 6477 6242 +6 6238 6230 6228 6240 6241 6242 +6 6239 6228 6241 6248 6032 6033 +6 6239 6240 6242 6243 6244 6248 +6 6239 6241 6243 6477 6238 6478 +6 6242 6241 6244 6245 6478 6480 +6 6243 6241 6245 6246 6247 6248 +6 6243 6244 6246 6482 6480 6483 +6 6245 6244 6247 6483 6254 6252 +6 6246 6244 6248 6034 6249 6252 +6 6247 6244 6241 6240 6032 6034 +6 6247 6034 6035 6250 6251 6252 +6 6249 6035 6036 6251 6264 6256 +6 6249 6250 6252 6253 6255 6256 +6 6249 6251 6253 6254 6246 6247 +6 6252 6251 6254 6255 6485 6486 +6 6252 6253 6483 6246 6484 6485 +6 6253 6251 6256 6257 6258 6486 +6 6255 6251 6257 6264 6261 6250 +6 6255 6256 6258 6259 6260 6261 +6 6255 6257 6259 6486 6494 6495 +6 6258 6257 6260 6495 6496 6497 +7 6259 6257 6261 6262 6497 6274 6268 +6 6260 6257 6262 6263 6264 6256 +6 6260 6261 6263 6046 6267 6268 +6 6262 6261 6264 6265 6266 6046 +6 6263 6261 6265 6256 6250 6036 +6 6263 6264 6266 6036 6041 6037 +5 6263 6265 6046 6044 6041 +6 6046 6262 6268 6269 6270 6047 +6 6262 6267 6269 6273 6274 6260 +6 6268 6267 6270 6271 6272 6273 +6 6269 6267 6047 6271 6280 6281 +6 6269 6270 6272 6278 6279 6280 +6 6269 6271 6273 6276 6277 6278 +6 6269 6272 6268 6274 6275 6276 +6 6268 6273 6275 6497 6260 6498 +6 6274 6273 6276 6501 6498 6502 +6 6275 6273 6272 6277 6502 6503 +6 6276 6272 6278 6503 6504 6505 +6 6277 6272 6271 6279 6505 6506 +7 6278 6271 6280 6055 6282 6283 6506 +5 6279 6271 6270 6281 6055 +6 6280 6270 6047 6055 6052 6048 +5 6279 6055 6283 6284 6056 +6 6279 6282 6284 6507 6506 6508 +6 6283 6282 6056 6285 6508 6286 +6 6284 6056 6057 6058 6061 6286 +6 6285 6061 6287 6508 6284 6509 +7 6286 6061 6288 6509 6329 6512 6291 +6 6287 6061 6059 6289 6290 6291 +6 6288 6059 6060 6062 6064 6290 +5 6288 6289 6291 6292 6064 +5 6288 6290 6292 6329 6287 +7 6291 6290 6064 6293 6327 6328 6329 +6 6292 6064 6065 6069 6294 6327 +6 6293 6069 6295 6296 6326 6327 +6 6294 6069 6070 6296 6297 6072 +6 6294 6295 6297 6300 6325 6326 +6 6296 6295 6072 6298 6299 6300 +6 6297 6072 6074 6079 6081 6299 +6 6298 6081 6297 6300 6301 6302 +5 6297 6299 6301 6325 6296 +6 6300 6299 6302 6304 6324 6325 +6 6301 6299 6081 6082 6303 6304 +6 6302 6082 6304 6305 6309 6315 +6 6302 6303 6305 6306 6324 6301 +6 6304 6303 6306 6307 6308 6309 +6 6304 6305 6307 6324 6338 6339 +6 6306 6305 6308 6339 6342 6343 +6 6307 6305 6309 6310 6343 6344 +6 6308 6305 6303 6310 6311 6315 +6 6308 6309 6311 6312 6344 6347 +6 6310 6309 6312 6313 6314 6315 +6 6310 6311 6313 6322 6323 6347 +6 6312 6311 6314 6316 6317 6322 +6 6313 6311 6315 6083 6085 6316 +6 6314 6311 6083 6082 6303 6309 +6 6314 6085 6313 6317 6318 6319 +6 6313 6316 6318 6320 6321 6322 +6 6317 6316 6319 3770 1572 6320 +5 6318 6316 3770 6085 6089 +5 6318 1572 1573 6321 6317 +7 6320 1573 1574 6317 6322 6323 6361 +5 6317 6321 6323 6313 6312 +7 6322 6321 6312 6348 6347 6349 6361 +6 6304 6306 6301 6325 6336 6338 +7 6301 6324 6300 6296 6326 6337 6336 +6 6296 6325 6294 6327 6337 6332 +6 6294 6326 6293 6292 6328 6332 +6 6292 6327 6329 6330 6331 6332 +6 6292 6328 6330 6512 6287 6291 +6 6329 6328 6331 6511 6512 6520 +7 6330 6328 6332 6333 6334 6520 6519 +6 6331 6328 6333 6337 6326 6327 +6 6331 6332 6334 6335 6336 6337 +5 6331 6333 6335 6519 6521 +6 6334 6333 6336 6521 6529 6530 +7 6335 6333 6337 6325 6324 6338 6530 +5 6336 6333 6332 6326 6325 +6 6336 6324 6306 6339 6340 6530 +6 6338 6306 6307 6340 6341 6342 +6 6338 6339 6341 6531 6528 6530 +5 6340 6339 6342 6546 6531 +6 6341 6339 6307 6343 6547 6546 +6 6342 6307 6308 6344 6345 6547 +6 6343 6308 6345 6346 6347 6310 +6 6343 6344 6346 6547 6544 6548 +6 6345 6344 6347 6348 6550 6548 +6 6346 6344 6348 6323 6312 6310 +6 6346 6347 6323 6349 6350 6550 +6 6348 6323 6350 6351 6360 6361 +6 6348 6349 6351 6352 6551 6550 +6 6350 6349 6352 6353 6354 6360 +6 6350 6351 6353 6553 6551 6554 +6 6352 6351 6354 6355 6356 6554 +6 6353 6351 6355 1590 2477 6360 +7 6353 6354 6356 6357 1595 1591 1590 +6 6353 6355 6357 6358 6554 6555 +5 6356 6355 6358 6359 1595 +6 6356 6357 6359 6555 6556 3972 +6 6358 6357 1595 3972 3971 1596 +6 2477 6354 6351 6349 6361 6362 +6 6360 6349 6362 1574 6321 6323 +5 6360 6361 1574 2476 2477 +6 6184 6185 6364 6365 6645 6646 +6 6363 6185 6365 6366 6367 6368 +6 6363 6364 6366 6645 6649 6650 +6 6365 6364 6367 9728 9674 6650 +6 6366 6364 6368 9728 9729 6369 +6 6367 6364 6185 6186 6189 6369 +6 6368 6189 6370 6371 9729 6367 +6 6369 6189 6190 6371 6372 6373 +6 6369 6370 6372 9729 9730 9731 +6 6371 6370 6373 6375 6376 9731 +6 6372 6370 6190 6193 6374 6375 +6 6373 6193 6375 6383 6381 6194 +6 6373 6374 6372 6376 6377 6381 +6 6372 6375 6377 6378 6468 9731 +6 6376 6375 6378 6379 6380 6381 +5 6376 6377 6379 9694 6468 +7 6378 6377 6380 6458 6456 6461 9694 +6 6379 6377 6381 6382 6458 6459 +6 6380 6377 6382 6383 6374 6375 +6 6380 6381 6383 6460 6459 6205 +6 6382 6381 6374 6194 6204 6205 +7 6096 6097 6385 9704 5862 5861 5859 +5 6384 6097 6099 5857 5859 +6 5852 6105 6387 6946 5851 6947 +7 6386 6105 6106 6107 6388 6947 6948 +5 6387 6107 6110 6389 6948 +6 6388 6110 6111 6390 6948 6949 +6 6389 6111 6391 6392 6949 6950 +6 6390 6111 6392 6393 6394 6112 +6 6390 6391 6393 6395 6396 6950 +6 6392 6391 6394 6395 9738 6399 +6 6393 6391 6112 6113 6116 9738 +6 6392 6393 6396 6397 6398 6399 +6 6392 6395 6397 6950 6951 6952 +6 6396 6395 6398 6952 6953 6400 +6 6397 6395 6399 6134 6136 6400 +6 6398 6395 6134 6133 9738 6393 +6 6398 6136 6401 6953 6397 6954 +6 6400 6136 6137 6402 6954 6955 +6 6401 6137 6139 6403 6955 6961 +6 6402 6139 6141 6404 6961 6411 +6 6403 6141 6143 6405 6409 6411 +6 6404 6143 6406 6407 6408 6409 +6 6405 6143 6144 6407 6437 6435 +6 6405 6406 6408 6432 6430 6435 +6 6405 6407 6409 6410 6429 6430 +6 6405 6408 6410 6404 6411 6412 +6 6409 6408 6412 6413 6414 6429 +6 6404 6409 6412 6960 6961 6403 +6 6411 6409 6410 6413 6960 6962 +6 6412 6410 6414 6415 6964 6962 +6 6413 6410 6415 6416 6428 6429 +6 6413 6414 6416 6417 6964 6965 +6 6415 6414 6417 6418 6419 6428 +6 6415 6416 6418 6559 6560 6965 +6 6417 6416 6419 6420 6559 6566 +6 6418 6416 6420 6421 6428 6425 +6 6418 6419 6421 6422 6574 6566 +6 6420 6419 6422 6423 6424 6425 +6 6420 6421 6423 6574 6573 6575 +6 6422 6421 6424 6581 6578 6575 +6 6423 6421 6425 6426 6581 6582 +6 6424 6421 6426 6427 6428 6419 +6 6424 6425 6427 6585 6582 6431 +6 6426 6425 6428 6429 6430 6431 +6 6427 6425 6419 6416 6414 6429 +6 6428 6414 6410 6408 6427 6430 +6 6427 6429 6408 6431 6432 6407 +6 6427 6430 6432 6433 6585 6426 +6 6431 6430 6407 6433 6434 6435 +6 6431 6432 6434 6585 6586 6587 +6 6433 6432 6435 6436 6590 6587 +6 6434 6432 6436 6437 6406 6407 +6 6434 6435 6437 6438 6590 6591 +6 6436 6435 6406 6438 6146 6144 +6 6436 6437 6146 6439 6591 6592 +6 6438 6146 6147 6440 6592 6593 +6 6439 6147 6441 6596 6593 6444 +6 6440 6147 6148 6442 6443 6444 +6 6441 6148 6150 6152 6154 6443 +6 6442 6154 6441 6444 6445 6156 +6 6441 6443 6445 6596 6440 6454 +6 6444 6443 6156 6446 6447 6454 +6 6445 6156 6447 6448 5970 6157 +6 6445 6446 6448 6450 6453 6454 +6 6447 6446 5970 5971 6449 6450 +5 6448 5971 5973 5976 6450 +7 6449 5976 6448 6451 6452 6453 6447 +7 6450 5976 5977 6452 6608 6599 6609 +6 6450 6451 6453 6597 6598 6599 +5 6450 6452 6447 6454 6597 +6 6447 6453 6596 6444 6445 6597 +5 6213 6225 6232 6456 6457 +7 6455 6232 6457 6458 6379 6233 6461 +6 6455 6456 6458 6459 6212 6213 +5 6457 6456 6379 6380 6459 +6 6458 6380 6457 6212 6460 6382 +6 6212 6459 6208 6382 6205 6206 +5 6456 6233 6462 9694 6379 +6 6461 6233 6234 6463 6466 9694 +6 6462 6234 6236 6464 6465 6466 +6 6463 6236 6465 6470 6471 6472 +6 6463 6464 6466 6467 6469 6470 +6 6463 6465 6462 6467 6468 9694 +6 6466 6465 6468 6469 9732 9733 +7 6466 6467 9694 6378 6376 9731 9732 +6 6467 6465 6470 7510 7511 9733 +7 6469 6465 6464 6471 7508 7510 7507 +6 6470 6464 6472 6473 7507 7506 +6 6471 6464 6236 6473 6474 6237 +6 6471 6472 6474 6475 7505 7506 +6 6473 6472 6237 6475 6476 6477 +7 6473 6474 6476 7504 7505 9693 9781 +6 6475 6474 6477 6478 6479 9693 +6 6476 6474 6237 6238 6242 6478 +6 6477 6242 6243 6476 6479 6480 +7 6476 6478 6480 6481 9693 9779 9780 +6 6479 6478 6243 6481 6482 6245 +6 6479 6480 6482 6488 9706 9779 +6 6481 6480 6245 6483 6487 6488 +6 6482 6245 6246 6254 6484 6487 +5 6483 6254 6485 6487 6490 +7 6484 6254 6253 6486 6490 6491 6492 +7 6485 6253 6255 6258 6492 6493 6494 +6 6483 6484 6482 6488 6489 6490 +5 6482 6487 6489 9706 6481 +7 6488 6487 6490 9705 2195 2196 9706 +6 6489 6487 6484 6485 6491 9705 +6 6490 6485 6492 2252 2253 9705 +6 6491 6485 6486 6493 2252 9707 +6 6492 6486 6494 9707 3336 9708 +5 6493 6486 6258 6495 9708 +6 6494 6258 6259 6496 9708 6500 +6 6495 6259 6497 6498 6499 6500 +5 6496 6259 6260 6274 6498 +6 6497 6274 6496 6499 6501 6275 +6 6496 6498 6500 2512 2513 6501 +7 6496 6499 2512 3335 9708 3882 6495 +6 2513 6499 6498 6275 6502 9711 +6 6501 6275 6276 6503 9710 9711 +6 6502 6276 6277 6504 9709 9710 +6 6503 6277 6505 6513 9709 9712 +6 6504 6277 6278 6506 6507 6513 +5 6505 6278 6507 6283 6279 +7 6505 6506 6283 6508 6513 6514 6510 +6 6507 6283 6284 6286 6509 6510 +6 6508 6286 6287 6510 6511 6512 +6 6508 6509 6511 6514 6507 6515 +7 6510 6509 6512 6330 6515 6516 6520 +5 6511 6509 6330 6329 6287 +6 6504 6505 6507 6514 9712 9718 +5 6513 6507 6510 6515 9718 +7 6514 6510 6511 6516 6517 9718 9719 +6 6515 6511 6517 6518 6519 6520 +6 6515 6516 6518 9719 9720 6523 +6 6517 6516 6519 6521 6522 6523 +6 6518 6516 6520 6331 6334 6521 +5 6519 6516 6511 6330 6331 +7 6519 6334 6335 6518 6522 6526 6529 +6 6518 6521 6523 6524 6525 6526 +7 6518 6522 6524 2215 9720 6517 2214 +5 6523 6522 6525 2214 3349 +7 6524 6522 6526 6527 3349 3348 6533 +6 6525 6522 6521 6527 6528 6529 +6 6525 6526 6528 6531 6532 6533 +6 6527 6526 6529 6531 6340 6530 +5 6528 6526 6521 6335 6530 +6 6529 6335 6336 6340 6528 6338 +7 6527 6528 6532 6341 6546 6340 6535 +6 6527 6531 6533 3864 6534 6535 +5 6527 6532 3864 3348 6525 +6 3864 6532 6535 6536 6537 6717 +6 6534 6532 6536 6545 6546 6531 +6 6534 6535 6537 6538 6545 6542 +6 6534 6536 6538 6539 6716 6717 +6 6537 6536 6539 6540 6541 6542 +7 6537 6538 6540 6715 3888 3887 6716 +6 6539 6538 6541 6715 6719 6720 +6 6540 6538 6542 6543 6720 6709 +6 6541 6538 6543 6544 6545 6536 +6 6541 6542 6544 6548 6549 6709 +6 6543 6542 6545 6547 6345 6548 +6 6544 6542 6536 6535 6546 6547 +6 6545 6535 6547 6342 6341 6531 +6 6545 6546 6544 6342 6343 6345 +6 6544 6345 6543 6549 6550 6346 +6 6543 6548 6550 6551 6552 6709 +6 6549 6548 6346 6348 6551 6350 +6 6549 6550 6552 6553 6352 6350 +6 6549 6551 6553 6706 6708 6709 +6 6552 6551 6352 6554 6555 6706 +5 6553 6352 6353 6356 6555 +6 6554 6356 6358 6556 6553 6706 +7 6555 6358 3972 6706 6707 9748 3492 +6 3970 1598 1599 6558 4039 3969 +6 6557 1599 4039 3765 613 612 +6 6417 6418 6560 6561 6565 6566 +6 6417 6559 6561 6562 6965 6966 +6 6560 6559 6562 6563 6564 6565 +6 6560 6561 6563 6966 6967 6968 +6 6562 6561 6564 6986 6984 6968 +6 6563 6561 6565 6986 6987 6568 +6 6564 6561 6559 6566 6567 6568 +6 6565 6559 6418 6567 6574 6420 +6 6565 6566 6568 6569 6570 6574 +6 6565 6567 6569 6987 6564 6988 +6 6568 6567 6570 6571 6991 6988 +6 6569 6567 6571 6572 6573 6574 +6 6569 6570 6572 6998 6991 6999 +6 6571 6570 6573 6576 7002 6999 +6 6572 6570 6574 6422 6575 6576 +6 6573 6570 6567 6566 6420 6422 +6 6573 6422 6576 6577 6578 6423 +6 6573 6575 6577 7004 7002 6572 +6 6576 6575 6578 6579 7004 7005 +6 6577 6575 6579 6580 6581 6423 +6 6577 6578 6580 7005 7006 7007 +6 6579 6578 6581 7007 7008 6583 +6 6580 6578 6423 6424 6582 6583 +6 6581 6424 6583 6584 6585 6426 +6 6581 6582 6584 7008 6580 7009 +6 6583 6582 6585 6721 7009 6586 +6 6584 6582 6426 6431 6433 6586 +6 6585 6433 6587 6588 6721 6584 +6 6586 6433 6588 6589 6590 6434 +6 6586 6587 6589 6721 6722 6729 +6 6588 6587 6590 6729 6730 6731 +6 6589 6587 6434 6436 6591 6731 +6 6590 6436 6438 6592 6731 6732 +6 6591 6438 6439 6593 6594 6732 +6 6592 6439 6594 6595 6596 6440 +6 6592 6593 6595 6732 6733 6734 +7 6594 6593 6596 6601 6734 6598 6597 +6 6595 6593 6440 6444 6454 6597 +6 6596 6454 6453 6452 6598 6595 +6 6597 6452 6599 6600 6601 6595 +6 6598 6452 6600 6607 6608 6451 +6 6598 6599 6601 6602 6603 6607 +5 6598 6600 6602 6734 6595 +6 6601 6600 6603 6604 6735 6734 +6 6602 6600 6604 6605 6606 6607 +7 6602 6603 6605 6735 6736 6737 6738 +5 6604 6603 6606 6738 6739 +7 6605 6603 6607 6739 6740 6749 6746 +6 6606 6603 6600 6599 6608 6749 +6 6607 6599 6451 6609 6748 6749 +6 6608 6451 5977 6610 6611 6748 +6 6609 5977 5978 6611 6612 6613 +6 6609 6610 6612 6748 6747 6750 +6 6611 6610 6613 6620 6621 6750 +6 6612 6610 5978 6614 6617 6620 +6 6613 5978 5979 6615 6616 6617 +6 6614 5979 6616 6640 6641 5980 +6 6614 6615 6617 6618 6639 6640 +6 6614 6616 6618 6619 6620 6613 +6 6617 6616 6619 6637 6638 6639 +6 6617 6618 6620 6622 6623 6637 +6 6617 6619 6613 6612 6621 6622 +6 6612 6620 6622 6751 6750 6627 +6 6621 6620 6619 6623 6624 6627 +6 6622 6619 6624 6625 6636 6637 +6 6622 6623 6625 6626 6627 6628 +6 6624 6623 6626 6634 6635 6636 +6 6624 6625 6628 6629 6633 6634 +6 6622 6624 6628 6751 6621 6752 +6 6627 6624 6626 6629 6630 6752 +6 6628 6626 6630 6631 6632 6633 +6 6628 6629 6631 6757 6754 6752 +6 6630 6629 6632 6757 6758 6759 +6 6631 6629 6633 6759 6767 6768 +6 6632 6629 6626 6634 6768 6769 +6 6633 6626 6625 6635 6769 6770 +6 6634 6625 6636 6770 6771 6772 +6 6635 6625 6623 6637 9786 6772 +6 6636 6623 6619 6618 6638 9786 +6 6637 6618 6639 6786 6784 9786 +6 6638 6618 6616 6640 9778 6786 +6 6639 6616 6615 6641 9778 6643 +6 6640 6615 5980 5982 6642 6643 +6 6641 5982 5984 6643 6644 5986 +7 6641 6642 6644 9778 6640 6788 9783 +6 6643 6642 5986 6169 9783 9784 +6 6363 6365 6646 6647 6648 6649 +6 6363 6645 6184 6647 9725 9800 +6 6646 6645 6648 9724 9725 6656 +6 6647 6645 6649 6653 6655 6656 +6 6648 6645 6365 6650 6651 6653 +6 6649 6365 6651 6652 9674 6366 +6 6649 6650 6652 6653 6654 9671 +6 6651 6650 9671 9672 9673 9674 +6 6649 6651 6654 6648 6655 3174 +6 6653 6651 9671 9692 3173 3174 +6 6648 6653 3174 6656 3451 3176 +6 6648 6655 3451 6657 9724 6647 +6 6656 3451 6658 6659 9722 9724 +6 6657 3451 6659 3180 6660 6668 +6 6657 6658 6668 6669 6670 9722 +6 6658 3180 6661 6664 6665 6668 +6 6660 3180 3179 6662 6663 6664 +6 6661 3179 3181 2859 2860 6663 +5 6661 6662 6664 6667 2860 +6 6661 6663 6660 6665 6666 6667 +6 6660 6664 6666 6668 6669 6673 +7 6665 6664 6667 6673 6674 4565 4564 +6 6666 6664 6663 4564 6675 2860 +5 6660 6665 6669 6659 6658 +7 6668 6665 6659 6670 6671 6672 6673 +6 6659 6669 6671 6775 6776 9722 +6 6670 6669 6672 6774 6773 6775 +6 6671 6669 6673 6674 6791 6774 +5 6672 6669 6665 6666 6674 +5 6673 6666 4565 6672 6791 +6 4564 6667 4562 6676 2861 2860 +6 4562 6675 2861 6677 4561 9793 +6 6676 2861 2854 2855 6678 9793 +6 6677 2855 6679 6680 6682 9793 +5 6678 2855 6680 6681 2856 +6 6678 6679 6681 6682 6683 6684 +6 6680 6679 6686 6684 6687 2856 +6 6678 6680 6683 9751 9762 9793 +6 6682 6680 6684 5157 5158 9751 +6 6683 6680 5157 6685 6686 6681 +6 5157 6684 6686 6693 6694 6695 +6 6685 6684 6681 6687 6688 6693 +6 6686 6681 6688 6689 6690 2856 +6 6686 6687 6689 6693 6697 6700 +6 6688 6687 6690 6691 6700 6701 +6 6689 6687 6691 6692 2857 2856 +6 6689 6690 6692 6701 6703 2552 +5 6691 6690 2857 2551 2552 +6 6686 6688 6685 6694 6696 6697 +6 6685 6693 6695 4524 4523 6696 +5 6685 6694 4524 4533 5157 +6 4523 6694 6693 6697 6698 6705 +6 6696 6693 6688 6698 6699 6700 +7 6696 6697 6699 6704 3506 3507 6705 +6 6698 6697 6700 6701 6702 6704 +5 6699 6697 6688 6689 6701 +7 6700 6689 6691 6699 6702 2223 6703 +6 6699 6701 2223 65 66 6704 +5 2223 6701 6691 2552 2222 +6 6699 6702 66 67 6698 3506 +5 6698 3507 3508 4523 6696 +7 6553 6555 6556 6707 6552 6708 9750 +6 6706 6556 9748 3503 9749 9750 +6 6552 6706 6709 6710 6711 9750 +7 6552 6708 6710 6720 6541 6549 6543 +6 6709 6708 6711 6712 6719 6720 +7 6710 6708 6712 6713 3504 9749 9750 +7 6710 6711 6713 3118 3120 6714 6719 +6 6712 6711 3504 3505 3117 3118 +6 6712 3120 3122 3888 6715 6719 +5 6714 3888 6539 6540 6719 +6 6539 3887 6537 6717 3863 6718 +5 6537 6716 6534 3864 3863 +6 3863 6716 3862 3343 3886 3887 +6 6715 6540 6714 6712 6710 6720 +5 6719 6540 6541 6710 6709 +6 6586 6588 6722 6723 7009 6584 +6 6721 6588 6723 6724 6728 6729 +6 6721 6722 6724 6725 7010 7009 +6 6723 6722 6725 6726 6727 6728 +6 6723 6724 6726 7010 7011 7012 +6 6725 6724 6727 7023 7012 7024 +6 6726 6724 6728 7024 7027 7028 +6 6727 6724 6722 6729 7028 7031 +6 6728 6722 6588 6589 6730 7031 +6 6729 6589 6731 7031 7032 7033 +6 6730 6589 6590 6591 6732 7033 +6 6731 6591 6592 6594 6733 7033 +6 6732 6594 6734 6735 7033 7034 +6 6733 6594 6735 6602 6601 6595 +6 6733 6734 6602 6604 6736 7034 +6 6735 6604 6737 7034 7035 7036 +6 6736 6604 6738 6741 7036 7037 +5 6737 6604 6605 6739 6741 +7 6738 6605 6606 6740 6741 6742 6743 +6 6739 6606 6743 6744 6745 6746 +6 6737 6738 6739 6742 7037 7038 +6 6741 6739 6743 7038 7039 7040 +6 6742 6739 6740 6744 7040 7041 +7 6743 6740 6745 7041 7042 6755 7043 +5 6744 6740 6746 6747 7043 +6 6745 6740 6747 6748 6749 6606 +7 6745 6746 6748 6611 6750 6751 7043 +6 6747 6746 6749 6608 6609 6611 +5 6748 6746 6608 6606 6607 +5 6747 6611 6751 6621 6612 +7 6747 6750 6621 6627 6752 6753 7043 +6 6751 6627 6753 6754 6630 6628 +5 6751 6752 6754 6755 7043 +6 6753 6752 6755 6756 6757 6630 +7 6753 6754 6756 7042 6744 7043 7142 +5 6755 6754 6757 7142 6760 +6 6756 6754 6630 6631 6758 6760 +6 6757 6631 6759 6760 6761 6762 +6 6758 6631 6632 6762 6763 6767 +6 6757 6758 6761 7142 6756 7143 +6 6760 6758 6762 7143 7144 7145 +6 6761 6758 6759 6763 6764 7145 +6 6762 6759 6764 4560 6765 6767 +6 6762 6763 4560 4552 7145 4551 +6 4560 6763 4559 4566 6766 6767 +5 4566 6765 6767 6791 6768 +6 6766 6765 6763 6759 6632 6768 +6 6767 6632 6633 6769 6791 6766 +6 6768 6633 6634 6770 6774 6791 +6 6769 6634 6635 6771 6773 6774 +6 6770 6635 6772 6773 6778 6779 +6 6771 6635 6779 6780 6636 9786 +6 6770 6771 6774 6671 6775 6778 +6 6770 6773 6671 6672 6791 6769 +6 6671 6773 6670 6776 6777 6778 +6 6670 6775 6777 9722 9723 9799 +7 6776 6775 6778 6779 6781 9798 9799 +5 6777 6775 6773 6771 6779 +6 6778 6771 6772 6780 6781 6777 +6 6779 6772 6781 6782 6784 9786 +6 6779 6780 6782 6783 6777 9798 +6 6781 6780 6783 6177 6784 6785 +5 6781 6782 6177 6178 9798 +6 6782 6780 6785 6786 6638 9786 +7 6782 6784 6177 6175 6786 6787 6789 +7 6785 6784 6787 6788 9778 6639 6638 +6 6785 6786 6788 6789 6172 6790 +6 6787 6786 9778 6643 9783 6790 +5 6785 6787 6172 6173 6175 +5 6172 6787 6171 6788 9783 +8 6672 6674 6774 4565 4566 6766 6769 6768 +6 5419 5420 6793 7332 7333 7334 +6 6792 5420 5421 5429 6794 7334 +6 6793 5429 5430 6795 7334 7335 +6 6794 5430 5431 6796 7335 7336 +6 6795 5431 5433 5434 6797 7336 +6 6796 5434 5435 6798 7336 7337 +6 6797 5435 5436 6799 7337 7338 +6 6798 5436 5437 6800 7338 7339 +6 6799 5437 5438 6801 7339 7340 +6 6800 5438 5439 6802 7340 7341 +6 6801 5439 6803 7341 7342 7343 +6 6802 5439 5440 5441 6804 7343 +6 6803 5441 5442 6805 7343 7344 +6 6804 5442 5443 6806 7344 7345 +6 6805 5443 5445 6807 7345 7346 +6 6806 5445 5446 6808 7346 7347 +6 6807 5446 5447 6809 7347 7348 +6 6808 5447 6810 7348 7349 7350 +6 6809 5447 5448 6811 7350 6812 +5 6810 5448 5218 5219 6812 +6 6811 5219 5220 6813 7350 6810 +5 6812 5220 6814 7350 7351 +6 6813 5220 5221 6815 7351 7352 +7 6814 5221 5222 5223 6816 7352 7353 +5 6815 5223 6817 7353 7354 +7 6816 5223 5224 5225 6818 7354 7355 +5 6817 5225 6819 7355 7356 +6 6818 5225 6820 7356 7357 7358 +6 6819 5225 5226 5227 6821 7358 +5 6820 5227 5228 6822 7358 +6 6821 5228 6823 7358 7359 7360 +7 6822 5228 5229 5230 6824 7360 7361 +5 6823 5230 6825 6826 7361 +5 6824 5230 6826 6827 5168 +7 6824 6825 6827 6828 6829 7363 7361 +5 6826 6825 5168 5169 6828 +6 6827 5169 6826 6829 6830 6831 +6 6826 6828 6830 7363 7364 7365 +6 6829 6828 6831 7365 7366 7367 +6 6830 6828 5169 5170 6832 7367 +7 6831 5170 6833 7367 7368 7369 6835 +5 6832 5170 6834 5239 6835 +5 6833 5170 5239 5019 5024 +6 6833 5239 5240 6836 7369 6832 +6 6835 5240 5649 6837 7376 7369 +7 6836 5649 6838 7376 7375 7377 7378 +6 6837 5649 5650 5652 6839 7378 +6 6838 5652 6840 7378 7379 7380 +6 6839 5652 5653 6841 6842 7380 +6 6840 5653 5654 5248 6842 5249 +6 6840 6841 5249 6843 7380 7381 +6 6842 5249 5250 6844 7381 7382 +6 6843 5250 6845 7382 7383 7384 +6 6844 5250 5029 5030 6846 7384 +6 6845 5030 5031 6847 6848 7384 +6 6846 5031 6848 6849 6850 5032 +6 6846 6847 6849 7385 7384 7386 +6 6848 6847 6850 7386 7387 7388 +6 6849 6847 5032 5033 6851 7388 +6 6850 5033 5034 5035 6852 7388 +6 6851 5035 6853 7388 7389 6855 +6 6852 5035 5036 5039 6854 6855 +6 6853 5039 6855 6856 6857 5040 +6 6853 6854 6856 7389 6852 7390 +6 6855 6854 6857 6858 6860 7390 +6 6856 6854 5040 6858 6859 5042 +6 6856 6857 6859 6860 6861 6862 +6 6858 6857 5042 6862 6863 6864 +6 6856 6858 6861 7390 7391 7398 +6 6860 6858 6862 7398 7399 7400 +6 6861 6858 6859 6863 7400 7401 +6 6862 6859 6864 6865 6866 7401 +6 6863 6859 6865 5043 6880 5042 +6 6863 6864 6866 6867 6880 6874 +6 6863 6865 6867 6868 7401 7402 +6 6866 6865 6868 6869 6873 6874 +6 6866 6867 6869 6870 7402 7403 +6 6868 6867 6870 6871 6872 6873 +6 6868 6869 6871 7406 7403 7407 +6 6870 6869 6872 7413 7407 7414 +6 6871 6869 6873 7420 7417 7414 +6 6872 6869 6867 6874 6875 7420 +6 6873 6867 6875 6876 6865 6880 +6 6873 6874 6876 6877 7420 7419 +6 6875 6874 6877 6878 6879 6880 +6 6875 6876 6878 6884 6885 7419 +6 6877 6876 6879 6881 6883 6884 +6 6878 6876 6880 6881 5044 5043 +6 6879 6876 5043 6864 6865 6874 +6 6878 6879 5044 5046 6882 6883 +6 6881 5046 6883 6888 6889 6890 +6 6881 6882 6878 6884 6887 6888 +6 6878 6883 6877 6885 6886 6887 +6 6877 6884 6886 7419 7421 7427 +6 6885 6884 6887 7427 7428 7429 +6 6886 6884 6883 6888 7429 7430 +6 6887 6883 6882 6889 7430 7431 +6 6888 6882 6890 6891 7431 7434 +6 6889 6882 5046 6891 4646 4645 +6 6889 6890 4646 4647 6892 7434 +6 6891 4647 4648 6893 7434 6894 +6 6892 4648 4254 4255 4731 6894 +6 6893 4731 6895 7434 6892 7433 +6 6894 4731 4732 6896 6898 7433 +6 6895 4732 6897 6898 6899 6900 +6 6896 4732 4733 6900 6901 6902 +6 6895 6896 6899 7433 7432 7435 +6 6898 6896 6900 7435 7436 7437 +6 6899 6896 6897 6901 7437 7438 +6 6900 6897 6902 7438 6905 6904 +6 6901 6897 4733 4263 6903 6904 +6 6902 4263 4264 4265 5232 6904 +6 6903 5232 5459 6905 6901 6902 +6 6904 5459 5460 6906 7438 6901 +6 6905 5460 6907 7438 7439 7440 +6 6906 5460 5461 6908 7440 7441 +6 6907 5461 5462 6909 7263 7441 +6 6908 5462 5463 6910 7263 7264 +6 6909 5463 6911 7264 7265 6912 +6 6910 5463 5464 5465 5466 6912 +6 6911 5466 6913 7265 6910 7266 +6 6912 5466 5467 6914 7266 7267 +6 6913 5467 5468 6915 7267 7268 +6 6914 5468 6916 7268 7269 7270 +6 6915 5468 5469 6917 6918 7270 +6 6916 5469 5470 5471 5472 6918 +6 6916 6917 5472 6919 7270 7271 +6 6918 5472 5473 6920 7271 7272 +6 6919 5473 5474 6921 7272 7273 +6 6920 5474 5475 5476 6922 7273 +6 6921 5476 6923 7275 7273 7276 +6 6922 5476 5477 6924 7276 7277 +6 6923 5477 5478 6925 7277 7278 +6 6924 5478 5479 6926 7278 7279 +6 6925 5479 5480 6927 7279 7280 +6 6926 5480 5481 5655 6928 7280 +6 6927 5655 5656 6929 7282 7280 +6 6928 5656 6930 7282 7283 7284 +6 6929 5656 5657 5658 6931 7284 +6 6930 5658 6932 7284 7285 7286 +6 6931 5658 5659 5832 6933 7286 +6 6932 5832 6934 7286 7287 7288 +6 6933 5832 5833 5841 6935 7288 +6 6934 5841 5842 6936 6937 7288 +6 6935 5842 5844 6937 6938 6019 +6 6935 6936 6938 6939 7288 7289 +6 6937 6936 6019 6939 6940 6941 +6 6937 6938 6940 7289 7290 7291 +6 6939 6938 6941 7291 7292 6942 +6 6940 6938 6019 5846 5848 6942 +6 6941 5848 6943 6944 7292 6940 +6 6942 5848 6944 6945 6946 5849 +6 6942 6943 6945 7292 7293 7294 +6 6944 6943 6946 7294 7295 7296 +7 6945 6943 5849 5851 6386 6947 7296 +6 6946 6386 6387 6948 7296 7297 +6 6947 6387 6388 6389 6949 7297 +6 6948 6389 6390 6950 7297 7298 +7 6949 6390 6392 6396 6951 7298 7299 +6 6950 6396 6952 7299 7301 7302 +6 6951 6396 6397 6953 7044 7302 +6 6952 6397 6400 6954 7044 7045 +6 6953 6400 6401 6955 6956 7045 +6 6954 6401 6402 6956 6957 6961 +6 6954 6955 6957 6958 7045 7046 +6 6956 6955 6958 6959 6960 6961 +6 6956 6957 6959 7046 7049 7050 +6 6958 6957 6960 6962 6963 7050 +6 6959 6957 6961 6411 6412 6962 +6 6960 6957 6955 6402 6403 6411 +6 6960 6412 6959 6963 6964 6413 +6 6959 6962 6964 7052 7050 7053 +6 6963 6962 6413 6415 6965 7053 +6 6964 6415 6417 6560 6966 7053 +6 6965 6560 6562 6967 7053 6972 +6 6966 6562 6968 6969 6971 6972 +6 6967 6562 6969 6970 6563 6984 +6 6967 6968 6970 6971 6975 6976 +6 6969 6968 6982 6976 6983 6984 +6 6967 6969 6972 6973 6974 6975 +6 6967 6971 6973 7053 6966 7052 +6 6972 6971 6974 7052 7051 7054 +6 6973 6971 6975 7063 7054 7064 +6 6974 6971 6969 6976 6977 7064 +6 6975 6969 6977 6978 6982 6970 +6 6975 6976 6978 6979 7064 7065 +6 6977 6976 6979 6980 6981 6982 +6 6977 6978 6980 7065 7066 7067 +6 6979 6978 6981 7067 7068 7072 +6 6980 6978 6982 7072 7073 7074 +6 6981 6978 6976 6970 6983 7074 +6 6982 6970 6984 6985 7074 7075 +6 6983 6970 6985 6986 6563 6968 +6 6983 6984 6986 7075 7076 7077 +6 6985 6984 6563 6564 6987 7077 +6 6986 6564 6568 6988 6989 7077 +6 6987 6568 6989 6990 6991 6569 +6 6987 6988 6990 6992 7077 7078 +6 6989 6988 6991 6992 6993 6997 +6 6990 6988 6997 6998 6571 6569 +6 6989 6990 6993 6994 7078 7079 +6 6992 6990 6994 6995 6996 6997 +6 6992 6993 6995 7079 7082 7083 +6 6994 6993 6996 7083 7086 7087 +6 6995 6993 6997 7087 7088 7089 +6 6996 6993 6990 6991 6998 7089 +6 6997 6991 6571 6999 7000 7089 +6 6998 6571 7000 7001 7002 6572 +6 6998 6999 7001 7089 7090 7093 +6 7000 6999 7002 7003 7093 7094 +6 7001 6999 7003 7004 6576 6572 +6 7001 7002 7004 7094 7095 7096 +6 7003 7002 6576 6577 7005 7096 +6 7004 6577 6579 7006 7096 7097 +6 7005 6579 7007 7097 7098 7099 +6 7006 6579 6580 7008 7013 7099 +6 7007 6580 6583 7009 7010 7013 +6 7008 6583 7010 6723 6721 6584 +6 7008 7009 6723 6725 7011 7013 +6 7010 6725 7012 7013 7014 7015 +6 7011 6725 7023 7021 7015 6726 +6 7010 7011 7008 7007 7014 7099 +6 7013 7011 7015 7016 7099 7100 +6 7014 7011 7016 7017 7021 7012 +6 7014 7015 7017 7018 7100 7101 +6 7016 7015 7018 7019 7020 7021 +6 7016 7017 7019 7108 7101 7114 +6 7018 7017 7020 7115 7114 7116 +6 7019 7017 7021 7022 7116 7117 +6 7020 7017 7015 7022 7023 7012 +6 7020 7021 7023 7025 7117 7118 +6 7022 7021 7012 6726 7024 7025 +6 7023 6726 6727 7025 7026 7027 +6 7022 7023 7024 7026 7118 7119 +6 7025 7024 7027 7119 7120 7121 +6 7026 7024 6727 7028 7029 7121 +6 7027 6727 6728 7029 7030 7031 +6 7027 7028 7030 7123 7121 7124 +6 7029 7028 7031 7124 7035 7032 +6 7030 7028 6728 6729 6730 7032 +6 7031 6730 7033 7035 7030 7034 +6 7032 6730 6731 6732 6733 7034 +6 7033 6733 6735 6736 7035 7032 +6 7034 6736 7036 7124 7030 7032 +5 7035 6736 6737 7037 7124 +6 7036 6737 6741 7038 7124 7123 +7 7037 6741 6742 7039 7123 7125 7126 +6 7038 6742 7040 7136 7126 7137 +6 7039 6742 6743 7041 7137 7138 +6 7040 6743 6744 7042 7138 7139 +5 7041 6744 6755 7142 7139 +6 6755 6744 6745 6747 6751 6753 +6 6952 6953 7045 7302 7303 7047 +6 7044 6953 6954 6956 7046 7047 +6 7045 6956 6958 7047 7048 7049 +6 7045 7046 7048 7303 7044 7304 +6 7047 7046 7049 7304 7057 7055 +6 7048 7046 6958 7050 7051 7055 +6 7049 6958 7051 7052 6963 6959 +6 7049 7050 7052 6973 7054 7055 +6 7051 7050 6963 7053 6972 6973 +6 7052 6963 6964 6965 6966 6972 +6 7051 6973 7055 7056 7063 6974 +6 7051 7054 7056 7057 7048 7049 +6 7055 7054 7057 7058 7059 7063 +6 7055 7056 7058 7304 7048 7305 +6 7057 7056 7059 7060 7308 7305 +6 7058 7056 7060 7061 7062 7063 +6 7058 7059 7061 7308 7477 7478 +6 7060 7059 7062 7478 7479 7480 +6 7061 7059 7063 7064 7065 7480 +6 7062 7059 7056 7054 6974 7064 +6 7063 6974 6975 6977 7062 7065 +6 7062 7064 6977 6979 7066 7480 +6 7065 6979 7067 7480 7481 7482 +6 7066 6979 6980 7068 7069 7482 +6 7067 6980 7069 7070 7071 7072 +6 7067 7068 7070 7484 7482 7463 +6 7069 7068 7071 7463 7485 7486 +6 7070 7068 7072 7486 7487 7488 +6 7071 7068 6980 6981 7073 7488 +6 7072 6981 7074 7488 7489 7493 +6 7073 6981 6982 6983 7075 7493 +6 7074 6983 6985 7076 7494 7493 +6 7075 6985 7077 7494 7080 7078 +6 7076 6985 6986 6987 6989 7078 +6 7077 6989 6992 7079 7080 7076 +6 7078 6992 6994 7080 7081 7082 +6 7078 7079 7081 7692 7494 7076 +6 7080 7079 7082 7224 7225 7692 +6 7081 7079 6994 7083 7084 7224 +6 7082 6994 6995 7084 7085 7086 +6 7082 7083 7085 7227 7224 7228 +6 7084 7083 7086 7228 7229 7230 +6 7085 7083 6995 7087 7233 7230 +6 7086 6995 6996 7088 7233 7234 +6 7087 6996 7089 7090 7091 7234 +6 7088 6996 6997 6998 7000 7090 +6 7089 7000 7088 7091 7092 7093 +6 7088 7090 7092 7234 7235 7236 +6 7091 7090 7093 7236 7237 7238 +6 7092 7090 7000 7001 7094 7238 +6 7093 7001 7003 7095 7238 7239 +6 7094 7003 7096 7239 7240 7104 +6 7095 7003 7004 7005 7097 7104 +6 7096 7005 7006 7098 7103 7104 +6 7097 7006 7099 7100 7102 7103 +6 7098 7006 7007 7013 7014 7100 +6 7099 7014 7016 7101 7102 7098 +6 7100 7016 7102 7107 7108 7018 +6 7100 7101 7098 7103 7106 7107 +6 7098 7102 7097 7104 7105 7106 +6 7097 7103 7105 7240 7095 7096 +6 7104 7103 7106 7242 7240 7243 +6 7105 7103 7102 7107 7243 7244 +6 7106 7102 7101 7108 7109 7244 +6 7107 7101 7018 7109 7110 7114 +6 7107 7108 7110 7111 7244 7245 +6 7109 7108 7111 7112 7113 7114 +6 7109 7110 7112 7248 7245 7249 +6 7111 7110 7113 7249 7250 7251 +6 7112 7110 7114 7115 7251 7252 +6 7113 7110 7115 7019 7018 7108 +6 7113 7114 7019 7116 7252 7255 +6 7115 7019 7020 7117 7255 7256 +6 7116 7020 7022 7118 7259 7256 +6 7117 7022 7025 7119 7259 7260 +6 7118 7025 7026 7120 7260 7129 +6 7119 7026 7121 7122 7128 7129 +6 7120 7026 7122 7123 7029 7027 +6 7120 7121 7123 7125 7127 7128 +7 7122 7121 7029 7124 7037 7038 7125 +6 7123 7029 7030 7035 7036 7037 +5 7123 7038 7126 7127 7122 +5 7125 7038 7127 7136 7039 +7 7125 7126 7122 7128 7131 7132 7136 +6 7122 7127 7120 7129 7130 7131 +6 7120 7128 7130 7262 7260 7119 +6 7129 7128 7131 7262 7533 7531 +6 7130 7128 7127 7132 7133 7533 +6 7131 7127 7133 7134 7135 7136 +6 7131 7132 7134 7533 7532 7534 +6 7133 7132 7135 7534 7535 7536 +6 7134 7132 7136 7536 7537 7137 +6 7135 7132 7127 7126 7039 7137 +6 7136 7039 7040 7138 7537 7135 +6 7137 7040 7041 7139 7140 7537 +6 7138 7041 7140 7141 7142 7042 +6 7138 7139 7141 7149 7151 7537 +6 7140 7139 7142 7143 7148 7149 +7 7141 7139 7042 6755 6756 6760 7143 +6 7141 7142 6760 6761 7144 7148 +6 7143 6761 7145 7146 7147 7148 +7 7144 6761 7146 4553 4552 6764 6762 +5 7144 7145 4553 4555 7147 +6 7146 4555 4557 7144 7148 7149 +5 7144 7147 7149 7141 7143 +7 7148 7147 4557 7141 7140 7150 7151 +6 7149 4557 7151 7152 7153 7154 +6 7149 7150 7140 7152 7537 7536 +6 7151 7150 7153 7536 7535 7538 +6 7152 7150 7154 7155 7156 7538 +6 7153 7150 7155 4650 4556 4557 +6 7153 7154 7156 7157 7167 4650 +6 7153 7155 7157 7158 7538 7539 +6 7156 7155 7158 7159 7160 7167 +6 7156 7157 7159 7539 7540 7555 +6 7158 7157 7160 7161 7555 7556 +6 7159 7157 7161 7162 7163 7167 +6 7159 7160 7162 7164 7168 7556 +6 7161 7160 7163 7164 4138 7165 +5 7162 7160 7165 7166 7167 +6 7161 7162 4138 7168 7169 4139 +7 4138 7162 7163 7166 4414 4135 4136 +5 7165 7163 4414 4416 7167 +7 4416 7166 7163 7160 7157 7155 4650 +6 7161 7164 7169 7556 7557 7561 +7 7168 7164 4139 7170 7561 7562 7563 +5 7169 4139 4140 7171 7563 +7 7170 4140 4141 7172 7563 7564 7565 +6 7171 4141 4125 7173 7174 7565 +6 7172 4125 7174 7175 4123 9790 +6 7172 7173 7175 7176 7177 7565 +6 7174 7173 7176 9789 9788 9790 +6 7174 7175 7177 7178 7179 9789 +7 7174 7176 7178 7565 7564 7569 7570 +6 7177 7176 7179 7180 7181 7570 +6 7178 7176 7180 9789 3536 3538 +6 7178 7179 7181 7182 7183 3538 +6 7178 7180 7182 7571 7570 7572 +6 7181 7180 7183 7572 7573 7574 +6 7182 7180 3538 3539 7184 7574 +6 7183 3539 7185 7576 7574 7188 +6 7184 3539 3540 7186 7187 7188 +6 7185 3540 7187 7212 7211 7213 +6 7185 7186 7188 7189 7212 7193 +6 7185 7187 7189 7190 7576 7184 +6 7188 7187 7190 7191 7192 7193 +6 7188 7189 7191 7576 7577 7580 +6 7190 7189 7192 7194 7580 7581 +6 7191 7189 7193 7194 7195 7199 +6 7192 7189 7199 7200 7212 7187 +6 7191 7192 7195 7196 7581 7582 +6 7194 7192 7196 7197 7198 7199 +6 7194 7195 7197 7582 7583 7584 +6 7196 7195 7198 7584 3197 3196 +6 7197 7195 7199 3196 7201 7204 +6 7198 7195 7192 7193 7200 7201 +6 7199 7193 7201 7202 7212 7209 +6 7199 7200 7202 7203 7204 7198 +6 7201 7200 7203 7207 7208 7209 +6 7201 7202 7204 7205 7206 7207 +6 7201 7203 7205 3195 3196 7198 +6 7204 7203 7206 7221 7222 3195 +6 7205 7203 7207 9746 7219 7221 +6 7206 7203 7202 7208 9746 9747 +6 7207 7202 7209 7210 9747 7214 +6 7208 7202 7210 7211 7212 7200 +6 7208 7209 7211 4374 4375 7214 +6 7210 7209 7212 7186 7213 4374 +6 7211 7209 7200 7193 7187 7186 +6 7211 7186 3540 3541 4373 4374 +6 7210 4375 4376 7215 9747 7208 +6 7214 4376 4378 7216 7217 9747 +6 7215 4378 7217 2864 1628 2863 +6 7215 7216 2864 7218 9746 9747 +6 7217 2864 2865 2866 7219 9746 +6 7218 2866 7220 7221 7206 9746 +5 7219 2866 7221 3215 2867 +6 7219 7220 3215 7222 7206 7205 +6 7221 3215 3216 7223 3195 7205 +5 7222 3216 3217 3194 3195 +6 7081 7082 7225 7226 7227 7084 +6 7081 7224 7226 7692 7691 7693 +6 7225 7224 7227 7693 7694 7675 +6 7226 7224 7084 7228 7675 7695 +6 7227 7084 7085 7229 7695 7696 +6 7228 7085 7230 7231 7696 7697 +6 7229 7085 7231 7232 7233 7086 +6 7229 7230 7232 7697 7698 7702 +6 7231 7230 7233 7702 7703 7704 +6 7232 7230 7086 7087 7234 7704 +6 7233 7087 7088 7091 7235 7704 +6 7234 7091 7236 7719 7705 7704 +6 7235 7091 7092 7237 7719 7718 +6 7236 7092 7238 7718 7720 7721 +6 7237 7092 7093 7094 7239 7721 +6 7238 7094 7095 7240 7241 7721 +6 7239 7095 7104 7241 7242 7105 +6 7239 7240 7242 7721 7722 7723 +6 7241 7240 7105 7243 7723 7726 +6 7242 7105 7106 7244 7246 7726 +6 7243 7106 7107 7109 7245 7246 +6 7244 7109 7246 7247 7248 7111 +6 7244 7245 7247 7729 7726 7243 +6 7246 7245 7248 7965 7729 7966 +6 7247 7245 7111 7249 7966 7967 +6 7248 7111 7112 7250 7967 7968 +6 7249 7112 7251 7512 7968 7969 +6 7250 7112 7113 7252 7253 7512 +6 7251 7113 7115 7253 7254 7255 +6 7251 7252 7254 7512 7513 7517 +6 7253 7252 7255 7257 9776 7517 +6 7254 7252 7115 7116 7256 7257 +6 7255 7116 7257 7258 7259 7117 +6 7255 7256 7258 7524 7254 9776 +6 7257 7256 7259 7261 7525 7524 +6 7258 7256 7117 7118 7260 7261 +6 7259 7118 7119 7261 7262 7129 +6 7259 7260 7262 7530 7525 7258 +6 7261 7260 7129 7130 7531 7530 +6 6908 6909 7264 7441 7443 7444 +6 7263 6909 6910 7265 7444 7445 +6 7264 6910 6912 7266 7445 7446 +6 7265 6912 6913 7267 7446 7447 +6 7266 6913 6914 7268 7450 7447 +6 7267 6914 6915 7269 7450 7451 +6 7268 6915 7270 7451 7452 7453 +6 7269 6915 6916 6918 7271 7453 +6 7270 6918 6919 7272 7453 7454 +6 7271 6919 6920 7273 7274 7454 +6 7272 6920 7274 7275 6922 6921 +6 7272 7273 7275 7454 7455 7456 +6 7274 7273 6922 7276 7456 7457 +6 7275 6922 6923 7277 7457 7458 +6 7276 6923 6924 7278 7458 7459 +6 7277 6924 6925 7279 7459 7460 +6 7278 6925 6926 7280 7281 7460 +6 7279 6926 7281 7282 6928 6927 +6 7279 7280 7282 7460 7461 7465 +6 7281 7280 6928 6929 7283 7465 +6 7282 6929 7284 7465 7466 7467 +6 7283 6929 6930 6931 7285 7467 +6 7284 6931 7286 7467 7468 7469 +6 7285 6931 6932 6933 7287 7469 +6 7286 6933 7288 7469 7470 7289 +6 7287 6933 6934 6935 6937 7289 +6 7288 6937 6939 7290 7470 7287 +6 7289 6939 7291 7470 7471 7472 +6 7290 6939 6940 7292 7472 7473 +6 7291 6940 6942 6944 7293 7473 +6 7292 6944 7294 7473 7474 7475 +6 7293 6944 6945 7295 7475 7300 +6 7294 6945 7296 7298 7299 7300 +6 7295 6945 6946 6947 7297 7298 +5 7296 6947 6948 6949 7298 +6 7297 6949 6950 7296 7295 7299 +6 7295 7298 6950 6951 7300 7301 +5 7295 7299 7301 7475 7294 +7 7300 7299 6951 7302 7475 7306 7303 +5 7301 6951 6952 7044 7303 +6 7302 7044 7047 7304 7306 7301 +6 7303 7047 7048 7057 7305 7306 +6 7304 7057 7306 7307 7308 7058 +6 7304 7305 7307 7475 7301 7303 +6 7306 7305 7308 7475 7474 7476 +6 7307 7305 7058 7060 7476 7477 +5 4703 4704 7310 7856 7857 +6 7309 4704 4705 7311 7857 7858 +6 7310 4705 4706 7312 7858 7859 +6 7311 4706 4707 7313 7859 7860 +6 7312 4707 4708 5171 7314 7860 +6 7313 5171 7315 7860 7861 7862 +6 7314 5171 5172 7316 7862 7863 +6 7315 5172 5173 7317 7863 7864 +6 7316 5173 5174 7318 7864 7865 +6 7317 5174 5175 7319 7865 7866 +6 7318 5175 5176 7320 7866 7867 +6 7319 5176 5177 7321 7867 7868 +6 7320 5177 5178 5179 7322 7868 +6 7321 5179 7323 7868 7869 7870 +6 7322 5179 5180 7324 7870 7871 +6 7323 5180 5181 5412 7325 7871 +6 7324 5412 7326 7871 7872 7873 +6 7325 5412 5413 7327 7873 7874 +6 7326 5413 5414 5415 7328 7874 +6 7327 5415 7329 7874 7875 7876 +6 7328 5415 5416 5417 7330 7876 +6 7329 5417 7331 7876 7877 7878 +6 7330 5417 5418 5419 7332 7878 +6 7331 5419 6792 7333 7878 7879 +6 7332 6792 7334 7879 7880 7881 +6 7333 6792 6793 6794 7335 7881 +6 7334 6794 6795 7336 7881 7882 +6 7335 6795 6796 6797 7337 7882 +6 7336 6797 6798 7338 7882 7883 +6 7337 6798 6799 7339 7883 7884 +6 7338 6799 6800 7340 7884 7885 +6 7339 6800 6801 7341 7885 7886 +6 7340 6801 6802 7342 7886 7887 +6 7341 6802 7343 7887 7888 7889 +6 7342 6802 6803 6804 7344 7889 +6 7343 6804 6805 7345 7889 7890 +6 7344 6805 6806 7346 7890 7891 +6 7345 6806 6807 7347 7891 7892 +6 7346 6807 6808 7348 7892 7893 +6 7347 6808 6809 7349 7893 7894 +6 7348 6809 7350 7894 7895 7896 +7 7349 6809 6810 6812 6813 7351 7896 +6 7350 6813 6814 7352 7896 7897 +6 7351 6814 6815 7353 7897 7898 +5 7352 6815 6816 7354 7898 +7 7353 6816 6817 7355 7898 7899 7900 +5 7354 6817 6818 7356 7900 +7 7355 6818 6819 7357 7900 7901 7902 +6 7356 6819 7358 7902 7903 7904 +7 7357 6819 6820 6821 6822 7359 7904 +6 7358 6822 7360 7904 7905 7906 +6 7359 6822 6823 7361 7362 7906 +6 7360 6823 6824 7362 7363 6826 +6 7360 7361 7363 7906 7907 7908 +6 7362 7361 6826 6829 7364 7908 +6 7363 6829 7365 7908 7909 7910 +5 7364 6829 6830 7366 7910 +7 7365 6830 7367 7370 7372 7910 7911 +6 7366 6830 6831 6832 7368 7370 +6 7367 6832 7369 7370 7371 7376 +5 7368 6832 7376 6836 6835 +6 7367 7368 7371 7366 7372 7373 +6 7370 7368 7373 7374 7375 7376 +6 7366 7370 7373 7911 7912 7913 +6 7372 7370 7371 7374 7913 7914 +6 7373 7371 7375 7914 7915 7916 +6 7374 7371 7376 6837 7377 7916 +6 7375 7371 7368 7369 6836 6837 +6 7375 6837 7378 7916 7917 7918 +6 7377 6837 6838 6839 7379 7918 +5 7378 6839 7380 7602 7918 +6 7379 6839 6840 6842 7381 7602 +6 7380 6842 6843 7382 7602 7603 +6 7381 6843 6844 7383 7606 7603 +6 7382 6844 7384 7385 7606 7607 +6 7383 6844 7385 6848 6846 6845 +6 7383 7384 6848 7386 7607 7608 +6 7385 6848 6849 7387 7608 7393 +6 7386 6849 7388 7389 7392 7393 +6 7387 6849 6850 6851 6852 7389 +6 7388 6852 6855 7390 7392 7387 +6 7389 6855 6856 6860 7391 7392 +6 7390 6860 7392 7397 7394 7398 +6 7390 7391 7389 7387 7393 7394 +6 7387 7392 7394 7395 7608 7386 +6 7393 7392 7395 7396 7397 7391 +6 7393 7394 7396 7608 7609 7612 +6 7395 7394 7397 7612 7613 7623 +6 7396 7394 7391 7398 7623 7624 +6 7397 7391 6860 6861 7399 7624 +5 7398 6861 7400 7624 7625 +6 7399 6861 6862 7401 7625 7626 +7 7400 6862 6863 6866 7402 7626 7627 +6 7401 6866 6868 7403 7404 7627 +6 7402 6868 7404 7405 7406 6870 +6 7402 7403 7405 7627 7628 7629 +6 7404 7403 7406 7409 7629 7630 +6 7405 7403 6870 7407 7408 7409 +6 7406 6870 7408 7412 7413 6871 +6 7406 7407 7409 7410 7411 7412 +6 7406 7408 7405 7410 7633 7630 +6 7409 7408 7411 7633 7634 7635 +6 7410 7408 7412 7635 7636 7643 +6 7411 7408 7407 7413 7643 7644 +6 7412 7407 6871 7414 7415 7644 +6 7413 6871 7415 7416 7417 6872 +6 7413 7414 7416 7644 7645 7646 +6 7415 7414 7417 7418 7646 7647 +6 7416 7414 7418 7419 7420 6872 +6 7416 7417 7419 7421 7422 7647 +7 7418 7417 7420 6875 6877 6885 7421 +5 7419 7417 6872 6873 6875 +6 7419 6885 7418 7422 7423 7427 +6 7418 7421 7423 7424 7647 7648 +6 7422 7421 7424 7425 7426 7427 +6 7422 7423 7425 7648 7649 7650 +6 7424 7423 7426 7650 7651 7652 +6 7425 7423 7427 7652 7653 7428 +6 7426 7423 7421 6885 6886 7428 +6 7427 6886 7429 7653 7426 7654 +6 7428 6886 6887 7430 7654 7655 +6 7429 6887 6888 7431 7432 7655 +6 7430 6888 6889 7432 7433 7434 +6 7430 7431 7433 6898 7435 7655 +6 7432 7431 7434 6894 6895 6898 +6 7433 7431 6889 6891 6892 6894 +6 7432 6898 6899 7436 7656 7655 +6 7435 6899 7437 7656 7657 7661 +6 7436 6899 6900 7438 7661 7439 +6 7437 6900 6901 6905 6906 7439 +6 7438 6906 7440 7661 7437 7662 +6 7439 6906 6907 7441 7442 7662 +6 7440 6907 6908 7263 7442 7443 +6 7440 7441 7443 7662 7663 7664 +6 7442 7441 7263 7444 7664 7665 +6 7443 7263 7264 7445 7665 7666 +6 7444 7264 7265 7446 7666 7667 +6 7445 7265 7266 7447 7448 7667 +6 7446 7266 7448 7449 7450 7267 +6 7446 7447 7449 7669 7667 7672 +6 7448 7447 7450 7672 7677 7674 +6 7449 7447 7267 7268 7451 7677 +6 7450 7268 7269 7452 7677 7678 +6 7451 7269 7453 7678 7679 7683 +6 7452 7269 7270 7271 7454 7683 +6 7453 7271 7272 7274 7455 7683 +6 7454 7274 7456 7683 7682 7684 +6 7455 7274 7275 7457 7687 7684 +6 7456 7275 7276 7458 7687 7688 +6 7457 7276 7277 7459 7688 7689 +6 7458 7277 7278 7460 7689 7462 +6 7459 7278 7279 7281 7461 7462 +6 7460 7281 7462 7463 7464 7465 +6 7460 7461 7463 7689 7459 7485 +7 7462 7461 7464 7484 7069 7070 7485 +6 7463 7461 7465 7484 7483 7466 +6 7464 7461 7281 7282 7283 7466 +6 7465 7283 7467 7483 7464 7495 +6 7466 7283 7284 7285 7468 7495 +6 7467 7285 7469 7495 7496 7497 +6 7468 7285 7286 7287 7470 7497 +6 7469 7287 7289 7290 7471 7497 +6 7470 7290 7472 7497 7498 7499 +6 7471 7290 7291 7473 7499 7476 +6 7472 7291 7292 7293 7474 7476 +5 7473 7293 7475 7307 7476 +7 7474 7293 7294 7300 7301 7306 7307 +7 7474 7307 7308 7477 7499 7472 7473 +5 7476 7308 7060 7478 7499 +6 7477 7060 7061 7479 7498 7499 +7 7478 7061 7480 7481 7498 7496 7500 +6 7479 7061 7062 7065 7066 7481 +6 7479 7480 7066 7482 7483 7500 +6 7481 7066 7483 7484 7069 7067 +7 7481 7482 7484 7464 7466 7495 7500 +5 7483 7482 7069 7463 7464 +5 7463 7070 7486 7689 7462 +6 7485 7070 7071 7487 7688 7689 +6 7486 7071 7488 7687 7688 7686 +7 7487 7071 7072 7073 7489 7490 7686 +6 7488 7073 7490 7491 7492 7493 +5 7488 7489 7491 7686 7685 +6 7490 7489 7492 7685 7690 7691 +6 7491 7489 7493 7494 7691 7692 +6 7492 7489 7494 7075 7074 7073 +6 7492 7493 7075 7076 7692 7080 +6 7483 7466 7467 7468 7496 7500 +6 7495 7468 7497 7498 7479 7500 +6 7496 7468 7469 7470 7471 7498 +6 7497 7471 7499 7478 7479 7496 +6 7498 7471 7472 7478 7477 7476 +5 7496 7479 7481 7483 7495 +6 428 5613 5614 7502 7503 9769 +6 7501 5614 7503 7504 7505 7506 +6 7501 7502 7504 9769 9770 9771 +6 7503 7502 7505 6475 9771 9781 +5 7504 7502 6475 6473 7506 +7 6473 7505 7502 5614 5615 7507 6471 +5 7506 5615 7508 6470 6471 +6 7507 5615 5616 7509 7510 6470 +6 7508 5616 7510 7511 9735 4519 +5 7508 7509 7511 6470 6469 +6 7510 7509 6469 9733 9734 9735 +6 7250 7251 7253 7513 7514 7969 +6 7512 7253 7514 7515 7516 7517 +6 7512 7513 7515 7969 7970 7971 +6 7514 7513 7516 7971 7972 7973 +6 7515 7513 7517 7518 7519 7973 +6 7516 7513 7253 7518 9776 7254 +6 7516 7517 7519 7520 7521 9776 +6 7516 7518 7520 7973 7974 7978 +6 7519 7518 7521 7522 7978 7979 +6 7520 7518 7522 7523 7524 9776 +6 7520 7521 7523 7990 7979 7527 +6 7522 7521 7524 7525 7526 7527 +6 7523 7521 7525 7257 7258 9776 +6 7523 7524 7526 7261 7530 7258 +6 7523 7525 7527 7528 7529 7530 +6 7523 7526 7528 7990 7522 7991 +6 7527 7526 7529 7991 7547 7546 +6 7528 7526 7530 7531 7532 7546 +6 7529 7526 7531 7262 7261 7525 +6 7529 7530 7262 7532 7533 7130 +7 7529 7531 7533 7133 7534 7544 7546 +5 7532 7531 7130 7131 7133 +6 7532 7133 7134 7535 7545 7544 +6 7534 7134 7536 7152 7538 7545 +6 7535 7134 7135 7537 7151 7152 +6 7536 7135 7137 7138 7140 7151 +6 7535 7152 7153 7156 7539 7545 +6 7538 7156 7158 7540 7541 7545 +6 7539 7158 7541 7542 7554 7555 +6 7539 7540 7542 7543 7544 7545 +6 7541 7540 7543 7548 7554 7551 +6 7541 7542 7544 7546 7547 7548 +6 7541 7543 7545 7534 7532 7546 +6 7541 7544 7534 7535 7538 7539 +6 7532 7544 7543 7547 7528 7529 +6 7546 7543 7548 7549 7991 7528 +6 7547 7543 7542 7549 7550 7551 +6 7547 7548 7550 7991 7990 7992 +6 7549 7548 7551 7552 7992 7993 +6 7550 7548 7552 7553 7554 7542 +6 7550 7551 7553 7993 7995 7996 +7 7552 7551 7554 7558 7557 7559 7996 +6 7553 7551 7542 7540 7555 7558 +6 7554 7540 7158 7159 7556 7558 +6 7555 7159 7161 7168 7557 7558 +7 7556 7168 7558 7553 7559 7560 7561 +5 7556 7557 7555 7554 7553 +5 7553 7557 7560 7996 7997 +7 7559 7557 7561 7997 8000 7567 7562 +5 7560 7557 7168 7169 7562 +6 7561 7169 7563 7566 7567 7560 +6 7562 7169 7170 7171 7564 7566 +6 7563 7171 7565 7177 7566 7569 +5 7564 7171 7172 7174 7177 +6 7563 7564 7562 7567 7568 7569 +6 7562 7566 7568 8000 7560 8001 +6 7567 7566 7569 7570 7571 8001 +5 7568 7566 7564 7177 7570 +6 7569 7177 7568 7571 7181 7178 +6 7568 7570 7181 7572 8001 8002 +6 7571 7181 7182 7573 8002 8003 +6 7572 7182 7574 7575 8003 8004 +6 7573 7182 7575 7576 7184 7183 +6 7573 7574 7576 7577 7578 8004 +6 7575 7574 7184 7188 7190 7577 +6 7576 7190 7575 7578 7579 7580 +6 7575 7577 7579 8004 8005 8006 +6 7578 7577 7580 8006 8007 8008 +6 7579 7577 7190 7191 7581 8008 +6 7580 7191 7194 7582 8008 8009 +6 7581 7194 7196 7583 8009 8010 +6 7582 7196 7584 7586 8013 8010 +6 7583 7196 7197 3197 7585 7586 +6 7584 3197 3187 7586 7587 3188 +6 7584 7585 7587 7588 7583 8013 +6 7586 7585 7588 7589 3959 3188 +6 7586 7587 7589 7730 8014 8013 +6 7588 7587 3959 3961 7590 7730 +6 7589 3961 7591 7730 7731 7732 +6 7590 3961 3962 7592 7732 7733 +6 7591 3962 7593 7739 7733 7740 +6 7592 3962 2891 2892 7594 7740 +6 7593 2892 7595 7596 7740 7741 +6 7594 2892 7596 7597 7598 2893 +6 7594 7595 7597 7741 7742 7746 +6 7596 7595 7598 7599 7746 7747 +6 7597 7595 7599 7600 7601 2893 +6 7597 7598 7600 4090 7747 7752 +5 7599 7598 7601 4090 4087 +6 7600 7598 4087 2881 2880 2893 +7 7379 7380 7381 7603 7604 7918 7919 +6 7602 7381 7604 7605 7606 7382 +6 7602 7603 7605 7927 7921 7919 +5 7604 7603 7606 7927 7928 +7 7605 7603 7382 7383 7607 7610 7928 +6 7606 7383 7385 7608 7609 7610 +6 7607 7385 7386 7393 7395 7609 +6 7608 7395 7607 7610 7611 7612 +6 7607 7609 7611 7930 7928 7606 +6 7610 7609 7612 7614 7617 7930 +6 7611 7609 7395 7396 7613 7614 +6 7612 7396 7614 7615 7622 7623 +6 7612 7613 7615 7616 7617 7611 +6 7614 7613 7616 7620 7621 7622 +6 7614 7615 7617 7618 7619 7620 +6 7614 7616 7618 8158 7930 7611 +6 7617 7616 7619 8156 8158 8157 +6 7618 7616 7620 8157 8159 8160 +6 7619 7616 7615 7621 8160 8161 +6 7620 7615 7622 8161 8162 8163 +6 7621 7615 7613 7623 8163 8164 +6 7622 7613 7396 7397 7624 8164 +6 7623 7397 7398 7399 7625 8164 +6 7624 7399 7400 7626 8164 8165 +6 7625 7400 7401 7627 8165 7628 +5 7626 7401 7402 7404 7628 +6 7627 7404 7629 8165 7626 8166 +6 7628 7404 7405 7630 7631 8166 +6 7629 7405 7631 7632 7633 7409 +6 7629 7630 7632 8166 8167 8168 +6 7631 7630 7633 8171 8168 8172 +6 7632 7630 7409 7410 7634 8172 +6 7633 7410 7635 8174 8172 8175 +6 7634 7410 7411 7636 7637 8175 +6 7635 7411 7637 7638 7642 7643 +6 7635 7636 7638 7639 8175 8176 +6 7637 7636 7639 7640 7641 7642 +6 7637 7638 7640 8176 8177 8178 +6 7639 7638 7641 8178 8179 8180 +6 7640 7638 7642 8180 8181 8182 +6 7641 7638 7636 7643 8182 8183 +6 7642 7636 7411 7412 7644 8183 +6 7643 7412 7413 7415 7645 8183 +6 7644 7415 7646 8184 8183 8185 +6 7645 7415 7416 7647 8185 8186 +6 7646 7416 7418 7422 7648 8186 +6 7647 7422 7424 7649 8186 8187 +6 7648 7424 7650 8187 8188 8189 +6 7649 7424 7425 7651 8189 8190 +6 7650 7425 7652 8190 8191 8192 +6 7651 7425 7426 7653 8192 8193 +6 7652 7426 7428 7654 8193 7658 +6 7653 7428 7429 7655 7656 7658 +6 7654 7429 7430 7656 7435 7432 +6 7654 7655 7435 7436 7657 7658 +6 7656 7436 7658 7659 7660 7661 +6 7656 7657 7659 8193 7653 7654 +6 7658 7657 7660 8193 8194 8195 +6 7659 7657 7661 8195 7663 7662 +6 7660 7657 7436 7437 7439 7662 +6 7661 7439 7440 7442 7663 7660 +6 7662 7442 7664 8195 7660 8196 +6 7663 7442 7443 7665 8209 8196 +6 7664 7443 7444 7666 8209 8208 +6 7665 7444 7445 7667 7668 8208 +6 7666 7445 7668 7669 7448 7446 +6 7666 7667 7669 7670 8207 8208 +6 7668 7667 7448 7670 7671 7672 +6 7668 7669 7671 7699 8207 9791 +6 7670 7669 7672 7673 7696 9791 +6 7671 7669 7448 7449 7673 7674 +6 7671 7672 7674 7675 7696 7695 +6 7673 7672 7675 7676 7677 7449 +7 7673 7674 7676 7694 7226 7227 7695 +6 7675 7674 7677 7678 7680 7694 +6 7676 7674 7449 7450 7451 7678 +6 7677 7451 7452 7679 7680 7676 +6 7678 7452 7680 7681 7682 7683 +7 7678 7679 7681 7676 7694 7693 7690 +5 7680 7679 7682 7690 7685 +6 7681 7679 7683 7455 7684 7685 +6 7682 7679 7452 7453 7454 7455 +6 7682 7455 7685 7686 7687 7456 +7 7682 7684 7686 7490 7491 7690 7681 +6 7685 7684 7687 7487 7488 7490 +6 7686 7684 7456 7457 7688 7487 +6 7687 7457 7458 7487 7486 7689 +6 7486 7688 7458 7459 7462 7485 +6 7685 7491 7691 7693 7680 7681 +6 7690 7491 7492 7692 7225 7693 +6 7691 7492 7494 7080 7081 7225 +6 7691 7225 7226 7694 7680 7690 +5 7693 7226 7675 7676 7680 +5 7675 7227 7228 7696 7673 +7 7695 7228 7229 7697 7671 7673 9791 +6 7696 7229 7231 7698 7699 9791 +6 7697 7231 7699 7700 7701 7702 +6 7697 7698 7700 8207 7670 9791 +6 7699 7698 7701 8206 8204 8207 +6 7700 7698 7702 8319 8206 7708 +6 7701 7698 7231 7232 7703 7708 +6 7702 7232 7704 7705 7706 7708 +6 7703 7232 7705 7235 7234 7233 +6 7703 7704 7706 7707 7719 7235 +6 7703 7705 7707 7708 7709 7710 +6 7706 7705 7710 7711 7712 7719 +6 7703 7706 7709 8319 7701 7702 +6 7708 7706 7710 8319 8482 8318 +6 7709 7706 7707 7711 8482 8483 +6 7710 7707 7712 7713 7714 8483 +6 7711 7707 7713 7717 7718 7719 +6 7711 7712 7714 7715 7716 7717 +6 7711 7713 7715 8483 8484 8485 +6 7714 7713 7716 8485 9766 8487 +6 7715 7713 7717 9766 7724 9768 +6 7716 7713 7712 7718 9768 7720 +6 7717 7712 7719 7236 7237 7720 +6 7718 7712 7707 7705 7235 7236 +6 7718 7237 7721 9768 7717 7722 +6 7720 7237 7238 7239 7241 7722 +6 7721 7241 7723 7724 9768 7720 +6 7722 7241 7242 7724 7725 7726 +7 7722 7723 7725 7727 9766 7716 9768 +6 7724 7723 7726 7727 7728 7729 +6 7725 7723 7729 7246 7243 7242 +6 7724 7725 7728 7963 9766 9765 +6 7727 7725 7729 7963 7964 7965 +6 7728 7725 7726 7246 7965 7247 +6 7588 7589 7590 7731 8014 8015 +6 7730 7590 7732 8015 8016 7735 +6 7731 7590 7591 7733 7734 7735 +6 7732 7591 7734 7738 7739 7592 +6 7732 7733 7735 7736 7737 7738 +6 7732 7734 7736 8016 7731 8017 +6 7735 7734 7737 8017 8018 8019 +6 7736 7734 7738 8019 8020 8021 +6 7737 7734 7733 7739 8021 8022 +6 7738 7733 7592 7740 9767 8022 +6 7739 7592 7593 7594 7741 9767 +6 7740 7594 7596 7742 7743 9767 +6 7741 7596 7743 7744 7745 7746 +6 7741 7742 7744 8026 8024 9767 +6 7743 7742 7745 8026 8027 8028 +6 7744 7742 7746 7748 7749 8028 +6 7745 7742 7596 7597 7747 7748 +6 7746 7597 7599 7748 7751 7752 +6 7746 7747 7745 7749 7750 7751 +6 7745 7748 7750 8028 8032 8033 +6 7749 7748 7751 8033 8037 7760 +6 7750 7748 7747 7752 7753 7760 +7 7751 7747 7599 4090 4091 7753 7754 +7 7751 7752 7754 4380 7755 7759 7760 +4 7753 7752 4091 4380 +5 7753 4380 4381 7756 7759 +6 7755 4381 4383 7757 7758 7759 +6 7756 4383 7758 7763 7764 7765 +6 7756 7757 7759 7761 7762 7763 +6 7756 7758 7755 7753 7760 7761 +6 7753 7759 7761 8037 7750 7751 +5 7760 7759 7758 7762 8037 +7 7761 7758 7763 8037 8641 8636 8036 +7 7762 7758 7757 7764 8853 8640 8641 +6 7763 7757 7765 7766 8853 8854 +6 7764 7757 4383 4384 4390 7766 +6 7764 7765 4390 7767 8320 8854 +6 7766 4390 4391 7768 8320 8321 +6 7767 4391 3143 7769 7770 8321 +6 7768 3143 7770 7771 7775 3144 +6 7768 7769 7771 7772 8323 8321 +6 7770 7769 7772 7773 7774 7775 +6 7770 7771 7773 8323 8324 8325 +6 7772 7771 7774 8325 8326 7778 +6 7773 7771 7775 7776 7777 7778 +6 7774 7771 7769 3144 3145 7776 +6 7775 3145 7774 7777 3146 9792 +6 7774 7776 7778 7779 3415 9792 +6 7774 7777 7779 8326 7773 8327 +6 7778 7777 3415 3416 7780 8327 +6 7779 3416 5383 5385 7781 8327 +6 7780 5385 5387 7782 8327 8328 +6 7781 5387 5389 7783 8330 8328 +6 7782 5389 5617 7784 8330 8331 +6 7783 5617 7785 8331 8332 8333 +6 7784 5617 5618 7786 8038 8333 +6 7785 5618 7787 7788 8038 8039 +6 7786 5618 5619 7788 7789 7790 +6 7786 7787 7789 8039 8040 8041 +6 7788 7787 7790 8046 8041 7795 +6 7789 7787 5619 5620 7791 7795 +6 7790 5620 7792 7793 7794 7795 +6 7791 5620 7793 3780 3779 5621 +6 7791 7792 7794 7798 7799 3780 +6 7791 7793 7795 7796 7797 7798 +6 7791 7794 7796 8046 7789 7790 +6 7795 7794 7797 8046 8047 8048 +6 7796 7794 7798 8049 8048 8050 +6 7797 7794 7793 7799 8050 7800 +6 7798 7793 3780 3781 3784 7800 +6 7799 3784 3785 7801 8050 7798 +6 7800 3785 3786 3789 7802 8050 +6 7801 3789 3791 7803 8049 8050 +6 7802 3791 3792 3794 7804 8049 +6 7803 3794 7805 7807 8048 8049 +6 7804 3794 3795 7806 7807 7808 +6 7805 3795 7808 7809 7810 3796 +6 7804 7805 7808 8047 8048 8344 +6 7807 7805 7806 7809 8345 8344 +6 7808 7806 7810 8345 8346 7931 +6 7809 7806 3796 3797 7811 7931 +6 7810 3797 3953 7812 7931 7932 +6 7811 3953 7813 7932 7933 7937 +6 7812 3953 3954 7814 7937 7938 +6 7813 3954 3955 7815 7938 7939 +6 7814 3955 7816 7939 7940 7817 +6 7815 3955 3956 3957 4239 7817 +6 7816 4239 4504 7818 7940 7815 +6 7817 4504 4505 7819 7940 7941 +6 7818 4505 7820 7941 7942 7943 +6 7819 4505 4506 7821 7943 7944 +6 7820 4506 4507 4508 7822 7944 +6 7821 4508 7823 7944 7945 7946 +6 7822 4508 4509 7824 7946 7947 +6 7823 4509 4510 7825 7947 7948 +6 7824 4510 7826 7827 7948 7949 +6 7825 4510 4511 7827 7828 7829 +6 7825 7826 7828 7949 7950 7951 +6 7827 7826 7829 7951 7952 7953 +6 7828 7826 4511 4420 7830 7953 +6 7829 4420 4248 7831 7953 7833 +6 7830 4248 4249 4740 7832 7833 +6 7831 4740 5004 7833 7834 7835 +6 7831 7832 7834 7953 7830 7954 +6 7833 7832 7835 7954 7955 7956 +6 7834 7832 5004 5005 7836 7956 +6 7835 5005 5006 7837 7956 7957 +6 7836 5006 7838 7957 7958 7959 +6 7837 5006 4751 4752 7839 7959 +6 7838 4752 4758 7840 7959 7960 +6 7839 4758 7841 7960 7961 7847 +6 7840 4758 4759 7842 7847 7962 +6 7841 4759 4662 4663 7843 7962 +6 7842 4663 4664 4690 7844 7962 +6 7843 4690 4691 7845 7962 7846 +6 7844 4691 4692 5159 5160 7846 +5 7845 5160 7847 7962 7844 +7 7846 5160 7848 7961 7840 7841 7962 +6 7847 5160 5161 7849 8083 7961 +6 7848 5161 5162 7850 8083 8084 +6 7849 5162 5163 7851 8084 8085 +6 7850 5163 7852 8085 8086 8087 +6 7851 5163 5164 5165 7853 8087 +6 7852 5165 7854 8087 8088 8089 +6 7853 5165 5166 7855 8089 8090 +7 7854 5166 4701 4702 4703 7856 8090 +5 7855 4703 7309 7857 8090 +7 7856 7309 7310 7858 8090 8091 8092 +7 7857 7310 7311 7859 8092 8093 8094 +6 7858 7311 7312 7860 8094 8095 +6 7859 7312 7313 7314 7861 8095 +6 7860 7314 7862 8095 8096 8097 +6 7861 7314 7315 7863 8097 8098 +6 7862 7315 7316 7864 8098 8099 +6 7863 7316 7317 7865 8099 8100 +6 7864 7317 7318 7866 8100 8101 +6 7865 7318 7319 7867 8101 8102 +6 7866 7319 7320 7868 8102 8103 +6 7867 7320 7321 7322 7869 8103 +6 7868 7322 7870 8103 8104 8105 +6 7869 7322 7323 7871 8105 8106 +6 7870 7323 7324 7325 7872 8106 +6 7871 7325 7873 8106 8107 8108 +6 7872 7325 7326 7874 8108 8109 +6 7873 7326 7327 7328 7875 8109 +6 7874 7328 7876 8109 8110 8111 +6 7875 7328 7329 7330 7877 8111 +6 7876 7330 7878 8111 8112 8113 +6 7877 7330 7331 7332 7879 8113 +6 7878 7332 7333 7880 8113 8114 +6 7879 7333 7881 8114 8115 8116 +6 7880 7333 7334 7335 7882 8116 +6 7881 7335 7336 7337 7883 8116 +6 7882 7337 7338 7884 8116 8117 +7 7883 7338 7339 7885 8117 8118 8119 +6 7884 7339 7340 7886 8119 8120 +6 7885 7340 7341 7887 8120 8121 +6 7886 7341 7342 7888 8121 8122 +6 7887 7342 7889 8122 8123 8124 +6 7888 7342 7343 7344 7890 8124 +6 7889 7344 7345 7891 8124 8125 +6 7890 7345 7346 7892 8125 8126 +6 7891 7346 7347 7893 8126 8127 +6 7892 7347 7348 7894 8127 8128 +6 7893 7348 7349 7895 8128 8129 +6 7894 7349 7896 8129 8130 8131 +6 7895 7349 7350 7351 7897 8131 +6 7896 7351 7352 7898 8131 8132 +7 7897 7352 7353 7354 7899 8132 8133 +5 7898 7354 7900 8133 8134 +7 7899 7354 7355 7356 7901 8134 8135 +6 7900 7356 7902 8135 8136 8137 +5 7901 7356 7357 7903 8137 +7 7902 7357 7904 8137 8138 8139 7905 +5 7903 7357 7358 7359 7905 +6 7904 7359 7906 8139 7903 8140 +6 7905 7359 7360 7362 7907 8140 +6 7906 7362 7908 8140 8141 8142 +6 7907 7362 7363 7364 7909 8142 +6 7908 7364 7910 8142 8143 8144 +6 7909 7364 7365 7366 7911 8144 +6 7910 7366 7372 7912 8144 8145 +6 7911 7372 7913 8145 8146 8147 +5 7912 7372 7373 7914 8147 +7 7913 7373 7374 7915 8147 8148 8149 +6 7914 7374 7916 8149 8150 8151 +6 7915 7374 7375 7377 7917 8151 +6 7916 7377 7918 7919 7920 8151 +6 7917 7377 7378 7379 7602 7919 +6 7918 7602 7917 7920 7921 7604 +6 7917 7919 7921 7922 7923 8151 +6 7920 7919 7922 7926 7927 7604 +6 7920 7921 7923 7924 7925 7926 +6 7920 7922 7924 8151 8152 8150 +6 7923 7922 7925 8152 8153 8154 +6 7924 7922 7926 8154 8155 8156 +6 7925 7922 7921 7927 8156 7929 +6 7926 7921 7604 7605 7928 7929 +6 7927 7605 7929 7930 7610 7606 +6 7927 7928 7930 8156 7926 8158 +6 7929 7928 7610 8158 7617 7611 +6 7810 7811 7932 8051 8346 7809 +6 7931 7811 7812 7933 7934 8051 +6 7932 7812 7934 7935 7936 7937 +6 7932 7933 7935 8051 8052 8053 +6 7934 7933 7936 8053 8054 8058 +6 7935 7933 7937 8060 8058 8061 +6 7936 7933 7812 7813 7938 8061 +6 7937 7813 7814 7939 8061 8062 +6 7938 7814 7815 7940 8062 8063 +6 7939 7815 7817 7818 7941 8063 +6 7940 7818 7819 7942 8063 8064 +6 7941 7819 7943 8064 8065 8066 +6 7942 7819 7820 7944 8066 8067 +6 7943 7820 7821 7822 7945 8067 +6 7944 7822 7946 8067 8068 8069 +6 7945 7822 7823 7947 8069 8070 +6 7946 7823 7824 7948 8070 8071 +6 7947 7824 7825 7949 8071 8072 +6 7948 7825 7827 7950 8072 8073 +6 7949 7827 7951 8073 8074 8075 +6 7950 7827 7828 7952 8075 8076 +6 7951 7828 7953 8076 8077 7954 +6 7952 7828 7829 7830 7833 7954 +6 7953 7833 7834 7955 8077 7952 +6 7954 7834 7956 8077 8078 8079 +6 7955 7834 7835 7836 7957 8079 +6 7956 7836 7837 7958 8079 8080 +6 7957 7837 7959 8080 8081 8082 +6 7958 7837 7838 7839 7960 8082 +6 7959 7839 7840 7961 8082 8083 +5 7960 7840 7847 8083 7848 +6 7847 7841 7842 7843 7844 7846 +6 7727 7728 7964 8467 8469 9765 +6 7963 7728 7965 8467 8488 8489 +6 7964 7728 7729 7247 7966 8489 +6 7965 7247 7248 7967 8489 8490 +6 7966 7248 7249 7968 8490 8491 +6 7967 7249 7250 7969 8491 8492 +6 7968 7250 7512 7514 7970 8492 +6 7969 7514 7971 8494 8492 8495 +6 7970 7514 7515 7972 8495 8496 +6 7971 7515 7973 8496 8497 7975 +6 7972 7515 7516 7519 7974 7975 +6 7973 7519 7975 7976 7977 7978 +6 7973 7974 7976 8497 7972 8498 +6 7975 7974 7977 8501 8498 7982 +6 7976 7974 7978 7980 7981 7982 +6 7977 7974 7519 7520 7979 7980 +6 7978 7520 7980 7989 7990 7522 +6 7978 7979 7977 7981 7988 7989 +6 7977 7980 7982 7983 7987 7988 +6 7977 7981 7983 7984 8501 7976 +6 7982 7981 7984 7985 7986 7987 +6 7982 7983 7985 8501 8502 8503 +6 7984 7983 7986 8503 8504 8505 +6 7985 7983 7987 8505 8506 8507 +6 7986 7983 7981 7988 8507 7994 +7 7987 7981 7980 7989 7992 7993 7994 +5 7988 7980 7979 7990 7992 +7 7989 7979 7522 7527 7991 7549 7992 +5 7990 7527 7528 7547 7549 +6 7990 7549 7550 7993 7988 7989 +6 7992 7550 7552 7988 7994 7995 +6 7988 7993 7995 8507 7987 8508 +6 7994 7993 7552 8508 7998 7996 +6 7552 7553 7559 7997 7998 7995 +6 7996 7559 7560 7998 7999 8000 +6 7996 7997 7999 8508 7995 8509 +6 7998 7997 8000 8509 8510 8511 +6 7999 7997 7560 7567 8001 8511 +6 8000 7567 7568 7571 8002 8511 +7 8001 7571 7572 8003 8511 8523 8512 +6 8002 7572 7573 8004 8523 8524 +7 8003 7573 7575 7578 8005 8521 8524 +7 8004 7578 8006 8520 8518 8521 8542 +5 8005 7578 7579 8007 8542 +6 8006 7579 8008 8611 8541 8542 +6 8007 7579 7580 7581 8009 8611 +6 8008 7581 7582 8010 8011 8611 +6 8009 7582 8011 8012 8013 7583 +8 8009 8010 8012 8610 8538 8539 8541 8611 +5 8011 8010 8013 8014 8610 +6 8012 8010 8014 7588 7583 7586 +7 8012 8013 7588 7730 8015 8609 8610 +6 8014 7730 7731 8016 8608 8609 +6 8015 7731 7735 8017 8612 8608 +6 8016 7735 7736 8018 8612 8613 +6 8017 7736 8019 8613 8614 8615 +6 8018 7736 7737 8020 8615 8616 +6 8019 7737 8021 8616 8619 8620 +6 8020 7737 7738 8022 8023 8620 +6 8021 7738 8023 8024 9767 7739 +6 8021 8022 8024 8025 8620 8621 +6 8023 8022 8025 8026 7743 9767 +6 8023 8024 8026 8621 8622 8029 +6 8025 8024 7743 7744 8027 8029 +6 8026 7744 8028 8029 8030 8031 +6 8027 7744 7745 7749 8031 8032 +6 8026 8027 8030 8622 8025 8623 +6 8029 8027 8031 8629 8623 8630 +6 8030 8027 8028 8032 8034 8630 +6 8031 8028 7749 8033 8034 8035 +6 8032 7749 7750 8035 8036 8037 +6 8031 8032 8035 8630 8631 8632 +6 8034 8032 8033 8036 8632 8633 +6 8035 8033 8037 7762 8636 8633 +6 8036 8033 7750 7760 7761 7762 +6 7785 7786 8039 8333 8334 8335 +6 8038 7786 7788 8040 8042 8335 +6 8039 7788 8041 8042 8043 8044 +6 8040 7788 8044 8045 8046 7789 +6 8039 8040 8043 8335 8336 8337 +6 8042 8040 8044 8337 8338 8342 +6 8043 8040 8041 8045 8342 8343 +6 8044 8041 8046 8343 8344 8047 +6 8045 8041 7789 7795 7796 8047 +6 8046 7796 8048 7807 8344 8045 +6 8047 7796 7807 7804 8049 7797 +6 7804 8048 7797 7803 7802 8050 +6 7802 8049 7797 7798 7800 7801 +6 7931 7932 7934 8052 8346 8347 +6 8051 7934 8053 8347 8348 8349 +6 8052 7934 7935 8054 8055 8349 +6 8053 7935 8055 8056 8057 8058 +6 8053 8054 8056 8349 8350 8351 +6 8055 8054 8057 8351 8352 8353 +6 8056 8054 8058 8059 8353 8354 +6 8057 8054 8059 8060 7936 7935 +6 8057 8058 8060 8354 8355 8356 +6 8059 8058 7936 8061 8356 8357 +6 8060 7936 7937 7938 8062 8357 +6 8061 7938 7939 8063 8357 8359 +6 8062 7939 7940 7941 8064 8359 +6 8063 7941 7942 8065 8360 8359 +6 8064 7942 8066 8360 8361 8362 +6 8065 7942 7943 8067 8362 8363 +6 8066 7943 7944 7945 8068 8363 +6 8067 7945 8069 8363 8364 8365 +6 8068 7945 7946 8070 8365 8366 +6 8069 7946 7947 8071 8366 8367 +6 8070 7947 7948 8072 8367 8368 +6 8071 7948 7949 8073 8368 8369 +6 8072 7949 7950 8074 8369 8370 +6 8073 7950 8075 8370 8371 8372 +6 8074 7950 7951 8076 8372 8373 +6 8075 7951 7952 8077 8373 8374 +6 8076 7952 7954 7955 8078 8374 +6 8077 7955 8079 8376 8374 8377 +6 8078 7955 7956 7957 8080 8377 +6 8079 7957 7958 8081 8377 8378 +6 8080 7958 8082 8210 8378 8379 +6 8081 7958 7959 7960 8083 8210 +7 8082 7960 7961 7848 7849 8084 8210 +6 8083 7849 7850 8085 8210 8211 +6 8084 7850 7851 8086 8211 8212 +6 8085 7851 8087 8212 8213 8214 +6 8086 7851 7852 7853 8088 8214 +6 8087 7853 8089 8214 8215 8216 +6 8088 7853 7854 8090 8216 8091 +6 8089 7854 7855 7856 7857 8091 +5 8090 7857 8092 8216 8089 +7 8091 7857 7858 8093 8216 8217 8218 +5 8092 7858 8094 8218 8219 +6 8093 7858 7859 8095 8219 8220 +6 8094 7859 7860 7861 8096 8220 +6 8095 7861 8097 8220 8221 8222 +6 8096 7861 7862 8098 8222 8223 +6 8097 7862 7863 8099 8223 8224 +6 8098 7863 7864 8100 8224 8225 +6 8099 7864 7865 8101 8225 8226 +6 8100 7865 7866 8102 8226 8227 +6 8101 7866 7867 8103 8227 8228 +6 8102 7867 7868 7869 8104 8228 +6 8103 7869 8105 8228 8229 8230 +6 8104 7869 7870 8106 8230 8231 +6 8105 7870 7871 7872 8107 8231 +6 8106 7872 8108 8231 8232 8233 +6 8107 7872 7873 8109 8233 8234 +6 8108 7873 7874 7875 8110 8234 +6 8109 7875 8111 8234 8235 8236 +6 8110 7875 7876 7877 8112 8236 +6 8111 7877 8113 8236 8237 8238 +6 8112 7877 7878 7879 8114 8238 +6 8113 7879 7880 8115 8238 8239 +6 8114 7880 8116 8239 8240 8117 +6 8115 7880 7881 7882 7883 8117 +6 8116 7883 7884 8118 8240 8115 +6 8117 7884 8119 8240 8241 8242 +5 8118 7884 7885 8120 8242 +6 8119 7885 7886 8121 8242 8243 +6 8120 7886 7887 8122 8243 8244 +6 8121 7887 7888 8123 8244 8245 +6 8122 7888 8124 8245 8246 8247 +6 8123 7888 7889 7890 8125 8247 +6 8124 7890 7891 8126 8247 8248 +6 8125 7891 7892 8127 8248 8249 +6 8126 7892 7893 8128 8249 8250 +6 8127 7893 7894 8129 8250 8251 +6 8128 7894 7895 8130 8251 8252 +6 8129 7895 8131 8252 8253 8254 +6 8130 7895 7896 7897 8132 8254 +6 8131 7897 7898 8133 8254 8255 +5 8132 7898 7899 8134 8255 +7 8133 7899 7900 8135 8255 8256 8257 +5 8134 7900 7901 8136 8257 +7 8135 7901 8137 8257 8258 8259 8260 +6 8136 7901 7902 7903 8138 8260 +6 8137 7903 8139 8260 8261 8262 +6 8138 7903 7905 8140 8262 8263 +6 8139 7905 7906 7907 8141 8263 +6 8140 7907 8142 8263 8264 8265 +6 8141 7907 7908 7909 8143 8265 +6 8142 7909 8144 8265 8266 8267 +6 8143 7909 7910 7911 8145 8267 +6 8144 7911 7912 8146 8267 8268 +6 8145 7912 8147 8268 8269 8270 +6 8146 7912 7913 7914 8148 8270 +6 8147 7914 8149 8270 8271 8272 +6 8148 7914 7915 8150 8152 8272 +5 8149 7915 8151 8152 7923 +6 8150 7915 7916 7917 7920 7923 +7 8149 8150 7923 7924 8153 8272 8273 +5 8152 7924 8154 8273 8274 +7 8153 7924 7925 8155 8274 8275 8276 +6 8154 7925 8156 8157 8276 8277 +7 8155 7925 8157 7926 7929 8158 7618 +6 8155 8156 7618 7619 8159 8277 +5 8156 7929 7930 7617 7618 +6 8157 7619 8160 8277 8278 8279 +6 8159 7619 7620 8161 8279 8280 +7 8160 7620 7621 8162 8280 8281 8282 +5 8161 7621 8163 8282 8283 +7 8162 7621 7622 8164 8283 8284 8165 +6 8163 7622 7623 7624 7625 8165 +7 8164 7625 7626 7628 8166 8284 8163 +6 8165 7628 7629 7631 8167 8284 +6 8166 7631 8168 8169 8284 8283 +6 8167 7631 8169 8170 8171 7632 +6 8167 8168 8170 8283 8285 8286 +6 8169 8168 8171 8286 8287 8288 +6 8170 8168 7632 8172 8173 8288 +6 8171 7632 8173 8174 7634 7633 +6 8171 8172 8174 8288 8289 8290 +6 8173 8172 7634 8175 8290 8291 +6 8174 7634 7635 7637 8176 8291 +6 8175 7637 7639 8177 8291 8292 +6 8176 7639 8178 8292 8293 8294 +6 8177 7639 7640 8179 8294 8295 +6 8178 7640 8180 8295 8296 8297 +6 8179 7640 7641 8181 8297 8298 +6 8180 7641 8182 8308 8298 8309 +6 8181 7641 7642 8183 8184 8309 +6 8182 7642 8184 7645 7644 7643 +6 8182 8183 7645 8185 8309 8310 +6 8184 7645 7646 8186 8310 8311 +7 8185 7646 7647 7648 8187 8311 8312 +6 8186 7648 7649 8188 8312 8313 +6 8187 7649 8189 8313 8314 8315 +6 8188 7649 7650 8190 8315 8316 +6 8189 7650 7651 8191 8316 8201 +6 8190 7651 8192 8198 8200 8201 +6 8191 7651 7652 8193 8198 8194 +6 8192 7652 7653 7658 7659 8194 +6 8193 7659 8195 8197 8198 8192 +6 8194 7659 7660 7663 8196 8197 +6 8195 7663 8197 8209 8205 7664 +6 8195 8196 8194 8198 8199 8205 +6 8194 8197 8199 8200 8191 8192 +6 8198 8197 8200 8203 8204 8205 +6 8198 8199 8191 8201 8202 8203 +6 8191 8200 8202 8316 8190 8317 +6 8201 8200 8203 8317 8318 8319 +6 8202 8200 8199 8204 8206 8319 +6 8203 8199 8205 8206 7700 8207 +7 8204 8199 8207 8208 8209 8196 8197 +5 8203 8204 7700 8319 7701 +7 7700 8204 8205 7699 7670 7668 8208 +6 7668 8207 8205 8209 7665 7666 +5 8208 8205 8196 7664 7665 +6 8081 8082 8083 8084 8211 8379 +5 8210 8084 8085 8212 8379 +6 8211 8085 8086 8213 8379 8380 +6 8212 8086 8214 8380 8381 8382 +6 8213 8086 8087 8088 8215 8382 +6 8214 8088 8216 8382 8383 8217 +6 8215 8088 8089 8091 8092 8217 +6 8216 8092 8218 8383 8215 8384 +6 8217 8092 8093 8219 8384 8385 +6 8218 8093 8094 8220 8385 8386 +6 8219 8094 8095 8096 8221 8386 +5 8220 8096 8222 8386 8387 +6 8221 8096 8097 8223 8387 8388 +6 8222 8097 8098 8224 8388 8389 +6 8223 8098 8099 8225 8389 8390 +6 8224 8099 8100 8226 8390 8391 +6 8225 8100 8101 8227 8391 8392 +6 8226 8101 8102 8228 8392 8393 +6 8227 8102 8103 8104 8229 8393 +6 8228 8104 8230 8393 8394 8395 +6 8229 8104 8105 8231 8395 8396 +6 8230 8105 8106 8107 8232 8396 +6 8231 8107 8233 8396 8397 8398 +6 8232 8107 8108 8234 8398 8399 +6 8233 8108 8109 8110 8235 8399 +6 8234 8110 8236 8399 8400 8401 +6 8235 8110 8111 8112 8237 8401 +6 8236 8112 8238 8401 8402 8403 +6 8237 8112 8113 8114 8239 8403 +6 8238 8114 8115 8240 8403 8404 +6 8239 8115 8117 8118 8241 8404 +6 8240 8118 8242 8404 8405 8406 +6 8241 8118 8119 8120 8243 8406 +6 8242 8120 8121 8244 8406 8407 +6 8243 8121 8122 8245 8407 8408 +6 8244 8122 8123 8246 8408 8409 +6 8245 8123 8247 8409 8410 8411 +6 8246 8123 8124 8125 8248 8411 +6 8247 8125 8126 8249 8411 8412 +6 8248 8126 8127 8250 8412 8413 +6 8249 8127 8128 8251 8413 8414 +6 8250 8128 8129 8252 8414 8415 +6 8251 8129 8130 8253 8415 8416 +6 8252 8130 8254 8416 8417 8418 +6 8253 8130 8131 8132 8255 8418 +7 8254 8132 8133 8134 8256 8418 8419 +5 8255 8134 8257 8419 8420 +7 8256 8134 8135 8136 8258 8420 8421 +5 8257 8136 8259 8421 8422 +6 8258 8136 8260 8422 8423 8261 +5 8259 8136 8137 8138 8261 +6 8260 8138 8262 8423 8259 8424 +6 8261 8138 8139 8263 8424 8425 +6 8262 8139 8140 8141 8264 8425 +6 8263 8141 8265 8425 8426 8427 +6 8264 8141 8142 8143 8266 8427 +6 8265 8143 8267 8427 8428 8429 +7 8266 8143 8144 8145 8268 8429 8430 +6 8267 8145 8146 8269 8430 8431 +6 8268 8146 8270 8431 8432 8433 +6 8269 8146 8147 8148 8271 8433 +6 8270 8148 8272 8433 8434 8435 +6 8271 8148 8149 8152 8273 8435 +5 8272 8152 8153 8274 8435 +7 8273 8153 8154 8275 8435 8436 8437 +6 8274 8154 8276 8437 8438 8439 +6 8275 8154 8155 8277 8439 8278 +5 8276 8155 8157 8159 8278 +6 8277 8159 8279 8439 8276 8440 +6 8278 8159 8160 8280 8440 8441 +7 8279 8160 8161 8281 8441 8442 8446 +6 8280 8161 8282 8446 8447 8285 +5 8281 8161 8162 8283 8285 +7 8282 8162 8163 8284 8167 8169 8285 +5 8283 8163 8165 8166 8167 +6 8283 8169 8286 8447 8281 8282 +6 8285 8169 8170 8287 8447 8448 +6 8286 8170 8288 8448 8450 8451 +6 8287 8170 8171 8173 8289 8451 +6 8288 8173 8290 8451 8452 8453 +6 8289 8173 8174 8291 8453 8454 +6 8290 8174 8175 8176 8292 8454 +6 8291 8176 8177 8293 8454 8455 +6 8292 8177 8294 8455 8456 8457 +6 8293 8177 8178 8295 8457 8458 +6 8294 8178 8179 8296 8458 8459 +6 8295 8179 8297 8462 8459 8300 +6 8296 8179 8180 8298 8299 8300 +6 8297 8180 8299 8308 8306 8181 +6 8297 8298 8300 8301 8302 8306 +6 8297 8299 8301 8462 8296 8463 +6 8300 8299 8302 8303 8463 8464 +6 8301 8299 8303 8304 8305 8306 +6 8301 8302 8304 8464 8465 8466 +6 8303 8302 8305 8466 8467 8468 +6 8304 8302 8306 8307 8471 8468 +6 8305 8302 8299 8307 8308 8298 +6 8305 8306 8308 8471 8472 8473 +6 8307 8306 8298 8181 8309 8473 +6 8308 8181 8182 8184 8310 8473 +6 8309 8184 8185 8311 8473 8474 +6 8310 8185 8186 8312 8474 8475 +5 8311 8186 8187 8313 8475 +6 8312 8187 8188 8314 8475 8476 +6 8313 8188 8315 8479 8476 8480 +6 8314 8188 8189 8316 8480 8481 +6 8315 8189 8190 8201 8317 8481 +5 8316 8201 8202 8318 8481 +6 8317 8202 8319 8481 8482 7709 +7 8318 8202 8203 8206 7701 7708 7709 +6 7766 7767 8321 8322 8854 8855 +6 8320 7767 7768 8322 8323 7770 +7 8320 8321 8323 8855 8856 8857 8324 +5 8322 8321 7770 7772 8324 +6 8323 7772 8325 8857 8322 8858 +6 8324 7772 7773 8326 8858 8329 +6 8325 7773 7778 8327 8328 8329 +6 8326 7778 7779 7780 7781 8328 +6 8327 7781 8326 8329 8330 7782 +6 8326 8328 8330 8858 8325 8859 +6 8329 8328 7782 7783 8331 8859 +6 8330 7783 7784 8332 8859 8860 +6 8331 7784 8333 8866 8863 8860 +6 8332 7784 7785 8038 8334 8866 +6 8333 8038 8335 8867 8866 8868 +6 8334 8038 8039 8042 8336 8868 +6 8335 8042 8337 8868 8869 8870 +6 8336 8042 8043 8338 8339 8870 +6 8337 8043 8339 8340 8341 8342 +6 8337 8338 8340 8870 8871 8875 +6 8339 8338 8341 8875 8876 8348 +6 8340 8338 8342 8348 8347 8877 +6 8341 8338 8043 8044 8343 8877 +6 8342 8044 8045 8344 8345 8877 +6 8343 8045 8345 7808 7807 8047 +6 8343 8344 7808 7809 8346 8877 +6 8345 7809 7931 8051 8347 8877 +6 8346 8051 8052 8348 8341 8877 +6 8347 8052 8349 8876 8340 8341 +6 8348 8052 8053 8055 8350 8876 +6 8349 8055 8351 8903 8876 8902 +6 8350 8055 8056 8352 8902 8904 +6 8351 8056 8353 8904 8905 8906 +6 8352 8056 8057 8354 8906 8907 +6 8353 8057 8059 8355 8907 8908 +6 8354 8059 8356 8908 8909 8910 +6 8355 8059 8060 8357 8358 8910 +6 8356 8060 8061 8062 8358 8359 +6 8356 8357 8359 8360 8910 8911 +6 8358 8357 8062 8063 8360 8064 +6 8358 8359 8064 8065 8361 8911 +6 8360 8065 8362 8913 8911 8914 +6 8361 8065 8066 8363 8914 8915 +6 8362 8066 8067 8068 8364 8915 +6 8363 8068 8365 8917 8915 8918 +6 8364 8068 8069 8366 8918 8919 +6 8365 8069 8070 8367 8919 8920 +6 8366 8070 8071 8368 8920 8921 +6 8367 8071 8072 8369 8921 8922 +6 8368 8072 8073 8370 8922 8923 +6 8369 8073 8074 8371 8923 8924 +6 8370 8074 8372 8924 8925 8926 +6 8371 8074 8075 8373 8926 8927 +6 8372 8075 8076 8374 8375 8927 +6 8373 8076 8077 8375 8376 8078 +6 8373 8374 8376 8927 8928 8929 +6 8375 8374 8078 8377 8929 8930 +6 8376 8078 8079 8080 8378 8930 +6 8377 8080 8081 8379 8930 8380 +6 8378 8081 8210 8211 8212 8380 +7 8379 8212 8213 8381 8930 8378 8931 +5 8380 8213 8382 8931 8932 +7 8381 8213 8214 8215 8383 8744 8932 +6 8382 8215 8217 8384 8642 8744 +6 8383 8217 8218 8385 8642 8643 +6 8384 8218 8219 8386 8643 8644 +6 8385 8219 8220 8221 8387 8644 +7 8386 8221 8222 8388 8644 8645 8646 +6 8387 8222 8223 8389 8646 8647 +6 8388 8223 8224 8390 8647 8648 +6 8389 8224 8225 8391 8648 8649 +7 8390 8225 8226 8392 8649 8650 8651 +6 8391 8226 8227 8393 8651 8652 +6 8392 8227 8228 8229 8394 8652 +6 8393 8229 8395 8652 8653 8654 +6 8394 8229 8230 8396 8654 8655 +6 8395 8230 8231 8232 8397 8655 +5 8396 8232 8398 8655 8656 +6 8397 8232 8233 8399 8656 8657 +7 8398 8233 8234 8235 8400 8657 8658 +5 8399 8235 8401 8658 8659 +7 8400 8235 8236 8237 8402 8659 8660 +5 8401 8237 8403 8660 8661 +6 8402 8237 8238 8239 8404 8661 +6 8403 8239 8240 8241 8405 8661 +6 8404 8241 8406 8661 8662 8663 +6 8405 8241 8242 8243 8407 8663 +6 8406 8243 8244 8408 8663 8664 +7 8407 8244 8245 8409 8664 8665 8666 +6 8408 8245 8246 8410 8666 8667 +6 8409 8246 8411 8667 8668 8669 +6 8410 8246 8247 8248 8412 8669 +6 8411 8248 8249 8413 8669 8670 +6 8412 8249 8250 8414 8670 8671 +6 8413 8250 8251 8415 8671 8672 +6 8414 8251 8252 8416 8672 8673 +6 8415 8252 8253 8417 8673 8674 +6 8416 8253 8418 8674 8675 8676 +6 8417 8253 8254 8255 8419 8676 +6 8418 8255 8256 8420 8676 8677 +6 8419 8256 8257 8421 8677 8678 +6 8420 8257 8258 8422 8678 8679 +6 8421 8258 8259 8423 8679 8680 +6 8422 8259 8261 8424 8680 8681 +7 8423 8261 8262 8425 8681 8682 8683 +6 8424 8262 8263 8264 8426 8683 +6 8425 8264 8427 8683 8684 8688 +6 8426 8264 8265 8266 8428 8688 +6 8427 8266 8429 8688 8689 8690 +6 8428 8266 8267 8430 8690 8691 +5 8429 8267 8268 8431 8691 +6 8430 8268 8269 8432 8543 8691 +6 8431 8269 8433 8543 8544 8545 +6 8432 8269 8270 8271 8434 8545 +6 8433 8271 8435 8545 8546 8547 +7 8434 8271 8272 8273 8274 8436 8547 +6 8435 8274 8437 8547 8548 8549 +6 8436 8274 8275 8438 8549 8550 +6 8437 8275 8439 8550 8551 8440 +5 8438 8275 8276 8278 8440 +7 8439 8278 8279 8441 8551 8438 8552 +6 8440 8279 8280 8442 8443 8552 +6 8441 8280 8443 8444 8445 8446 +6 8441 8442 8444 8552 8553 8554 +6 8443 8442 8445 8554 8555 8556 +7 8444 8442 8446 8447 8448 8449 8556 +5 8445 8442 8280 8281 8447 +6 8446 8281 8285 8286 8448 8445 +6 8447 8286 8287 8445 8449 8450 +5 8445 8448 8450 8556 8557 +6 8449 8448 8287 8451 8557 8558 +7 8450 8287 8288 8289 8452 8558 8559 +6 8451 8289 8453 8559 8560 8561 +6 8452 8289 8290 8454 8561 8562 +6 8453 8290 8291 8292 8455 8562 +6 8454 8292 8293 8456 8562 8563 +6 8455 8293 8457 8563 8564 8565 +6 8456 8293 8294 8458 8565 8566 +6 8457 8294 8295 8459 8460 8566 +6 8458 8295 8460 8461 8462 8296 +6 8458 8459 8461 8566 8567 8568 +6 8460 8459 8462 8568 8569 8570 +6 8461 8459 8296 8300 8463 8570 +6 8462 8300 8301 8464 8570 8571 +6 8463 8301 8303 8465 8571 8572 +6 8464 8303 8466 8572 8573 8574 +6 8465 8303 8304 8467 8574 8488 +7 8466 8304 8468 8469 7963 7964 8488 +6 8467 8304 8469 8470 8471 8305 +6 8467 8468 8470 7963 9764 9765 +7 8469 8468 8471 9095 8486 9764 8487 +6 8470 8468 8305 8307 8472 9095 +6 8471 8307 8473 8477 9095 8474 +6 8472 8307 8308 8309 8310 8474 +6 8473 8310 8311 8475 8477 8472 +6 8474 8311 8312 8313 8476 8477 +6 8475 8313 8477 8478 8479 8314 +7 8475 8476 8478 8486 9095 8472 8474 +6 8477 8476 8479 8484 8485 8486 +6 8478 8476 8314 8480 8484 8483 +6 8479 8314 8315 8481 8483 8482 +6 8480 8315 8316 8317 8318 8482 +6 8481 8318 7709 7710 8483 8480 +7 8482 7710 7711 7714 8484 8479 8480 +5 8483 7714 8485 8478 8479 +6 8484 7714 7715 8478 8486 8487 +6 8478 8485 8487 8470 9095 8477 +6 8486 8485 9766 9764 8470 7715 +5 8467 7964 8489 8574 8466 +7 8488 7964 7965 7966 8490 8574 8575 +5 8489 7966 7967 8491 8575 +7 8490 7967 7968 8492 8493 8575 8576 +6 8491 7968 8493 8494 7970 7969 +5 8491 8492 8494 8576 8577 +6 8493 8492 7970 8495 8577 8578 +6 8494 7970 7971 8496 8578 8579 +6 8495 7971 7972 8497 8579 8580 +6 8496 7972 7975 8498 8499 8580 +6 8497 7975 8499 8500 8501 7976 +6 8497 8498 8500 8580 8581 8582 +6 8499 8498 8501 8582 8583 8502 +6 8500 8498 7976 7982 7984 8502 +6 8501 7984 8503 8583 8500 8584 +6 8502 7984 7985 8504 8587 8584 +6 8503 7985 8505 8528 8587 8527 +6 8504 7985 7986 8506 8527 8589 +6 8505 7986 8507 8589 8514 8590 +6 8506 7986 7987 7994 8508 8590 +6 8507 7994 7995 7998 8509 8590 +6 8508 7998 7999 8510 8514 8590 +6 8509 7999 8511 8512 8513 8514 +6 8510 7999 8000 8001 8002 8512 +6 8510 8511 8513 8522 8523 8002 +6 8510 8512 8514 8515 8516 8522 +7 8510 8513 8515 8589 8506 8590 8509 +6 8514 8513 8516 8517 8527 8589 +6 8515 8513 8517 8518 8521 8522 +6 8515 8516 8518 8519 8525 8527 +6 8517 8516 8519 8520 8005 8521 +6 8517 8518 8520 8525 8526 8532 +6 8519 8518 8005 8542 8540 8532 +6 8005 8518 8004 8516 8522 8524 +6 8521 8516 8513 8512 8523 8524 +5 8522 8512 8002 8003 8524 +5 8523 8003 8522 8521 8004 +6 8517 8519 8526 8527 8528 8529 +6 8525 8519 8529 8530 8531 8532 +7 8517 8525 8528 8504 8505 8589 8515 +5 8527 8525 8529 8587 8504 +6 8528 8525 8526 8530 8588 8587 +6 8529 8526 8531 8603 8588 8604 +6 8530 8526 8532 8533 8534 8604 +6 8531 8526 8533 8520 8540 8519 +6 8531 8532 8534 8535 8539 8540 +6 8531 8533 8535 8536 8604 8605 +6 8534 8533 8536 8537 8538 8539 +6 8534 8535 8537 8605 8606 8607 +6 8536 8535 8538 8607 8608 8609 +6 8537 8535 8539 8609 8610 8011 +6 8538 8535 8533 8540 8541 8011 +6 8539 8533 8541 8542 8520 8532 +6 8539 8540 8542 8011 8611 8007 +6 8541 8540 8520 8007 8006 8005 +6 8431 8432 8544 8691 8692 8693 +6 8543 8432 8545 8693 8694 8695 +6 8544 8432 8433 8434 8546 8695 +6 8545 8434 8547 8695 8696 8548 +5 8546 8434 8435 8436 8548 +6 8547 8436 8549 8696 8546 8697 +6 8548 8436 8437 8550 8697 8698 +6 8549 8437 8438 8551 8698 8699 +6 8550 8438 8440 8552 8699 8553 +5 8551 8440 8441 8443 8553 +7 8552 8443 8554 8699 8551 8700 8701 +6 8553 8443 8444 8555 8701 8702 +6 8554 8444 8556 8702 8703 8704 +6 8555 8444 8445 8449 8557 8704 +6 8556 8449 8450 8558 8704 8705 +6 8557 8450 8451 8559 8705 8706 +6 8558 8451 8452 8560 8706 8707 +6 8559 8452 8561 8707 8708 8709 +5 8560 8452 8453 8562 8709 +6 8561 8453 8454 8455 8563 8709 +6 8562 8455 8456 8564 8709 8710 +6 8563 8456 8565 8710 8711 8712 +6 8564 8456 8457 8566 8712 8713 +7 8565 8457 8458 8460 8567 8713 8714 +5 8566 8460 8568 8714 8715 +6 8567 8460 8461 8569 8715 8716 +6 8568 8461 8570 8716 8717 8718 +6 8569 8461 8462 8463 8571 8718 +7 8570 8463 8464 8572 8591 8593 8718 +5 8571 8464 8465 8573 8591 +7 8572 8465 8574 8575 8576 8577 8591 +6 8573 8465 8466 8488 8489 8575 +6 8574 8489 8490 8491 8576 8573 +5 8575 8491 8493 8577 8573 +7 8576 8493 8494 8578 8573 8591 8592 +6 8577 8494 8495 8579 8595 8592 +6 8578 8495 8496 8580 8595 8596 +6 8579 8496 8497 8499 8581 8596 +6 8580 8499 8582 8596 8597 8598 +6 8581 8499 8500 8583 8598 8599 +6 8582 8500 8502 8584 8585 8599 +6 8583 8502 8585 8586 8587 8503 +6 8583 8584 8586 8599 8600 8601 +6 8585 8584 8587 8588 8601 8602 +7 8586 8584 8588 8529 8528 8504 8503 +6 8586 8587 8529 8602 8603 8530 +5 8527 8505 8506 8514 8515 +5 8514 8506 8507 8509 8508 +6 8573 8577 8592 8572 8571 8593 +6 8591 8577 8593 8594 8595 8578 +5 8571 8591 8592 8594 8718 +7 8593 8592 8595 8718 8717 8719 8720 +6 8594 8592 8578 8579 8596 8720 +7 8595 8579 8580 8581 8597 8720 8721 +6 8596 8581 8598 8721 8722 8723 +6 8597 8581 8582 8599 8723 8724 +6 8598 8582 8583 8585 8600 8724 +6 8599 8585 8601 8724 8725 8726 +6 8600 8585 8586 8602 8726 8727 +6 8601 8586 8588 8603 8727 8728 +5 8602 8588 8530 8604 8728 +6 8603 8530 8531 8534 8605 8728 +6 8604 8534 8536 8606 8728 8729 +6 8605 8536 8607 8729 8732 8733 +6 8606 8536 8537 8608 8612 8733 +6 8607 8537 8609 8612 8016 8015 +6 8608 8537 8538 8610 8015 8014 +5 8609 8538 8011 8014 8012 +5 8011 8541 8009 8008 8007 +6 8607 8608 8016 8017 8613 8733 +6 8612 8017 8018 8614 8733 8734 +6 8613 8018 8615 8734 8735 8736 +6 8614 8018 8019 8616 8617 8736 +6 8615 8019 8020 8617 8618 8619 +6 8615 8616 8618 8736 8737 8738 +6 8617 8616 8619 8738 8739 8740 +6 8618 8616 8020 8620 8740 8743 +6 8619 8020 8021 8023 8621 8743 +6 8620 8023 8025 8622 8625 8743 +6 8621 8025 8029 8623 8624 8625 +6 8622 8029 8624 8628 8629 8030 +6 8622 8623 8625 8626 8627 8628 +6 8622 8624 8626 8742 8743 8621 +6 8625 8624 8627 8838 8742 8839 +6 8626 8624 8628 8839 8840 8841 +6 8627 8624 8623 8629 8841 8842 +6 8628 8623 8030 8630 8842 8843 +6 8629 8030 8031 8034 8631 8843 +6 8630 8034 8632 8843 8844 8845 +6 8631 8034 8035 8633 8634 8845 +6 8632 8035 8634 8635 8636 8036 +6 8632 8633 8635 8845 8846 8847 +6 8634 8633 8636 8637 8638 8847 +6 8635 8633 8637 8641 7762 8036 +6 8635 8636 8638 8639 8640 8641 +6 8635 8637 8639 8847 8849 8850 +6 8638 8637 8640 8850 8851 8852 +6 8639 8637 8641 8852 8853 7763 +5 8640 8637 8636 7762 7763 +6 8383 8384 8643 8744 8745 8746 +6 8642 8384 8385 8644 8746 8747 +6 8643 8385 8386 8387 8645 8747 +6 8644 8387 8646 8747 8748 8749 +6 8645 8387 8388 8647 8749 8750 +6 8646 8388 8389 8648 8750 8751 +6 8647 8389 8390 8649 8751 8752 +6 8648 8390 8391 8650 8752 8753 +6 8649 8391 8651 8753 8754 8755 +5 8650 8391 8392 8652 8755 +6 8651 8392 8393 8394 8653 8755 +6 8652 8394 8654 8755 8756 8757 +6 8653 8394 8395 8655 8757 8758 +6 8654 8395 8396 8397 8656 8758 +6 8655 8397 8398 8657 8758 8759 +7 8656 8398 8399 8658 8759 8760 8761 +5 8657 8399 8400 8659 8761 +7 8658 8400 8401 8660 8761 8762 8763 +5 8659 8401 8402 8661 8763 +8 8660 8402 8403 8404 8405 8662 8763 8764 +5 8661 8405 8663 8764 8765 +6 8662 8405 8406 8407 8664 8765 +6 8663 8407 8408 8665 8765 8766 +6 8664 8408 8666 8766 8767 8768 +5 8665 8408 8409 8667 8768 +6 8666 8409 8410 8668 8768 8769 +6 8667 8410 8669 8769 8770 8771 +6 8668 8410 8411 8412 8670 8771 +6 8669 8412 8413 8671 8771 8772 +6 8670 8413 8414 8672 8772 8773 +6 8671 8414 8415 8673 8773 8774 +6 8672 8415 8416 8674 8774 8775 +6 8673 8416 8417 8675 8775 8776 +6 8674 8417 8676 8776 8777 8778 +6 8675 8417 8418 8419 8677 8778 +6 8676 8419 8420 8678 8778 8779 +6 8677 8420 8421 8679 8779 8780 +6 8678 8421 8422 8680 8780 8781 +6 8679 8422 8423 8681 8781 8782 +6 8680 8423 8424 8682 8782 8783 +6 8681 8424 8683 8783 8784 8685 +6 8682 8424 8425 8426 8684 8685 +6 8683 8426 8685 8686 8687 8688 +5 8683 8684 8686 8784 8682 +6 8685 8684 8687 8784 8785 8786 +6 8686 8684 8688 8786 8787 8788 +7 8687 8684 8426 8427 8428 8689 8788 +5 8688 8428 8690 8788 8789 +6 8689 8428 8429 8691 8789 8790 +7 8690 8429 8430 8431 8543 8692 8790 +6 8691 8543 8693 8790 8791 8792 +5 8692 8543 8544 8694 8792 +7 8693 8544 8695 8792 8793 8794 8795 +6 8694 8544 8545 8546 8696 8795 +6 8695 8546 8548 8697 8795 8796 +7 8696 8548 8549 8698 8796 8797 8798 +6 8697 8549 8550 8699 8798 8799 +6 8698 8550 8551 8553 8700 8799 +6 8699 8553 8701 8799 8800 8801 +6 8700 8553 8554 8702 8801 8804 +6 8701 8554 8555 8703 8804 8805 +6 8702 8555 8704 8805 8806 8807 +6 8703 8555 8556 8557 8705 8807 +6 8704 8557 8558 8706 8807 8808 +6 8705 8558 8559 8707 8808 8809 +6 8706 8559 8560 8708 8809 8810 +6 8707 8560 8709 8810 8811 8812 +7 8708 8560 8561 8562 8563 8710 8812 +5 8709 8563 8564 8711 8812 +7 8710 8564 8712 8812 8813 8814 8815 +6 8711 8564 8565 8713 8815 8816 +6 8712 8565 8566 8714 8816 8817 +5 8713 8566 8567 8715 8817 +7 8714 8567 8568 8716 8817 8818 8819 +6 8715 8568 8569 8717 8819 8820 +6 8716 8569 8718 8594 8719 8820 +6 8717 8569 8570 8571 8593 8594 +6 8717 8594 8720 8820 8821 8721 +5 8719 8594 8595 8596 8721 +6 8720 8596 8597 8722 8821 8719 +6 8721 8597 8723 8821 8822 8823 +5 8722 8597 8598 8724 8823 +6 8723 8598 8599 8600 8725 8823 +6 8724 8600 8726 8823 8824 8825 +6 8725 8600 8601 8727 8825 8826 +6 8726 8601 8602 8728 8826 8730 +7 8727 8602 8603 8604 8605 8729 8730 +6 8728 8605 8606 8730 8731 8732 +5 8728 8729 8731 8826 8727 +6 8730 8729 8732 8826 8828 8829 +6 8731 8729 8606 8733 8829 8830 +7 8732 8606 8607 8612 8613 8734 8830 +6 8733 8613 8614 8735 8831 8830 +6 8734 8614 8736 8831 8832 8737 +5 8735 8614 8615 8617 8737 +6 8736 8617 8738 8832 8735 8833 +6 8737 8617 8618 8739 8833 8834 +6 8738 8618 8740 8741 8834 8835 +6 8739 8618 8619 8741 8742 8743 +6 8739 8740 8742 8835 8836 8837 +7 8741 8740 8743 8625 8837 8838 8626 +6 8742 8740 8625 8621 8620 8619 +6 8382 8383 8642 8745 8932 8933 +5 8744 8642 8746 8933 8934 +6 8745 8642 8643 8747 8934 8935 +6 8746 8643 8644 8645 8748 8935 +6 8747 8645 8749 8935 8936 8937 +6 8748 8645 8646 8750 8937 8938 +6 8749 8646 8647 8751 8938 8939 +6 8750 8647 8648 8752 8939 8940 +6 8751 8648 8649 8753 8940 8941 +6 8752 8649 8650 8754 8941 8942 +6 8753 8650 8755 8942 8943 8944 +7 8754 8650 8651 8652 8653 8756 8944 +5 8755 8653 8757 8944 8945 +6 8756 8653 8654 8758 8945 8946 +6 8757 8654 8655 8656 8759 8946 +7 8758 8656 8657 8760 8946 8947 8948 +5 8759 8657 8761 8948 8949 +6 8760 8657 8658 8659 8762 8949 +6 8761 8659 8763 8949 8950 8951 +6 8762 8659 8660 8661 8764 8951 +5 8763 8661 8662 8765 8951 +7 8764 8662 8663 8664 8766 8951 8952 +6 8765 8664 8665 8767 8952 8953 +6 8766 8665 8768 8953 8954 8955 +6 8767 8665 8666 8667 8769 8955 +6 8768 8667 8668 8770 8955 8956 +6 8769 8668 8771 8956 8957 8958 +6 8770 8668 8669 8670 8772 8958 +6 8771 8670 8671 8773 8958 8959 +6 8772 8671 8672 8774 8959 8960 +6 8773 8672 8673 8775 8960 8961 +6 8774 8673 8674 8776 8961 8962 +6 8775 8674 8675 8777 8962 8963 +6 8776 8675 8778 8963 8964 8965 +6 8777 8675 8676 8677 8779 8965 +6 8778 8677 8678 8780 8965 8966 +6 8779 8678 8679 8781 8966 8967 +6 8780 8679 8680 8782 8967 8968 +6 8781 8680 8681 8783 8968 8969 +6 8782 8681 8682 8784 8969 8970 +6 8783 8682 8685 8686 8785 8970 +6 8784 8686 8786 8970 8971 8972 +6 8785 8686 8687 8787 8972 8973 +6 8786 8687 8788 8973 8974 8975 +6 8787 8687 8688 8689 8789 8975 +6 8788 8689 8690 8790 8975 8976 +6 8789 8690 8691 8692 8791 8976 +6 8790 8692 8792 8976 8977 8978 +6 8791 8692 8693 8694 8793 8978 +6 8792 8694 8794 8978 8979 8980 +6 8793 8694 8795 8980 8981 8796 +5 8794 8694 8695 8696 8796 +6 8795 8696 8697 8797 8981 8794 +6 8796 8697 8798 8981 8982 8983 +6 8797 8697 8698 8799 8983 8800 +5 8798 8698 8699 8700 8800 +6 8799 8700 8801 8802 8983 8798 +6 8800 8700 8701 8802 8803 8804 +6 8800 8801 8803 8983 8984 8985 +6 8802 8801 8804 8985 8986 8987 +6 8803 8801 8701 8702 8805 8987 +6 8804 8702 8703 8806 8987 8988 +6 8805 8703 8807 8988 8989 8990 +6 8806 8703 8704 8705 8808 8990 +6 8807 8705 8706 8809 8990 8991 +7 8808 8706 8707 8810 8993 8991 8994 +5 8809 8707 8708 8811 8994 +6 8810 8708 8812 8994 8995 8813 +6 8811 8708 8709 8710 8711 8813 +6 8812 8711 8814 8995 8811 8996 +6 8813 8711 8815 8996 8997 8998 +6 8814 8711 8712 8816 8998 8999 +5 8815 8712 8713 8817 8999 +7 8816 8713 8714 8715 8818 8999 9000 +6 8817 8715 8819 9000 9001 9002 +6 8818 8715 8716 8820 9002 9003 +6 8819 8716 8717 8719 8821 9003 +6 8820 8719 8721 8722 8822 9003 +6 8821 8722 8823 9003 9004 8824 +6 8822 8722 8723 8724 8725 8824 +6 8823 8725 8825 9004 8822 9005 +6 8824 8725 8726 8826 8827 9005 +7 8825 8726 8727 8730 8731 8827 8828 +6 8825 8826 8828 9005 9006 9007 +6 8827 8826 8731 8829 9013 9007 +6 8828 8731 8732 8830 8831 9013 +5 8829 8732 8831 8734 8733 +7 8829 8830 8734 8735 8832 9012 9013 +6 8831 8735 8737 8833 9014 9012 +7 8832 8737 8738 8834 9014 9015 9016 +6 8833 8738 8739 8835 9016 9017 +6 8834 8739 8741 8836 9017 9018 +6 8835 8741 8837 9018 9019 9020 +6 8836 8741 8742 8838 9020 9021 +5 8837 8742 8626 8839 9021 +6 8838 8626 8627 8840 9021 9022 +6 8839 8627 8841 9022 9023 9024 +6 8840 8627 8628 8842 9024 9025 +6 8841 8628 8629 8843 9025 9026 +6 8842 8629 8630 8631 8844 9026 +6 8843 8631 8845 9026 9027 9031 +6 8844 8631 8632 8634 8846 9031 +6 8845 8634 8847 8848 9032 9031 +6 8846 8634 8635 8638 8848 8849 +6 8846 8847 8849 9032 9033 9034 +6 8848 8847 8638 8850 9043 9034 +6 8849 8638 8639 8851 9044 9043 +6 8850 8639 8852 9044 9045 9046 +6 8851 8639 8640 8853 9046 9049 +6 8852 8640 7763 7764 8854 9049 +6 8853 7764 7766 8320 8855 9049 +6 8854 8320 8322 8856 9048 9049 +6 8855 8322 8857 9048 9050 9051 +5 8856 8322 8324 8858 9051 +7 8857 8324 8325 8329 8859 9051 8861 +6 8858 8329 8330 8331 8860 8861 +6 8859 8331 8861 8862 8863 8332 +6 8859 8860 8862 9051 8858 9052 +6 8861 8860 8863 8864 9052 9053 +6 8862 8860 8864 8865 8866 8332 +6 8862 8863 8865 8878 9059 9053 +6 8864 8863 8866 8867 8878 8879 +6 8865 8863 8867 8334 8333 8332 +6 8865 8866 8334 8868 8879 8880 +6 8867 8334 8335 8336 8869 8880 +6 8868 8336 8870 8880 8881 8872 +6 8869 8336 8337 8339 8871 8872 +6 8870 8339 8872 8873 8874 8875 +6 8870 8871 8873 8895 8881 8869 +6 8872 8871 8874 8897 8895 8898 +6 8873 8871 8875 8898 8899 8903 +6 8874 8871 8339 8340 8876 8903 +6 8875 8340 8348 8903 8350 8349 +6 8347 8341 8342 8343 8345 8346 +5 8864 8865 8879 9059 8883 +6 8878 8865 8867 8880 8882 8883 +6 8879 8867 8868 8869 8881 8882 +6 8880 8869 8882 8894 8895 8872 +6 8880 8881 8879 8883 8884 8894 +6 8879 8882 8884 8885 9059 8878 +6 8883 8882 8885 8886 8893 8894 +6 8883 8884 8886 8887 8888 9059 +6 8885 8884 8887 8891 8892 8893 +6 8885 8886 8888 8889 8890 8891 +6 8885 8887 8889 9059 9058 9060 +6 8888 8887 8890 9060 9061 9062 +6 8889 8887 8891 9062 9063 9064 +6 8890 8887 8886 8892 9064 9065 +6 8891 8886 8893 9065 9066 9067 +6 8892 8886 8884 8894 9067 8896 +6 8893 8884 8882 8881 8895 8896 +6 8894 8881 8896 8897 8873 8872 +6 8894 8895 8897 9067 8893 9068 +6 8896 8895 8873 8898 9068 9069 +6 8897 8873 8874 8899 8900 9069 +6 8898 8874 8900 8901 8902 8903 +6 8898 8899 8901 9069 9070 9071 +6 8900 8899 8902 9071 9072 8904 +6 8901 8899 8903 8350 8351 8904 +6 8902 8899 8874 8875 8876 8350 +6 8902 8351 8352 8905 9072 8901 +6 8904 8352 8906 9072 9073 9074 +6 8905 8352 8353 8907 9074 9075 +6 8906 8353 8354 8908 9075 9076 +6 8907 8354 8355 8909 9076 9077 +6 8908 8355 8910 9077 9078 8912 +6 8909 8355 8356 8358 8911 8912 +6 8910 8358 8912 8913 8361 8360 +6 8910 8911 8913 9078 8909 9079 +6 8912 8911 8361 8914 9079 9080 +6 8913 8361 8362 8915 8916 9080 +6 8914 8362 8363 8916 8917 8364 +6 8914 8915 8917 9080 9081 9082 +6 8916 8915 8364 8918 9082 9083 +6 8917 8364 8365 8919 9083 9084 +6 8918 8365 8366 8920 9084 9085 +6 8919 8366 8367 8921 9094 9085 +6 8920 8367 8368 8922 9094 9101 +6 8921 8368 8369 8923 9101 9102 +6 8922 8369 8370 8924 9102 9103 +6 8923 8370 8371 8925 9103 9104 +6 8924 8371 8926 9104 9105 9106 +6 8925 8371 8372 8927 9106 9107 +6 8926 8372 8373 8375 8928 9107 +6 8927 8375 8929 9107 9108 8932 +6 8928 8375 8376 8930 8932 8931 +6 8929 8376 8377 8378 8380 8931 +5 8930 8380 8381 8932 8929 +8 8931 8381 8382 8744 8933 9108 8928 8929 +5 8932 8744 8745 8934 9108 +8 8933 8745 8746 8935 9108 9107 9106 9109 +6 8934 8746 8747 8748 8936 9109 +6 8935 8748 8937 9109 9110 9111 +6 8936 8748 8749 8938 9111 9112 +6 8937 8749 8750 8939 9112 9113 +6 8938 8750 8751 8940 9113 9114 +6 8939 8751 8752 8941 9114 9115 +6 8940 8752 8753 8942 9115 9116 +6 8941 8753 8754 8943 9116 9117 +6 8942 8754 8944 9117 9118 8945 +5 8943 8754 8755 8756 8945 +7 8944 8756 8757 8946 9118 8943 9119 +7 8945 8757 8758 8759 8947 9119 9120 +5 8946 8759 8948 9120 9121 +6 8947 8759 8760 8949 9121 9122 +7 8948 8760 8761 8762 8950 9122 9123 +6 8949 8762 8951 9123 9124 8952 +6 8950 8762 8763 8764 8765 8952 +6 8951 8765 8766 8953 9124 8950 +6 8952 8766 8767 8954 9124 9125 +6 8953 8767 8955 9125 9126 9127 +6 8954 8767 8768 8769 8956 9127 +6 8955 8769 8770 8957 9127 9128 +6 8956 8770 8958 9128 9129 9130 +6 8957 8770 8771 8772 8959 9130 +6 8958 8772 8773 8960 9130 9131 +6 8959 8773 8774 8961 9131 9132 +6 8960 8774 8775 8962 9132 9133 +6 8961 8775 8776 8963 9133 9134 +6 8962 8776 8777 8964 9134 9135 +6 8963 8777 8965 9135 9136 9137 +6 8964 8777 8778 8779 8966 9137 +6 8965 8779 8780 8967 9137 9138 +6 8966 8780 8781 8968 9138 9139 +6 8967 8781 8782 8969 9139 9140 +6 8968 8782 8783 8970 9140 9141 +7 8969 8783 8784 8785 8971 9141 9142 +5 8970 8785 8972 9142 9143 +7 8971 8785 8786 8973 9143 9144 9145 +6 8972 8786 8787 8974 9145 9146 +6 8973 8787 8975 9146 9147 9148 +6 8974 8787 8788 8789 8976 9148 +6 8975 8789 8790 8791 8977 9148 +6 8976 8791 8978 9148 9149 9150 +6 8977 8791 8792 8793 8979 9150 +6 8978 8793 8980 9150 9151 9152 +6 8979 8793 8794 8981 9152 9153 +6 8980 8794 8796 8797 8982 9153 +6 8981 8797 8983 9153 9154 8984 +6 8982 8797 8798 8800 8802 8984 +6 8983 8802 8985 9154 8982 9155 +6 8984 8802 8803 8986 9155 9156 +6 8985 8803 8987 9156 9157 9158 +7 8986 8803 8804 8805 8988 9158 9159 +5 8987 8805 8806 8989 9159 +7 8988 8806 8990 8991 8992 9159 9160 +5 8989 8806 8807 8808 8991 +6 8990 8808 8989 8992 8993 8809 +6 8989 8991 8993 9160 9161 9162 +6 8992 8991 8809 8994 9165 9162 +6 8993 8809 8810 8811 8995 9165 +6 8994 8811 8813 8996 9165 9166 +7 8995 8813 8814 8997 9166 9168 9169 +5 8996 8814 8998 9169 9170 +6 8997 8814 8815 8999 9170 9171 +7 8998 8815 8816 8817 9000 9171 9172 +5 8999 8817 8818 9001 9172 +6 9000 8818 9002 9172 9173 9174 +6 9001 8818 8819 9003 9174 9004 +6 9002 8819 8820 8821 8822 9004 +6 9003 8822 8824 9005 9174 9002 +6 9004 8824 8825 8827 9006 9174 +6 9005 8827 9007 9008 9009 9174 +6 9006 8827 9008 9012 9013 8828 +6 9006 9007 9009 9010 9011 9012 +6 9006 9008 9010 9174 9173 9175 +5 9009 9008 9011 9175 9178 +6 9010 9008 9012 9014 9178 9015 +7 9011 9008 9007 9013 9014 8832 8831 +5 9012 9007 8831 8829 8828 +5 9011 9012 8832 8833 9015 +6 9014 8833 9016 9178 9011 9179 +6 9015 8833 8834 9017 9182 9179 +5 9016 8834 8835 9018 9182 +7 9017 8835 8836 9019 9182 9183 9189 +6 9018 8836 9020 9189 9190 9191 +6 9019 8836 8837 9021 9191 9192 +6 9020 8837 8838 8839 9022 9192 +6 9021 8839 8840 9023 9192 9193 +6 9022 8840 9024 9193 9196 9197 +6 9023 8840 8841 9025 9197 9198 +6 9024 8841 8842 9026 9198 9028 +6 9025 8842 8843 8844 9027 9028 +6 9026 8844 9028 9029 9030 9031 +6 9026 9027 9029 9198 9025 9199 +6 9028 9027 9030 9199 9200 9204 +5 9029 9027 9031 9032 9204 +6 9030 9027 8844 9032 8846 8845 +7 9030 9031 8846 8848 9033 9204 9205 +6 9032 8848 9034 9035 9205 9206 +6 9033 8848 9035 9036 9043 8849 +6 9033 9034 9036 9037 9038 9206 +6 9035 9034 9037 9041 9042 9043 +6 9035 9036 9038 9039 9040 9041 +6 9035 9037 9039 9206 9207 9208 +6 9038 9037 9040 9208 9209 9210 +6 9039 9037 9041 9210 9063 9062 +6 9040 9037 9036 9042 9062 9061 +6 9041 9036 9043 9044 9061 9211 +6 9042 9036 9034 8849 9044 8850 +6 9042 9043 8850 8851 9045 9211 +7 9044 8851 9046 9047 9056 9057 9211 +6 9045 8851 8852 9047 9048 9049 +6 9045 9046 9048 9054 9056 9050 +6 9047 9046 9049 8855 8856 9050 +6 9048 9046 8852 8855 8854 8853 +6 9048 8856 9051 9052 9054 9047 +6 9050 8856 8857 8858 8861 9052 +6 9051 8861 8862 9053 9054 9050 +6 9052 8862 9054 9055 9059 8864 +6 9052 9053 9055 9056 9047 9050 +6 9054 9053 9056 9057 9058 9059 +5 9054 9055 9047 9045 9057 +6 9045 9056 9055 9058 9060 9211 +5 9057 9055 9059 8888 9060 +8 9058 9055 9053 8864 8878 8883 8885 8888 +6 9058 8888 8889 9061 9211 9057 +6 9060 8889 9062 9041 9042 9211 +6 9061 8889 8890 9063 9040 9041 +6 9062 8890 9064 9210 9040 9212 +6 9063 8890 8891 9065 9212 9213 +6 9064 8891 8892 9066 9213 9214 +6 9065 8892 9067 9214 9215 9216 +6 9066 8892 8893 8896 9068 9216 +6 9067 8896 8897 9069 9216 9217 +6 9068 8897 8898 8900 9070 9217 +6 9069 8900 9071 9217 9218 9219 +6 9070 8900 8901 9072 9219 9220 +7 9071 8901 8904 8905 9073 9220 9221 +5 9072 8905 9074 9221 9222 +7 9073 8905 8906 9075 9222 9223 9224 +6 9074 8906 8907 9076 9224 9226 +6 9075 8907 8908 9077 9226 9227 +5 9076 8908 8909 9078 9227 +7 9077 8909 8912 9079 9227 9228 9229 +5 9078 8912 8913 9080 9229 +6 9079 8913 8914 8916 9081 9229 +6 9080 8916 9082 9229 9230 9231 +6 9081 8916 8917 9083 9231 9232 +6 9082 8917 8918 9084 9232 9233 +6 9083 8918 8919 9085 9086 9233 +6 9084 8919 9086 9087 9094 8920 +6 9084 9085 9087 9088 9233 9234 +6 9086 9085 9088 9089 9093 9094 +6 9086 9087 9089 9090 9234 9235 +6 9088 9087 9090 9091 9092 9093 +6 9088 9089 9091 9096 9235 9236 +6 9090 9089 9092 9096 9097 9098 +6 9091 9089 9093 9098 9099 9100 +6 9092 9089 9087 9094 9100 9101 +6 9093 9087 9085 8920 8921 9101 +5 8470 8471 8486 8477 8472 +6 9090 9091 9097 9236 9237 9238 +6 9096 9091 9098 9238 9239 9240 +6 9097 9091 9092 9099 9240 9241 +6 9098 9092 9100 9241 9242 9243 +6 9099 9092 9093 9101 9243 9102 +6 9100 9093 9094 8921 8922 9102 +6 9101 8922 8923 9103 9243 9100 +6 9102 8923 8924 9104 9243 9244 +6 9103 8924 8925 9105 9244 9245 +6 9104 8925 9106 9110 9245 9109 +6 9105 8925 8926 9107 8934 9109 +6 9106 8926 8927 8928 9108 8934 +5 9107 8928 8932 8933 8934 +6 9106 8934 8935 8936 9110 9105 +5 9109 8936 9111 9245 9105 +7 9110 8936 8937 9112 9246 9245 9349 +6 9111 8937 8938 9113 9351 9349 +5 9112 8938 8939 9114 9351 +6 9113 8939 8940 9115 9351 9352 +6 9114 8940 8941 9116 9352 9353 +6 9115 8941 8942 9117 9353 9354 +6 9116 8942 8943 9118 9247 9354 +6 9117 8943 8945 9119 9247 9248 +6 9118 8945 8946 9120 9248 9249 +5 9119 8946 8947 9121 9249 +7 9120 8947 8948 9122 9249 9250 9251 +6 9121 8948 8949 9123 9251 9252 +5 9122 8949 8950 9124 9252 +6 9123 8950 8952 8953 9125 9252 +6 9124 8953 8954 9126 9252 9253 +6 9125 8954 9127 9253 9254 9255 +6 9126 8954 8955 8956 9128 9255 +6 9127 8956 8957 9129 9255 9256 +6 9128 8957 9130 9256 9257 9258 +6 9129 8957 8958 8959 9131 9258 +6 9130 8959 8960 9132 9258 9259 +6 9131 8960 8961 9133 9259 9260 +6 9132 8961 8962 9134 9260 9261 +6 9133 8962 8963 9135 9261 9262 +6 9134 8963 8964 9136 9262 9263 +6 9135 8964 9137 9263 9264 9265 +6 9136 8964 8965 8966 9138 9265 +6 9137 8966 8967 9139 9265 9266 +6 9138 8967 8968 9140 9266 9267 +6 9139 8968 8969 9141 9267 9268 +6 9140 8969 8970 9142 9268 9269 +5 9141 8970 8971 9143 9269 +7 9142 8971 8972 9144 9269 9270 9271 +6 9143 8972 9145 9271 9272 9273 +5 9144 8972 8973 9146 9273 +6 9145 8973 8974 9147 9273 9274 +6 9146 8974 9148 9274 9275 9149 +6 9147 8974 8975 8976 8977 9149 +6 9148 8977 9150 9275 9147 9276 +6 9149 8977 8978 8979 9151 9276 +6 9150 8979 9152 9276 9277 9278 +6 9151 8979 8980 9153 9278 9279 +7 9152 8980 8981 8982 9154 9279 9280 +6 9153 8982 8984 9155 9280 9281 +6 9154 8984 8985 9156 9281 9282 +6 9155 8985 8986 9157 9282 9283 +6 9156 8986 9158 9283 9284 9285 +6 9157 8986 8987 9159 9285 9286 +6 9158 8987 8988 8989 9160 9286 +6 9159 8989 8992 9161 9286 9287 +6 9160 8992 9162 9163 9287 9288 +6 9161 8992 9163 9164 9165 8993 +6 9161 9162 9164 9288 9289 9290 +6 9163 9162 9165 9166 9167 9290 +6 9164 9162 8993 8994 8995 9166 +6 9165 8995 8996 9164 9167 9168 +6 9164 9166 9168 9290 9291 9187 +6 9167 9166 8996 9169 9187 9186 +6 9168 8996 8997 9170 9186 9185 +7 9169 8997 8998 9171 9185 9180 9177 +6 9170 8998 8999 9172 9177 9176 +6 9171 8999 9000 9001 9173 9176 +6 9172 9001 9174 9009 9175 9176 +7 9173 9001 9002 9004 9005 9006 9009 +6 9173 9009 9010 9176 9177 9178 +5 9173 9175 9177 9171 9172 +6 9176 9175 9178 9180 9170 9171 +7 9177 9175 9010 9011 9015 9179 9180 +6 9178 9015 9180 9181 9182 9016 +6 9178 9179 9181 9185 9170 9177 +6 9180 9179 9182 9183 9184 9185 +6 9181 9179 9016 9017 9018 9183 +6 9182 9018 9181 9184 9188 9189 +6 9181 9183 9185 9186 9187 9188 +6 9181 9184 9186 9169 9170 9180 +5 9185 9184 9187 9168 9169 +6 9186 9184 9188 9291 9167 9168 +6 9187 9184 9183 9189 9291 9292 +6 9188 9183 9018 9019 9190 9292 +5 9189 9019 9191 9292 9293 +6 9190 9019 9020 9192 9293 9194 +6 9191 9020 9021 9022 9193 9194 +6 9192 9022 9023 9194 9195 9196 +6 9192 9193 9195 9293 9191 9294 +6 9194 9193 9196 9294 9295 9296 +6 9195 9193 9023 9197 9296 9297 +6 9196 9023 9024 9198 9303 9297 +7 9197 9024 9025 9028 9199 9303 9304 +6 9198 9028 9029 9200 9201 9304 +6 9199 9029 9201 9202 9203 9204 +6 9199 9200 9202 9304 9302 9305 +6 9201 9200 9203 9305 9306 9307 +6 9202 9200 9204 9307 9308 9205 +6 9203 9200 9029 9030 9032 9205 +7 9204 9032 9033 9206 9308 9203 9207 +5 9205 9033 9035 9038 9207 +6 9206 9038 9208 9308 9205 9309 +6 9207 9038 9039 9209 9309 9310 +6 9208 9039 9210 9310 9311 9315 +6 9209 9039 9040 9063 9212 9315 +6 9061 9042 9044 9060 9057 9045 +6 9210 9063 9064 9213 9315 9316 +6 9212 9064 9065 9214 9316 9317 +6 9213 9065 9066 9215 9320 9317 +6 9214 9066 9216 9320 9321 9322 +6 9215 9066 9067 9068 9217 9322 +6 9216 9068 9069 9070 9218 9322 +7 9217 9070 9219 9322 9321 9323 9324 +5 9218 9070 9071 9220 9324 +7 9219 9071 9072 9221 9324 9325 9326 +5 9220 9072 9073 9222 9326 +7 9221 9073 9074 9223 9326 9327 9328 +6 9222 9074 9224 9225 9328 9329 +5 9223 9074 9075 9225 9226 +6 9223 9224 9226 9329 9330 9331 +6 9225 9224 9075 9076 9227 9331 +7 9226 9076 9077 9078 9228 9331 9332 +6 9227 9078 9229 9332 9333 9230 +6 9228 9078 9079 9080 9081 9230 +7 9229 9081 9231 9333 9228 9334 9335 +6 9230 9081 9082 9232 9335 9336 +6 9231 9082 9083 9233 9336 9337 +7 9232 9083 9084 9086 9234 9337 9338 +5 9233 9086 9088 9235 9338 +7 9234 9088 9090 9236 9338 9339 9340 +5 9235 9090 9096 9237 9340 +7 9236 9096 9238 9340 9341 9342 9343 +6 9237 9096 9097 9239 9343 9344 +6 9238 9097 9240 9344 9345 9346 +6 9239 9097 9098 9241 9346 9347 +6 9240 9098 9099 9242 9347 9348 +6 9241 9099 9243 9348 9246 9244 +6 9242 9099 9100 9102 9103 9244 +6 9243 9103 9104 9245 9246 9242 +6 9244 9104 9246 9111 9110 9105 +6 9244 9245 9111 9348 9242 9349 +6 9117 9118 9248 9354 9355 9356 +6 9247 9118 9119 9249 9356 9357 +6 9248 9119 9120 9121 9250 9357 +6 9249 9121 9251 9357 9358 9359 +6 9250 9121 9122 9252 9359 9253 +6 9251 9122 9123 9124 9125 9253 +7 9252 9125 9126 9254 9359 9251 9360 +5 9253 9126 9255 9360 9361 +7 9254 9126 9127 9128 9256 9361 9362 +6 9255 9128 9129 9257 9362 9363 +6 9256 9129 9258 9363 9364 9365 +6 9257 9129 9130 9131 9259 9365 +7 9258 9131 9132 9260 9365 9366 9367 +6 9259 9132 9133 9261 9367 9368 +6 9260 9133 9134 9262 9368 9369 +6 9261 9134 9135 9263 9369 9370 +6 9262 9135 9136 9264 9370 9371 +6 9263 9136 9265 9371 9372 9373 +6 9264 9136 9137 9138 9266 9373 +6 9265 9138 9139 9267 9373 9374 +6 9266 9139 9140 9268 9374 9375 +6 9267 9140 9141 9269 9375 9376 +7 9268 9141 9142 9143 9270 9376 9377 +5 9269 9143 9271 9377 9378 +6 9270 9143 9144 9272 9378 9382 +6 9271 9144 9273 9382 9383 9384 +6 9272 9144 9145 9146 9274 9384 +6 9273 9146 9147 9275 9384 9385 +6 9274 9147 9149 9276 9385 9386 +7 9275 9149 9150 9151 9277 9386 9387 +5 9276 9151 9278 9387 9389 +6 9277 9151 9152 9279 9389 9390 +6 9278 9152 9153 9280 9390 9391 +6 9279 9153 9154 9281 9391 9392 +5 9280 9154 9155 9282 9392 +6 9281 9155 9156 9283 9394 9392 +6 9282 9156 9157 9284 9394 9395 +6 9283 9157 9285 9395 9396 9397 +6 9284 9157 9158 9286 9397 9398 +6 9285 9158 9159 9160 9287 9398 +6 9286 9160 9161 9288 9398 9399 +5 9287 9161 9163 9289 9399 +7 9288 9163 9290 9399 9400 9401 9402 +6 9289 9163 9164 9167 9291 9402 +7 9290 9167 9187 9188 9292 9403 9402 +6 9291 9188 9189 9190 9293 9403 +7 9292 9190 9191 9194 9294 9403 9401 +6 9293 9194 9195 9295 9401 9404 +6 9294 9195 9296 9404 9405 9406 +6 9295 9195 9196 9297 9298 9406 +6 9296 9196 9298 9299 9303 9197 +6 9296 9297 9299 9300 9406 9407 +6 9298 9297 9300 9301 9302 9303 +6 9298 9299 9301 9410 9407 9411 +6 9300 9299 9302 9411 9412 9413 +7 9301 9299 9303 9304 9201 9305 9413 +6 9302 9299 9297 9197 9198 9304 +5 9303 9198 9199 9201 9302 +5 9302 9201 9202 9306 9413 +7 9305 9202 9307 9413 9414 9415 9419 +5 9306 9202 9203 9308 9419 +6 9307 9203 9205 9207 9309 9419 +6 9308 9207 9208 9310 9418 9419 +6 9309 9208 9209 9311 9312 9418 +6 9310 9209 9312 9313 9314 9315 +6 9310 9311 9313 9417 9418 9420 +6 9312 9311 9314 9420 9421 9425 +7 9313 9311 9315 9425 9426 9318 9316 +6 9314 9311 9209 9210 9212 9316 +6 9315 9212 9213 9317 9318 9314 +6 9316 9213 9318 9319 9320 9214 +6 9316 9317 9319 9426 9314 9427 +6 9318 9317 9320 9427 9428 9429 +6 9319 9317 9214 9215 9321 9429 +6 9320 9215 9322 9218 9323 9429 +5 9321 9215 9216 9217 9218 +6 9321 9218 9324 9429 9430 9431 +6 9323 9218 9219 9220 9325 9431 +6 9324 9220 9326 9431 9432 9433 +6 9325 9220 9221 9222 9327 9433 +6 9326 9222 9328 9433 9434 9435 +6 9327 9222 9223 9329 9435 9436 +5 9328 9223 9225 9330 9436 +7 9329 9225 9331 9436 9437 9438 9439 +6 9330 9225 9226 9227 9332 9439 +6 9331 9227 9228 9333 9439 9440 +6 9332 9228 9230 9334 9443 9440 +6 9333 9230 9335 9443 9444 9447 +5 9334 9230 9231 9336 9447 +6 9335 9231 9232 9337 9447 9448 +6 9336 9232 9233 9338 9448 9449 +6 9337 9233 9234 9235 9339 9449 +6 9338 9235 9340 9449 9450 9451 +6 9339 9235 9236 9237 9341 9451 +6 9340 9237 9342 9451 9452 9453 +6 9341 9237 9343 9453 9454 9455 +6 9342 9237 9238 9344 9455 9456 +5 9343 9238 9239 9345 9456 +7 9344 9239 9346 9456 9457 9458 9459 +6 9345 9239 9240 9347 9459 9350 +5 9346 9240 9241 9348 9350 +6 9347 9241 9242 9246 9349 9350 +6 9348 9246 9350 9351 9112 9111 +7 9348 9349 9351 9459 9346 9347 9352 +6 9350 9349 9112 9113 9114 9352 +7 9351 9114 9115 9353 9459 9350 9460 +6 9352 9115 9116 9354 9460 9461 +6 9353 9116 9117 9247 9355 9461 +6 9354 9247 9356 9461 9462 9463 +6 9355 9247 9248 9357 9463 9464 +6 9356 9248 9249 9250 9358 9464 +6 9357 9250 9359 9464 9465 9466 +6 9358 9250 9251 9253 9360 9466 +5 9359 9253 9254 9361 9466 +7 9360 9254 9255 9362 9466 9467 9468 +5 9361 9255 9256 9363 9468 +6 9362 9256 9257 9364 9468 9469 +6 9363 9257 9365 9469 9470 9471 +6 9364 9257 9258 9259 9366 9471 +6 9365 9259 9367 9471 9472 9473 +5 9366 9259 9260 9368 9473 +6 9367 9260 9261 9369 9473 9474 +6 9368 9261 9262 9370 9474 9475 +6 9369 9262 9263 9371 9475 9476 +6 9370 9263 9264 9372 9476 9477 +6 9371 9264 9373 9477 9478 9479 +6 9372 9264 9265 9266 9374 9479 +6 9373 9266 9267 9375 9479 9480 +6 9374 9267 9268 9376 9480 9481 +6 9375 9268 9269 9377 9481 9482 +6 9376 9269 9270 9378 9379 9482 +7 9377 9270 9271 9379 9380 9381 9382 +5 9377 9378 9380 9482 9483 +6 9379 9378 9381 9483 9484 9485 +6 9380 9378 9382 9485 9486 9383 +5 9381 9378 9271 9272 9383 +6 9382 9272 9384 9486 9381 9487 +7 9383 9272 9273 9274 9385 9487 9488 +6 9384 9274 9275 9386 9488 9489 +6 9385 9275 9276 9387 9388 9489 +5 9386 9276 9277 9388 9389 +6 9386 9387 9389 9489 9490 9491 +7 9388 9387 9277 9278 9390 9491 9492 +6 9389 9278 9279 9391 9492 9493 +6 9390 9279 9280 9392 9393 9493 +6 9391 9280 9393 9394 9282 9281 +6 9391 9392 9394 9493 9494 9495 +6 9393 9392 9282 9283 9395 9495 +6 9394 9283 9284 9396 9495 9496 +6 9395 9284 9397 9496 9497 9498 +6 9396 9284 9285 9398 9499 9498 +6 9397 9285 9286 9287 9399 9499 +6 9398 9287 9288 9289 9400 9499 +6 9399 9289 9401 9499 9405 9404 +7 9400 9289 9402 9403 9293 9294 9404 +5 9401 9289 9403 9291 9290 +5 9401 9402 9291 9292 9293 +5 9401 9294 9295 9405 9400 +6 9404 9295 9406 9499 9400 9408 +6 9405 9295 9296 9298 9407 9408 +6 9406 9298 9408 9409 9410 9300 +6 9406 9407 9409 9498 9499 9405 +6 9408 9407 9410 9497 9498 9500 +6 9409 9407 9300 9411 9500 9501 +6 9410 9300 9301 9412 9501 9502 +6 9411 9301 9413 9502 9503 9414 +6 9412 9301 9302 9305 9306 9414 +6 9413 9306 9415 9416 9503 9412 +6 9414 9306 9416 9417 9418 9419 +6 9414 9415 9417 9503 9504 9505 +6 9416 9415 9418 9312 9420 9505 +6 9417 9415 9419 9309 9310 9312 +6 9418 9415 9309 9308 9307 9306 +6 9417 9312 9313 9421 9422 9505 +6 9420 9313 9422 9423 9424 9425 +6 9420 9421 9423 9505 9506 9507 +6 9422 9421 9424 9507 9508 9509 +6 9423 9421 9425 9512 9509 9513 +6 9424 9421 9313 9314 9426 9513 +5 9425 9314 9318 9427 9513 +6 9426 9318 9319 9428 9513 9514 +6 9427 9319 9429 9514 9515 9430 +6 9428 9319 9320 9321 9323 9430 +6 9429 9323 9431 9518 9515 9428 +6 9430 9323 9324 9325 9432 9518 +6 9431 9325 9433 9525 9518 9526 +6 9432 9325 9326 9327 9434 9526 +6 9433 9327 9435 9526 9527 9528 +6 9434 9327 9328 9436 9528 9529 +6 9435 9328 9329 9330 9437 9529 +6 9436 9330 9438 9529 9531 9532 +6 9437 9330 9439 9532 9533 9441 +6 9438 9330 9331 9332 9440 9441 +6 9439 9332 9441 9442 9443 9333 +5 9439 9440 9442 9533 9438 +7 9441 9440 9443 9444 9445 9533 9534 +5 9442 9440 9333 9334 9444 +6 9443 9334 9442 9445 9446 9447 +5 9442 9444 9446 9534 9535 +6 9445 9444 9447 9535 9536 9537 +7 9446 9444 9334 9335 9336 9448 9537 +6 9447 9336 9337 9449 9537 9538 +6 9448 9337 9338 9339 9450 9538 +6 9449 9339 9451 9538 9539 9452 +5 9450 9339 9340 9341 9452 +7 9451 9341 9453 9539 9450 9540 9541 +6 9452 9341 9342 9454 9541 9542 +6 9453 9342 9455 9542 9543 9544 +6 9454 9342 9343 9456 9544 9545 +6 9455 9343 9344 9345 9457 9545 +6 9456 9345 9458 9545 9546 9462 +6 9457 9345 9459 9462 9461 9460 +6 9458 9345 9346 9350 9352 9460 +5 9459 9352 9353 9461 9458 +6 9460 9353 9354 9355 9462 9458 +6 9461 9355 9463 9546 9457 9458 +5 9462 9355 9356 9464 9546 +7 9463 9356 9357 9358 9465 9546 9547 +6 9464 9358 9466 9547 9548 9549 +7 9465 9358 9359 9360 9361 9467 9549 +6 9466 9361 9468 9549 9550 9551 +6 9467 9361 9362 9363 9469 9551 +6 9468 9363 9364 9470 9551 9552 +6 9469 9364 9471 9552 9553 9554 +6 9470 9364 9365 9366 9472 9554 +6 9471 9366 9473 9554 9555 9556 +6 9472 9366 9367 9368 9474 9556 +6 9473 9368 9369 9475 9556 9557 +6 9474 9369 9370 9476 9557 9558 +6 9475 9370 9371 9477 9558 9559 +6 9476 9371 9372 9478 9559 9560 +6 9477 9372 9479 9560 9561 9562 +6 9478 9372 9373 9374 9480 9562 +6 9479 9374 9375 9481 9562 9563 +6 9480 9375 9376 9482 9563 9564 +6 9481 9376 9377 9379 9483 9564 +6 9482 9379 9380 9484 9564 9565 +6 9483 9380 9485 9565 9566 9567 +6 9484 9380 9381 9486 9567 9568 +6 9485 9381 9383 9487 9568 9569 +6 9486 9383 9384 9488 9569 9570 +6 9487 9384 9385 9489 9570 9571 +6 9488 9385 9386 9388 9490 9571 +6 9489 9388 9491 9571 9572 9573 +6 9490 9388 9389 9492 9573 9574 +6 9491 9389 9390 9493 9574 9575 +6 9492 9390 9391 9393 9494 9575 +6 9493 9393 9495 9575 9576 9577 +6 9494 9393 9394 9395 9496 9577 +6 9495 9395 9396 9497 9577 9578 +6 9496 9396 9498 9409 9500 9578 +6 9497 9396 9409 9408 9499 9397 +7 9408 9498 9397 9398 9399 9400 9405 +5 9497 9409 9410 9501 9578 +7 9500 9410 9411 9502 9578 9579 9580 +6 9501 9411 9412 9503 9580 9581 +6 9502 9412 9414 9416 9504 9581 +6 9503 9416 9505 9581 9582 9583 +7 9504 9416 9417 9420 9422 9506 9583 +5 9505 9422 9507 9583 9584 +6 9506 9422 9423 9508 9584 9585 +6 9507 9423 9509 9510 9585 9586 +6 9508 9423 9510 9511 9512 9424 +6 9508 9509 9511 9586 9587 9588 +6 9510 9509 9512 9519 9588 9522 +6 9511 9509 9424 9513 9519 9520 +7 9512 9424 9425 9426 9427 9514 9520 +6 9513 9427 9428 9515 9516 9520 +6 9514 9428 9516 9517 9518 9430 +6 9514 9515 9517 9520 9519 9521 +6 9516 9515 9518 9524 9521 9525 +6 9517 9515 9430 9431 9525 9432 +6 9511 9512 9520 9516 9521 9522 +5 9519 9512 9513 9514 9516 +6 9519 9516 9522 9523 9524 9517 +6 9519 9521 9523 9588 9511 9589 +6 9522 9521 9524 9589 9590 9591 +6 9523 9521 9517 9525 9591 9592 +6 9524 9517 9518 9432 9526 9592 +7 9525 9432 9433 9434 9527 9592 9593 +5 9526 9434 9528 9593 9594 +6 9527 9434 9435 9529 9530 9594 +6 9528 9435 9436 9437 9530 9531 +6 9528 9529 9531 9594 9595 9596 +6 9530 9529 9437 9532 9596 9597 +6 9531 9437 9438 9533 9597 9598 +7 9532 9438 9441 9442 9534 9598 9599 +5 9533 9442 9445 9535 9599 +7 9534 9445 9446 9536 9599 9600 9601 +6 9535 9446 9537 9601 9602 9603 +7 9536 9446 9447 9448 9538 9603 9604 +6 9537 9448 9449 9450 9539 9604 +6 9538 9450 9452 9540 9604 9605 +6 9539 9452 9541 9605 9606 9607 +6 9540 9452 9453 9542 9607 9608 +5 9541 9453 9454 9543 9608 +7 9542 9454 9544 9608 9609 9610 9611 +5 9543 9454 9455 9545 9611 +7 9544 9455 9456 9457 9546 9611 9547 +6 9545 9457 9462 9463 9464 9547 +6 9546 9464 9465 9548 9611 9545 +6 9547 9465 9549 9611 9610 9550 +5 9548 9465 9466 9467 9550 +6 9549 9467 9551 9610 9548 9612 +6 9550 9467 9468 9469 9552 9612 +6 9551 9469 9470 9553 9612 9613 +6 9552 9470 9554 9613 9614 9615 +6 9553 9470 9471 9472 9555 9615 +6 9554 9472 9556 9615 9616 9617 +6 9555 9472 9473 9474 9557 9617 +6 9556 9474 9475 9558 9617 9618 +6 9557 9475 9476 9559 9618 9619 +6 9558 9476 9477 9560 9619 9620 +6 9559 9477 9478 9561 9620 9621 +6 9560 9478 9562 9621 9622 9623 +6 9561 9478 9479 9480 9563 9623 +6 9562 9480 9481 9564 9623 9624 +6 9563 9481 9482 9483 9565 9624 +6 9564 9483 9484 9566 9624 9625 +6 9565 9484 9567 9625 9626 9627 +6 9566 9484 9485 9568 9627 9628 +6 9567 9485 9486 9569 9628 9629 +7 9568 9486 9487 9570 9629 9630 9631 +6 9569 9487 9488 9571 9631 9632 +6 9570 9488 9489 9490 9572 9632 +6 9571 9490 9573 9632 9633 9634 +6 9572 9490 9491 9574 9634 9635 +6 9573 9491 9492 9575 9635 9636 +6 9574 9492 9493 9494 9576 9636 +6 9575 9494 9577 9636 9637 9579 +6 9576 9494 9495 9496 9578 9579 +6 9577 9496 9497 9500 9501 9579 +6 9578 9501 9580 9637 9576 9577 +6 9579 9501 9502 9581 9637 9582 +5 9580 9502 9503 9504 9582 +6 9581 9504 9583 9637 9580 9638 +6 9582 9504 9505 9506 9584 9638 +6 9583 9506 9507 9585 9638 9639 +6 9584 9507 9508 9586 9639 9634 +6 9585 9508 9510 9587 9634 9633 +6 9586 9510 9588 9633 9640 9630 +6 9587 9510 9511 9522 9589 9630 +6 9588 9522 9523 9590 9630 9629 +6 9589 9523 9591 9629 9628 9641 +6 9590 9523 9524 9592 9641 9642 +6 9591 9524 9525 9526 9593 9642 +6 9592 9526 9527 9594 9642 9643 +7 9593 9527 9528 9530 9595 9643 9644 +5 9594 9530 9596 9644 9645 +6 9595 9530 9531 9597 9645 9646 +6 9596 9531 9532 9598 9646 9647 +6 9597 9532 9533 9599 9647 9648 +6 9598 9533 9534 9535 9600 9648 +5 9599 9535 9601 9648 9649 +7 9600 9535 9536 9602 9649 9650 9651 +5 9601 9536 9603 9651 9652 +6 9602 9536 9537 9604 9652 9605 +5 9603 9537 9538 9539 9605 +6 9604 9539 9540 9606 9652 9603 +6 9605 9540 9607 9652 9653 9654 +6 9606 9540 9541 9608 9654 9614 +6 9607 9541 9542 9543 9609 9614 +6 9608 9543 9610 9614 9613 9612 +6 9609 9543 9611 9548 9550 9612 +6 9610 9543 9544 9545 9547 9548 +6 9610 9550 9551 9552 9613 9609 +5 9612 9552 9553 9614 9609 +7 9613 9553 9615 9654 9607 9608 9609 +6 9614 9553 9554 9555 9616 9654 +6 9615 9555 9617 9654 9653 9655 +6 9616 9555 9556 9557 9618 9655 +6 9617 9557 9558 9619 9655 9656 +6 9618 9558 9559 9620 9656 9657 +6 9619 9559 9560 9621 9657 9658 +6 9620 9560 9561 9622 9658 9659 +6 9621 9561 9623 9659 9660 9661 +6 9622 9561 9562 9563 9624 9661 +6 9623 9563 9564 9565 9625 9661 +7 9624 9565 9566 9626 9661 9662 9663 +5 9625 9566 9627 9663 9664 +7 9626 9566 9567 9628 9664 9665 9641 +6 9627 9567 9568 9629 9590 9641 +6 9628 9568 9569 9630 9589 9590 +7 9629 9569 9631 9640 9587 9588 9589 +5 9630 9569 9570 9632 9640 +6 9631 9570 9571 9572 9633 9640 +6 9632 9572 9634 9586 9587 9640 +7 9633 9572 9573 9635 9639 9585 9586 +6 9634 9573 9574 9636 9638 9639 +6 9635 9574 9575 9576 9637 9638 +6 9636 9576 9579 9580 9582 9638 +7 9637 9582 9583 9584 9639 9636 9635 +5 9638 9584 9585 9634 9635 +5 9633 9587 9630 9631 9632 +6 9628 9590 9591 9642 9665 9627 +6 9641 9591 9592 9593 9643 9665 +6 9642 9593 9594 9644 9665 9664 +6 9643 9594 9595 9645 9664 9663 +7 9644 9595 9596 9646 9663 9662 9666 +7 9645 9596 9597 9647 9666 9660 9667 +6 9646 9597 9598 9648 9667 9668 +6 9647 9598 9599 9600 9649 9668 +6 9648 9600 9601 9650 9668 9669 +6 9649 9601 9651 9669 9657 9656 +6 9650 9601 9602 9652 9656 9670 +7 9651 9602 9603 9605 9606 9653 9670 +6 9652 9606 9654 9616 9655 9670 +6 9653 9606 9607 9614 9615 9616 +6 9653 9616 9617 9618 9656 9670 +7 9655 9618 9619 9657 9650 9651 9670 +6 9656 9619 9620 9658 9669 9650 +5 9657 9620 9621 9659 9669 +6 9658 9621 9622 9660 9669 9667 +6 9659 9622 9661 9666 9646 9667 +7 9660 9622 9623 9624 9625 9662 9666 +5 9661 9625 9663 9645 9666 +6 9662 9625 9626 9664 9644 9645 +6 9663 9626 9627 9665 9643 9644 +5 9664 9627 9641 9642 9643 +5 9662 9645 9646 9660 9661 +6 9660 9646 9647 9668 9669 9659 +5 9667 9647 9648 9649 9669 +7 9668 9649 9650 9657 9658 9659 9667 +5 9656 9651 9652 9653 9655 +6 6654 6651 6652 9672 9692 9682 +6 9671 6652 9673 9677 9681 9682 +6 9672 6652 9674 9675 9676 9677 +6 9673 6652 9675 6650 9728 6366 +6 9673 9674 9676 9726 9727 9728 +6 9673 9675 9677 9678 9679 9726 +6 9673 9676 9678 9680 9681 9672 +5 9677 9676 9679 5236 9680 +7 9678 9676 5236 9735 4520 9726 9734 +6 9678 5236 5237 9677 9681 9684 +7 9677 9680 9672 9682 9683 4655 9684 +6 9672 9681 9683 9692 9671 9686 +5 9682 9681 4655 4656 9686 +6 4655 9681 9680 5237 4653 9685 +6 4653 9684 4651 423 5238 5237 +6 9683 4656 9687 9688 9692 9682 +6 9686 4656 9688 3170 9689 4657 +6 9686 9687 3170 3171 9692 3173 +7 3170 9687 4657 9690 3169 2844 9691 +5 9689 4657 5381 431 9691 +6 2844 9689 9690 431 2842 430 +6 9686 9688 3173 6654 9671 9682 +6 6476 6479 6475 9780 9775 9781 +6 6461 6462 6466 6468 6378 6379 +6 5863 5864 9696 9703 9704 9701 +6 9695 5864 5865 9697 5720 9701 +5 9696 5865 5866 5719 5720 +6 5719 5866 5867 5868 9699 9700 +6 9698 5868 9700 5696 5695 5869 +5 9698 9699 5696 5697 5719 +6 9696 5720 5721 9702 9703 9695 +5 9701 5721 5722 5725 9703 +6 9702 5725 6096 9704 9695 9701 +6 9703 6096 6384 9695 5863 5862 +6 6491 2253 416 2195 6489 6490 +7 6489 2196 6488 6481 2197 9774 9779 +5 2252 6492 3337 6493 3336 +6 3336 6493 3335 6500 6494 6495 +6 6503 6504 9710 2190 9712 9713 +6 6503 9709 2190 6502 9711 2191 +6 6502 9710 6501 2191 2192 2513 +7 9709 6504 6513 9713 9716 9717 9718 +5 9709 9712 2190 9714 9716 +6 2190 9713 2188 2198 9715 9716 +6 2198 9714 9716 2216 2217 9721 +6 9715 9714 9713 9712 9717 2216 +7 9716 9712 9718 9719 9720 2215 2216 +6 9717 9712 6513 6514 6515 9719 +5 9718 6515 6517 9720 9717 +5 9719 6517 9717 2215 6523 +6 9715 2217 2218 2201 2199 2198 +6 6670 6776 9723 9724 6657 6659 +5 9722 6776 9724 9725 9799 +6 9722 9723 9725 6647 6657 6656 +6 9724 9723 6647 6646 9800 9799 +6 9676 9675 9727 9679 9734 9736 +6 9726 9675 9728 9730 9736 9729 +6 9727 9675 9674 6366 6367 9729 +6 9728 6367 6369 6371 9730 9727 +6 9729 6371 9731 9732 9736 9727 +6 9730 6371 6372 6376 6468 9732 +6 9731 6468 6467 9733 9736 9730 +6 9732 6467 6469 7511 9734 9736 +6 9733 7511 9735 9736 9679 9726 +6 9734 7511 7509 4519 4520 9679 +6 9733 9734 9732 9730 9727 9726 +6 6042 6040 6039 6020 5873 5875 +6 6133 6399 6393 6394 6116 9739 +6 9738 6116 6117 6133 6132 6123 +6 570 572 9741 9745 569 9744 +6 9740 572 574 9742 9743 9744 +6 9741 574 917 918 9743 919 +6 9741 9742 919 9744 922 920 +6 9741 9743 922 564 9745 9740 +6 9744 564 565 568 569 9740 +6 7206 7207 9747 7219 7218 7217 +6 9746 7207 7208 7214 7217 7215 +6 3492 3493 3497 3503 6707 6556 +5 6707 3503 9750 3504 6711 +5 6707 9749 6711 6708 6706 +5 6683 5158 4668 6682 9762 +5 3202 3471 3411 3201 3412 +6 5933 5911 5916 5917 9756 5932 +5 4916 4918 9755 4881 4880 +7 9754 4918 4912 4881 9757 4905 9760 +7 9753 5917 5932 5922 5921 5920 9759 +6 4881 9755 9758 4896 4898 9760 +5 4881 9757 4896 4885 4882 +5 5920 9756 5919 5917 5918 +6 9755 4905 4902 4899 4898 9757 +6 4639 4913 4876 4873 4870 4869 +7 6682 9751 4668 4669 9763 4561 9793 +5 9762 4669 4547 4549 4561 +5 8469 8470 9765 9766 8487 +5 8469 9764 9766 7727 7963 +7 9765 9764 8487 7715 7716 7724 7727 +6 8024 8022 7739 7740 7741 7743 +5 7724 7716 7717 7720 7722 +6 428 7501 7503 9770 47 46 +6 9769 7503 9771 9773 45 46 +7 9770 7503 7504 9772 9773 9775 9781 +7 2197 44 2 9773 9771 9774 9775 +5 9772 2 9771 9770 45 +6 2197 9772 9775 9706 9779 9780 +6 9774 9772 9771 9780 9693 9781 +6 7254 7257 7524 7521 7518 7517 +6 2096 2084 2085 6094 3139 3132 +5 6639 6640 6643 6788 6786 +5 9706 9774 9780 6479 6481 +5 9779 9774 9775 9693 6479 +5 9693 9775 6475 9771 7504 +6 3853 3130 27 26 1527 3131 +6 6788 6643 6644 9784 6790 6171 +5 9783 6644 6169 6170 6171 +6 4397 4530 4396 4122 4120 4531 +6 6638 6784 6780 6637 6636 6772 +6 4119 3530 3532 9788 9790 4121 +6 9787 3532 3534 9789 7175 9790 +6 9788 3534 3536 7179 7176 7175 +6 9788 7175 9787 4121 4123 7173 +5 7671 7696 7697 7699 7670 +6 7776 3146 4232 3414 3415 7777 +6 4561 6676 6677 6678 6682 9762 +6 3660 3661 4909 9795 4370 4372 +5 9794 4909 4643 4371 4370 +6 5544 5546 5701 5541 5542 5543 +6 6178 6179 9798 9799 6182 9800 +6 6783 6178 9797 9799 6777 6781 +7 9798 9797 6777 9800 9725 9723 6776 +6 9797 6182 6184 6646 9725 9799 diff --git a/scotch_6.0.3/src/check/data/bump_imbal_32.grf b/scotch_6.0.3/src/check/data/bump_imbal_32.grf new file mode 100644 index 00000000..4f9c24ea --- /dev/null +++ b/scotch_6.0.3/src/check/data/bump_imbal_32.grf @@ -0,0 +1,9803 @@ +0 +9800 57978 +0 001 +1 3 413 407 6 +1 4 9771 43 9772 44 +2 4 76 1474 1475 77 +1 3 1242 147 148 +1 3 693 206 207 +1 3 521 348 349 +1 4 7 412 413 0 +1 4 6 412 8 647 +1 4 9 3238 647 7 +1 4 3235 3238 8 10 +1 4 11 3233 3235 9 +1 4 3234 3233 10 12 +1 4 3684 3234 11 13 +1 4 14 418 3684 12 +1 4 15 417 418 13 +1 4 14 417 16 3088 +1 4 17 3086 3088 15 +1 4 16 3086 3087 18 +1 4 3087 17 3095 19 +1 4 3095 18 3096 20 +1 4 21 414 3096 19 +1 4 20 414 1171 22 +1 4 1171 21 1172 23 +1 4 1172 22 1173 24 +1 4 1173 23 1526 25 +1 4 1526 24 26 9781 +1 4 27 3852 9781 25 +1 4 28 2179 3852 26 +1 4 27 2179 2180 29 +1 4 2180 28 30 2503 +1 4 31 2505 2503 29 +1 4 2508 2505 30 32 +1 4 3330 2508 33 31 +1 4 3330 32 3331 34 +1 4 35 2248 3331 33 +1 4 34 2248 2249 36 +1 4 2249 35 2250 37 +1 4 38 416 2250 36 +1 4 39 415 416 37 +1 4 38 415 2194 40 +1 4 2194 39 2195 41 +1 4 2195 40 2196 42 +1 3 2196 41 43 +1 4 42 2196 9771 1 +1 4 9769 9772 1 45 +1 4 46 9768 9769 44 +1 4 47 427 9768 45 +1 4 48 426 427 46 +1 4 47 426 49 411 +1 4 50 410 411 48 +1 4 49 410 51 421 +1 4 50 421 422 52 +1 4 422 51 4650 53 +1 4 4650 52 4651 54 +1 4 4657 4651 53 55 +1 4 5380 4657 54 56 +1 4 57 430 5380 55 +1 4 56 430 429 58 +1 4 59 408 429 57 +1 4 58 408 2218 60 +1 4 2218 59 2219 61 +1 4 2219 60 2220 62 +1 4 2220 61 2221 63 +1 4 2221 62 2222 64 +1 4 6701 2222 63 65 +1 4 6701 64 6703 66 +1 4 6703 65 3505 67 +1 4 68 3452 3505 66 +1 4 69 3451 3452 67 +1 4 3441 3451 68 70 +2 4 71 2491 3441 69 +2 4 70 2491 2492 72 +2 4 73 409 2492 71 +2 4 72 409 74 428 +2 4 73 428 75 1603 +2 4 74 1603 1604 76 +2 4 2 1474 1604 75 +2 4 1475 2 1476 78 +2 4 1476 77 1477 79 +2 4 1477 78 1478 80 +2 4 1478 79 1479 81 +2 4 1479 80 1480 82 +2 4 1480 81 1481 83 +2 4 1481 82 1482 84 +2 4 1482 83 1483 85 +2 4 86 1160 1483 84 +2 4 85 1160 1161 87 +2 4 1161 86 1162 88 +2 4 1162 87 1163 89 +2 4 1163 88 1186 90 +2 4 1186 89 1185 91 +2 4 1185 90 1187 92 +2 4 1187 91 1188 93 +2 4 1188 92 1189 94 +2 4 1189 93 1190 95 +2 4 1190 94 1191 96 +2 4 1191 95 1192 97 +2 4 1192 96 1193 98 +2 4 1193 97 1194 99 +2 4 1194 98 1195 100 +2 4 1195 99 1196 101 +2 4 1196 100 1197 102 +2 4 1197 101 1198 103 +2 4 1198 102 1199 104 +2 4 1199 103 1200 105 +2 4 1200 104 1201 106 +2 4 1201 105 1202 107 +2 4 1202 106 1203 108 +2 4 1203 107 1204 109 +2 4 1204 108 1205 110 +2 4 1205 109 1206 111 +2 4 1206 110 1207 112 +2 4 1207 111 1208 113 +1 4 1208 112 1209 114 +1 4 1209 113 1210 115 +1 4 1210 114 1211 116 +1 4 1211 115 1212 117 +1 4 1212 116 1213 118 +1 4 1213 117 1214 119 +1 4 1214 118 1215 120 +1 4 1215 119 1216 121 +1 4 1216 120 1217 122 +1 4 1217 121 1218 123 +1 4 1218 122 1219 124 +1 4 1219 123 1220 125 +1 4 1220 124 1221 126 +1 4 1221 125 1222 127 +1 4 1222 126 1223 128 +1 4 1223 127 1224 129 +1 4 1224 128 1225 130 +1 4 1225 129 1226 131 +1 4 1226 130 1227 132 +1 4 1227 131 1228 133 +1 4 1228 132 1229 134 +1 4 1229 133 1230 135 +1 4 1230 134 1231 136 +1 4 1231 135 1232 137 +1 4 1232 136 1233 138 +1 4 1233 137 1234 139 +1 4 1234 138 1235 140 +1 4 1235 139 1236 141 +1 4 1236 140 1237 142 +1 4 1237 141 1238 143 +1 4 1238 142 1239 144 +1 4 1239 143 1240 145 +1 4 1240 144 1241 146 +1 4 1241 145 1242 147 +1 3 1242 146 3 +1 4 1242 3 1243 149 +1 4 1243 148 1244 150 +1 4 1244 149 1245 151 +1 4 1245 150 1246 152 +1 4 1246 151 1247 153 +1 4 1247 152 1248 154 +1 4 155 923 1248 153 +1 4 154 923 924 156 +1 4 924 155 925 157 +1 4 925 156 926 158 +1 4 926 157 927 159 +1 4 927 158 928 160 +1 4 928 159 929 161 +1 4 929 160 930 162 +1 4 930 161 931 163 +1 4 164 651 931 162 +1 4 163 651 652 165 +1 4 652 164 653 166 +1 4 653 165 654 167 +1 4 654 166 655 168 +1 4 655 167 656 169 +1 4 656 168 657 170 +1 4 657 169 658 171 +1 4 658 170 659 172 +1 4 659 171 660 173 +1 4 660 172 661 174 +1 4 661 173 662 175 +1 4 662 174 663 176 +1 4 663 175 664 177 +1 4 664 176 665 178 +1 4 665 177 666 179 +1 4 666 178 667 180 +1 4 667 179 668 181 +1 4 668 180 669 182 +1 4 669 181 670 183 +1 4 670 182 671 184 +1 4 671 183 672 185 +1 4 672 184 673 186 +1 4 673 185 674 187 +1 4 674 186 675 188 +1 4 675 187 676 189 +1 4 676 188 677 190 +1 4 677 189 678 191 +1 4 678 190 679 192 +1 4 679 191 680 193 +1 4 680 192 681 194 +1 4 681 193 682 195 +1 4 682 194 683 196 +1 4 683 195 684 197 +1 4 684 196 685 198 +1 4 685 197 686 199 +1 4 686 198 687 200 +1 4 687 199 688 201 +1 4 688 200 689 202 +1 4 689 201 690 203 +1 4 690 202 691 204 +1 4 691 203 692 205 +1 3 692 204 206 +1 4 692 205 693 4 +1 3 693 4 208 +1 4 693 207 694 209 +1 4 694 208 695 210 +1 4 695 209 696 211 +1 4 696 210 697 212 +1 4 697 211 698 213 +1 4 698 212 699 214 +1 4 699 213 700 215 +1 4 700 214 701 216 +1 4 701 215 702 217 +1 4 702 216 703 218 +1 4 703 217 704 219 +1 4 704 218 705 220 +1 4 705 219 706 221 +1 4 706 220 707 222 +1 4 707 221 708 223 +1 4 708 222 709 224 +1 4 709 223 710 225 +1 4 710 224 711 226 +1 4 711 225 712 227 +1 4 712 226 713 228 +1 4 713 227 714 229 +1 4 714 228 715 230 +1 4 715 229 716 231 +1 4 716 230 717 232 +1 4 717 231 718 233 +1 4 718 232 719 234 +1 4 719 233 720 235 +1 4 720 234 721 236 +1 4 721 235 722 237 +1 4 722 236 723 238 +1 4 723 237 724 239 +1 4 724 238 725 240 +1 4 725 239 726 241 +1 4 726 240 727 242 +1 4 727 241 728 243 +1 4 728 242 729 244 +1 4 729 243 730 245 +1 4 730 244 731 246 +1 4 731 245 732 247 +2 4 732 246 733 248 +2 4 733 247 734 249 +2 4 734 248 735 250 +2 4 735 249 736 251 +2 4 736 250 737 252 +2 4 737 251 738 253 +2 4 738 252 739 254 +2 4 739 253 740 255 +2 4 740 254 741 256 +2 4 741 255 742 257 +2 4 258 431 742 256 +2 4 257 431 432 259 +2 4 432 258 433 260 +2 4 433 259 434 261 +2 4 434 260 435 262 +2 4 435 261 436 263 +2 4 436 262 437 264 +2 4 437 263 438 265 +2 4 438 264 439 266 +2 4 439 265 440 267 +2 4 440 266 441 268 +2 4 441 267 442 269 +2 4 442 268 443 270 +2 4 443 269 444 271 +2 4 444 270 445 272 +1 4 445 271 446 273 +1 4 446 272 447 274 +1 4 447 273 448 275 +1 4 448 274 449 276 +1 4 449 275 450 277 +1 4 450 276 451 278 +1 4 451 277 452 279 +1 4 452 278 453 280 +1 4 453 279 454 281 +1 4 454 280 455 282 +1 4 455 281 456 283 +1 4 456 282 457 284 +1 4 457 283 458 285 +1 4 458 284 459 286 +1 4 459 285 460 287 +1 4 460 286 461 288 +1 4 461 287 462 289 +1 4 462 288 463 290 +1 4 463 289 464 291 +1 4 464 290 465 292 +1 4 465 291 466 293 +1 4 466 292 467 294 +1 4 467 293 468 295 +1 4 468 294 469 296 +1 4 469 295 470 297 +1 4 470 296 471 298 +1 4 471 297 472 299 +1 4 472 298 473 300 +1 4 473 299 474 301 +1 4 474 300 475 302 +1 4 475 301 476 303 +1 4 476 302 477 304 +1 4 477 303 478 305 +1 4 478 304 479 306 +1 4 479 305 480 307 +1 4 480 306 481 308 +1 4 481 307 482 309 +1 4 482 308 483 310 +1 4 483 309 484 311 +1 4 484 310 485 312 +1 4 485 311 486 313 +1 4 486 312 487 314 +1 4 487 313 488 315 +1 4 488 314 489 316 +1 4 489 315 490 317 +1 4 490 316 491 318 +1 4 491 317 492 319 +1 4 492 318 493 320 +1 4 493 319 494 321 +1 4 494 320 495 322 +1 4 495 321 496 323 +1 4 496 322 497 324 +1 4 497 323 498 325 +1 4 498 324 499 326 +1 4 499 325 500 327 +1 4 500 326 501 328 +1 4 501 327 502 329 +1 4 502 328 503 330 +1 4 503 329 504 331 +1 4 504 330 505 332 +1 4 505 331 506 333 +1 4 506 332 507 334 +1 4 507 333 508 335 +1 4 508 334 509 336 +1 4 509 335 510 337 +1 4 510 336 511 338 +1 4 511 337 512 339 +1 4 512 338 513 340 +1 4 513 339 514 341 +1 4 514 340 515 342 +1 4 515 341 516 343 +1 4 516 342 517 344 +1 4 517 343 518 345 +1 4 518 344 519 346 +1 4 519 345 520 347 +1 4 520 346 521 348 +1 3 521 347 5 +1 4 521 5 522 350 +1 4 522 349 523 351 +1 4 523 350 524 352 +1 4 524 351 525 353 +1 4 525 352 526 354 +1 4 526 353 527 355 +1 4 527 354 528 356 +1 4 528 355 529 357 +1 4 529 356 530 358 +1 4 530 357 531 359 +1 4 531 358 532 360 +1 4 532 359 533 361 +1 4 533 360 534 362 +1 4 534 361 535 363 +1 4 535 362 536 364 +1 4 536 363 537 365 +1 4 537 364 538 366 +1 4 538 365 539 367 +1 4 539 366 540 368 +1 4 540 367 541 369 +1 4 541 368 542 370 +1 4 542 369 543 371 +1 4 543 370 544 372 +1 4 544 371 545 373 +1 4 545 372 546 374 +1 4 546 373 547 375 +1 4 550 547 374 376 +1 4 550 375 551 377 +1 4 551 376 552 378 +1 4 552 377 553 379 +1 4 556 553 378 380 +1 4 566 556 379 381 +1 4 566 380 567 382 +1 4 567 381 568 383 +1 4 568 382 569 384 +1 4 569 383 570 385 +1 4 425 570 386 384 +1 4 387 423 425 385 +1 4 386 423 424 388 +1 4 579 424 389 387 +1 4 584 579 388 390 +1 4 584 389 585 391 +1 4 585 390 586 392 +1 4 586 391 420 393 +1 4 394 419 420 392 +1 4 393 419 594 395 +1 4 396 596 594 394 +1 4 622 596 395 397 +1 4 622 396 623 398 +1 4 623 397 624 399 +1 4 398 624 626 400 +1 4 626 399 628 401 +1 4 630 628 402 400 +1 4 630 401 631 403 +1 4 402 631 2097 404 +1 4 405 649 2097 403 +1 4 648 649 404 406 +1 4 648 405 413 407 +1 3 413 406 0 +1 6 58 59 429 2218 2545 2841 +2 6 72 73 2492 2493 1606 428 +1 6 49 50 411 4521 4515 421 +1 6 49 410 48 426 4514 4515 +1 6 6 7 413 647 646 648 +1 6 6 412 648 406 407 0 +1 6 20 21 1171 3882 3128 3096 +1 6 38 39 416 2194 2252 9704 +1 6 38 415 37 2250 2251 2252 +1 6 14 15 418 3088 3098 3099 +1 6 14 417 13 3099 3100 3684 +1 6 393 394 420 593 588 594 +1 6 393 419 586 392 587 588 +1 6 50 51 422 5237 4521 410 +1 6 421 51 52 4650 9684 5237 +1 6 386 387 424 425 577 575 +1 6 423 387 577 578 579 388 +1 6 386 423 572 570 385 575 +1 6 47 48 427 411 4514 5612 +1 6 47 426 46 5612 7500 9768 +2 6 73 74 1603 1605 1606 409 +1 6 58 408 430 57 2841 9690 +1 6 56 57 429 9689 5380 9690 +2 6 257 258 432 742 743 744 +2 6 431 258 259 433 744 745 +2 6 432 259 260 434 745 746 +2 6 433 260 261 435 746 747 +2 6 434 261 262 436 747 748 +2 6 435 262 263 437 748 749 +2 6 436 263 264 438 749 750 +2 6 437 264 265 439 750 751 +2 6 438 265 266 440 751 752 +2 6 439 266 267 441 752 753 +2 6 440 267 268 442 753 754 +2 6 441 268 269 443 754 755 +2 6 442 269 270 444 755 756 +2 6 443 270 271 445 756 757 +2 6 444 271 272 446 757 758 +1 6 445 272 273 447 758 759 +1 6 446 273 274 448 759 760 +1 6 447 274 275 449 760 761 +1 6 448 275 276 450 761 762 +1 6 449 276 277 451 762 763 +1 6 450 277 278 452 763 764 +1 6 451 278 279 453 764 765 +1 6 452 279 280 454 765 766 +1 6 453 280 281 455 766 767 +1 6 454 281 282 456 767 768 +1 6 455 282 283 457 768 769 +1 6 456 283 284 458 769 770 +1 6 457 284 285 459 770 771 +1 6 458 285 286 460 771 772 +1 6 459 286 287 461 772 773 +1 6 460 287 288 462 773 774 +1 6 461 288 289 463 774 775 +1 6 462 289 290 464 775 776 +1 6 463 290 291 465 776 777 +1 6 464 291 292 466 777 778 +1 6 465 292 293 467 778 779 +1 6 466 293 294 468 779 780 +1 6 467 294 295 469 780 781 +1 6 468 295 296 470 781 782 +1 6 469 296 297 471 782 783 +1 6 470 297 298 472 783 784 +1 6 471 298 299 473 784 785 +1 6 472 299 300 474 785 786 +1 6 473 300 301 475 786 787 +1 6 474 301 302 476 787 788 +1 6 475 302 303 477 788 789 +1 6 476 303 304 478 789 790 +1 6 477 304 305 479 790 791 +1 6 478 305 306 480 791 792 +1 6 479 306 307 481 792 793 +1 6 480 307 308 482 793 794 +1 6 481 308 309 483 794 795 +1 6 482 309 310 484 795 796 +1 6 483 310 311 485 796 797 +1 6 484 311 312 486 797 798 +1 6 485 312 313 487 798 799 +1 6 486 313 314 488 799 800 +1 6 487 314 315 489 800 801 +1 6 488 315 316 490 801 802 +1 6 489 316 317 491 802 803 +1 6 490 317 318 492 803 804 +1 6 491 318 319 493 804 805 +1 6 492 319 320 494 805 806 +1 6 493 320 321 495 806 807 +1 6 494 321 322 496 807 808 +1 6 495 322 323 497 808 809 +1 6 496 323 324 498 809 810 +1 6 497 324 325 499 810 811 +1 6 498 325 326 500 811 812 +1 6 499 326 327 501 812 813 +1 6 500 327 328 502 813 814 +1 6 501 328 329 503 814 815 +1 6 502 329 330 504 815 816 +1 6 503 330 331 505 816 817 +1 6 504 331 332 506 817 818 +1 6 505 332 333 507 818 819 +1 6 506 333 334 508 819 820 +1 6 507 334 335 509 820 821 +1 6 508 335 336 510 821 822 +1 6 509 336 337 511 822 823 +1 6 510 337 338 512 823 824 +1 6 511 338 339 513 824 825 +1 6 512 339 340 514 825 826 +1 6 513 340 341 515 826 827 +1 6 514 341 342 516 827 828 +1 6 515 342 343 517 828 829 +1 6 516 343 344 518 829 830 +1 6 517 344 345 519 830 831 +1 6 518 345 346 520 831 832 +1 6 519 346 347 521 832 833 +1 7 520 347 348 5 349 522 833 +1 6 521 349 350 523 833 834 +1 5 522 350 351 524 834 +1 6 523 351 352 525 834 835 +1 6 524 352 353 526 835 836 +1 6 525 353 354 527 836 837 +1 6 526 354 355 528 837 838 +1 6 527 355 356 529 838 839 +1 6 528 356 357 530 839 840 +1 6 529 357 358 531 840 841 +1 6 530 358 359 532 841 842 +1 6 531 359 360 533 842 843 +1 6 532 360 361 534 843 844 +1 6 533 361 362 535 844 845 +1 6 534 362 363 536 845 846 +1 6 535 363 364 537 846 847 +1 6 536 364 365 538 847 848 +1 6 537 365 366 539 848 849 +1 6 538 366 367 540 849 850 +1 6 539 367 368 541 853 850 +1 6 540 368 369 542 855 853 +1 6 541 369 370 543 855 856 +1 6 542 370 371 544 856 857 +1 6 543 371 372 545 857 858 +1 6 544 372 373 546 858 859 +1 6 545 373 374 547 548 859 +1 6 546 374 548 549 550 375 +1 6 546 547 549 859 860 861 +1 6 548 547 550 861 862 863 +1 6 549 547 375 376 551 863 +1 6 550 376 377 552 863 864 +1 6 551 377 378 553 554 864 +1 6 552 378 554 555 556 379 +1 6 552 553 555 557 864 865 +1 6 554 553 556 557 558 565 +1 6 555 553 379 565 566 380 +1 6 554 555 558 559 865 866 +1 6 557 555 559 560 561 565 +1 6 557 558 560 866 867 868 +1 6 559 558 561 562 922 868 +1 6 560 558 562 563 564 565 +1 6 560 561 563 921 920 922 +1 6 562 561 564 9743 921 9744 +1 6 563 561 565 566 9744 567 +1 6 564 561 558 555 556 566 +1 6 565 556 380 381 567 564 +1 6 566 381 382 568 9744 564 +1 6 567 382 383 569 9744 9739 +1 6 568 383 384 570 571 9739 +1 6 569 384 571 572 425 385 +1 6 569 570 572 573 9739 9740 +1 6 571 570 425 573 574 575 +1 6 571 572 574 9740 9741 916 +1 6 573 572 575 576 916 915 +1 6 574 572 425 576 577 423 +1 6 574 575 577 915 2474 1515 +1 6 576 575 423 424 578 1515 +1 6 577 424 579 580 581 1515 +1 6 578 424 388 580 584 389 +1 6 578 579 581 582 583 584 +1 6 578 580 582 1515 1516 1517 +1 6 581 580 583 1517 1508 1506 +1 6 582 580 584 585 589 1506 +1 6 583 580 579 389 390 585 +1 6 584 390 391 586 589 583 +1 6 585 391 392 420 587 589 +1 6 586 420 588 589 590 591 +1 6 587 420 591 592 593 419 +1 6 586 587 590 585 583 1506 +1 6 589 587 591 1506 1507 1514 +1 6 590 587 588 592 599 1514 +1 6 591 588 593 597 598 599 +1 6 592 588 419 594 595 597 +1 6 593 419 394 595 596 395 +1 6 593 594 596 597 621 606 +1 6 595 594 621 622 396 395 +1 6 593 595 592 598 605 606 +1 6 592 597 599 600 604 605 +1 6 592 598 600 601 1514 591 +1 6 599 598 601 602 603 604 +1 6 599 600 602 1513 1514 1539 +1 6 601 600 603 1539 1540 1583 +1 6 602 600 604 1602 1583 608 +1 6 603 600 598 605 607 608 +1 6 604 598 597 606 607 614 +1 6 605 597 621 620 595 614 +1 6 604 605 608 609 610 614 +1 6 604 607 609 1602 603 1600 +1 6 608 607 610 611 1599 1600 +1 6 609 607 611 612 613 614 +1 6 609 610 612 6557 1598 1599 +1 6 611 610 613 615 3764 6557 +1 6 612 610 614 615 616 620 +1 6 613 610 620 606 605 607 +1 6 612 613 616 617 3760 3764 +1 6 615 613 617 618 619 620 +1 6 615 616 618 3760 3761 625 +1 6 617 616 619 623 624 625 +1 6 618 616 620 621 623 622 +1 6 619 616 613 614 621 606 +1 6 619 620 606 595 596 622 +1 6 621 596 396 397 623 619 +1 6 622 397 398 624 618 619 +1 6 623 398 618 625 626 399 +1 6 618 624 626 627 3761 617 +1 6 625 624 627 628 399 400 +1 6 625 626 628 629 3761 3762 +1 6 627 626 629 630 401 400 +1 6 627 628 630 635 3762 632 +1 6 629 628 401 402 631 632 +1 6 630 402 632 633 403 2097 +1 6 630 631 633 634 635 629 +1 6 632 631 634 2097 650 641 +1 6 632 633 635 636 637 641 +1 6 632 634 636 3217 3762 629 +1 6 635 634 637 638 3217 3218 +1 6 636 634 638 639 640 641 +1 6 636 637 639 3218 3219 3220 +1 6 638 637 640 3220 3239 3240 +1 6 639 637 641 642 643 3239 +1 6 640 637 642 633 650 634 +1 6 640 641 643 644 645 650 +1 6 640 642 644 3237 3236 3239 +1 6 643 642 645 646 647 3237 +1 6 644 642 646 648 649 650 +1 5 644 645 647 412 648 +1 7 644 646 412 8 3238 3237 7 +1 7 412 646 645 649 405 406 413 +1 6 648 645 650 405 404 2097 +1 6 649 645 633 2097 641 642 +1 6 163 164 652 931 932 933 +1 6 651 164 165 653 933 934 +1 6 652 165 166 654 934 935 +1 6 653 166 167 655 935 936 +1 6 654 167 168 656 936 937 +1 6 655 168 169 657 937 938 +1 6 656 169 170 658 938 939 +1 6 657 170 171 659 939 940 +1 6 658 171 172 660 940 941 +1 6 659 172 173 661 941 942 +1 6 660 173 174 662 942 943 +1 6 661 174 175 663 943 944 +1 6 662 175 176 664 944 945 +1 6 663 176 177 665 945 946 +1 6 664 177 178 666 946 947 +1 6 665 178 179 667 947 948 +1 6 666 179 180 668 948 949 +1 6 667 180 181 669 949 950 +1 6 668 181 182 670 950 951 +1 6 669 182 183 671 951 952 +1 6 670 183 184 672 952 953 +1 6 671 184 185 673 953 954 +1 6 672 185 186 674 954 955 +1 6 673 186 187 675 955 956 +1 6 674 187 188 676 956 957 +1 6 675 188 189 677 957 958 +1 6 676 189 190 678 958 959 +1 6 677 190 191 679 959 960 +1 6 678 191 192 680 960 961 +1 6 679 192 193 681 961 962 +1 6 680 193 194 682 962 963 +1 6 681 194 195 683 963 964 +1 6 682 195 196 684 964 965 +1 6 683 196 197 685 965 966 +1 6 684 197 198 686 966 967 +1 6 685 198 199 687 967 968 +1 6 686 199 200 688 968 969 +1 6 687 200 201 689 969 970 +1 6 688 201 202 690 970 971 +1 6 689 202 203 691 971 972 +1 6 690 203 204 692 972 973 +1 7 691 204 205 206 693 973 694 +1 6 692 206 4 207 208 694 +1 7 693 208 209 695 973 692 974 +1 6 694 209 210 696 974 975 +1 6 695 210 211 697 975 976 +1 6 696 211 212 698 976 977 +1 6 697 212 213 699 977 978 +1 6 698 213 214 700 978 979 +1 6 699 214 215 701 979 980 +1 6 700 215 216 702 980 981 +1 6 701 216 217 703 981 982 +1 6 702 217 218 704 982 983 +1 6 703 218 219 705 983 984 +1 6 704 219 220 706 984 985 +1 6 705 220 221 707 985 986 +1 6 706 221 222 708 986 987 +1 6 707 222 223 709 987 988 +1 6 708 223 224 710 988 989 +1 6 709 224 225 711 989 990 +1 6 710 225 226 712 990 991 +1 6 711 226 227 713 991 992 +1 6 712 227 228 714 992 993 +1 6 713 228 229 715 993 994 +1 6 714 229 230 716 994 995 +1 6 715 230 231 717 995 996 +1 6 716 231 232 718 996 997 +1 6 717 232 233 719 997 998 +1 6 718 233 234 720 998 999 +1 6 719 234 235 721 999 1000 +1 6 720 235 236 722 1000 1001 +1 6 721 236 237 723 1001 1002 +1 6 722 237 238 724 1002 1003 +1 6 723 238 239 725 1003 1004 +1 6 724 239 240 726 1004 1005 +1 6 725 240 241 727 1005 1006 +1 6 726 241 242 728 1006 1007 +1 6 727 242 243 729 1007 1008 +1 6 728 243 244 730 1008 1009 +1 6 729 244 245 731 1009 1010 +1 6 730 245 246 732 1010 1011 +2 6 731 246 247 733 1011 1012 +2 6 732 247 248 734 1012 1013 +2 6 733 248 249 735 1016 1013 +2 6 734 249 250 736 1016 1017 +2 6 735 250 251 737 1017 1018 +2 6 736 251 252 738 1018 1019 +2 6 737 252 253 739 1019 1020 +2 6 738 253 254 740 1020 1021 +2 6 739 254 255 741 1021 1022 +2 6 740 255 256 742 1022 1023 +2 6 741 256 257 431 743 1023 +2 6 742 431 744 1023 1024 1025 +2 6 743 431 432 745 1025 1026 +2 6 744 432 433 746 1026 1027 +2 6 745 433 434 747 1027 1028 +2 6 746 434 435 748 1028 1029 +2 6 747 435 436 749 1029 1030 +2 6 748 436 437 750 1030 1031 +2 6 749 437 438 751 1031 1032 +2 6 750 438 439 752 1032 1033 +2 6 751 439 440 753 1033 1034 +2 6 752 440 441 754 1034 1035 +2 6 753 441 442 755 1035 1036 +2 6 754 442 443 756 1036 1037 +2 6 755 443 444 757 1037 1038 +2 6 756 444 445 758 1038 1039 +1 6 757 445 446 759 1039 1040 +1 6 758 446 447 760 1040 1041 +1 6 759 447 448 761 1041 1042 +1 6 760 448 449 762 1042 1043 +1 6 761 449 450 763 1043 1044 +1 6 762 450 451 764 1044 1045 +1 6 763 451 452 765 1045 1046 +1 6 764 452 453 766 1046 1047 +1 6 765 453 454 767 1047 1048 +1 6 766 454 455 768 1048 1049 +1 6 767 455 456 769 1049 1050 +1 6 768 456 457 770 1050 1051 +1 6 769 457 458 771 1051 1052 +1 6 770 458 459 772 1052 1053 +1 6 771 459 460 773 1053 1054 +1 6 772 460 461 774 1054 1055 +1 6 773 461 462 775 1055 1056 +1 6 774 462 463 776 1056 1057 +1 6 775 463 464 777 1057 1058 +1 6 776 464 465 778 1058 1059 +1 6 777 465 466 779 1059 1060 +1 6 778 466 467 780 1060 1061 +1 6 779 467 468 781 1061 1062 +1 6 780 468 469 782 1062 1063 +1 6 781 469 470 783 1063 1064 +1 6 782 470 471 784 1064 1065 +1 6 783 471 472 785 1065 1066 +1 6 784 472 473 786 1066 1067 +1 6 785 473 474 787 1067 1068 +1 6 786 474 475 788 1068 1069 +1 6 787 475 476 789 1069 1070 +1 6 788 476 477 790 1070 1071 +1 6 789 477 478 791 1071 1072 +1 6 790 478 479 792 1072 1073 +1 6 791 479 480 793 1073 1074 +1 6 792 480 481 794 1074 1075 +1 6 793 481 482 795 1075 1076 +1 6 794 482 483 796 1076 1077 +1 6 795 483 484 797 1077 1078 +1 6 796 484 485 798 1078 1079 +1 6 797 485 486 799 1079 1080 +1 6 798 486 487 800 1080 1081 +1 6 799 487 488 801 1081 1082 +1 6 800 488 489 802 1082 1083 +1 6 801 489 490 803 1083 1084 +1 6 802 490 491 804 1084 1085 +1 6 803 491 492 805 1085 1086 +1 6 804 492 493 806 1086 1087 +1 6 805 493 494 807 1087 1088 +1 6 806 494 495 808 1088 1089 +1 6 807 495 496 809 1089 1090 +1 6 808 496 497 810 1090 1091 +1 6 809 497 498 811 1091 1092 +1 6 810 498 499 812 1092 1093 +1 6 811 499 500 813 1093 1094 +1 6 812 500 501 814 1094 1095 +1 6 813 501 502 815 1095 1096 +1 6 814 502 503 816 1096 1097 +1 6 815 503 504 817 1097 1098 +1 6 816 504 505 818 1098 1099 +1 6 817 505 506 819 1099 1100 +1 6 818 506 507 820 1100 1101 +1 6 819 507 508 821 1101 1102 +1 6 820 508 509 822 1102 1103 +1 6 821 509 510 823 1103 1104 +1 6 822 510 511 824 1104 1105 +1 6 823 511 512 825 1105 1106 +1 6 824 512 513 826 1106 1107 +1 6 825 513 514 827 1107 1108 +1 6 826 514 515 828 1108 1109 +1 6 827 515 516 829 1109 1110 +1 6 828 516 517 830 1110 1111 +1 6 829 517 518 831 1111 1112 +1 6 830 518 519 832 1112 1113 +1 6 831 519 520 833 1113 1114 +1 6 832 520 521 522 834 1114 +1 6 833 522 523 524 835 1114 +1 7 834 524 525 836 1114 1115 1116 +1 6 835 525 526 837 1116 1117 +1 6 836 526 527 838 1117 1118 +1 6 837 527 528 839 1118 1119 +1 6 838 528 529 840 1119 1120 +1 6 839 529 530 841 1120 1121 +1 6 840 530 531 842 1121 1122 +1 6 841 531 532 843 1122 1123 +1 6 842 532 533 844 1123 1124 +1 6 843 533 534 845 1124 1125 +1 6 844 534 535 846 1125 1126 +1 6 845 535 536 847 1126 1127 +1 6 846 536 537 848 1127 1128 +1 6 847 537 538 849 1128 1129 +1 6 848 538 539 850 851 1129 +1 6 849 539 851 852 853 540 +1 6 849 850 852 1129 1130 1131 +1 6 851 850 853 854 1131 1132 +1 6 852 850 854 855 541 540 +1 6 852 853 855 1132 1133 1134 +1 6 854 853 541 542 856 1134 +1 6 855 542 543 857 1134 1135 +1 6 856 543 544 858 1135 1136 +1 6 857 544 545 859 1136 1137 +1 6 858 545 546 548 860 1137 +1 6 859 548 861 1137 1138 1139 +1 6 860 548 549 862 1139 1140 +1 6 861 549 863 1140 1141 1142 +1 6 862 549 550 551 864 1142 +1 6 863 551 552 554 865 1142 +1 6 864 554 557 866 1142 1143 +1 6 865 557 559 867 1143 1144 +1 6 866 559 868 869 1144 1145 +1 6 867 559 869 870 922 560 +1 6 867 868 870 871 1145 1146 +1 6 869 868 871 872 873 922 +1 6 869 870 872 1146 1147 1148 +1 6 871 870 873 874 1151 1148 +1 6 872 870 874 875 922 920 +1 6 872 873 875 876 1170 1151 +1 6 874 873 876 877 919 920 +1 6 874 875 877 878 879 1170 +1 6 876 875 878 918 882 919 +1 6 876 877 879 880 881 882 +1 6 876 878 880 884 886 1170 +1 6 879 878 881 884 885 891 +1 6 880 878 882 883 891 892 +1 6 881 878 883 917 918 877 +1 6 881 882 912 892 913 917 +1 6 879 880 885 886 887 888 +1 6 884 880 888 889 890 891 +1 6 879 884 887 1964 1169 1170 +1 6 886 884 888 1965 1964 2075 +1 6 887 884 885 889 2075 2076 +1 6 888 885 890 2076 2077 2081 +1 6 889 885 891 893 894 2081 +1 6 890 885 880 881 892 893 +1 6 891 881 893 896 912 883 +1 6 891 892 890 894 895 896 +1 6 890 893 895 897 898 2081 +1 6 894 893 896 897 909 910 +1 6 895 893 892 910 911 912 +1 6 894 895 898 899 900 909 +1 6 894 897 899 901 2081 2080 +1 6 898 897 900 901 902 906 +1 6 899 897 906 907 908 909 +1 6 898 899 902 903 2080 2082 +1 6 901 899 903 904 905 906 +1 6 901 902 904 2082 2083 2084 +1 6 903 902 905 2084 2085 1565 +1 6 904 902 906 1563 1564 1565 +1 6 905 902 899 900 907 1563 +1 6 906 900 908 1543 1563 1536 +1 6 907 900 909 1522 1523 1536 +1 6 908 900 897 895 910 1522 +1 6 909 895 896 911 1520 1522 +1 6 910 896 912 1521 1520 914 +1 6 911 896 892 883 913 914 +1 6 912 883 914 915 916 917 +1 6 912 913 915 2474 1521 911 +1 6 914 913 916 574 576 2474 +1 6 915 913 917 9741 573 574 +1 6 916 913 883 882 918 9741 +1 6 917 882 877 919 9742 9741 +1 6 918 877 875 920 921 9742 +1 6 919 875 921 562 922 873 +1 6 919 920 562 9743 9742 563 +1 6 562 920 873 870 868 560 +1 6 154 155 924 1248 1249 1250 +1 6 923 155 156 925 1250 1251 +1 6 924 156 157 926 1251 1252 +1 6 925 157 158 927 1252 1253 +1 6 926 158 159 928 1253 1254 +1 6 927 159 160 929 1254 1255 +1 6 928 160 161 930 1255 1256 +1 6 929 161 162 931 1256 1257 +1 6 930 162 163 651 932 1257 +1 6 931 651 933 1257 1258 1259 +1 6 932 651 652 934 1259 1260 +1 6 933 652 653 935 1260 1261 +1 6 934 653 654 936 1261 1262 +1 6 935 654 655 937 1262 1263 +1 6 936 655 656 938 1263 1264 +1 6 937 656 657 939 1264 1265 +1 6 938 657 658 940 1265 1266 +1 6 939 658 659 941 1266 1267 +1 6 940 659 660 942 1267 1268 +1 6 941 660 661 943 1268 1269 +1 6 942 661 662 944 1269 1270 +1 6 943 662 663 945 1270 1271 +1 6 944 663 664 946 1271 1272 +1 6 945 664 665 947 1272 1273 +1 6 946 665 666 948 1273 1274 +1 6 947 666 667 949 1274 1275 +1 6 948 667 668 950 1275 1276 +1 6 949 668 669 951 1276 1277 +1 6 950 669 670 952 1277 1278 +1 6 951 670 671 953 1278 1279 +1 6 952 671 672 954 1279 1280 +1 6 953 672 673 955 1280 1281 +1 6 954 673 674 956 1281 1282 +1 6 955 674 675 957 1282 1283 +1 6 956 675 676 958 1283 1284 +1 6 957 676 677 959 1284 1285 +1 6 958 677 678 960 1285 1286 +1 6 959 678 679 961 1286 1287 +1 6 960 679 680 962 1287 1288 +1 6 961 680 681 963 1288 1289 +1 6 962 681 682 964 1289 1290 +1 6 963 682 683 965 1290 1291 +1 6 964 683 684 966 1291 1292 +1 6 965 684 685 967 1292 1293 +1 6 966 685 686 968 1293 1294 +1 6 967 686 687 969 1294 1295 +1 6 968 687 688 970 1295 1296 +1 6 969 688 689 971 1296 1297 +1 6 970 689 690 972 1297 1298 +1 6 971 690 691 973 1298 1299 +1 6 972 691 692 694 974 1299 +1 5 973 694 695 975 1299 +1 6 974 695 696 976 1299 1300 +1 6 975 696 697 977 1300 1301 +1 6 976 697 698 978 1301 1302 +1 6 977 698 699 979 1302 1303 +1 6 978 699 700 980 1303 1304 +1 6 979 700 701 981 1304 1305 +1 6 980 701 702 982 1305 1306 +1 6 981 702 703 983 1306 1307 +1 6 982 703 704 984 1307 1308 +1 6 983 704 705 985 1308 1309 +1 6 984 705 706 986 1309 1310 +1 6 985 706 707 987 1310 1311 +1 6 986 707 708 988 1311 1312 +1 6 987 708 709 989 1312 1313 +1 6 988 709 710 990 1313 1314 +1 6 989 710 711 991 1314 1315 +1 6 990 711 712 992 1315 1316 +1 6 991 712 713 993 1316 1317 +1 6 992 713 714 994 1317 1318 +1 6 993 714 715 995 1318 1319 +1 6 994 715 716 996 1319 1320 +1 6 995 716 717 997 1320 1321 +1 6 996 717 718 998 1321 1322 +1 6 997 718 719 999 1322 1323 +1 6 998 719 720 1000 1323 1324 +1 6 999 720 721 1001 1324 1325 +1 6 1000 721 722 1002 1325 1326 +1 6 1001 722 723 1003 1326 1327 +1 6 1002 723 724 1004 1327 1328 +1 6 1003 724 725 1005 1328 1329 +1 6 1004 725 726 1006 1329 1330 +1 6 1005 726 727 1007 1330 1331 +1 6 1006 727 728 1008 1331 1332 +1 6 1007 728 729 1009 1332 1333 +1 6 1008 729 730 1010 1333 1334 +1 6 1009 730 731 1011 1334 1335 +2 6 1010 731 732 1012 1335 1336 +2 6 1011 732 733 1013 1014 1336 +2 6 1012 733 1014 1015 1016 734 +2 6 1012 1013 1015 1336 1337 1338 +2 6 1014 1013 1016 1338 1339 1340 +2 6 1015 1013 734 735 1017 1340 +2 6 1016 735 736 1018 1340 1341 +2 6 1017 736 737 1019 1341 1342 +2 6 1018 737 738 1020 1342 1343 +2 6 1019 738 739 1021 1343 1344 +2 6 1020 739 740 1022 1344 1345 +2 6 1021 740 741 1023 1345 1346 +2 6 1022 741 742 743 1024 1346 +2 6 1023 743 1025 1346 1347 1348 +2 6 1024 743 744 1026 1348 1349 +2 6 1025 744 745 1027 1349 1350 +2 6 1026 745 746 1028 1350 1351 +2 6 1027 746 747 1029 1351 1352 +2 6 1028 747 748 1030 1352 1353 +2 6 1029 748 749 1031 1353 1354 +2 6 1030 749 750 1032 1354 1355 +2 6 1031 750 751 1033 1355 1356 +2 6 1032 751 752 1034 1356 1357 +2 6 1033 752 753 1035 1357 1358 +2 6 1034 753 754 1036 1358 1359 +2 6 1035 754 755 1037 1359 1360 +2 6 1036 755 756 1038 1360 1361 +2 6 1037 756 757 1039 1361 1362 +1 6 1038 757 758 1040 1362 1363 +1 6 1039 758 759 1041 1363 1364 +1 6 1040 759 760 1042 1364 1365 +1 6 1041 760 761 1043 1365 1366 +1 6 1042 761 762 1044 1366 1367 +1 6 1043 762 763 1045 1367 1368 +1 6 1044 763 764 1046 1368 1369 +1 6 1045 764 765 1047 1369 1370 +1 6 1046 765 766 1048 1370 1371 +1 6 1047 766 767 1049 1371 1372 +1 6 1048 767 768 1050 1372 1373 +1 6 1049 768 769 1051 1373 1374 +1 6 1050 769 770 1052 1374 1375 +1 6 1051 770 771 1053 1375 1376 +1 6 1052 771 772 1054 1376 1377 +1 6 1053 772 773 1055 1377 1378 +1 6 1054 773 774 1056 1378 1379 +1 6 1055 774 775 1057 1379 1380 +1 6 1056 775 776 1058 1380 1381 +1 6 1057 776 777 1059 1381 1382 +1 6 1058 777 778 1060 1382 1383 +1 6 1059 778 779 1061 1383 1384 +1 6 1060 779 780 1062 1384 1385 +1 6 1061 780 781 1063 1385 1386 +1 6 1062 781 782 1064 1386 1387 +1 6 1063 782 783 1065 1387 1388 +1 6 1064 783 784 1066 1388 1389 +1 6 1065 784 785 1067 1389 1390 +1 6 1066 785 786 1068 1390 1391 +1 6 1067 786 787 1069 1391 1392 +1 6 1068 787 788 1070 1392 1393 +1 6 1069 788 789 1071 1393 1394 +1 6 1070 789 790 1072 1394 1395 +1 6 1071 790 791 1073 1395 1396 +1 6 1072 791 792 1074 1396 1397 +1 6 1073 792 793 1075 1397 1398 +1 6 1074 793 794 1076 1398 1399 +1 6 1075 794 795 1077 1399 1400 +1 6 1076 795 796 1078 1400 1401 +1 6 1077 796 797 1079 1401 1402 +1 6 1078 797 798 1080 1402 1403 +1 6 1079 798 799 1081 1403 1404 +1 6 1080 799 800 1082 1404 1405 +1 6 1081 800 801 1083 1405 1406 +1 6 1082 801 802 1084 1406 1407 +1 6 1083 802 803 1085 1407 1408 +1 6 1084 803 804 1086 1408 1409 +1 6 1085 804 805 1087 1409 1410 +1 6 1086 805 806 1088 1410 1411 +1 6 1087 806 807 1089 1411 1412 +1 6 1088 807 808 1090 1412 1413 +1 6 1089 808 809 1091 1413 1414 +1 6 1090 809 810 1092 1414 1415 +1 6 1091 810 811 1093 1415 1416 +1 6 1092 811 812 1094 1416 1417 +1 6 1093 812 813 1095 1417 1418 +1 6 1094 813 814 1096 1418 1419 +1 6 1095 814 815 1097 1419 1420 +1 6 1096 815 816 1098 1420 1421 +1 6 1097 816 817 1099 1421 1422 +1 6 1098 817 818 1100 1422 1423 +1 6 1099 818 819 1101 1423 1424 +1 6 1100 819 820 1102 1424 1425 +1 6 1101 820 821 1103 1425 1426 +1 6 1102 821 822 1104 1426 1427 +1 6 1103 822 823 1105 1427 1428 +1 6 1104 823 824 1106 1428 1429 +1 6 1105 824 825 1107 1429 1430 +1 6 1106 825 826 1108 1430 1431 +1 6 1107 826 827 1109 1431 1432 +1 6 1108 827 828 1110 1432 1433 +1 6 1109 828 829 1111 1433 1434 +1 6 1110 829 830 1112 1434 1435 +1 6 1111 830 831 1113 1435 1436 +1 6 1112 831 832 1114 1436 1115 +1 6 1113 832 833 834 835 1115 +1 6 1114 835 1116 1436 1113 1437 +1 5 1115 835 836 1117 1437 +1 6 1116 836 837 1118 1437 1438 +1 6 1117 837 838 1119 1438 1439 +1 6 1118 838 839 1120 1439 1440 +1 6 1119 839 840 1121 1440 1441 +1 6 1120 840 841 1122 1441 1442 +1 6 1121 841 842 1123 1442 1443 +1 6 1122 842 843 1124 1443 1444 +1 6 1123 843 844 1125 1444 1445 +1 6 1124 844 845 1126 1445 1446 +1 6 1125 845 846 1127 1446 1447 +1 6 1126 846 847 1128 1447 1448 +1 6 1127 847 848 1129 1448 1449 +1 6 1128 848 849 851 1130 1449 +1 6 1129 851 1131 1449 1450 1451 +1 6 1130 851 852 1132 1451 1452 +1 6 1131 852 854 1133 1452 1453 +1 6 1132 854 1134 1456 1453 1152 +1 6 1133 854 855 856 1135 1152 +1 6 1134 856 857 1136 1152 1153 +1 6 1135 857 858 1137 1153 1154 +1 6 1136 858 859 860 1138 1154 +1 6 1137 860 1139 1154 1155 1156 +1 6 1138 860 861 1140 1156 1157 +1 6 1139 861 862 1141 1157 1158 +1 6 1140 862 1142 1158 1159 1143 +1 6 1141 862 863 864 865 1143 +1 6 1142 865 866 1144 1159 1141 +1 6 1143 866 867 1145 1498 1159 +1 6 1144 867 869 1146 1498 1499 +1 6 1145 869 871 1147 1164 1499 +1 6 1146 871 1148 1149 1164 1165 +1 6 1147 871 1149 1150 1151 872 +1 6 1147 1148 1150 1165 1166 1167 +1 6 1149 1148 1151 1167 1168 1169 +1 6 1150 1148 872 1169 1170 874 +1 6 1134 1135 1153 1473 1456 1133 +1 6 1152 1135 1136 1154 1473 1490 +1 6 1153 1136 1137 1138 1155 1490 +1 6 1154 1138 1156 1490 1491 1492 +1 6 1155 1138 1139 1157 1492 1493 +1 6 1156 1139 1140 1158 1493 1494 +1 6 1157 1140 1141 1159 1497 1494 +1 6 1158 1141 1143 1144 1498 1497 +2 6 85 86 1161 1483 1484 1488 +2 6 1160 86 87 1162 1174 1488 +2 6 1161 87 88 1163 1174 1175 +2 6 1162 88 89 1175 1177 1186 +1 6 1146 1147 1165 1499 1527 1528 +1 6 1164 1147 1149 1166 1528 1533 +1 6 1165 1149 1167 1535 1533 1541 +1 6 1166 1149 1150 1168 1541 1962 +1 6 1167 1150 1169 1962 1963 1964 +1 6 1168 1150 1151 1170 886 1964 +1 6 1169 1151 874 886 879 876 +1 6 414 21 22 1172 3337 3882 +1 6 1171 22 23 1173 1524 3337 +1 6 1172 23 24 1524 1525 1526 +2 6 1161 1162 1175 1176 1488 1489 +2 6 1174 1162 1176 1163 1177 1178 +2 6 1174 1175 1489 1642 1643 1178 +2 6 1175 1163 1178 1179 1186 1183 +2 6 1175 1177 1179 1180 1643 1176 +2 6 1178 1177 1180 1181 1182 1183 +2 6 1178 1179 1181 1643 1644 1645 +2 6 1180 1179 1182 1645 1646 1647 +2 6 1181 1179 1183 1184 3097 1647 +2 6 1182 1179 1184 1185 1186 1177 +2 6 1182 1183 1185 3097 2241 1187 +2 6 1184 1183 1186 90 91 1187 +2 6 1185 1183 1177 1163 89 90 +2 6 1185 91 92 1188 2241 1184 +2 6 1187 92 93 1189 2241 1659 +2 6 1188 93 94 1190 1660 1659 +2 6 1189 94 95 1191 1662 1660 +2 6 1190 95 96 1192 1670 1662 +2 6 1191 96 97 1193 1670 1671 +2 6 1192 97 98 1194 1671 1672 +2 6 1193 98 99 1195 1672 1673 +2 6 1194 99 100 1196 1673 1674 +2 6 1195 100 101 1197 1674 1675 +2 6 1196 101 102 1198 1500 1675 +2 6 1197 102 103 1199 1457 1500 +2 6 1198 103 104 1200 1457 1458 +2 6 1199 104 105 1201 1458 1459 +2 6 1200 105 106 1202 1459 1460 +2 6 1201 106 107 1203 1460 1685 +2 6 1202 107 108 1204 1687 1685 +2 6 1203 108 109 1205 1687 1688 +2 6 1204 109 110 1206 1688 1689 +2 6 1205 110 111 1207 1689 1690 +2 6 1206 111 112 1208 1693 1690 +1 6 1207 112 113 1209 1693 1694 +1 6 1208 113 114 1210 1694 1695 +1 6 1209 114 115 1211 1556 1695 +1 6 1210 115 116 1212 1546 1556 +1 6 1211 116 117 1213 1546 1547 +1 6 1212 117 118 1214 1547 1548 +1 6 1213 118 119 1215 1548 1549 +1 6 1214 119 120 1216 1549 1550 +1 6 1215 120 121 1217 1553 1550 +1 6 1216 121 122 1218 1555 1553 +1 6 1217 122 123 1219 1716 1555 +1 6 1218 123 124 1220 1716 1717 +1 6 1219 124 125 1221 1717 1718 +1 6 1220 125 126 1222 1718 1719 +1 6 1221 126 127 1223 1719 1720 +1 6 1222 127 128 1224 1720 1721 +1 6 1223 128 129 1225 1721 1722 +1 6 1224 129 130 1226 1722 1723 +1 6 1225 130 131 1227 1726 1723 +1 6 1226 131 132 1228 1726 1727 +1 6 1227 132 133 1229 1727 1728 +1 6 1228 133 134 1230 1728 1729 +1 6 1229 134 135 1231 1729 1730 +1 6 1230 135 136 1232 1733 1730 +1 6 1231 136 137 1233 1733 1734 +1 6 1232 137 138 1234 1734 1735 +1 6 1233 138 139 1235 1735 1736 +1 6 1234 139 140 1236 1736 1737 +1 6 1235 140 141 1237 1737 1738 +1 6 1236 141 142 1238 1738 1739 +1 6 1237 142 143 1239 1739 1740 +1 6 1238 143 144 1240 1740 1741 +1 6 1239 144 145 1241 1741 1742 +1 6 1240 145 146 1242 1742 1743 +1 7 1241 146 147 3 148 1243 1743 +1 5 1242 148 149 1244 1743 +1 6 1243 149 150 1245 1743 1744 +1 6 1244 150 151 1246 1744 1745 +1 6 1245 151 152 1247 1745 1746 +1 6 1246 152 153 1248 1746 1747 +1 6 1247 153 154 923 1249 1747 +1 6 1248 923 1250 1747 1748 1749 +1 6 1249 923 924 1251 1749 1750 +1 6 1250 924 925 1252 1750 1751 +1 6 1251 925 926 1253 1751 1752 +1 6 1252 926 927 1254 1752 1753 +1 6 1253 927 928 1255 1753 1754 +1 6 1254 928 929 1256 1754 1755 +1 6 1255 929 930 1257 1755 1756 +1 6 1256 930 931 932 1258 1756 +1 6 1257 932 1259 1756 1757 1758 +1 6 1258 932 933 1260 1758 1759 +1 6 1259 933 934 1261 1759 1760 +1 6 1260 934 935 1262 1760 1761 +1 6 1261 935 936 1263 1761 1762 +1 6 1262 936 937 1264 1762 1763 +1 6 1263 937 938 1265 1763 1764 +1 6 1264 938 939 1266 1764 1765 +1 6 1265 939 940 1267 1765 1766 +1 6 1266 940 941 1268 1766 1767 +1 6 1267 941 942 1269 1767 1768 +1 6 1268 942 943 1270 1768 1769 +1 6 1269 943 944 1271 1769 1770 +1 6 1270 944 945 1272 1770 1771 +1 6 1271 945 946 1273 1771 1772 +1 6 1272 946 947 1274 1772 1773 +1 6 1273 947 948 1275 1773 1774 +1 6 1274 948 949 1276 1774 1775 +1 6 1275 949 950 1277 1775 1776 +1 6 1276 950 951 1278 1776 1777 +1 6 1277 951 952 1279 1777 1778 +1 6 1278 952 953 1280 1778 1779 +1 6 1279 953 954 1281 1779 1780 +1 6 1280 954 955 1282 1780 1781 +1 6 1281 955 956 1283 1781 1782 +1 6 1282 956 957 1284 1782 1783 +1 6 1283 957 958 1285 1783 1784 +1 6 1284 958 959 1286 1784 1785 +1 6 1285 959 960 1287 1785 1786 +1 6 1286 960 961 1288 1786 1787 +1 6 1287 961 962 1289 1787 1788 +1 6 1288 962 963 1290 1788 1789 +1 6 1289 963 964 1291 1789 1790 +1 6 1290 964 965 1292 1790 1791 +1 6 1291 965 966 1293 1791 1792 +1 6 1292 966 967 1294 1792 1793 +1 6 1293 967 968 1295 1793 1794 +1 6 1294 968 969 1296 1794 1795 +1 6 1295 969 970 1297 1795 1796 +1 6 1296 970 971 1298 1796 1797 +1 6 1297 971 972 1299 1797 1300 +1 6 1298 972 973 974 975 1300 +1 7 1299 975 976 1301 1797 1298 2100 +1 6 1300 976 977 1302 2100 2101 +1 6 1301 977 978 1303 2101 2102 +1 6 1302 978 979 1304 2102 2103 +1 6 1303 979 980 1305 2103 2104 +1 6 1304 980 981 1306 2104 2105 +1 6 1305 981 982 1307 2105 2106 +1 6 1306 982 983 1308 1798 2106 +1 6 1307 983 984 1309 1798 1799 +1 6 1308 984 985 1310 1799 1800 +1 6 1309 985 986 1311 1800 1801 +1 6 1310 986 987 1312 1801 1802 +1 6 1311 987 988 1313 1802 1803 +1 6 1312 988 989 1314 1803 1804 +1 6 1313 989 990 1315 1804 1805 +1 6 1314 990 991 1316 1805 1806 +1 6 1315 991 992 1317 1806 1807 +1 6 1316 992 993 1318 1807 1808 +1 6 1317 993 994 1319 1808 1809 +1 6 1318 994 995 1320 1809 1810 +1 6 1319 995 996 1321 1810 1811 +1 6 1320 996 997 1322 1811 1812 +1 6 1321 997 998 1323 1812 1813 +1 6 1322 998 999 1324 1813 1814 +1 6 1323 999 1000 1325 1814 1815 +1 6 1324 1000 1001 1326 1815 1816 +1 6 1325 1001 1002 1327 1816 1817 +1 6 1326 1002 1003 1328 1817 1818 +1 6 1327 1003 1004 1329 1818 1819 +1 6 1328 1004 1005 1330 1819 1820 +1 6 1329 1005 1006 1331 1820 1821 +1 6 1330 1006 1007 1332 1821 1822 +1 6 1331 1007 1008 1333 1822 1823 +1 6 1332 1008 1009 1334 1823 1824 +1 6 1333 1009 1010 1335 1824 1825 +1 6 1334 1010 1011 1336 1825 1826 +2 6 1335 1011 1012 1014 1337 1826 +2 6 1336 1014 1338 1826 1827 1828 +2 6 1337 1014 1015 1339 1828 1829 +2 6 1338 1015 1340 1829 1830 1831 +2 6 1339 1015 1016 1017 1341 1831 +2 6 1340 1017 1018 1342 1831 1832 +2 6 1341 1018 1019 1343 1832 1833 +2 6 1342 1019 1020 1344 1833 1834 +2 6 1343 1020 1021 1345 1834 1835 +2 6 1344 1021 1022 1346 1835 1836 +2 6 1345 1022 1023 1024 1347 1836 +2 6 1346 1024 1348 1836 1837 1838 +2 6 1347 1024 1025 1349 1838 1839 +2 6 1348 1025 1026 1350 1839 1840 +2 6 1349 1026 1027 1351 1840 1841 +2 6 1350 1027 1028 1352 1841 1842 +2 6 1351 1028 1029 1353 1842 1843 +2 6 1352 1029 1030 1354 1843 1844 +2 6 1353 1030 1031 1355 1844 1845 +2 6 1354 1031 1032 1356 1845 1846 +2 6 1355 1032 1033 1357 1846 1847 +2 6 1356 1033 1034 1358 1847 1848 +2 6 1357 1034 1035 1359 1848 1849 +2 6 1358 1035 1036 1360 1849 1850 +2 6 1359 1036 1037 1361 1850 1851 +2 6 1360 1037 1038 1362 1851 1852 +2 6 1361 1038 1039 1363 1852 1853 +1 6 1362 1039 1040 1364 1853 1854 +1 6 1363 1040 1041 1365 1854 1855 +1 6 1364 1041 1042 1366 1855 1856 +1 6 1365 1042 1043 1367 1856 1857 +1 6 1366 1043 1044 1368 1857 1858 +1 6 1367 1044 1045 1369 1858 1859 +1 6 1368 1045 1046 1370 1859 1860 +1 6 1369 1046 1047 1371 1860 1861 +1 6 1370 1047 1048 1372 1861 1862 +1 6 1371 1048 1049 1373 1862 1863 +1 6 1372 1049 1050 1374 1863 1864 +1 6 1373 1050 1051 1375 1864 1865 +1 6 1374 1051 1052 1376 1865 1866 +1 6 1375 1052 1053 1377 1866 1867 +1 6 1376 1053 1054 1378 1867 1868 +1 6 1377 1054 1055 1379 1868 1869 +1 6 1378 1055 1056 1380 1869 1870 +1 6 1379 1056 1057 1381 1870 1871 +1 6 1380 1057 1058 1382 1871 1872 +1 6 1381 1058 1059 1383 1872 1873 +1 6 1382 1059 1060 1384 1873 1874 +1 6 1383 1060 1061 1385 1874 1875 +1 6 1384 1061 1062 1386 1875 1876 +1 6 1385 1062 1063 1387 1876 1877 +1 6 1386 1063 1064 1388 1877 1878 +1 6 1387 1064 1065 1389 1878 1879 +1 6 1388 1065 1066 1390 1879 1880 +1 6 1389 1066 1067 1391 1880 1881 +1 6 1390 1067 1068 1392 1881 1882 +1 6 1391 1068 1069 1393 1882 1883 +1 6 1392 1069 1070 1394 1883 1884 +1 6 1393 1070 1071 1395 1884 1885 +1 6 1394 1071 1072 1396 1885 1886 +1 6 1395 1072 1073 1397 1886 1887 +1 6 1396 1073 1074 1398 1887 1888 +1 6 1397 1074 1075 1399 1888 1889 +1 6 1398 1075 1076 1400 1889 1890 +1 6 1399 1076 1077 1401 1890 1891 +1 6 1400 1077 1078 1402 1891 1892 +1 6 1401 1078 1079 1403 1892 1893 +1 6 1402 1079 1080 1404 1893 1894 +1 6 1403 1080 1081 1405 1894 1895 +1 6 1404 1081 1082 1406 1895 1896 +1 6 1405 1082 1083 1407 1896 1897 +1 6 1406 1083 1084 1408 1897 1898 +1 6 1407 1084 1085 1409 1898 1899 +1 6 1408 1085 1086 1410 1899 1900 +1 6 1409 1086 1087 1411 1900 1901 +1 6 1410 1087 1088 1412 1901 1902 +1 6 1411 1088 1089 1413 1902 1903 +1 6 1412 1089 1090 1414 1903 1904 +1 6 1413 1090 1091 1415 1904 1905 +1 6 1414 1091 1092 1416 1905 1906 +1 6 1415 1092 1093 1417 1906 1907 +1 6 1416 1093 1094 1418 1907 1908 +1 6 1417 1094 1095 1419 1908 1909 +1 6 1418 1095 1096 1420 1909 1910 +1 6 1419 1096 1097 1421 1910 1911 +1 6 1420 1097 1098 1422 1911 1912 +1 6 1421 1098 1099 1423 1912 1913 +1 6 1422 1099 1100 1424 1913 1914 +1 6 1423 1100 1101 1425 1914 1915 +1 6 1424 1101 1102 1426 1915 1916 +1 6 1425 1102 1103 1427 1916 1917 +1 6 1426 1103 1104 1428 1917 1918 +1 6 1427 1104 1105 1429 1918 1919 +1 6 1428 1105 1106 1430 1919 1920 +1 6 1429 1106 1107 1431 1920 1921 +1 6 1430 1107 1108 1432 1921 1922 +1 6 1431 1108 1109 1433 1922 1923 +1 6 1432 1109 1110 1434 1923 1924 +1 6 1433 1110 1111 1435 1924 1925 +1 6 1434 1111 1112 1436 1925 1926 +1 6 1435 1112 1113 1115 1437 1926 +1 6 1436 1115 1116 1117 1438 1926 +1 6 1437 1117 1118 1439 1926 1927 +1 6 1438 1118 1119 1440 1927 1928 +1 6 1439 1119 1120 1441 1928 1929 +1 6 1440 1120 1121 1442 1929 1930 +1 6 1441 1121 1122 1443 1930 1931 +1 6 1442 1122 1123 1444 1931 1932 +1 6 1443 1123 1124 1445 1461 1932 +1 6 1444 1124 1125 1446 1461 1462 +1 6 1445 1125 1126 1447 1462 1463 +1 6 1446 1126 1127 1448 1463 1464 +1 6 1447 1127 1128 1449 1464 1465 +1 6 1448 1128 1129 1130 1450 1465 +1 6 1449 1130 1451 1465 1466 1467 +1 6 1450 1130 1131 1452 1467 1468 +1 6 1451 1131 1132 1453 1454 1468 +1 6 1452 1132 1454 1455 1456 1133 +1 6 1452 1453 1455 1468 1469 1470 +1 6 1454 1453 1456 1470 1471 1472 +1 6 1455 1453 1133 1472 1473 1152 +2 6 1198 1199 1458 1500 1501 1679 +2 6 1457 1199 1200 1459 1679 1680 +2 6 1458 1200 1201 1460 1680 1681 +2 6 1459 1201 1202 1681 1684 1685 +1 6 1444 1445 1462 1932 1933 1934 +1 6 1461 1445 1446 1463 1934 1935 +1 6 1462 1446 1447 1464 1935 1936 +1 6 1463 1447 1448 1465 1936 1937 +1 6 1464 1448 1449 1450 1466 1937 +1 6 1465 1450 1467 1937 1938 1939 +1 6 1466 1450 1451 1468 1939 1940 +1 6 1467 1451 1452 1454 1469 1940 +1 6 1468 1454 1470 1940 1941 1942 +1 6 1469 1454 1455 1471 1942 1943 +1 6 1470 1455 1472 1943 1944 1945 +1 6 1471 1455 1456 1473 1945 1946 +1 6 1472 1456 1152 1153 1490 1946 +2 7 76 2 1475 1608 1604 1609 1618 +2 6 1474 2 77 1476 1620 1618 +2 6 1475 77 78 1477 1620 1621 +2 6 1476 78 79 1478 1621 1622 +2 6 1477 79 80 1479 1630 1622 +2 6 1478 80 81 1480 1630 1631 +2 6 1479 81 82 1481 1631 1632 +2 6 1480 82 83 1482 1635 1632 +2 6 1481 83 84 1483 1485 1635 +2 6 1482 84 85 1160 1484 1485 +2 6 1483 1160 1485 1486 1487 1488 +2 6 1483 1484 1486 1502 1635 1482 +2 6 1485 1484 1487 1502 1503 1504 +2 6 1486 1484 1488 1504 1505 1489 +2 6 1487 1484 1160 1161 1174 1489 +2 6 1488 1174 1176 1505 1487 1642 +1 6 1473 1153 1154 1155 1491 1946 +1 6 1490 1155 1492 1946 1947 1948 +1 6 1491 1155 1156 1493 1948 1949 +1 6 1492 1156 1157 1494 1495 1949 +1 6 1493 1157 1495 1496 1497 1158 +1 6 1493 1494 1496 1951 1949 1952 +1 6 1495 1494 1497 1952 1530 1529 +1 6 1496 1494 1158 1159 1498 1529 +1 6 1144 1145 1499 1159 1497 1529 +1 6 1498 1145 1146 1164 1527 1529 +2 6 1197 1198 1457 1501 1675 1676 +2 6 1500 1457 1676 1677 1678 1679 +2 6 1485 1486 1503 1637 1634 1635 +2 6 1502 1486 1504 1637 1638 1639 +2 6 1503 1486 1487 1505 1639 1640 +2 6 1504 1487 1489 1640 1641 1642 +1 6 583 589 590 1507 1508 582 +1 6 1506 590 1508 1509 1513 1514 +1 6 1506 1507 1509 1510 1517 582 +1 6 1508 1507 1510 1511 1512 1513 +1 6 1508 1509 1511 1517 1518 1519 +1 6 1510 1509 1512 1523 1519 1537 +1 6 1511 1509 1513 1537 1538 1539 +1 6 1512 1509 1507 1514 601 1539 +1 6 1513 1507 601 599 591 590 +1 6 577 578 581 1516 2474 576 +1 6 1515 581 1517 1518 1521 2474 +1 6 1516 581 582 1508 1510 1518 +1 6 1517 1510 1519 1520 1521 1516 +1 6 1518 1510 1520 1522 1523 1511 +1 6 1518 1519 1521 911 910 1522 +1 6 1518 1520 911 1516 2474 914 +1 6 910 1520 1519 1523 908 909 +1 6 1522 1519 1511 908 1536 1537 +1 6 1172 1173 1525 3337 3338 4250 +1 6 1524 1173 1526 3130 2205 4250 +1 6 1525 1173 24 25 3130 9781 +1 6 1499 1164 1528 1529 1530 1531 +1 6 1527 1164 1165 1531 1532 1533 +1 6 1497 1498 1499 1527 1530 1496 +1 6 1529 1527 1531 1952 1496 1953 +1 6 1530 1527 1528 1532 1953 1954 +1 6 1531 1528 1533 1534 1954 1955 +1 6 1532 1528 1534 1535 1166 1165 +1 6 1532 1533 1535 1955 1956 1957 +1 6 1534 1533 1166 1541 1960 1957 +1 6 908 1523 1537 1542 1543 907 +1 6 1536 1523 1511 1512 1538 1542 +1 6 1537 1512 1539 1540 1545 1542 +1 6 1538 1512 1513 601 602 1540 +1 6 1539 602 1538 1582 1545 1583 +1 6 1535 1166 1167 1960 1961 1962 +1 6 1536 1537 1543 1544 1545 1538 +1 6 1536 1542 1544 1562 1563 907 +1 6 1543 1542 1545 1562 1580 1577 +1 6 1544 1542 1538 1582 1580 1540 +1 6 1211 1212 1547 1556 1557 1558 +1 6 1546 1212 1213 1548 1561 1558 +1 6 1547 1213 1214 1549 1710 1561 +1 6 1548 1214 1215 1550 1551 1710 +1 6 1549 1215 1551 1552 1553 1216 +1 6 1549 1550 1552 1710 1711 1712 +1 6 1551 1550 1553 1554 1712 1713 +1 6 1552 1550 1554 1555 1217 1216 +1 6 1552 1553 1555 1713 1714 1715 +1 6 1554 1553 1217 1715 1716 1218 +1 6 1210 1211 1546 1557 1695 1696 +1 6 1556 1546 1558 1559 1696 1697 +1 6 1557 1546 1559 1560 1561 1547 +1 6 1557 1558 1560 1697 1698 1699 +1 6 1559 1558 1561 1699 1700 1709 +1 6 1560 1558 1547 1709 1710 1548 +1 6 1543 1544 1563 1564 1576 1577 +1 6 1543 1562 1564 905 907 906 +1 6 1563 1562 905 1565 1566 1576 +1 6 905 1564 1566 1567 2085 904 +1 6 1565 1564 1567 1568 1569 1576 +1 6 1565 1566 1568 2085 3766 3767 +1 6 1567 1566 1569 1570 1571 3767 +1 6 1568 1566 1570 1574 1575 1576 +1 6 1568 1569 1571 1572 1573 1574 +1 7 1568 1570 1572 3769 3767 6317 6319 +1 5 1571 1570 1573 6319 6320 +1 7 1572 1570 1574 6320 6361 6360 2475 +1 6 1573 1570 1569 1575 1578 2475 +1 6 1574 1569 1576 1577 1578 1579 +1 6 1575 1569 1566 1564 1562 1577 +1 6 1576 1562 1575 1579 1580 1544 +1 6 1574 1575 1579 1586 1587 2475 +1 6 1578 1575 1577 1580 1581 1586 +1 6 1579 1577 1544 1581 1582 1545 +1 6 1579 1580 1582 1584 1585 1586 +1 6 1581 1580 1545 1540 1583 1584 +1 6 1582 1540 1584 1602 603 602 +1 6 1582 1583 1581 1585 1601 1602 +1 6 1581 1584 1586 1591 1588 1601 +1 6 1581 1585 1579 1578 1587 1588 +1 6 1578 1586 1588 1589 2475 2476 +1 6 1587 1586 1589 1590 1591 1585 +1 6 1587 1588 1590 6354 6353 2476 +1 6 1589 1588 1591 1592 1594 6354 +1 6 1590 1588 1585 1592 1593 1601 +1 6 1590 1591 1593 1594 1595 1596 +1 6 1592 1591 1599 1596 1600 1601 +1 6 1590 1592 1595 6358 6356 6354 +1 6 1594 1592 1596 1597 3970 6358 +1 6 1595 1592 1597 1598 1599 1593 +1 6 1595 1596 1598 3970 3969 6556 +1 6 1597 1596 1599 6556 6557 611 +1 6 1598 1596 1593 1600 611 609 +1 6 1599 1593 1601 1602 608 609 +1 6 1600 1593 1591 1585 1584 1602 +1 6 1600 1601 1584 1583 603 608 +2 6 74 75 1604 428 1605 1608 +2 5 1603 75 76 1608 1474 +2 6 428 1603 1606 1607 1608 3519 +2 6 428 1605 1607 2493 409 3516 +2 6 1606 1605 3518 3516 1613 3519 +2 7 1605 1603 1604 1474 1609 1610 3519 +2 5 1608 1474 1610 1611 1618 +2 6 1608 1609 1611 1612 1613 3519 +2 6 1610 1609 1612 1616 1617 1618 +2 6 1610 1611 1613 1614 1615 1616 +2 7 1610 1612 1614 3518 1607 3519 3523 +2 6 1613 1612 1615 3523 3524 3528 +2 6 1614 1612 1616 3093 3544 3528 +2 6 1615 1612 1611 1617 3093 3094 +2 6 1616 1611 1618 1619 3094 1624 +2 7 1617 1611 1619 1620 1475 1609 1474 +2 6 1617 1618 1620 1621 1623 1624 +2 5 1619 1618 1475 1476 1621 +2 6 1620 1476 1477 1622 1623 1619 +2 6 1621 1477 1623 1629 1630 1478 +2 6 1621 1622 1619 1624 1625 1629 +2 7 1619 1623 1625 1626 1617 3094 4367 +2 6 1624 1623 1626 1627 1628 1629 +2 5 1624 1625 1627 4376 4367 +2 7 1626 1625 1628 4377 4376 2862 7215 +2 6 1627 1625 1629 2861 1633 2862 +2 6 1628 1625 1623 1622 1630 2861 +2 6 1629 1622 1478 1479 1631 2861 +2 6 1630 1479 1480 1632 1633 2861 +2 6 1631 1480 1633 1634 1635 1481 +2 7 1631 1632 1634 1636 2861 1628 2862 +2 6 1633 1632 1635 1636 1637 1502 +2 6 1634 1632 1481 1502 1485 1482 +2 5 1633 1634 1637 2862 2863 +2 7 1636 1634 1502 1503 1638 2863 2864 +2 5 1637 1503 1639 2864 2865 +2 6 1638 1503 1504 1640 2865 2866 +2 6 1639 1504 1505 1641 2866 2867 +2 6 1640 1505 1642 2479 2490 2867 +2 6 1641 1505 1489 1176 1643 2479 +2 6 1642 1176 1178 1180 1644 2479 +2 6 1643 1180 1645 2479 2480 2481 +2 6 1644 1180 1181 1646 2481 1650 +2 6 1645 1181 1647 1648 1649 1650 +2 6 1646 1181 1648 1655 3097 1182 +2 6 1646 1647 1649 1653 1654 1655 +2 6 1646 1648 1650 1651 1652 1653 +2 6 1646 1649 1651 2481 1645 2495 +2 6 1650 1649 1652 2495 2496 2497 +2 6 1651 1649 1653 2497 2498 2499 +2 6 1652 1649 1648 1654 2499 2500 +2 6 1653 1648 1655 1656 2500 2501 +2 6 1654 1648 1647 1656 1657 3097 +2 6 1654 1655 1657 1658 2501 2812 +2 6 1656 1655 1658 1659 2241 3097 +2 6 1656 1657 1659 1660 1661 2812 +2 6 1658 1657 1660 1189 1188 2241 +2 6 1658 1659 1661 1662 1190 1189 +2 6 1658 1660 1662 1663 1664 2812 +2 6 1661 1660 1663 1670 1191 1190 +2 6 1661 1662 1664 1665 1669 1670 +2 6 1661 1663 1665 1666 2812 2811 +2 6 1664 1663 1666 1667 1668 1669 +2 6 1664 1665 1667 2811 2813 2814 +2 6 1666 1665 1668 2814 2815 2816 +2 6 1667 1665 1669 2816 2821 2822 +2 6 1668 1665 1663 1670 1671 2822 +2 6 1669 1663 1662 1191 1192 1671 +2 6 1670 1192 1193 1672 2822 1669 +2 6 1671 1193 1194 1673 2823 2822 +2 6 1672 1194 1195 1674 3147 2823 +2 6 1673 1195 1196 1675 3147 3412 +2 6 1674 1196 1197 1500 1676 3412 +2 6 1675 1500 1501 1677 3412 3413 +2 6 1676 1501 1678 3413 3414 3415 +2 6 1677 1501 1679 3415 5381 5382 +2 6 1678 1501 1457 1458 1680 5381 +2 6 1679 1458 1459 1681 1682 5381 +2 6 1680 1459 1460 1682 1683 1684 +2 6 1680 1681 1683 3774 5383 5381 +2 6 1682 1681 1684 3774 3775 3776 +2 6 1683 1681 1460 1685 1686 3776 +2 6 1684 1460 1686 1687 1203 1202 +2 6 1684 1685 1687 3776 3777 3781 +2 6 1686 1685 1203 1204 1688 3781 +2 6 1687 1204 1205 1689 3781 3782 +2 6 1688 1205 1206 1690 1691 3782 +2 6 1689 1206 1691 1692 1693 1207 +2 6 1689 1690 1692 3782 3783 3784 +2 6 1691 1690 1693 3784 3785 3786 +2 6 1692 1690 1207 1208 1694 3786 +1 6 1693 1208 1209 1695 3786 3416 +1 6 1694 1209 1210 1556 1696 3416 +1 6 1695 1556 1557 1697 3416 3417 +1 6 1696 1557 1559 1698 3417 3418 +1 6 1697 1559 1699 1703 2223 3418 +1 6 1698 1559 1560 1700 1701 1703 +1 6 1699 1560 1701 1702 1708 1709 +1 6 1699 1700 1702 1703 1704 1705 +1 6 1701 1700 1705 1706 1707 1708 +1 6 1699 1701 1704 1698 2223 2224 +1 6 1703 1701 1705 2224 2225 2226 +1 6 1704 1701 1702 1706 2226 2227 +1 6 1705 1702 1707 2227 2228 2229 +1 6 1706 1702 1708 2229 2230 2231 +1 6 1707 1702 1700 1709 1711 2231 +1 6 1708 1700 1560 1561 1710 1711 +1 6 1709 1561 1548 1549 1551 1711 +1 6 1710 1551 1712 2231 1708 1709 +1 6 1711 1551 1552 1713 2232 2231 +1 6 1712 1552 1554 1714 2240 2232 +1 6 1713 1554 1715 2240 2560 2564 +1 6 1714 1554 1555 1716 2564 2565 +1 6 1715 1555 1218 1219 1717 2565 +1 6 1716 1219 1220 1718 2565 2566 +1 6 1717 1220 1221 1719 2569 2566 +1 6 1718 1221 1222 1720 3463 2569 +1 6 1719 1222 1223 1721 3462 3463 +1 6 1720 1223 1224 1722 3469 3462 +1 6 1721 1224 1225 1723 1724 3469 +1 6 1722 1225 1724 1725 1726 1226 +1 6 1722 1723 1725 2172 3467 3469 +1 6 1724 1723 1726 2172 2173 2174 +1 6 1725 1723 1226 1227 1727 2174 +1 6 1726 1227 1228 1728 2174 2175 +1 6 1727 1228 1229 1729 2175 2176 +1 6 1728 1229 1230 1730 1731 2176 +1 6 1729 1230 1731 1732 1733 1231 +1 6 1729 1730 1732 2178 2176 2808 +1 6 1731 1730 1733 3404 2808 3405 +1 6 1732 1730 1231 1232 1734 3405 +1 6 1733 1232 1233 1735 3405 3406 +1 6 1734 1233 1234 1736 3406 3407 +1 6 1735 1234 1235 1737 3407 3408 +1 6 1736 1235 1236 1738 3408 3409 +1 6 1737 1236 1237 1739 3409 3410 +1 6 1738 1237 1238 1740 3410 3411 +1 6 1739 1238 1239 1741 3197 3411 +1 6 1740 1239 1240 1742 3191 3197 +1 6 1741 1240 1241 1743 3191 1744 +1 6 1742 1241 1242 1243 1244 1744 +1 7 1743 1244 1245 1745 3191 1742 3199 +1 6 1744 1245 1246 1746 2893 3199 +1 6 1745 1246 1247 1747 2751 2893 +1 6 1746 1247 1248 1249 1748 2751 +1 6 1747 1249 1749 2233 2751 2752 +1 6 1748 1249 1250 1750 2233 2234 +1 6 1749 1250 1251 1751 2237 2234 +1 6 1750 1251 1252 1752 2247 2237 +1 6 1751 1252 1253 1753 2247 2253 +1 6 1752 1253 1254 1754 2253 2254 +1 6 1753 1254 1255 1755 2254 2255 +1 6 1754 1255 1256 1756 2255 2256 +1 6 1755 1256 1257 1258 1757 2256 +1 6 1756 1258 1758 2256 2257 2258 +1 6 1757 1258 1259 1759 2258 2259 +1 6 1758 1259 1260 1760 2259 2260 +1 6 1759 1260 1261 1761 2260 2261 +1 6 1760 1261 1262 1762 2261 2262 +1 6 1761 1262 1263 1763 2262 2263 +1 6 1762 1263 1264 1764 2263 2264 +1 6 1763 1264 1265 1765 2264 2265 +1 6 1764 1265 1266 1766 2265 2266 +1 6 1765 1266 1267 1767 2266 2267 +1 6 1766 1267 1268 1768 2267 2268 +1 6 1767 1268 1269 1769 2268 2269 +1 6 1768 1269 1270 1770 2269 2270 +1 6 1769 1270 1271 1771 2270 2271 +1 6 1770 1271 1272 1772 2271 2272 +1 6 1771 1272 1273 1773 2272 2273 +1 6 1772 1273 1274 1774 2273 2274 +1 6 1773 1274 1275 1775 2274 2275 +1 6 1774 1275 1276 1776 2275 2276 +1 6 1775 1276 1277 1777 2276 2277 +1 6 1776 1277 1278 1778 2277 2278 +1 6 1777 1278 1279 1779 2278 2279 +1 6 1778 1279 1280 1780 2279 2280 +1 6 1779 1280 1281 1781 2280 2281 +1 6 1780 1281 1282 1782 2281 2282 +1 6 1781 1282 1283 1783 2282 2283 +1 6 1782 1283 1284 1784 2283 2284 +1 6 1783 1284 1285 1785 2284 2285 +1 6 1784 1285 1286 1786 2285 2286 +1 6 1785 1286 1287 1787 2286 2287 +1 6 1786 1287 1288 1788 2287 2288 +1 6 1787 1288 1289 1789 2288 2289 +1 6 1788 1289 1290 1790 2289 2290 +1 6 1789 1290 1291 1791 2290 2291 +1 6 1790 1291 1292 1792 2291 2292 +1 6 1791 1292 1293 1793 2292 2293 +1 6 1792 1293 1294 1794 2293 2294 +1 6 1793 1294 1295 1795 2294 2295 +1 6 1794 1295 1296 1796 2098 2295 +1 6 1795 1296 1297 1797 2098 2099 +1 6 1796 1297 1298 1300 2099 2100 +1 6 1307 1308 1799 2106 2107 2108 +1 6 1798 1308 1309 1800 2108 2109 +1 6 1799 1309 1310 1801 2109 2110 +1 6 1800 1310 1311 1802 2110 2111 +1 6 1801 1311 1312 1803 2111 2112 +1 6 1802 1312 1313 1804 2112 2113 +1 6 1803 1313 1314 1805 2113 2114 +1 6 1804 1314 1315 1806 2114 2115 +1 6 1805 1315 1316 1807 2115 2116 +1 6 1806 1316 1317 1808 2116 2117 +1 6 1807 1317 1318 1809 2117 2118 +1 6 1808 1318 1319 1810 2118 2119 +1 6 1809 1319 1320 1811 2119 2120 +1 6 1810 1320 1321 1812 2120 2121 +1 6 1811 1321 1322 1813 2121 2122 +1 6 1812 1322 1323 1814 2122 2123 +1 6 1813 1323 1324 1815 2123 2124 +1 6 1814 1324 1325 1816 2124 2125 +1 6 1815 1325 1326 1817 2125 2126 +1 6 1816 1326 1327 1818 2126 2127 +1 6 1817 1327 1328 1819 2127 2128 +1 6 1818 1328 1329 1820 2128 2129 +1 6 1819 1329 1330 1821 2129 2130 +1 6 1820 1330 1331 1822 2130 2131 +1 6 1821 1331 1332 1823 2131 2132 +1 6 1822 1332 1333 1824 2132 2133 +1 6 1823 1333 1334 1825 2133 2134 +1 6 1824 1334 1335 1826 2134 2135 +2 6 1825 1335 1336 1337 1827 2135 +2 6 1826 1337 1828 2135 2136 2137 +2 6 1827 1337 1338 1829 2137 2138 +2 6 1828 1338 1339 1830 2138 2139 +2 6 1829 1339 1831 2139 2140 2141 +2 6 1830 1339 1340 1341 1832 2141 +2 6 1831 1341 1342 1833 2141 2142 +2 6 1832 1342 1343 1834 2142 2143 +2 6 1833 1343 1344 1835 2143 2144 +2 6 1834 1344 1345 1836 2144 2145 +2 6 1835 1345 1346 1347 1837 2145 +2 6 1836 1347 1838 2150 2145 2165 +2 6 1837 1347 1348 1839 2165 2166 +2 6 1838 1348 1349 1840 2166 2167 +2 6 1839 1349 1350 1841 2167 2168 +2 6 1840 1350 1351 1842 2171 2168 +2 6 1841 1351 1352 1843 2349 2171 +2 6 1842 1352 1353 1844 2349 2350 +2 6 1843 1353 1354 1845 2350 2351 +2 6 1844 1354 1355 1846 2351 2352 +2 6 1845 1355 1356 1847 2352 2353 +2 6 1846 1356 1357 1848 2353 2354 +2 6 1847 1357 1358 1849 2354 2355 +2 6 1848 1358 1359 1850 2355 2356 +2 6 1849 1359 1360 1851 2356 2357 +2 6 1850 1360 1361 1852 2357 2358 +2 6 1851 1361 1362 1853 2358 2359 +2 6 1852 1362 1363 1854 2359 2360 +1 6 1853 1363 1364 1855 2360 2361 +1 6 1854 1364 1365 1856 1966 2361 +1 6 1855 1365 1366 1857 1966 1967 +1 6 1856 1366 1367 1858 1967 1968 +1 6 1857 1367 1368 1859 1968 1969 +1 6 1858 1368 1369 1860 1969 1970 +1 6 1859 1369 1370 1861 1970 1971 +1 6 1860 1370 1371 1862 1971 1972 +1 6 1861 1371 1372 1863 1972 1973 +1 6 1862 1372 1373 1864 1973 1974 +1 6 1863 1373 1374 1865 1974 1975 +1 6 1864 1374 1375 1866 1975 1976 +1 6 1865 1375 1376 1867 1976 1977 +1 6 1866 1376 1377 1868 1977 1978 +1 6 1867 1377 1378 1869 1978 1979 +1 6 1868 1378 1379 1870 1979 1980 +1 6 1869 1379 1380 1871 1980 1981 +1 6 1870 1380 1381 1872 1981 1982 +1 6 1871 1381 1382 1873 1982 1983 +1 6 1872 1382 1383 1874 1983 1984 +1 6 1873 1383 1384 1875 1984 1985 +1 6 1874 1384 1385 1876 1985 1986 +1 6 1875 1385 1386 1877 1986 1987 +1 6 1876 1386 1387 1878 1987 1988 +1 6 1877 1387 1388 1879 1988 1989 +1 6 1878 1388 1389 1880 1989 1990 +1 6 1879 1389 1390 1881 1990 1991 +1 6 1880 1390 1391 1882 1991 1992 +1 6 1881 1391 1392 1883 1992 1993 +1 6 1882 1392 1393 1884 1993 1994 +1 6 1883 1393 1394 1885 1994 1995 +1 6 1884 1394 1395 1886 1995 1996 +1 6 1885 1395 1396 1887 1996 1997 +1 6 1886 1396 1397 1888 1997 1998 +1 6 1887 1397 1398 1889 1998 1999 +1 6 1888 1398 1399 1890 1999 2000 +1 6 1889 1399 1400 1891 2000 2001 +1 6 1890 1400 1401 1892 2001 2002 +1 6 1891 1401 1402 1893 2002 2003 +1 6 1892 1402 1403 1894 2003 2004 +1 6 1893 1403 1404 1895 2004 2005 +1 6 1894 1404 1405 1896 2005 2006 +1 6 1895 1405 1406 1897 2006 2007 +1 6 1896 1406 1407 1898 2007 2008 +1 6 1897 1407 1408 1899 2008 2009 +1 6 1898 1408 1409 1900 2009 2010 +1 6 1899 1409 1410 1901 2010 2011 +1 6 1900 1410 1411 1902 2011 2012 +1 6 1901 1411 1412 1903 2012 2013 +1 6 1902 1412 1413 1904 2013 2014 +1 6 1903 1413 1414 1905 2014 2015 +1 6 1904 1414 1415 1906 2015 2016 +1 6 1905 1415 1416 1907 2016 2017 +1 6 1906 1416 1417 1908 2017 2018 +1 6 1907 1417 1418 1909 2018 2019 +1 6 1908 1418 1419 1910 2019 2020 +1 6 1909 1419 1420 1911 2020 2021 +1 6 1910 1420 1421 1912 2021 2022 +1 6 1911 1421 1422 1913 2022 2023 +1 6 1912 1422 1423 1914 2023 2024 +1 6 1913 1423 1424 1915 2024 2025 +1 6 1914 1424 1425 1916 2025 2026 +1 6 1915 1425 1426 1917 2026 2027 +1 6 1916 1426 1427 1918 2027 2028 +1 6 1917 1427 1428 1919 2028 2029 +1 6 1918 1428 1429 1920 2029 2030 +1 6 1919 1429 1430 1921 2030 2031 +1 6 1920 1430 1431 1922 2031 2032 +1 6 1921 1431 1432 1923 2032 2033 +1 6 1922 1432 1433 1924 2033 2034 +1 6 1923 1433 1434 1925 2034 2035 +1 6 1924 1434 1435 1926 2035 1927 +1 6 1925 1435 1436 1437 1438 1927 +1 7 1926 1438 1439 1928 2035 1925 2036 +1 6 1927 1439 1440 1929 2036 2037 +1 6 1928 1440 1441 1930 2037 2038 +1 6 1929 1441 1442 1931 2038 2039 +1 6 1930 1442 1443 1932 2039 2040 +1 7 1931 1443 1444 1461 1933 2040 2041 +1 5 1932 1461 1934 2041 2042 +1 6 1933 1461 1462 1935 2042 2043 +1 6 1934 1462 1463 1936 2043 2044 +1 6 1935 1463 1464 1937 2044 2045 +1 6 1936 1464 1465 1466 1938 2045 +1 6 1937 1466 1939 2045 2046 2047 +1 6 1938 1466 1467 1940 2047 2048 +1 6 1939 1467 1468 1469 1941 2048 +1 6 1940 1469 1942 2048 2049 2050 +1 6 1941 1469 1470 1943 2050 2051 +1 6 1942 1470 1471 1944 2051 2052 +1 6 1943 1471 1945 2052 2053 2054 +1 6 1944 1471 1472 1946 2054 1947 +1 6 1945 1472 1473 1490 1491 1947 +1 6 1946 1491 1948 2054 1945 2055 +1 6 1947 1491 1492 1949 1950 2055 +1 6 1948 1492 1950 1951 1495 1493 +1 6 1948 1949 1951 2055 2056 2057 +1 6 1950 1949 1495 1952 2057 2058 +1 6 1951 1495 1496 1530 1953 2058 +1 6 1952 1530 1531 1954 2058 2059 +1 6 1953 1531 1532 1955 2059 2060 +1 6 1954 1532 1534 1956 2060 2061 +1 6 1955 1534 1957 1958 2061 2062 +1 6 1956 1534 1958 1959 1960 1535 +1 6 1956 1957 1959 2062 2063 2064 +1 6 1958 1957 1960 2064 2065 2066 +1 6 1959 1957 1535 1541 1961 2066 +1 6 1960 1541 1962 2066 2067 2068 +1 6 1961 1541 1167 1168 1963 2068 +1 6 1962 1168 1964 1965 2070 2068 +1 6 1963 1168 1965 887 886 1169 +1 6 1963 1964 887 2072 2070 2075 +1 6 1855 1856 1967 2361 2362 2363 +1 6 1966 1856 1857 1968 2363 2364 +1 6 1967 1857 1858 1969 2364 2365 +1 6 1968 1858 1859 1970 2365 2366 +1 6 1969 1859 1860 1971 2366 2367 +1 6 1970 1860 1861 1972 2367 2368 +1 6 1971 1861 1862 1973 2368 2369 +1 6 1972 1862 1863 1974 2369 2370 +1 6 1973 1863 1864 1975 2370 2371 +1 6 1974 1864 1865 1976 2371 2372 +1 6 1975 1865 1866 1977 2372 2373 +1 6 1976 1866 1867 1978 2373 2374 +1 6 1977 1867 1868 1979 2374 2375 +1 6 1978 1868 1869 1980 2375 2376 +1 6 1979 1869 1870 1981 2376 2377 +1 6 1980 1870 1871 1982 2377 2378 +1 6 1981 1871 1872 1983 2378 2379 +1 6 1982 1872 1873 1984 2379 2380 +1 6 1983 1873 1874 1985 2380 2381 +1 6 1984 1874 1875 1986 2381 2382 +1 6 1985 1875 1876 1987 2382 2383 +1 6 1986 1876 1877 1988 2383 2384 +1 6 1987 1877 1878 1989 2384 2385 +1 6 1988 1878 1879 1990 2385 2386 +1 6 1989 1879 1880 1991 2386 2387 +1 6 1990 1880 1881 1992 2387 2388 +1 6 1991 1881 1882 1993 2388 2389 +1 6 1992 1882 1883 1994 2389 2390 +1 6 1993 1883 1884 1995 2390 2391 +1 6 1994 1884 1885 1996 2391 2392 +1 6 1995 1885 1886 1997 2392 2393 +1 6 1996 1886 1887 1998 2393 2394 +1 6 1997 1887 1888 1999 2394 2395 +1 6 1998 1888 1889 2000 2395 2396 +1 6 1999 1889 1890 2001 2396 2397 +1 6 2000 1890 1891 2002 2397 2398 +1 6 2001 1891 1892 2003 2398 2399 +1 6 2002 1892 1893 2004 2399 2400 +1 6 2003 1893 1894 2005 2400 2401 +1 6 2004 1894 1895 2006 2401 2402 +1 6 2005 1895 1896 2007 2402 2403 +1 6 2006 1896 1897 2008 2403 2404 +1 6 2007 1897 1898 2009 2404 2405 +1 6 2008 1898 1899 2010 2405 2406 +1 6 2009 1899 1900 2011 2406 2407 +1 6 2010 1900 1901 2012 2407 2408 +1 6 2011 1901 1902 2013 2408 2409 +1 6 2012 1902 1903 2014 2409 2410 +1 6 2013 1903 1904 2015 2410 2411 +1 6 2014 1904 1905 2016 2411 2412 +1 6 2015 1905 1906 2017 2412 2413 +1 6 2016 1906 1907 2018 2413 2414 +1 6 2017 1907 1908 2019 2414 2415 +1 6 2018 1908 1909 2020 2415 2416 +1 6 2019 1909 1910 2021 2416 2417 +1 6 2020 1910 1911 2022 2417 2418 +1 6 2021 1911 1912 2023 2418 2419 +1 6 2022 1912 1913 2024 2419 2420 +1 6 2023 1913 1914 2025 2420 2421 +1 6 2024 1914 1915 2026 2421 2422 +1 6 2025 1915 1916 2027 2422 2423 +1 6 2026 1916 1917 2028 2423 2424 +1 6 2027 1917 1918 2029 2424 2425 +1 6 2028 1918 1919 2030 2425 2426 +1 6 2029 1919 1920 2031 2426 2427 +1 6 2030 1920 1921 2032 2427 2428 +1 6 2031 1921 1922 2033 2428 2429 +1 6 2032 1922 1923 2034 2429 2430 +1 6 2033 1923 1924 2035 2430 2431 +1 6 2034 1924 1925 1927 2036 2431 +1 5 2035 1927 1928 2037 2431 +1 6 2036 1928 1929 2038 2431 2432 +1 6 2037 1929 1930 2039 2432 2433 +1 6 2038 1930 1931 2040 2433 2434 +1 7 2039 1931 1932 2041 2434 2435 2436 +1 5 2040 1932 1933 2042 2436 +1 7 2041 1933 1934 2043 2436 2437 2438 +1 6 2042 1934 1935 2044 2438 2439 +1 6 2043 1935 1936 2045 2439 2440 +1 6 2044 1936 1937 1938 2046 2440 +1 6 2045 1938 2047 2440 2441 2442 +1 6 2046 1938 1939 2048 2442 2443 +1 6 2047 1939 1940 1941 2049 2443 +1 6 2048 1941 2050 2443 2444 2448 +1 6 2049 1941 1942 2051 2448 2449 +1 6 2050 1942 1943 2052 2449 2450 +1 6 2051 1943 1944 2053 2450 2451 +1 6 2052 1944 2054 2451 2452 2453 +1 6 2053 1944 1945 1947 2055 2453 +1 6 2054 1947 1948 1950 2056 2453 +1 6 2055 1950 2057 2453 2454 2455 +1 6 2056 1950 1951 2058 2455 2456 +1 6 2057 1951 1952 1953 2059 2456 +1 6 2058 1953 1954 2060 2456 2457 +1 6 2059 1954 1955 2061 2457 2458 +1 6 2060 1955 1956 2062 2458 2459 +1 6 2061 1956 1958 2063 2459 2460 +1 6 2062 1958 2064 2460 2461 2462 +1 6 2063 1958 1959 2065 2462 2463 +1 6 2064 1959 2066 2463 2464 2465 +1 6 2065 1959 1960 1961 2067 2465 +1 6 2066 1961 2068 2069 2465 2466 +1 6 2067 1961 1962 2069 2070 1963 +1 6 2067 2068 2070 2071 2466 2469 +1 6 2069 2068 1963 2071 2072 1965 +1 6 2069 2070 2072 2073 2469 2470 +1 6 2071 2070 1965 2073 2074 2075 +1 6 2071 2072 2074 2473 2470 2086 +1 6 2073 2072 2075 2076 2078 2086 +1 6 2074 2072 1965 887 888 2076 +1 6 2075 888 889 2077 2078 2074 +1 6 2076 889 2078 2079 2080 2081 +1 6 2076 2077 2079 2074 2086 2087 +1 6 2078 2077 2080 2096 2087 2082 +1 6 2079 2077 2081 898 901 2082 +1 6 2080 2077 889 890 894 898 +1 6 2080 901 903 2083 2096 2079 +1 6 2082 903 2084 2096 2095 9776 +1 6 2083 903 904 2085 6093 9776 +1 6 2084 904 1565 1567 3766 6093 +1 6 2074 2078 2087 2088 2473 2073 +1 6 2086 2078 2088 2089 2096 2079 +1 6 2086 2087 2089 2090 2091 2473 +1 6 2088 2087 2090 2094 2095 2096 +1 6 2088 2089 2091 2092 2093 2094 +1 6 2088 2090 2092 2489 2472 2473 +1 6 2091 2090 2093 2489 5947 5948 +1 6 2092 2090 2094 3135 5947 3132 +1 6 2093 2090 2089 2095 3131 3132 +1 6 2094 2089 2096 3131 2083 9776 +1 6 2095 2089 2087 2079 2082 2083 +1 6 631 403 633 650 649 404 +1 6 1795 1796 2099 2295 2296 2297 +1 6 2098 1796 1797 2100 2297 2101 +1 5 2099 1797 1300 1301 2101 +1 6 2100 1301 1302 2102 2297 2099 +1 6 2101 1302 1303 2103 2297 2298 +1 6 2102 1303 1304 2104 2298 2299 +1 6 2103 1304 1305 2105 2299 2300 +1 6 2104 1305 1306 2106 2300 2301 +1 7 2105 1306 1307 1798 2107 2301 2302 +1 5 2106 1798 2108 2302 2303 +1 6 2107 1798 1799 2109 2303 2304 +1 6 2108 1799 1800 2110 2304 2305 +1 6 2109 1800 1801 2111 2305 2306 +1 6 2110 1801 1802 2112 2306 2307 +1 6 2111 1802 1803 2113 2307 2308 +1 6 2112 1803 1804 2114 2308 2309 +1 6 2113 1804 1805 2115 2309 2310 +1 6 2114 1805 1806 2116 2310 2311 +1 6 2115 1806 1807 2117 2311 2312 +1 6 2116 1807 1808 2118 2312 2313 +1 6 2117 1808 1809 2119 2313 2314 +1 6 2118 1809 1810 2120 2314 2315 +1 6 2119 1810 1811 2121 2315 2316 +1 6 2120 1811 1812 2122 2316 2317 +1 6 2121 1812 1813 2123 2317 2318 +1 6 2122 1813 1814 2124 2318 2319 +1 6 2123 1814 1815 2125 2319 2320 +1 6 2124 1815 1816 2126 2320 2321 +1 6 2125 1816 1817 2127 2321 2322 +1 6 2126 1817 1818 2128 2322 2323 +1 6 2127 1818 1819 2129 2323 2324 +1 6 2128 1819 1820 2130 2324 2325 +1 6 2129 1820 1821 2131 2325 2326 +1 6 2130 1821 1822 2132 2326 2327 +1 6 2131 1822 1823 2133 2151 2327 +1 6 2132 1823 1824 2134 2151 2152 +1 6 2133 1824 1825 2135 2152 2153 +1 6 2134 1825 1826 1827 2136 2153 +2 6 2135 1827 2137 2153 2154 2155 +2 6 2136 1827 1828 2138 2155 2156 +2 6 2137 1828 1829 2139 2156 2157 +2 6 2138 1829 1830 2140 2157 2158 +2 6 2139 1830 2141 2146 2158 2159 +2 6 2140 1830 1831 1832 2142 2146 +2 6 2141 1832 1833 2143 2146 2147 +2 6 2142 1833 1834 2144 2147 2148 +2 6 2143 1834 1835 2145 2148 2149 +2 6 2144 1835 1836 2149 2150 1837 +2 6 2140 2141 2142 2147 2159 2160 +2 6 2146 2142 2143 2148 2160 2161 +2 6 2147 2143 2144 2149 2161 2162 +2 6 2148 2144 2145 2150 2162 2163 +2 6 2149 2145 1837 2163 2164 2165 +1 6 2132 2133 2152 2327 2328 2329 +1 6 2151 2133 2134 2153 2329 2330 +1 6 2152 2134 2135 2136 2154 2330 +2 6 2153 2136 2155 2330 2331 2332 +2 6 2154 2136 2137 2156 2332 2333 +2 6 2155 2137 2138 2157 2333 2334 +2 6 2156 2138 2139 2158 2334 2335 +2 6 2157 2139 2140 2159 2335 2336 +2 6 2158 2140 2146 2160 2336 2337 +2 6 2159 2146 2147 2161 2337 2338 +2 6 2160 2147 2148 2162 2338 2339 +2 6 2161 2148 2149 2163 2339 2340 +2 6 2162 2149 2150 2164 2340 2341 +2 6 2163 2150 2165 2341 2342 2343 +2 6 2164 2150 1837 1838 2166 2343 +2 6 2165 1838 1839 2167 2343 2344 +2 6 2166 1839 1840 2168 2169 2344 +2 6 2167 1840 2169 2170 2171 1841 +2 6 2167 2168 2170 2344 2345 2346 +2 6 2169 2168 2171 2346 2347 2348 +2 6 2170 2168 1841 2348 2349 1842 +1 6 1724 1725 2173 3468 3467 4747 +1 6 2172 1725 2174 2804 3395 4747 +1 6 2173 1725 1726 1727 2175 2804 +1 6 2174 1727 1728 2176 2177 2804 +1 6 2175 1728 2177 2178 1731 1729 +1 6 2175 2176 2178 2804 2805 2806 +1 6 2177 2176 1731 2806 2807 2808 +1 6 27 28 2180 2181 3851 3852 +1 6 2179 28 29 2181 2182 2503 +1 6 2179 2180 2182 2183 2199 3851 +1 6 2181 2180 2183 2184 2502 2503 +1 6 2181 2182 2184 2185 2198 2199 +1 6 2183 2182 2185 2186 2193 2502 +1 6 2183 2184 2186 2187 2197 2198 +1 6 2185 2184 2187 2188 2192 2193 +1 6 2185 2186 2188 2189 2197 9713 +1 6 2187 2186 2189 2190 2191 2192 +1 7 2187 2188 2190 9709 9708 9712 9713 +1 5 2189 2188 2191 9710 9709 +1 6 2190 2188 2192 2510 2512 9710 +1 6 2191 2188 2186 2193 2510 2506 +1 6 2192 2186 2184 2502 2504 2506 +1 6 415 39 40 2195 9704 6488 +1 6 2194 40 41 2196 6488 9705 +1 7 2195 41 42 9705 43 9771 9773 +1 6 2185 2187 2198 9713 9714 9720 +1 6 2185 2197 2183 2199 2200 9720 +1 6 2183 2198 2200 2201 2181 3851 +1 6 2199 2198 2201 2202 9720 2217 +1 6 2199 2200 2202 2203 3129 3851 +1 6 2201 2200 2203 2204 2217 2208 +1 6 2201 2202 2204 2205 3129 3130 +1 6 2203 2202 2205 2206 2207 2208 +1 6 2203 2204 2206 3130 1525 4250 +1 6 2205 2204 2207 3343 3341 4250 +1 6 2206 2204 2208 2209 3343 3344 +1 6 2207 2204 2209 2210 2217 2202 +1 6 2207 2208 2210 2211 3344 3345 +1 6 2209 2208 2211 2212 2216 2217 +1 6 2209 2210 2212 2213 3348 3345 +1 6 2211 2210 2213 2214 2215 2216 +1 6 2211 2212 2214 6522 6523 3348 +1 6 2213 2212 2215 9716 9719 6522 +1 6 2214 2212 2216 9716 9715 9714 +1 6 2215 2212 2210 2217 9714 9720 +1 6 2216 2210 2208 2202 9720 2200 +1 6 408 59 60 2219 2545 2546 +1 6 2218 60 61 2220 2549 2546 +1 6 2219 61 62 2221 2549 2551 +1 6 2220 62 63 2222 2551 6702 +1 6 2221 63 6701 6700 6702 64 +1 6 1698 1703 2224 3418 3419 3420 +1 6 2223 1703 1704 2225 3420 3421 +1 6 2224 1704 2226 3421 3422 3426 +1 6 2225 1704 1705 2227 3426 3427 +1 6 2226 1705 1706 2228 3427 3428 +1 6 2227 1706 2229 3428 3429 3430 +1 6 2228 1706 1707 2230 2238 3430 +1 6 2229 1707 2231 2232 2238 2239 +1 6 2230 1707 2232 1712 1711 1708 +1 6 2230 2231 1712 2239 2240 1713 +1 6 1748 1749 2234 2235 2242 2752 +1 6 2233 1749 2235 2236 2237 1750 +1 6 2233 2234 2236 2242 2243 2244 +1 6 2235 2234 2237 2244 2245 2246 +1 6 2236 2234 1750 2246 2247 1751 +1 6 2229 2230 2239 3430 3431 3435 +1 6 2238 2230 2232 2240 3435 2561 +1 6 2239 2232 1713 1714 2560 2561 +2 6 1187 1188 1659 1657 3097 1184 +1 6 2233 2235 2243 2752 2753 2754 +1 6 2242 2235 2244 2754 2755 2756 +1 6 2243 2235 2236 2245 2756 2757 +1 6 2244 2236 2246 2757 2758 2759 +1 6 2245 2236 2237 2247 2759 2760 +1 6 2246 2237 1751 1752 2253 2760 +1 6 34 35 2249 3331 3332 3333 +1 6 2248 35 36 2250 3336 3333 +1 6 2249 36 37 416 2251 3336 +1 7 2250 416 2252 6490 6491 9706 3336 +1 5 2251 416 415 6490 9704 +1 6 2247 1752 1753 2254 2760 2761 +1 6 2253 1753 1754 2255 2761 2762 +1 6 2254 1754 1755 2256 2762 2763 +1 6 2255 1755 1756 1757 2257 2763 +1 6 2256 1757 2258 2763 2764 2765 +1 6 2257 1757 1758 2259 2765 2766 +1 6 2258 1758 1759 2260 2766 2767 +1 6 2259 1759 1760 2261 2767 2768 +1 6 2260 1760 1761 2262 2768 2769 +1 6 2261 1761 1762 2263 2571 2769 +1 6 2262 1762 1763 2264 2571 2572 +1 6 2263 1763 1764 2265 2572 2573 +1 6 2264 1764 1765 2266 2573 2574 +1 6 2265 1765 1766 2267 2574 2575 +1 6 2266 1766 1767 2268 2575 2576 +1 6 2267 1767 1768 2269 2576 2577 +1 6 2268 1768 1769 2270 2577 2578 +1 6 2269 1769 1770 2271 2578 2579 +1 6 2270 1770 1771 2272 2579 2580 +1 6 2271 1771 1772 2273 2580 2581 +1 6 2272 1772 1773 2274 2581 2582 +1 6 2273 1773 1774 2275 2582 2583 +1 6 2274 1774 1775 2276 2583 2584 +1 6 2275 1775 1776 2277 2584 2585 +1 6 2276 1776 1777 2278 2585 2586 +1 6 2277 1777 1778 2279 2586 2587 +1 6 2278 1778 1779 2280 2587 2588 +1 6 2279 1779 1780 2281 2588 2589 +1 6 2280 1780 1781 2282 2589 2590 +1 6 2281 1781 1782 2283 2590 2591 +1 6 2282 1782 1783 2284 2591 2592 +1 6 2283 1783 1784 2285 2592 2593 +1 6 2284 1784 1785 2286 2593 2594 +1 6 2285 1785 1786 2287 2594 2595 +1 6 2286 1786 1787 2288 2595 2596 +1 6 2287 1787 1788 2289 2596 2597 +1 6 2288 1788 1789 2290 2597 2598 +1 6 2289 1789 1790 2291 2598 2599 +1 6 2290 1790 1791 2292 2599 2600 +1 6 2291 1791 1792 2293 2600 2601 +1 6 2292 1792 1793 2294 2601 2602 +1 6 2293 1793 1794 2295 2602 2603 +1 6 2294 1794 1795 2098 2296 2603 +1 6 2295 2098 2297 2603 2604 2605 +1 7 2296 2098 2099 2101 2102 2298 2605 +1 6 2297 2102 2103 2299 2605 2606 +1 6 2298 2103 2104 2300 2606 2607 +1 6 2299 2104 2105 2301 2607 2608 +1 6 2300 2105 2106 2302 2608 2609 +1 6 2301 2106 2107 2303 2609 2610 +1 6 2302 2107 2108 2304 2610 2611 +1 6 2303 2108 2109 2305 2611 2612 +1 6 2304 2109 2110 2306 2612 2613 +1 6 2305 2110 2111 2307 2613 2614 +1 6 2306 2111 2112 2308 2614 2615 +1 6 2307 2112 2113 2309 2615 2616 +1 6 2308 2113 2114 2310 2619 2616 +1 6 2309 2114 2115 2311 2619 2620 +1 6 2310 2115 2116 2312 2620 2621 +1 6 2311 2116 2117 2313 2621 2622 +1 6 2312 2117 2118 2314 2622 2623 +1 6 2313 2118 2119 2315 2623 2624 +1 6 2314 2119 2120 2316 2624 2625 +1 6 2315 2120 2121 2317 2625 2626 +1 6 2316 2121 2122 2318 2626 2627 +1 6 2317 2122 2123 2319 2627 2628 +1 6 2318 2123 2124 2320 2628 2629 +1 6 2319 2124 2125 2321 2629 2630 +1 6 2320 2125 2126 2322 2630 2631 +1 6 2321 2126 2127 2323 2631 2632 +1 6 2322 2127 2128 2324 2632 2633 +1 6 2323 2128 2129 2325 2633 2634 +1 6 2324 2129 2130 2326 2634 2635 +1 6 2325 2130 2131 2327 2635 2636 +1 6 2326 2131 2132 2151 2328 2636 +1 6 2327 2151 2329 2636 2637 2638 +1 6 2328 2151 2152 2330 2641 2638 +1 6 2329 2152 2153 2154 2331 2641 +2 6 2330 2154 2332 2642 2641 2643 +2 6 2331 2154 2155 2333 2643 2644 +2 6 2332 2155 2156 2334 2644 2645 +2 6 2333 2156 2157 2335 2645 2646 +2 6 2334 2157 2158 2336 2646 2647 +2 6 2335 2158 2159 2337 2647 2648 +2 6 2336 2159 2160 2338 2648 2649 +2 6 2337 2160 2161 2339 2649 2650 +2 6 2338 2161 2162 2340 2650 2651 +2 6 2339 2162 2163 2341 2651 2652 +2 6 2340 2163 2164 2342 2652 2653 +2 6 2341 2164 2343 2653 2654 2655 +2 6 2342 2164 2165 2166 2344 2655 +2 6 2343 2166 2167 2169 2345 2655 +2 6 2344 2169 2346 2655 2656 2657 +2 6 2345 2169 2170 2347 2657 2658 +2 6 2346 2170 2348 2658 2659 2660 +2 6 2347 2170 2171 2349 2660 2661 +2 6 2348 2171 1842 1843 2350 2661 +2 6 2349 1843 1844 2351 2661 2662 +2 6 2350 1844 1845 2352 2662 2663 +2 6 2351 1845 1846 2353 2663 2664 +2 6 2352 1846 1847 2354 2664 2665 +2 6 2353 1847 1848 2355 2665 2666 +2 6 2354 1848 1849 2356 2666 2667 +2 6 2355 1849 1850 2357 2667 2668 +2 6 2356 1850 1851 2358 2668 2669 +2 6 2357 1851 1852 2359 2669 2670 +2 6 2358 1852 1853 2360 2670 2671 +2 6 2359 1853 1854 2361 2671 2672 +1 6 2360 1854 1855 1966 2362 2672 +1 6 2361 1966 2363 2672 2673 2674 +1 6 2362 1966 1967 2364 2674 2675 +1 6 2363 1967 1968 2365 2675 2676 +1 6 2364 1968 1969 2366 2676 2677 +1 6 2365 1969 1970 2367 2677 2678 +1 6 2366 1970 1971 2368 2678 2679 +1 6 2367 1971 1972 2369 2679 2680 +1 6 2368 1972 1973 2370 2680 2681 +1 6 2369 1973 1974 2371 2681 2682 +1 6 2370 1974 1975 2372 2682 2683 +1 6 2371 1975 1976 2373 2683 2684 +1 6 2372 1976 1977 2374 2684 2685 +1 6 2373 1977 1978 2375 2685 2686 +1 6 2374 1978 1979 2376 2686 2687 +1 6 2375 1979 1980 2377 2687 2688 +1 6 2376 1980 1981 2378 2688 2689 +1 6 2377 1981 1982 2379 2689 2690 +1 6 2378 1982 1983 2380 2690 2691 +1 6 2379 1983 1984 2381 2691 2692 +1 6 2380 1984 1985 2382 2692 2693 +1 6 2381 1985 1986 2383 2693 2694 +1 6 2382 1986 1987 2384 2694 2695 +1 6 2383 1987 1988 2385 2695 2696 +1 6 2384 1988 1989 2386 2696 2697 +1 6 2385 1989 1990 2387 2697 2698 +1 6 2386 1990 1991 2388 2698 2699 +1 6 2387 1991 1992 2389 2699 2700 +1 6 2388 1992 1993 2390 2700 2701 +1 6 2389 1993 1994 2391 2701 2702 +1 6 2390 1994 1995 2392 2702 2703 +1 6 2391 1995 1996 2393 2703 2704 +1 6 2392 1996 1997 2394 2704 2705 +1 6 2393 1997 1998 2395 2705 2706 +1 6 2394 1998 1999 2396 2706 2707 +1 6 2395 1999 2000 2397 2707 2708 +1 6 2396 2000 2001 2398 2708 2709 +1 6 2397 2001 2002 2399 2513 2709 +1 6 2398 2002 2003 2400 2513 2514 +1 6 2399 2003 2004 2401 2514 2515 +1 6 2400 2004 2005 2402 2515 2516 +1 6 2401 2005 2006 2403 2516 2517 +1 6 2402 2006 2007 2404 2517 2518 +1 6 2403 2007 2008 2405 2518 2519 +1 6 2404 2008 2009 2406 2519 2520 +1 6 2405 2009 2010 2407 2520 2521 +1 6 2406 2010 2011 2408 2521 2522 +1 6 2407 2011 2012 2409 2522 2523 +1 6 2408 2012 2013 2410 2523 2524 +1 6 2409 2013 2014 2411 2524 2525 +1 6 2410 2014 2015 2412 2525 2526 +1 6 2411 2015 2016 2413 2526 2527 +1 6 2412 2016 2017 2414 2527 2528 +1 6 2413 2017 2018 2415 2528 2529 +1 6 2414 2018 2019 2416 2529 2530 +1 6 2415 2019 2020 2417 2530 2531 +1 6 2416 2020 2021 2418 2531 2532 +1 6 2417 2021 2022 2419 2532 2533 +1 6 2418 2022 2023 2420 2533 2534 +1 6 2419 2023 2024 2421 2534 2535 +1 6 2420 2024 2025 2422 2535 2536 +1 6 2421 2025 2026 2423 2536 2537 +1 6 2422 2026 2027 2424 2537 2538 +1 6 2423 2027 2028 2425 2538 2539 +1 6 2424 2028 2029 2426 2539 2540 +1 6 2425 2029 2030 2427 2540 2541 +1 6 2426 2030 2031 2428 2541 2542 +1 6 2427 2031 2032 2429 2542 2543 +1 6 2428 2032 2033 2430 2543 2544 +1 6 2429 2033 2034 2431 2544 2432 +1 6 2430 2034 2035 2036 2037 2432 +1 7 2431 2037 2038 2433 2544 2430 2556 +1 6 2432 2038 2039 2434 2556 2557 +1 6 2433 2039 2040 2435 2557 2558 +1 6 2434 2040 2436 2558 2559 2437 +1 5 2435 2040 2041 2042 2437 +1 6 2436 2042 2438 2559 2435 2745 +1 6 2437 2042 2043 2439 2745 2746 +1 7 2438 2043 2044 2440 2746 2747 2748 +1 6 2439 2044 2045 2046 2441 2748 +1 6 2440 2046 2442 2748 2749 2750 +1 6 2441 2046 2047 2443 2750 2445 +1 6 2442 2047 2048 2049 2444 2445 +1 6 2443 2049 2445 2446 2447 2448 +1 6 2443 2444 2446 2750 2442 3060 +1 6 2445 2444 2447 3060 3061 3062 +1 6 2446 2444 2448 3062 3063 3064 +1 6 2447 2444 2049 2050 2449 3064 +1 6 2448 2050 2051 2450 3064 3065 +1 6 2449 2051 2052 2451 3065 3066 +1 6 2450 2052 2053 2452 3066 3067 +1 6 2451 2053 2453 3067 3068 2454 +1 6 2452 2053 2054 2055 2056 2454 +1 6 2453 2056 2455 3068 2452 3074 +1 6 2454 2056 2057 2456 3074 3075 +1 6 2455 2057 2058 2059 2457 3075 +1 6 2456 2059 2060 2458 3075 3076 +1 6 2457 2060 2061 2459 3076 3077 +1 6 2458 2061 2062 2460 3077 3078 +1 6 2459 2062 2063 2461 3078 3079 +1 6 2460 2063 2462 3079 3080 3081 +1 6 2461 2063 2064 2463 3081 3082 +1 6 2462 2064 2065 2464 3082 3083 +1 6 2463 2065 2465 2467 2482 3083 +1 6 2464 2065 2066 2067 2466 2467 +1 6 2465 2067 2069 2467 2468 2469 +1 6 2465 2466 2468 2464 2482 2483 +1 6 2467 2466 2469 2471 2477 2483 +1 6 2468 2466 2069 2071 2470 2471 +1 6 2469 2071 2471 2472 2473 2073 +1 6 2469 2470 2472 2468 2477 2478 +1 6 2471 2470 2473 2489 2478 2091 +1 6 2472 2470 2073 2091 2088 2086 +1 6 1516 1521 914 915 576 1515 +1 6 1578 1587 2476 1574 6361 1573 +1 6 2475 1587 1589 6353 6359 6361 +1 6 2468 2471 2478 2483 2484 2485 +1 6 2477 2471 2485 2488 2489 2472 +2 6 1642 1643 1644 2480 1641 2490 +2 6 2479 1644 2481 2490 2494 2869 +2 6 2480 1644 1645 1650 2494 2495 +1 6 2464 2467 2483 3085 3083 3926 +1 6 2482 2467 2468 2477 2484 3926 +1 6 2483 2477 2485 2486 3926 3150 +1 6 2484 2477 2478 2486 2487 2488 +1 6 2484 2485 2487 3148 3149 3150 +1 6 2486 2485 2488 3148 3967 3161 +1 6 2487 2485 2478 2489 5948 3967 +1 6 2488 2478 2472 2091 2092 5948 +2 6 1641 2479 2480 2867 2868 2869 +2 6 70 71 2492 3436 3437 3441 +2 6 2491 71 72 409 2493 3436 +2 6 2492 409 1606 3515 3436 3516 +2 6 2480 2481 2495 2869 2870 2871 +2 6 2494 2481 1650 1651 2496 2871 +2 6 2495 1651 2497 2871 2872 2882 +2 6 2496 1651 1652 2498 2882 2883 +2 6 2497 1652 2499 2883 4092 4093 +2 6 2498 1652 1653 2500 2809 4093 +2 6 2499 1653 1654 2501 2809 2810 +2 6 2500 1654 1656 2810 2811 2812 +1 6 2184 2182 2503 2193 2504 2505 +1 6 2502 2182 30 2505 29 2180 +1 6 2193 2502 2505 2506 2507 2508 +1 6 2504 2502 2508 31 30 2503 +1 6 2193 2504 2507 2509 2510 2192 +1 6 2506 2504 2508 2509 3330 3880 +1 6 2507 2504 2505 31 3330 32 +1 6 2506 2507 2510 2511 3880 3881 +1 6 2506 2509 2511 2512 2191 2192 +1 6 2510 2509 2512 6499 6498 3881 +1 6 2510 2511 2191 6498 6500 9710 +1 6 2398 2399 2514 2709 2710 2711 +1 6 2513 2399 2400 2515 2711 2712 +1 6 2514 2400 2401 2516 2712 2713 +1 6 2515 2401 2402 2517 2713 2714 +1 6 2516 2402 2403 2518 2714 2715 +1 6 2517 2403 2404 2519 2715 2716 +1 6 2518 2404 2405 2520 2716 2717 +1 6 2519 2405 2406 2521 2717 2718 +1 6 2520 2406 2407 2522 2718 2719 +1 6 2521 2407 2408 2523 2719 2720 +1 6 2522 2408 2409 2524 2720 2721 +1 6 2523 2409 2410 2525 2721 2722 +1 6 2524 2410 2411 2526 2722 2723 +1 6 2525 2411 2412 2527 2723 2724 +1 6 2526 2412 2413 2528 2724 2725 +1 6 2527 2413 2414 2529 2725 2726 +1 6 2528 2414 2415 2530 2726 2727 +1 6 2529 2415 2416 2531 2727 2728 +1 6 2530 2416 2417 2532 2728 2729 +1 6 2531 2417 2418 2533 2729 2730 +1 6 2532 2418 2419 2534 2730 2731 +1 6 2533 2419 2420 2535 2731 2732 +1 6 2534 2420 2421 2536 2732 2733 +1 6 2535 2421 2422 2537 2733 2734 +1 6 2536 2422 2423 2538 2734 2735 +1 6 2537 2423 2424 2539 2735 2736 +1 6 2538 2424 2425 2540 2736 2737 +1 6 2539 2425 2426 2541 2552 2737 +1 6 2540 2426 2427 2542 2552 2553 +1 6 2541 2427 2428 2543 2553 2554 +1 6 2542 2428 2429 2544 2554 2555 +1 6 2543 2429 2430 2432 2555 2556 +1 6 408 2218 2546 2547 2841 2842 +1 6 2545 2218 2547 2548 2549 2219 +1 6 2545 2546 2548 2842 2845 2846 +1 6 2547 2546 2549 2550 2857 2846 +1 6 2548 2546 2219 2220 2550 2551 +1 6 2548 2549 2551 6691 2856 2857 +1 7 2550 2549 2220 2221 6702 6690 6691 +1 6 2540 2541 2553 2737 2738 2739 +1 6 2552 2541 2542 2554 2739 2740 +1 6 2553 2542 2543 2555 2570 2740 +1 6 2554 2543 2544 2556 2570 2557 +1 5 2555 2544 2432 2433 2557 +1 7 2556 2433 2434 2558 2570 2555 2742 +1 5 2557 2434 2435 2559 2742 +1 7 2558 2435 2437 2742 2743 2744 2745 +1 6 2240 1714 2561 2562 2563 2564 +1 6 2240 2560 2562 3435 2239 3446 +1 6 2561 2560 2563 3446 3447 3448 +1 6 2562 2560 2564 3448 3449 2567 +1 6 2563 2560 1714 1715 2565 2567 +1 6 2564 1715 1716 1717 2566 2567 +1 6 2565 1717 2567 2568 2569 1718 +1 6 2565 2566 2568 3449 2563 2564 +1 6 2567 2566 2569 3458 3455 3449 +1 6 2568 2566 1718 3463 3458 1719 +1 6 2554 2555 2557 2740 2741 2742 +1 6 2262 2263 2572 2769 2770 2771 +1 6 2571 2263 2264 2573 2771 2772 +1 6 2572 2264 2265 2574 2772 2773 +1 6 2573 2265 2266 2575 2773 2774 +1 6 2574 2266 2267 2576 2774 2775 +1 6 2575 2267 2268 2577 2775 2776 +1 6 2576 2268 2269 2578 2776 2777 +1 6 2577 2269 2270 2579 2777 2778 +1 6 2578 2270 2271 2580 2778 2779 +1 6 2579 2271 2272 2581 2779 2780 +1 6 2580 2272 2273 2582 2780 2781 +1 6 2581 2273 2274 2583 2781 2782 +1 6 2582 2274 2275 2584 2782 2783 +1 6 2583 2275 2276 2585 2783 2784 +1 6 2584 2276 2277 2586 2784 2785 +1 6 2585 2277 2278 2587 2785 2786 +1 6 2586 2278 2279 2588 2786 2787 +1 6 2587 2279 2280 2589 2787 2788 +1 6 2588 2280 2281 2590 2788 2789 +1 6 2589 2281 2282 2591 2789 2790 +1 6 2590 2282 2283 2592 2790 2791 +1 6 2591 2283 2284 2593 2791 2792 +1 6 2592 2284 2285 2594 2792 2793 +1 6 2593 2285 2286 2595 2793 2794 +1 6 2594 2286 2287 2596 2794 2795 +1 6 2595 2287 2288 2597 2795 2796 +1 6 2596 2288 2289 2598 2796 2797 +1 6 2597 2289 2290 2599 2797 2798 +1 6 2598 2290 2291 2600 2798 2799 +1 6 2599 2291 2292 2601 2799 2800 +1 6 2600 2292 2293 2602 2800 2801 +1 6 2601 2293 2294 2603 2801 2802 +1 6 2602 2294 2295 2296 2604 2802 +1 6 2603 2296 2605 2802 2803 2606 +1 5 2604 2296 2297 2298 2606 +1 7 2605 2298 2299 2607 2803 2604 2826 +1 5 2606 2299 2300 2608 2826 +1 7 2607 2300 2301 2609 2826 2827 2828 +1 6 2608 2301 2302 2610 2828 2829 +1 6 2609 2302 2303 2611 2829 2830 +1 6 2610 2303 2304 2612 2830 2831 +1 6 2611 2304 2305 2613 2831 2832 +1 6 2612 2305 2306 2614 2832 2833 +1 6 2613 2306 2307 2615 2833 2834 +1 6 2614 2307 2308 2616 2617 2834 +1 6 2615 2308 2617 2618 2619 2309 +1 6 2615 2616 2618 2834 2835 2836 +1 6 2617 2616 2619 2836 2837 2838 +1 6 2618 2616 2309 2310 2620 2838 +1 6 2619 2310 2311 2621 2840 2838 +1 6 2620 2311 2312 2622 2959 2840 +1 6 2621 2312 2313 2623 2959 2960 +1 6 2622 2313 2314 2624 2960 2961 +1 6 2623 2314 2315 2625 2961 2962 +1 6 2624 2315 2316 2626 2962 2963 +1 6 2625 2316 2317 2627 2966 2963 +1 6 2626 2317 2318 2628 2966 2967 +1 6 2627 2318 2319 2629 2967 2968 +1 6 2628 2319 2320 2630 2968 2969 +1 6 2629 2320 2321 2631 2969 2970 +1 6 2630 2321 2322 2632 2970 2971 +1 6 2631 2322 2323 2633 2971 2972 +1 6 2632 2323 2324 2634 2972 2973 +1 6 2633 2324 2325 2635 2973 2974 +1 6 2634 2325 2326 2636 2974 2975 +1 6 2635 2326 2327 2328 2637 2975 +1 6 2636 2328 2638 2639 2975 2976 +1 6 2637 2328 2639 2640 2641 2329 +1 6 2637 2638 2640 2976 2977 2978 +1 6 2639 2638 2641 2642 2978 2979 +1 6 2640 2638 2642 2331 2330 2329 +2 6 2640 2641 2331 2643 2979 2980 +2 6 2642 2331 2332 2644 2980 2981 +2 6 2643 2332 2333 2645 2981 2982 +2 6 2644 2333 2334 2646 2982 2983 +2 6 2645 2334 2335 2647 2983 2984 +2 6 2646 2335 2336 2648 2984 2985 +2 6 2647 2336 2337 2649 2985 2986 +2 6 2648 2337 2338 2650 2986 2987 +2 6 2649 2338 2339 2651 2987 2988 +2 6 2650 2339 2340 2652 2988 2989 +2 6 2651 2340 2341 2653 2989 2990 +2 6 2652 2341 2342 2654 2990 2991 +2 6 2653 2342 2655 2991 2992 2656 +2 6 2654 2342 2343 2344 2345 2656 +2 6 2655 2345 2657 2992 2654 2993 +2 6 2656 2345 2346 2658 2993 2994 +2 6 2657 2346 2347 2659 2994 2995 +2 6 2658 2347 2660 2995 2996 2997 +2 6 2659 2347 2348 2661 2997 2998 +2 6 2660 2348 2349 2350 2662 2998 +2 6 2661 2350 2351 2663 2998 2999 +2 6 2662 2351 2352 2664 2999 3000 +2 6 2663 2352 2353 2665 3000 3001 +2 6 2664 2353 2354 2666 3001 3002 +2 6 2665 2354 2355 2667 3002 3565 +2 6 2666 2355 2356 2668 3565 3566 +2 6 2667 2356 2357 2669 3566 3567 +2 6 2668 2357 2358 2670 3567 3568 +2 6 2669 2358 2359 2671 3568 3569 +2 6 2670 2359 2360 2672 3569 3570 +2 6 2671 2360 2361 2362 2673 3570 +2 6 2672 2362 2674 3570 3571 3572 +1 6 2673 2362 2363 2675 3572 3573 +1 6 2674 2363 2364 2676 3391 3573 +1 6 2675 2364 2365 2677 3391 3392 +1 6 2676 2365 2366 2678 3392 3393 +1 6 2677 2366 2367 2679 3393 3394 +1 6 2678 2367 2368 2680 3394 3579 +1 6 2679 2368 2369 2681 3579 3580 +1 6 2680 2369 2370 2682 3580 3581 +1 6 2681 2370 2371 2683 3581 3582 +1 6 2682 2371 2372 2684 3582 3583 +1 6 2683 2372 2373 2685 3583 3584 +1 6 2684 2373 2374 2686 3584 3585 +1 6 2685 2374 2375 2687 3585 3586 +1 6 2686 2375 2376 2688 3586 3587 +1 6 2687 2376 2377 2689 3587 3588 +1 6 2688 2377 2378 2690 3278 3588 +1 6 2689 2378 2379 2691 3278 3279 +1 6 2690 2379 2380 2692 3279 3280 +1 6 2691 2380 2381 2693 3280 3281 +1 6 2692 2381 2382 2694 3281 3282 +1 6 2693 2382 2383 2695 3282 3283 +1 6 2694 2383 2384 2696 3283 3284 +1 6 2695 2384 2385 2697 3284 3285 +1 6 2696 2385 2386 2698 3285 3286 +1 6 2697 2386 2387 2699 3286 3287 +1 6 2698 2387 2388 2700 3287 3288 +1 6 2699 2388 2389 2701 3288 3289 +1 6 2700 2389 2390 2702 3289 3290 +1 6 2701 2390 2391 2703 3003 3290 +1 6 2702 2391 2392 2704 3003 3004 +1 6 2703 2392 2393 2705 3004 3005 +1 6 2704 2393 2394 2706 3005 3006 +1 6 2705 2394 2395 2707 3006 3007 +1 6 2706 2395 2396 2708 3007 3008 +1 6 2707 2396 2397 2709 3008 3009 +1 6 2708 2397 2398 2513 2710 3009 +1 6 2709 2513 2711 3009 3010 3011 +1 6 2710 2513 2514 2712 3011 3012 +1 6 2711 2514 2515 2713 3012 3013 +1 6 2712 2515 2516 2714 3013 3014 +1 6 2713 2516 2517 2715 3014 3015 +1 6 2714 2517 2518 2716 3015 3016 +1 6 2715 2518 2519 2717 3016 3017 +1 6 2716 2519 2520 2718 3017 3018 +1 6 2717 2520 2521 2719 3018 3019 +1 6 2718 2521 2522 2720 3019 3020 +1 6 2719 2522 2523 2721 3020 3021 +1 6 2720 2523 2524 2722 3021 3022 +1 6 2721 2524 2525 2723 3022 3023 +1 6 2722 2525 2526 2724 3023 3024 +1 6 2723 2526 2527 2725 3024 3025 +1 6 2724 2527 2528 2726 3025 3026 +1 6 2725 2528 2529 2727 3026 3027 +1 6 2726 2529 2530 2728 3027 3028 +1 6 2727 2530 2531 2729 3028 3029 +1 6 2728 2531 2532 2730 3029 3030 +1 6 2729 2532 2533 2731 3030 3031 +1 6 2730 2533 2534 2732 3031 3032 +1 6 2731 2534 2535 2733 3032 3033 +1 6 2732 2535 2536 2734 3033 3034 +1 6 2733 2536 2537 2735 3034 3035 +1 6 2734 2537 2538 2736 3035 3036 +1 6 2735 2538 2539 2737 3036 3037 +1 6 2736 2539 2540 2552 2738 3037 +1 6 2737 2552 2739 3037 3038 3039 +1 6 2738 2552 2553 2740 3039 3040 +1 6 2739 2553 2554 2570 2741 3040 +1 6 2740 2570 2742 3040 3041 2743 +1 6 2741 2570 2557 2558 2559 2743 +1 6 2742 2559 2744 3041 2741 3049 +1 5 2743 2559 2745 3049 3050 +1 6 2744 2559 2437 2438 2746 3050 +1 6 2745 2438 2439 2747 3050 3051 +1 6 2746 2439 2748 3051 3052 2749 +1 5 2747 2439 2440 2441 2749 +1 6 2748 2441 2750 3052 2747 3058 +1 7 2749 2441 2442 2445 3058 3059 3060 +1 6 1746 1747 1748 2752 2893 2894 +1 6 2751 1748 2233 2242 2753 2894 +1 6 2752 2242 2754 2894 2895 2896 +1 6 2753 2242 2243 2755 2896 2897 +1 6 2754 2243 2756 2897 2898 2899 +1 6 2755 2243 2244 2757 2899 2900 +1 6 2756 2244 2245 2758 2900 2901 +1 6 2757 2245 2759 2901 2902 2903 +1 6 2758 2245 2246 2760 2903 2904 +1 6 2759 2246 2247 2253 2761 2904 +1 6 2760 2253 2254 2762 2904 2905 +1 6 2761 2254 2255 2763 2905 2906 +1 6 2762 2255 2256 2257 2764 2906 +1 6 2763 2257 2765 2906 2907 2908 +1 6 2764 2257 2258 2766 2908 2909 +1 6 2765 2258 2259 2767 2909 2910 +1 6 2766 2259 2260 2768 2910 2911 +1 6 2767 2260 2261 2769 2911 2912 +1 6 2768 2261 2262 2571 2770 2912 +1 6 2769 2571 2771 2912 2913 2914 +1 6 2770 2571 2572 2772 2914 2915 +1 6 2771 2572 2573 2773 2915 2916 +1 6 2772 2573 2574 2774 2916 2917 +1 6 2773 2574 2575 2775 2917 2918 +1 6 2774 2575 2576 2776 2918 2919 +1 6 2775 2576 2577 2777 2919 2920 +1 6 2776 2577 2578 2778 2920 2921 +1 6 2777 2578 2579 2779 2921 2922 +1 6 2778 2579 2580 2780 2922 2923 +1 6 2779 2580 2581 2781 2923 2924 +1 6 2780 2581 2582 2782 2924 2925 +1 6 2781 2582 2583 2783 2925 2926 +1 6 2782 2583 2584 2784 2926 2927 +1 6 2783 2584 2585 2785 2927 2928 +1 6 2784 2585 2586 2786 2928 2929 +1 6 2785 2586 2587 2787 2929 2930 +1 6 2786 2587 2588 2788 2930 2931 +1 6 2787 2588 2589 2789 2931 2932 +1 6 2788 2589 2590 2790 2932 2933 +1 6 2789 2590 2591 2791 2933 2934 +1 6 2790 2591 2592 2792 2934 2935 +1 6 2791 2592 2593 2793 2935 2936 +1 6 2792 2593 2594 2794 2936 2937 +1 6 2793 2594 2595 2795 2937 2938 +1 6 2794 2595 2596 2796 2938 2939 +1 6 2795 2596 2597 2797 2939 2940 +1 6 2796 2597 2598 2798 2940 2941 +1 6 2797 2598 2599 2799 2941 2942 +1 6 2798 2599 2600 2800 2942 2943 +1 6 2799 2600 2601 2801 2943 2944 +1 6 2800 2601 2602 2802 2944 2824 +1 6 2801 2602 2603 2604 2803 2824 +1 6 2802 2604 2606 2824 2825 2826 +1 6 2173 2174 2175 2177 2805 3395 +1 6 2804 2177 2806 3395 3396 3400 +1 6 2805 2177 2178 2807 3400 3401 +1 6 2806 2178 2808 3401 3402 3403 +1 6 2807 2178 1731 3403 3404 1732 +2 6 2499 2500 2810 4095 4093 4388 +2 6 2809 2500 2501 2811 4388 2813 +2 6 2810 2501 2812 1664 1666 2813 +2 6 2811 2501 1656 1658 1661 1664 +2 6 2811 1666 2814 3139 4388 2810 +2 6 2813 1666 1667 2815 2817 3139 +2 6 2814 1667 2816 2817 2818 2819 +2 6 2815 1667 1668 2819 2820 2821 +2 6 2814 2815 2818 3139 3140 3141 +2 6 2817 2815 2819 3141 3142 3143 +2 6 2818 2815 2816 2820 3143 3144 +2 6 2819 2816 2821 3144 3145 3146 +2 6 2820 2816 1668 2822 2823 3146 +2 6 2821 1668 2823 1672 1671 1669 +2 6 2821 2822 1672 3146 3147 1673 +1 6 2802 2803 2825 2944 2801 2945 +1 6 2824 2803 2826 2945 2946 2827 +1 6 2825 2803 2606 2607 2608 2827 +1 6 2826 2608 2828 2946 2825 2947 +1 5 2827 2608 2609 2829 2947 +1 6 2828 2609 2610 2830 2947 2948 +1 6 2829 2610 2611 2831 2948 2949 +1 6 2830 2611 2612 2832 2949 2950 +1 6 2831 2612 2613 2833 2950 2951 +1 6 2832 2613 2614 2834 2951 2952 +1 7 2833 2614 2615 2617 2835 2952 2953 +1 5 2834 2617 2836 2953 2954 +1 6 2835 2617 2618 2837 2954 2955 +1 6 2836 2618 2838 2839 2955 2956 +1 6 2837 2618 2839 2840 2620 2619 +1 6 2837 2838 2840 2956 2957 2958 +1 6 2839 2838 2620 2958 2959 2621 +1 6 408 2545 2842 2843 9690 429 +1 6 2841 2545 2843 2844 2547 2845 +1 6 2841 2842 2844 3168 9688 9690 +1 6 2843 2842 3168 3165 3162 2845 +1 6 2842 2547 2846 2847 3162 2844 +1 6 2845 2547 2847 2848 2548 2857 +1 6 2845 2846 2848 2849 3162 3163 +1 6 2847 2846 2849 2850 2851 2857 +1 6 2847 2848 2850 2852 2858 3163 +1 6 2849 2848 2851 2852 2853 2854 +1 6 2850 2848 2854 2855 2856 2857 +1 6 2849 2850 2853 2858 2859 2860 +1 5 2852 2850 2854 2860 6676 +1 7 2853 2850 2851 2855 6676 6677 6678 +1 7 2854 2851 2856 6689 6686 6680 6678 +1 6 2855 2851 2857 6691 6689 2550 +1 6 2856 2851 2848 2550 2548 2846 +1 6 2849 2852 2859 3180 3163 6661 +1 7 2858 2852 2860 6661 6674 6666 6662 +1 6 2859 2852 2853 6675 6674 6676 +2 5 1631 1633 1628 1629 1630 +2 6 1628 1633 1636 2863 1627 7215 +2 7 2862 1636 1637 2864 7216 7215 7217 +2 5 2863 1637 1638 2865 7217 +2 7 2864 1638 1639 2866 7217 7218 7219 +2 7 2865 1639 1640 2867 3189 3214 7219 +2 6 2866 1640 1641 2490 2868 3189 +2 6 2867 2490 2869 3189 3190 3181 +2 6 2868 2490 2480 2494 2870 3181 +2 6 2869 2494 2871 2873 2884 3181 +2 6 2870 2494 2495 2496 2872 2873 +2 6 2871 2496 2873 2874 2881 2882 +2 6 2871 2872 2874 2875 2870 2884 +2 6 2873 2872 2875 2876 2880 2881 +2 6 2873 2874 2876 2877 2884 2885 +2 6 2875 2874 2877 2878 2879 2880 +2 6 2875 2876 2878 2885 2886 2887 +2 6 2877 2876 2879 2887 2888 2889 +2 6 2878 2876 2880 2892 2889 7600 +2 6 2879 2876 2874 2881 4086 7600 +2 6 2880 2874 2872 2882 4086 4087 +2 6 2881 2872 2496 2497 2883 4087 +2 6 2882 2497 2498 4087 4088 4092 +2 6 2870 2873 2875 2885 3181 3182 +2 6 2884 2875 2877 2886 3182 3183 +2 6 2885 2877 2887 3183 3184 3185 +2 6 2886 2877 2878 2888 3188 3185 +2 6 2887 2878 2889 2890 3959 3188 +2 6 2888 2878 2890 2891 2892 2879 +2 6 2888 2889 2891 3961 3959 7592 +2 6 2890 2889 2892 7592 7593 7594 +2 6 2891 2889 2879 7600 7597 7594 +1 6 1745 1746 2751 2894 3199 3198 +1 6 2893 2751 2752 2753 2895 3198 +1 6 2894 2753 2896 3198 3200 3201 +1 6 2895 2753 2754 2897 3201 3202 +1 6 2896 2754 2755 2898 3202 3203 +1 6 2897 2755 2899 3203 3204 3205 +1 6 2898 2755 2756 2900 3205 3206 +1 6 2899 2756 2757 2901 3206 3207 +1 6 2900 2757 2758 2902 3207 3208 +1 6 2901 2758 2903 3208 3209 3210 +1 6 2902 2758 2759 2904 3213 3210 +1 6 2903 2759 2760 2761 2905 3213 +1 6 2904 2761 2762 2906 3483 3213 +1 6 2905 2762 2763 2764 2907 3483 +1 6 2906 2764 2908 3482 3212 3483 +1 7 2907 2764 2765 2909 3500 3482 3697 +1 6 2908 2765 2766 2910 3697 3698 +1 6 2909 2766 2767 2911 3698 3699 +1 6 2910 2767 2768 2912 3699 3700 +1 6 2911 2768 2769 2770 2913 3700 +1 6 2912 2770 2914 3700 3701 3702 +1 6 2913 2770 2771 2915 3702 3703 +1 6 2914 2771 2772 2916 3703 3704 +1 6 2915 2772 2773 2917 3704 3705 +1 6 2916 2773 2774 2918 3705 3706 +1 6 2917 2774 2775 2919 3706 3707 +1 6 2918 2775 2776 2920 3707 3708 +1 6 2919 2776 2777 2921 3708 3709 +1 6 2920 2777 2778 2922 3709 3710 +1 6 2921 2778 2779 2923 3710 3711 +1 6 2922 2779 2780 2924 3711 3712 +1 6 2923 2780 2781 2925 3712 3713 +1 6 2924 2781 2782 2926 3713 3714 +1 6 2925 2782 2783 2927 3714 3715 +1 6 2926 2783 2784 2928 3715 3716 +1 6 2927 2784 2785 2929 3716 3717 +1 6 2928 2785 2786 2930 3717 3718 +1 6 2929 2786 2787 2931 3718 3719 +1 6 2930 2787 2788 2932 3719 3720 +1 6 2931 2788 2789 2933 3720 3721 +1 6 2932 2789 2790 2934 3721 3722 +1 6 2933 2790 2791 2935 3722 3723 +1 6 2934 2791 2792 2936 3723 3724 +1 6 2935 2792 2793 2937 3724 3725 +1 6 2936 2793 2794 2938 3725 3726 +1 6 2937 2794 2795 2939 3726 3727 +1 6 2938 2795 2796 2940 3727 3728 +1 6 2939 2796 2797 2941 3728 3729 +1 6 2940 2797 2798 2942 3729 3730 +1 6 2941 2798 2799 2943 3730 3731 +1 6 2942 2799 2800 2944 3731 3732 +1 6 2943 2800 2801 2824 2945 3732 +1 6 2944 2824 2825 2946 3732 3733 +1 6 2945 2825 2827 2947 3733 3734 +1 6 2946 2827 2828 2829 2948 3734 +1 7 2947 2829 2830 2949 3734 3735 3736 +1 6 2948 2830 2831 2950 3242 3736 +1 6 2949 2831 2832 2951 3242 3243 +1 6 2950 2832 2833 2952 3243 3244 +1 6 2951 2833 2834 2953 3244 3245 +1 5 2952 2834 2835 2954 3245 +1 7 2953 2835 2836 2955 3245 3246 3247 +1 6 2954 2836 2837 2956 3247 3248 +1 6 2955 2837 2839 2957 3248 3249 +1 6 2956 2839 2958 3249 3250 3251 +1 6 2957 2839 2840 2959 3251 3252 +1 6 2958 2840 2621 2622 2960 3252 +1 6 2959 2622 2623 2961 3254 3252 +1 6 2960 2623 2624 2962 3254 3255 +1 6 2961 2624 2625 2963 2964 3255 +1 6 2962 2625 2964 2965 2966 2626 +1 6 2962 2963 2965 3255 3256 3257 +1 6 2964 2963 2966 3257 3258 3259 +1 6 2965 2963 2626 2627 2967 3259 +1 6 2966 2627 2628 2968 3259 3260 +1 6 2967 2628 2629 2969 3260 3261 +1 6 2968 2629 2630 2970 3261 3262 +1 6 2969 2630 2631 2971 3262 3263 +1 6 2970 2631 2632 2972 3263 3264 +1 6 2971 2632 2633 2973 3264 3265 +1 6 2972 2633 2634 2974 3265 3266 +1 6 2973 2634 2635 2975 3266 3267 +1 6 2974 2635 2636 2637 2976 3267 +1 6 2975 2637 2639 2977 3267 3268 +1 6 2976 2639 2978 3268 3269 3270 +1 6 2977 2639 2640 2979 3270 3271 +2 6 2978 2640 2642 2980 3271 3272 +2 6 2979 2642 2643 2981 3272 3273 +2 6 2980 2643 2644 2982 3273 3274 +2 6 2981 2644 2645 2983 3274 3275 +2 6 2982 2645 2646 2984 3275 3276 +2 6 2983 2646 2647 2985 3276 3277 +2 6 2984 2647 2648 2986 3277 3824 +2 6 2985 2648 2649 2987 3545 3824 +2 6 2986 2649 2650 2988 3545 3546 +2 6 2987 2650 2651 2989 3546 3547 +2 6 2988 2651 2652 2990 3547 3548 +2 6 2989 2652 2653 2991 3548 3549 +2 6 2990 2653 2654 2992 3549 3550 +2 6 2991 2654 2656 2993 3550 3551 +2 6 2992 2656 2657 2994 3551 3552 +2 6 2993 2657 2658 2995 3552 3553 +2 6 2994 2658 2659 2996 3553 3554 +2 6 2995 2659 2997 3554 3555 3556 +2 6 2996 2659 2660 2998 3556 3557 +2 6 2997 2660 2661 2662 2999 3557 +2 6 2998 2662 2663 3000 3557 3558 +2 6 2999 2663 2664 3001 3558 3559 +2 6 3000 2664 2665 3002 3559 3560 +2 6 3001 2665 2666 3560 3561 3565 +1 6 2702 2703 3004 3290 3291 3292 +1 6 3003 2703 2704 3005 3292 3293 +1 6 3004 2704 2705 3006 3293 3294 +1 6 3005 2705 2706 3007 3294 3295 +1 6 3006 2706 2707 3008 3295 3296 +1 6 3007 2707 2708 3009 3296 3297 +1 6 3008 2708 2709 2710 3010 3297 +1 6 3009 2710 3011 3297 3298 3299 +1 6 3010 2710 2711 3012 3299 3300 +1 6 3011 2711 2712 3013 3300 3301 +1 6 3012 2712 2713 3014 3301 3302 +1 6 3013 2713 2714 3015 3302 3303 +1 6 3014 2714 2715 3016 3303 3304 +1 6 3015 2715 2716 3017 3304 3305 +1 6 3016 2716 2717 3018 3305 3306 +1 6 3017 2717 2718 3019 3306 3307 +1 6 3018 2718 2719 3020 3307 3308 +1 6 3019 2719 2720 3021 3308 3309 +1 6 3020 2720 2721 3022 3309 3310 +1 6 3021 2721 2722 3023 3310 3311 +1 6 3022 2722 2723 3024 3311 3312 +1 6 3023 2723 2724 3025 3312 3313 +1 6 3024 2724 2725 3026 3313 3314 +1 6 3025 2725 2726 3027 3314 3315 +1 6 3026 2726 2727 3028 3315 3316 +1 6 3027 2727 2728 3029 3316 3317 +1 6 3028 2728 2729 3030 3317 3318 +1 6 3029 2729 2730 3031 3318 3319 +1 6 3030 2730 2731 3032 3319 3320 +1 6 3031 2731 2732 3033 3320 3321 +1 6 3032 2732 2733 3034 3321 3322 +1 6 3033 2733 2734 3035 3042 3322 +1 6 3034 2734 2735 3036 3042 3043 +1 6 3035 2735 2736 3037 3043 3044 +1 6 3036 2736 2737 2738 3038 3044 +1 6 3037 2738 3039 3044 3045 3046 +1 6 3038 2738 2739 3040 3046 3047 +1 6 3039 2739 2740 2741 3041 3047 +1 6 3040 2741 2743 3047 3048 3049 +1 6 3034 3035 3043 3322 3323 3324 +1 6 3042 3035 3036 3044 3324 3325 +1 6 3043 3036 3037 3038 3045 3325 +1 6 3044 3038 3046 3325 3326 3327 +1 6 3045 3038 3039 3047 3053 3327 +1 6 3046 3039 3040 3041 3048 3053 +1 6 3047 3041 3049 3053 3054 3055 +1 6 3048 3041 2743 2744 3050 3055 +1 6 3049 2744 2745 2746 3051 3055 +1 6 3050 2746 2747 3052 3055 3056 +1 6 3051 2747 2749 3056 3057 3058 +1 6 3046 3047 3048 3054 3327 3328 +1 6 3053 3048 3055 3328 3329 3056 +1 6 3054 3048 3049 3050 3051 3056 +1 7 3055 3051 3052 3057 3329 3054 3641 +1 5 3056 3052 3058 3641 3642 +1 7 3057 3052 2749 2750 3059 3642 3643 +1 6 3058 2750 3060 3643 3644 3061 +1 5 3059 2750 2445 2446 3061 +1 6 3060 2446 3062 3644 3059 3910 +1 6 3061 2446 2447 3063 3910 3911 +1 6 3062 2447 3064 3069 3911 3912 +1 6 3063 2447 2448 2449 3065 3069 +1 6 3064 2449 2450 3066 3069 3070 +1 6 3065 2450 2451 3067 3070 3071 +1 6 3066 2451 2452 3068 3071 3072 +1 6 3067 2452 2454 3072 3073 3074 +1 6 3063 3064 3065 3070 3912 3913 +1 6 3069 3065 3066 3071 3913 3914 +1 6 3070 3066 3067 3072 3914 3915 +1 6 3071 3067 3068 3073 3915 3916 +1 6 3072 3068 3074 3916 3917 3918 +1 6 3073 3068 2454 2455 3075 3918 +1 6 3074 2455 2456 2457 3076 3918 +1 6 3075 2457 2458 3077 3349 3918 +1 6 3076 2458 2459 3078 3349 3350 +1 6 3077 2459 2460 3079 3107 3350 +1 6 3078 2460 2461 3080 3107 3108 +1 6 3079 2461 3081 3091 3108 3109 +1 6 3080 2461 2462 3082 3091 3092 +1 6 3081 2462 2463 3083 3084 3092 +1 6 3082 2463 3084 3085 2482 2464 +1 6 3082 3083 3085 3092 3112 3359 +1 6 3084 3083 2482 3926 3152 3359 +1 6 16 17 3087 3088 3089 3090 +1 6 3086 17 18 3095 3126 3090 +1 6 16 3086 3089 3098 417 15 +1 6 3088 3086 3090 3098 3103 3104 +1 6 3089 3086 3104 3105 3087 3126 +1 6 3080 3081 3092 3109 3110 3111 +1 6 3091 3081 3082 3084 3111 3112 +2 5 1615 1616 3094 4099 3544 +2 6 3093 1616 1617 4367 4099 1624 +1 6 3087 18 19 3096 3125 3126 +1 6 3095 19 20 3125 3128 414 +2 6 2241 1657 1655 1647 1182 1184 +1 6 3088 3089 417 3099 3102 3103 +1 6 417 3098 418 3100 3101 3102 +1 6 418 3099 3101 3228 3229 3684 +1 6 3100 3099 3102 3226 3228 3498 +1 7 3101 3099 3098 3103 3113 3498 3497 +1 6 3102 3098 3089 3104 3113 3114 +1 6 3103 3089 3090 3105 3106 3114 +1 6 3104 3090 3106 3126 3124 3118 +1 6 3104 3105 3116 3114 3117 3118 +1 6 3078 3079 3108 3350 3351 3352 +1 6 3107 3079 3080 3109 3352 3353 +1 6 3108 3080 3091 3110 3353 3354 +1 6 3109 3091 3111 3354 3355 3356 +1 6 3110 3091 3092 3112 3356 3357 +1 6 3111 3092 3084 3357 3358 3359 +1 5 3102 3103 3114 3115 3497 +1 6 3113 3103 3115 3116 3106 3104 +1 7 3113 3114 3116 3497 3504 3501 3495 +1 6 3115 3114 3106 3117 6712 3504 +1 6 3116 3106 3118 3119 6712 6711 +1 6 3117 3106 3119 3120 3124 3105 +1 6 3117 3118 3120 3121 6711 6713 +1 6 3119 3118 3121 3122 3123 3124 +1 6 3119 3120 3122 3884 3887 6713 +1 6 3121 3120 3123 3127 3883 3884 +1 6 3122 3120 3124 3125 3127 3128 +1 6 3123 3120 3118 3125 3126 3105 +1 6 3123 3124 3126 3128 3095 3096 +1 6 3125 3124 3105 3095 3087 3090 +1 6 3122 3123 3128 3882 3339 3883 +1 6 3127 3123 3125 414 3882 3096 +1 6 2201 2203 3130 3851 3852 9781 +1 6 3129 2203 2205 1525 1526 9781 +1 6 2094 2095 3132 3133 9776 3138 +1 6 2094 3131 3133 3134 3135 2093 +1 6 3132 3131 3134 3136 3137 3138 +1 6 3132 3133 3135 3136 5946 5945 +1 6 3132 3134 5945 5943 5947 2093 +1 6 3134 3133 3137 6090 6091 5946 +1 6 3136 3133 3138 6090 6089 6092 +1 6 3137 3133 6092 6093 9776 3131 +2 6 2813 2814 2817 3140 4388 4386 +2 6 3139 2817 3141 4385 4384 4386 +2 6 3140 2817 2818 3142 4390 4385 +2 6 3141 2818 3143 7767 4390 7768 +2 6 3142 2818 2819 3144 7774 7768 +2 6 3143 2819 2820 3145 7774 7775 +2 6 3144 2820 3146 4231 7775 9791 +2 6 3145 2820 2821 2823 3147 4231 +2 6 3146 2823 1673 1674 3412 4231 +1 6 2486 2487 3149 3156 3157 3161 +1 6 2486 3148 3150 3151 3155 3156 +1 6 2486 3149 3151 3152 3926 2484 +1 6 3150 3149 3152 3153 3154 3155 +1 6 3150 3151 3153 3926 3085 3359 +1 6 3152 3151 3154 3358 3359 3360 +1 6 3153 3151 3155 3360 3361 3362 +1 6 3154 3151 3149 3156 3677 3362 +1 6 3155 3149 3148 3157 3158 3677 +1 6 3156 3148 3158 3159 3160 3161 +1 6 3156 3157 3159 3676 3677 3945 +1 6 3158 3157 3160 3945 3946 3962 +1 6 3159 3157 3161 3962 3963 3964 +1 6 3160 3157 3148 3967 3964 2487 +1 6 2845 2847 3163 3164 3165 2844 +1 6 3162 2847 3164 3180 2858 2849 +1 6 3162 3163 3165 3166 3177 3180 +1 6 3162 3164 3166 3167 3168 2844 +1 6 3165 3164 3167 3177 3174 3171 +1 6 3165 3166 3168 3169 3170 3171 +1 6 3165 3167 3169 2843 2844 9688 +1 6 3168 3167 3170 9687 9686 9688 +1 5 3169 3167 3171 3172 9687 +1 6 3170 3167 3172 3173 3174 3166 +1 6 3170 3171 3173 9691 9687 6653 +1 7 3172 3171 3174 3175 6654 6652 6653 +1 6 3173 3171 3175 3176 3177 3166 +1 5 3173 3174 3176 3450 6654 +1 6 3175 3174 3177 3178 3179 3450 +1 6 3176 3174 3178 3166 3164 3180 +1 6 3176 3177 3179 3180 6660 6661 +1 6 3176 3178 3450 6657 6659 6660 +1 6 3177 3164 3178 3163 2858 6661 +2 6 2869 2870 2884 3182 3190 2868 +2 6 3181 2884 2885 3183 3216 3190 +2 6 3182 2885 2886 3184 3193 3216 +2 6 3183 2886 3185 3186 3192 3193 +2 6 3184 2886 3186 3187 3188 2887 +2 6 3184 3185 3187 3192 3196 7584 +2 6 3186 3185 3188 3958 7586 7584 +2 6 3187 3185 2887 3958 3959 2888 +2 6 2867 2868 3190 2866 3214 3215 +2 6 3189 2868 3181 3215 3216 3182 +1 6 1741 1742 1744 3197 3198 3199 +2 6 3184 3186 3193 3194 3195 3196 +2 6 3184 3192 3194 7222 3216 3183 +2 7 3193 3192 3195 7222 7221 7204 7203 +2 6 3194 3192 3196 7196 7197 7203 +2 6 3195 3192 3186 7583 7196 7584 +1 6 1740 1741 3191 3198 3411 3200 +1 7 3197 3191 3199 2893 2894 2895 3200 +1 5 3198 3191 1744 1745 2893 +1 6 3198 2895 3201 3411 3197 9751 +1 6 3200 2895 2896 3202 3470 9751 +1 6 3201 2896 2897 3203 3470 3471 +1 6 3202 2897 2898 3204 3471 3472 +1 6 3203 2898 3205 3472 3473 3474 +1 6 3204 2898 2899 3206 3474 3475 +1 6 3205 2899 2900 3207 3475 3476 +1 6 3206 2900 2901 3208 3476 3477 +1 6 3207 2901 2902 3209 3477 3478 +1 6 3208 2902 3210 3211 3478 3479 +1 6 3209 2902 3211 3212 3213 2903 +1 6 3209 3210 3212 3479 3480 3481 +1 7 3211 3210 3213 3481 3482 2907 3483 +1 6 3212 3210 2903 3483 2905 2904 +2 6 2866 3189 3215 7220 7219 7221 +2 6 3214 3189 3190 3216 7221 7222 +2 6 3215 3190 3182 7222 3193 3183 +1 6 635 636 3218 4040 3763 3762 +1 6 3217 636 638 3219 3484 4040 +1 6 3218 638 3220 3221 3222 3484 +1 6 3219 638 639 3221 3240 3241 +1 6 3219 3220 3222 3223 3224 3241 +1 6 3219 3221 3223 3484 3485 3486 +1 6 3222 3221 3224 3225 3486 3487 +1 6 3223 3221 3225 3226 3227 3241 +1 6 3223 3224 3226 3493 3487 3494 +1 7 3225 3224 3227 3228 3101 3494 3498 +1 6 3226 3224 3228 3229 3230 3241 +1 5 3226 3227 3101 3100 3229 +1 6 3100 3228 3227 3230 3231 3684 +1 6 3229 3227 3231 3232 3241 3240 +1 6 3229 3230 3232 3233 3234 3684 +1 6 3231 3230 3233 3240 3239 3236 +1 7 3231 3232 3234 11 10 3235 3236 +1 5 3231 3233 11 3684 12 +1 6 10 3233 3236 3237 3238 9 +1 6 3235 3233 3237 643 3239 3232 +1 6 3235 3236 3238 647 644 643 +1 5 3235 3237 9 8 647 +1 6 643 3236 640 639 3240 3232 +1 6 639 3239 3220 3241 3230 3232 +1 6 3220 3240 3221 3224 3227 3230 +1 6 2949 2950 3243 3736 3737 3738 +1 6 3242 2950 2951 3244 3738 3739 +1 6 3243 2951 2952 3245 3739 3740 +1 7 3244 2952 2953 2954 3246 3740 3741 +1 5 3245 2954 3247 3741 3742 +1 6 3246 2954 2955 3248 3742 3743 +1 6 3247 2955 2956 3249 3743 3744 +1 6 3248 2956 2957 3250 3744 3745 +1 6 3249 2957 3251 3745 3746 3747 +1 6 3250 2957 2958 3252 3253 3747 +1 6 3251 2958 3253 3254 2960 2959 +1 6 3251 3252 3254 3747 3748 3749 +1 6 3253 3252 2960 2961 3255 3749 +1 6 3254 2961 2962 2964 3256 3749 +1 6 3255 2964 3257 3749 3750 3751 +1 6 3256 2964 2965 3258 3751 3752 +1 6 3257 2965 3259 3752 3753 3754 +1 6 3258 2965 2966 2967 3260 3754 +1 6 3259 2967 2968 3261 3754 3755 +1 6 3260 2968 2969 3262 3755 3756 +1 6 3261 2969 2970 3263 3756 3757 +1 6 3262 2970 2971 3264 3757 3758 +1 6 3263 2971 2972 3265 3758 3759 +1 7 3264 2972 2973 3266 3759 4054 4051 +1 5 3265 2973 2974 3267 4054 +1 6 3266 2974 2975 2976 3268 4054 +1 7 3267 2976 2977 3269 4054 4053 4055 +1 5 3268 2977 3270 4055 4056 +1 6 3269 2977 2978 3271 4056 4057 +2 6 3270 2978 2979 3272 4057 4058 +2 6 3271 2979 2980 3273 4058 4059 +2 6 3272 2980 2981 3274 4059 4060 +2 6 3273 2981 2982 3275 4060 4061 +2 6 3274 2982 2983 3276 4064 4061 +2 6 3275 2983 2984 3277 4064 4065 +2 6 3276 2984 2985 3826 4065 3824 +1 6 2689 2690 3279 3588 3589 3590 +1 6 3278 2690 2691 3280 3590 3591 +1 6 3279 2691 2692 3281 3591 3592 +1 6 3280 2692 2693 3282 3592 3593 +1 6 3281 2693 2694 3283 3593 3594 +1 6 3282 2694 2695 3284 3594 3595 +1 6 3283 2695 2696 3285 3595 3596 +1 6 3284 2696 2697 3286 3596 3597 +1 6 3285 2697 2698 3287 3597 3598 +1 6 3286 2698 2699 3288 3598 3599 +1 6 3287 2699 2700 3289 3599 3600 +1 6 3288 2700 2701 3290 3600 3601 +1 6 3289 2701 2702 3003 3291 3601 +1 6 3290 3003 3292 3601 3602 3603 +1 6 3291 3003 3004 3293 3603 3604 +1 6 3292 3004 3005 3294 3604 3605 +1 6 3293 3005 3006 3295 3605 3606 +1 6 3294 3006 3007 3296 3606 3607 +1 6 3295 3007 3008 3297 3607 3608 +1 6 3296 3008 3009 3010 3298 3608 +1 6 3297 3010 3299 3608 3609 3610 +1 6 3298 3010 3011 3300 3610 3611 +1 6 3299 3011 3012 3301 3611 3612 +1 6 3300 3012 3013 3302 3612 3613 +1 6 3301 3013 3014 3303 3613 3614 +1 6 3302 3014 3015 3304 3614 3615 +1 6 3303 3015 3016 3305 3615 3616 +1 6 3304 3016 3017 3306 3616 3617 +1 6 3305 3017 3018 3307 3617 3618 +1 6 3306 3018 3019 3308 3618 3619 +1 6 3307 3019 3020 3309 3619 3620 +1 6 3308 3020 3021 3310 3620 3621 +1 6 3309 3021 3022 3311 3621 3622 +1 6 3310 3022 3023 3312 3622 3623 +1 6 3311 3023 3024 3313 3623 3624 +1 6 3312 3024 3025 3314 3624 3625 +1 6 3313 3025 3026 3315 3625 3626 +1 6 3314 3026 3027 3316 3626 3627 +1 6 3315 3027 3028 3317 3627 3628 +1 6 3316 3028 3029 3318 3628 3629 +1 6 3317 3029 3030 3319 3629 3630 +1 6 3318 3030 3031 3320 3630 3631 +1 6 3319 3031 3032 3321 3631 3632 +1 6 3320 3032 3033 3322 3632 3633 +1 6 3321 3033 3034 3042 3323 3633 +1 6 3322 3042 3324 3633 3634 3635 +1 6 3323 3042 3043 3325 3635 3636 +1 6 3324 3043 3044 3045 3326 3636 +1 6 3325 3045 3327 3636 3637 3638 +1 6 3326 3045 3046 3053 3328 3638 +1 6 3327 3053 3054 3329 3638 3639 +1 6 3328 3054 3056 3639 3640 3641 +1 6 2507 2508 32 33 3331 3880 +1 6 3330 33 34 2248 3332 3880 +1 6 3331 2248 3333 3334 3880 3881 +1 6 3332 2248 3334 3335 3336 2249 +1 6 3332 3333 3335 9707 6499 3881 +1 6 3334 3333 3336 9706 6492 9707 +1 6 3335 3333 2249 2250 2251 9706 +1 6 1171 1172 1524 3338 3339 3882 +1 6 3337 1524 3339 3340 3341 4250 +1 6 3337 3338 3340 3882 3127 3883 +1 6 3339 3338 3341 3342 3885 3883 +1 6 3340 3338 3342 3343 2206 4250 +1 6 3340 3341 3343 3861 6717 3885 +1 6 3342 3341 2206 2207 3344 3861 +1 6 3343 2207 2209 3345 3346 3861 +1 6 3344 2209 3346 3347 3348 2211 +1 6 3344 3345 3347 3861 3862 3863 +1 6 3346 3345 3348 6532 3863 6524 +1 6 3347 3345 2211 2213 6523 6524 +1 6 3076 3077 3350 3918 3917 3919 +1 6 3349 3077 3078 3107 3351 3919 +1 6 3350 3107 3352 3919 3920 3921 +1 6 3351 3107 3108 3353 3921 3922 +1 6 3352 3108 3109 3354 3922 3923 +1 6 3353 3109 3110 3355 3923 3924 +1 6 3354 3110 3356 3924 3925 3374 +1 6 3355 3110 3111 3357 3368 3374 +1 6 3356 3111 3112 3358 3367 3368 +1 6 3357 3112 3359 3153 3360 3367 +1 6 3358 3112 3153 3085 3152 3084 +1 6 3358 3153 3154 3361 3363 3367 +1 6 3360 3154 3362 3363 3364 3678 +1 6 3361 3154 3155 3677 3675 3678 +1 6 3360 3361 3364 3365 3366 3367 +1 6 3363 3361 3365 3678 3667 3668 +1 6 3363 3364 3366 3373 3370 3668 +1 6 3363 3365 3367 3368 3369 3370 +1 6 3363 3366 3368 3360 3358 3357 +1 6 3367 3366 3369 3357 3356 3374 +1 6 3368 3366 3370 3371 3374 3375 +1 6 3369 3366 3371 3372 3373 3365 +1 6 3369 3370 3372 3375 3376 3377 +1 6 3371 3370 3373 3377 3378 3379 +1 6 3372 3370 3365 3379 3380 3668 +1 6 3356 3368 3369 3375 3925 3355 +1 7 3374 3369 3371 3376 3943 3925 4342 +1 5 3375 3371 3377 4342 4343 +1 6 3376 3371 3372 3378 4343 4344 +1 6 3377 3372 3379 3645 4347 4344 +1 6 3378 3372 3373 3380 3381 3645 +1 6 3379 3373 3381 3382 3668 3656 +1 6 3379 3380 3382 3383 3384 3645 +1 6 3381 3380 3383 3390 3387 3656 +1 6 3381 3382 3384 3385 3386 3387 +1 6 3381 3383 3385 3645 3646 3647 +1 6 3384 3383 3386 3647 3648 3649 +1 6 3385 3383 3387 3388 3649 3650 +1 6 3386 3383 3388 3389 3390 3382 +1 6 3386 3387 3389 3650 3651 3652 +1 6 3388 3387 3390 3652 3653 3654 +1 6 3389 3387 3382 3654 3655 3656 +1 6 2675 2676 3392 3573 3574 3575 +1 6 3391 2676 2677 3393 3575 3576 +1 6 3392 2677 2678 3394 3576 3577 +1 6 3393 2678 2679 3577 3578 3579 +1 6 2173 2804 2805 3396 3397 4747 +1 6 3395 2805 3397 3398 3399 3400 +1 6 3395 3396 3398 3892 4747 4746 +1 6 3397 3396 3399 3892 3893 3894 +1 6 3398 3396 3400 3894 3895 3896 +1 6 3399 3396 2805 2806 3401 3896 +1 6 3400 2806 2807 3402 3896 3897 +1 6 3401 2807 3403 3897 3898 3899 +1 6 3402 2807 2808 3404 3899 3900 +1 6 3403 2808 1732 3405 3679 3900 +1 6 3404 1732 1733 1734 3406 3679 +1 6 3405 1734 1735 3407 3679 3680 +1 6 3406 1735 1736 3408 3680 3681 +1 6 3407 1736 1737 3409 3683 3681 +1 6 3408 1737 1738 3410 3470 3683 +1 6 3409 1738 1739 3411 9751 3470 +1 6 3410 1739 1740 3197 3200 9751 +2 6 3147 1674 1675 1676 3413 4231 +2 6 3412 1676 1677 3414 9791 4231 +2 6 3413 1677 3415 7778 7776 9791 +2 6 3414 1677 1678 7778 7779 5382 +1 6 1695 1696 3417 3786 1694 3787 +1 6 3416 1696 1697 3418 3787 3789 +1 6 3417 1697 1698 2223 3419 3789 +1 6 3418 2223 3420 3789 3790 3791 +1 6 3419 2223 2224 3421 3791 3792 +1 6 3420 2224 2225 3422 3423 3792 +1 6 3421 2225 3423 3424 3425 3426 +1 6 3421 3422 3424 3794 3792 3795 +1 6 3423 3422 3425 3795 3796 3797 +1 6 3424 3422 3426 3797 3798 3799 +1 6 3425 3422 2225 2226 3427 3799 +1 6 3426 2226 2227 3428 3799 3800 +1 6 3427 2227 2228 3429 3800 3801 +1 6 3428 2228 3430 3801 3802 3432 +1 6 3429 2228 2229 2238 3431 3432 +1 6 3430 2238 3432 3433 3434 3435 +1 6 3430 3431 3433 3442 3802 3429 +1 6 3432 3431 3434 3442 3443 3444 +1 6 3433 3431 3435 3444 3445 3446 +1 6 3434 3431 2238 2239 2561 3446 +2 6 2491 2492 3437 3438 3515 2493 +2 6 2491 3436 3438 3439 3440 3441 +2 6 3437 3436 3439 3513 3514 3515 +2 6 3437 3438 3440 3508 3509 3513 +2 6 3437 3439 3441 3451 3453 3508 +2 6 3437 3440 2491 70 3451 69 +1 6 3432 3433 3443 3802 3803 3804 +1 6 3442 3433 3444 3804 3805 3806 +1 6 3443 3433 3434 3445 3806 3807 +1 6 3444 3434 3446 3807 3808 3447 +1 6 3445 3434 3435 2561 2562 3447 +1 6 3446 2562 3448 3808 3445 4107 +1 6 3447 2562 2563 3449 3454 4107 +1 6 3448 2563 2567 3454 3455 2568 +1 7 3175 3176 3179 6655 6654 6656 6657 +1 6 3441 3440 69 68 3452 3453 +1 6 68 3451 3453 67 3505 3506 +1 6 3452 3451 3440 3506 3507 3508 +1 6 3448 3449 3455 3456 4107 4108 +1 6 3454 3449 3456 3457 3458 2568 +1 6 3454 3455 3457 3464 4110 4108 +1 6 3456 3455 3458 3459 3460 3464 +1 6 3457 3455 3459 3463 2569 2568 +1 6 3457 3458 3460 3461 3462 3463 +1 6 3457 3459 3461 3464 3465 3466 +1 6 3460 3459 3462 3466 3467 3469 +1 6 3461 3459 3463 1721 3469 1720 +1 6 3462 3459 3458 2569 1720 1719 +1 6 3456 3457 3460 3465 4394 4110 +1 6 3464 3460 3466 4404 4394 4745 +1 6 3465 3460 3461 3467 3468 4745 +1 6 3466 3461 3468 2172 1724 3469 +1 6 3466 3467 2172 4745 4746 4747 +1 6 1724 3467 1722 1721 3462 3461 +1 7 3201 3202 3471 9751 3410 3409 3683 +1 6 3470 3202 3203 3472 3681 3683 +1 6 3471 3203 3204 3473 3682 3681 +1 6 3472 3204 3474 3685 3902 3682 +1 6 3473 3204 3205 3475 3685 3686 +1 6 3474 3205 3206 3476 3686 3687 +1 6 3475 3206 3207 3477 3687 3688 +1 6 3476 3207 3208 3478 3688 3689 +1 6 3477 3208 3209 3479 3689 3690 +1 6 3478 3209 3211 3480 3690 3691 +1 6 3479 3211 3481 3499 3694 3691 +1 6 3480 3211 3212 3482 3499 3500 +1 5 3481 3212 2907 3500 2908 +1 5 2907 3212 3213 2905 2906 +1 6 3218 3219 3222 3485 4039 4040 +1 6 3484 3222 3486 3489 3968 4039 +1 6 3485 3222 3223 3487 3488 3489 +1 6 3486 3223 3488 3492 3493 3225 +1 6 3486 3487 3489 3490 3491 3492 +1 6 3486 3488 3490 3485 3968 3969 +1 6 3489 3488 3491 3969 3970 3971 +1 6 3490 3488 3492 3971 9747 6555 +1 6 3491 3488 3487 3493 3496 9747 +1 6 3492 3487 3225 3494 3495 3496 +1 6 3493 3225 3226 3495 3497 3498 +1 6 3493 3494 3496 3497 3501 3115 +1 6 3493 3495 3492 3501 3502 9747 +1 6 3495 3494 3498 3102 3113 3115 +1 5 3497 3494 3226 3101 3102 +1 6 3480 3481 3500 3694 3695 3696 +1 6 3499 3481 3482 2908 3696 3697 +1 6 3496 3495 3502 3503 3504 3115 +1 6 3496 3501 3503 9747 6706 9748 +1 6 3502 3501 3504 6712 6710 9748 +1 5 3503 3501 3115 6712 3116 +1 6 67 3452 3506 6697 6703 66 +1 6 3505 3452 3453 3507 6697 6704 +1 6 3506 3453 3508 3510 4522 6704 +2 6 3507 3453 3440 3439 3509 3510 +2 6 3508 3439 3510 3511 3512 3513 +2 6 3508 3509 3511 3770 3507 4522 +2 6 3510 3509 3512 3770 3771 3772 +2 6 3511 3509 3513 3772 3773 3520 +2 6 3512 3509 3439 3438 3514 3520 +2 6 3513 3438 3515 3520 3521 3517 +2 6 3514 3438 3436 2493 3516 3517 +2 6 3515 2493 3517 3518 1607 1606 +2 6 3515 3516 3518 3521 3514 3522 +2 6 3517 3516 1607 1613 3522 3523 +2 5 1613 1607 1605 1608 1610 +2 6 3513 3514 3521 3773 3512 4531 +2 6 3520 3514 3517 3522 4116 4531 +2 6 3521 3517 3518 3523 3525 4116 +2 6 3522 3518 1613 1614 3524 3525 +2 6 3523 1614 3525 3526 3527 3528 +2 6 3523 3524 3526 3522 4116 4117 +2 6 3525 3524 3527 3529 4117 4118 +2 6 3526 3524 3528 3529 3530 3543 +2 6 3527 3524 1614 3543 3544 1615 +2 6 3526 3527 3530 3531 4118 9786 +2 6 3529 3527 3531 3532 3542 3543 +2 6 3529 3530 3532 3533 9786 9787 +2 6 3531 3530 3533 3534 3541 3542 +2 6 3531 3532 3534 3535 9787 9788 +2 6 3533 3532 3535 3536 3540 3541 +2 6 3533 3534 3536 3537 9788 7178 +2 6 3535 3534 3537 3538 3539 3540 +2 6 3535 3536 3538 7182 7179 7178 +2 6 3537 3536 3539 7182 7183 7184 +2 6 3538 3536 3540 7184 7185 7212 +2 6 3539 3536 3534 3541 7212 4372 +2 6 3540 3534 3532 3542 4372 4097 +2 6 3541 3532 3530 3543 4096 4097 +2 6 3542 3530 3527 3528 3544 4096 +2 6 3543 3528 1615 4099 4096 3093 +2 6 2986 2987 3546 3824 3825 3829 +2 6 3545 2987 2988 3547 3829 3830 +2 6 3546 2988 2989 3548 3830 3831 +2 6 3547 2989 2990 3549 3831 3832 +2 6 3548 2990 2991 3550 3832 3833 +2 6 3549 2991 2992 3551 3809 3833 +2 6 3550 2992 2993 3552 3809 3810 +2 6 3551 2993 2994 3553 3810 3811 +2 6 3552 2994 2995 3554 3811 3812 +2 6 3553 2995 2996 3555 3812 3813 +2 6 3554 2996 3556 3813 3814 3815 +2 6 3555 2996 2997 3557 3815 3816 +2 6 3556 2997 2998 2999 3558 3816 +2 6 3557 2999 3000 3559 3816 3817 +2 6 3558 3000 3001 3560 3817 3818 +2 6 3559 3001 3002 3561 3562 3818 +2 6 3560 3002 3562 3563 3564 3565 +2 6 3560 3561 3563 3818 3819 3820 +2 6 3562 3561 3564 3820 3821 3822 +2 6 3563 3561 3565 3822 3823 3566 +2 6 3564 3561 3002 2666 2667 3566 +2 6 3565 2667 2668 3567 3823 3564 +2 6 3566 2668 2669 3568 3850 3823 +2 6 3567 2669 2670 3569 3879 3850 +2 6 3568 2670 2671 3570 3891 3879 +2 6 3569 2671 2672 2673 3571 3891 +2 6 3570 2673 3572 4237 3891 4257 +2 6 3571 2673 2674 3573 4257 4258 +1 6 3572 2674 2675 3391 3574 4258 +1 6 3573 3391 3575 4258 4259 4263 +1 6 3574 3391 3392 3576 4263 4264 +1 6 3575 3392 3393 3577 4264 4265 +1 6 3576 3393 3394 3578 4265 4266 +1 6 3577 3394 3579 4266 4267 4268 +1 6 3578 3394 2679 2680 3580 4268 +1 6 3579 2680 2681 3581 4141 4268 +1 6 3580 2681 2682 3582 4141 4142 +1 6 3581 2682 2683 3583 4142 4143 +1 6 3582 2683 2684 3584 4143 4144 +1 6 3583 2684 2685 3585 4144 4145 +1 6 3584 2685 2686 3586 4145 4146 +1 6 3585 2686 2687 3587 4146 4147 +1 6 3586 2687 2688 3588 4147 4148 +1 6 3587 2688 2689 3278 3589 4148 +1 6 3588 3278 3590 4148 4149 4150 +1 6 3589 3278 3279 3591 4150 4151 +1 6 3590 3279 3280 3592 4151 4152 +1 6 3591 3280 3281 3593 4152 4153 +1 6 3592 3281 3282 3594 4153 4154 +1 6 3593 3282 3283 3595 4154 4155 +1 6 3594 3283 3284 3596 4155 4156 +1 6 3595 3284 3285 3597 4156 4157 +1 6 3596 3285 3286 3598 4157 4158 +1 6 3597 3286 3287 3599 4158 4159 +1 6 3598 3287 3288 3600 4159 4160 +1 6 3599 3288 3289 3601 4160 4161 +1 6 3600 3289 3290 3291 3602 4161 +1 6 3601 3291 3603 4161 4162 4163 +1 6 3602 3291 3292 3604 4163 4164 +1 6 3603 3292 3293 3605 4164 4165 +1 6 3604 3293 3294 3606 4165 4166 +1 6 3605 3294 3295 3607 4166 4167 +1 6 3606 3295 3296 3608 4167 4168 +1 6 3607 3296 3297 3298 3609 4168 +1 6 3608 3298 3610 4168 4169 4170 +1 6 3609 3298 3299 3611 4170 4171 +1 6 3610 3299 3300 3612 4171 4172 +1 6 3611 3300 3301 3613 4172 4173 +1 6 3612 3301 3302 3614 4173 4174 +1 6 3613 3302 3303 3615 4174 4175 +1 6 3614 3303 3304 3616 4175 4176 +1 6 3615 3304 3305 3617 4176 4177 +1 6 3616 3305 3306 3618 4177 4178 +1 6 3617 3306 3307 3619 4178 4179 +1 6 3618 3307 3308 3620 4179 4180 +1 6 3619 3308 3309 3621 4180 4181 +1 6 3620 3309 3310 3622 4181 4182 +1 6 3621 3310 3311 3623 4182 4183 +1 6 3622 3311 3312 3624 4183 4184 +1 6 3623 3312 3313 3625 4184 4185 +1 6 3624 3313 3314 3626 4185 4186 +1 6 3625 3314 3315 3627 4186 4187 +1 6 3626 3315 3316 3628 4187 4188 +1 6 3627 3316 3317 3629 4188 4189 +1 6 3628 3317 3318 3630 4189 4190 +1 6 3629 3318 3319 3631 4190 4191 +1 6 3630 3319 3320 3632 4191 4192 +1 6 3631 3320 3321 3633 4192 4193 +1 6 3632 3321 3322 3323 3634 4193 +1 6 3633 3323 3635 3903 4193 4194 +1 6 3634 3323 3324 3636 3903 3904 +1 6 3635 3324 3325 3326 3637 3904 +1 6 3636 3326 3638 3904 3905 3906 +1 6 3637 3326 3327 3328 3639 3906 +1 6 3638 3328 3329 3640 3906 3907 +1 6 3639 3329 3641 3907 3908 3642 +1 5 3640 3329 3056 3057 3642 +1 7 3641 3057 3058 3643 3908 3640 3927 +1 6 3642 3058 3059 3644 3909 3927 +1 5 3643 3059 3061 3909 3910 +1 6 3381 3384 3646 3379 3378 4347 +1 6 3645 3384 3647 4347 4348 4349 +1 6 3646 3384 3385 3648 4352 4349 +1 6 3647 3385 3649 3657 4352 4353 +1 6 3648 3385 3386 3650 3657 3658 +1 6 3649 3386 3388 3651 3658 3659 +1 6 3650 3388 3652 3659 3660 3661 +1 6 3651 3388 3389 3653 3661 3662 +1 6 3652 3389 3654 3662 3663 3664 +1 6 3653 3389 3390 3655 3664 3665 +1 6 3654 3390 3656 3665 3666 3667 +1 6 3655 3390 3382 3667 3668 3380 +1 6 3648 3649 3658 4353 4354 4358 +1 6 3657 3649 3650 3659 4371 4358 +1 6 3658 3650 3651 3660 9793 4371 +1 6 3659 3651 3661 4906 4908 9793 +1 6 3660 3651 3652 3662 3669 4906 +1 6 3661 3652 3653 3663 3669 3670 +1 6 3662 3653 3664 3670 3671 3672 +1 6 3663 3653 3654 3665 3672 3673 +1 6 3664 3654 3655 3666 3673 3674 +1 6 3665 3655 3667 3674 3675 3678 +1 6 3666 3655 3656 3668 3364 3678 +1 6 3667 3656 3380 3364 3365 3373 +1 6 3661 3662 3670 4903 4905 4906 +1 6 3669 3662 3663 3671 4902 4903 +1 6 3670 3663 3672 5918 4902 3951 +1 6 3671 3663 3664 3673 3950 3951 +1 6 3672 3664 3665 3674 3944 3950 +1 6 3673 3665 3666 3675 3676 3944 +1 6 3674 3666 3676 3677 3362 3678 +1 6 3674 3675 3677 3158 3944 3945 +1 6 3676 3675 3158 3156 3155 3362 +1 6 3362 3675 3361 3364 3667 3666 +1 6 3404 3405 3406 3680 3900 3901 +1 6 3679 3406 3407 3681 3682 3901 +1 7 3680 3407 3682 3472 3471 3683 3408 +1 6 3680 3681 3472 3901 3902 3473 +1 5 3471 3681 3408 3409 3470 +1 7 418 3100 3229 3231 3234 12 13 +1 7 3473 3474 3686 3902 4665 4664 4688 +1 5 3685 3474 3475 3687 4688 +1 7 3686 3475 3476 3688 4688 4689 4690 +1 6 3687 3476 3477 3689 4690 4691 +1 6 3688 3477 3478 3690 4691 4692 +1 6 3689 3478 3479 3691 3692 4692 +1 6 3690 3479 3692 3693 3694 3480 +1 6 3690 3691 3693 4692 4693 4694 +1 6 3692 3691 3694 4694 4695 4696 +1 6 3693 3691 3480 3499 3695 4696 +1 6 3694 3499 3696 4696 4697 4698 +1 6 3695 3499 3500 3697 4698 4699 +1 6 3696 3500 2908 2909 3698 4699 +1 6 3697 2909 2910 3699 3972 4699 +1 6 3698 2910 2911 3700 3972 3973 +1 6 3699 2911 2912 2913 3701 3973 +1 6 3700 2913 3702 3973 3974 3975 +1 6 3701 2913 2914 3703 3975 3976 +1 6 3702 2914 2915 3704 3976 3977 +1 6 3703 2915 2916 3705 3977 3978 +1 6 3704 2916 2917 3706 3978 3979 +1 6 3705 2917 2918 3707 3979 3980 +1 6 3706 2918 2919 3708 3980 3981 +1 6 3707 2919 2920 3709 3981 3982 +1 6 3708 2920 2921 3710 3982 3983 +1 6 3709 2921 2922 3711 3983 3984 +1 6 3710 2922 2923 3712 3984 3985 +1 6 3711 2923 2924 3713 3985 3986 +1 6 3712 2924 2925 3714 3986 3987 +1 6 3713 2925 2926 3715 3987 3988 +1 6 3714 2926 2927 3716 3988 3989 +1 6 3715 2927 2928 3717 3989 3990 +1 6 3716 2928 2929 3718 3990 3991 +1 6 3717 2929 2930 3719 3991 3992 +1 6 3718 2930 2931 3720 3992 3993 +1 6 3719 2931 2932 3721 3993 3994 +1 6 3720 2932 2933 3722 3994 3995 +1 6 3721 2933 2934 3723 3995 3996 +1 6 3722 2934 2935 3724 3996 3997 +1 6 3723 2935 2936 3725 3997 3998 +1 6 3724 2936 2937 3726 3998 3999 +1 6 3725 2937 2938 3727 3999 4000 +1 6 3726 2938 2939 3728 4000 4001 +1 6 3727 2939 2940 3729 4001 4002 +1 6 3728 2940 2941 3730 4002 4003 +1 6 3729 2941 2942 3731 4003 4004 +1 6 3730 2942 2943 3732 4004 4005 +1 6 3731 2943 2944 2945 3733 4005 +1 6 3732 2945 2946 3734 4005 4006 +1 6 3733 2946 2947 2948 3735 4006 +1 6 3734 2948 3736 4006 4007 3737 +1 5 3735 2948 2949 3242 3737 +1 6 3736 3242 3738 4007 3735 4012 +1 6 3737 3242 3243 3739 4012 4013 +1 6 3738 3243 3244 3740 4013 4014 +1 6 3739 3244 3245 3741 4014 4015 +1 6 3740 3245 3246 3742 4015 4016 +1 6 3741 3246 3247 3743 4016 4017 +1 6 3742 3247 3248 3744 4017 4018 +1 6 3743 3248 3249 3745 4018 4019 +1 6 3744 3249 3250 3746 4019 4020 +1 6 3745 3250 3747 4020 4021 4022 +1 6 3746 3250 3251 3253 3748 4022 +1 6 3747 3253 3749 4022 4023 4024 +1 7 3748 3253 3254 3255 3256 3750 4024 +1 5 3749 3256 3751 4024 4025 +1 6 3750 3256 3257 3752 4025 4026 +1 6 3751 3257 3258 3753 4029 4026 +1 7 3752 3258 3754 4037 4029 4046 3755 +1 5 3753 3258 3259 3260 3755 +1 6 3754 3260 3261 3756 4046 3753 +1 6 3755 3261 3262 3757 4046 4047 +1 6 3756 3262 3263 3758 4047 4048 +1 6 3757 3263 3264 3759 4048 4049 +1 6 3758 3264 3265 4049 4050 4051 +1 6 615 617 3761 3764 3765 3763 +1 6 3760 617 625 627 3762 3763 +1 6 3761 627 3763 3217 635 629 +1 6 3761 3762 3765 3760 4040 3217 +1 6 615 3760 3765 4038 6557 612 +1 6 3764 3760 3763 4038 4039 4040 +1 5 2085 1567 3767 3768 6093 +1 6 3766 1567 3768 3769 1571 1568 +1 6 3766 3767 3769 6092 6093 6094 +1 7 3768 3767 1571 6094 6088 6317 6318 +1 6 3510 3511 3771 4522 4523 4524 +1 6 3770 3511 3772 4524 4525 4528 +2 6 3771 3511 3512 3773 4528 4529 +2 6 3772 3512 3520 4529 4530 4531 +2 6 1682 1683 3775 5391 5385 5383 +2 6 3774 1683 3776 5620 5391 3778 +2 6 3775 1683 1684 1686 3777 3778 +2 6 3776 1686 3778 3779 3780 3781 +2 6 3776 3777 3779 7791 5620 3775 +2 6 3778 3777 3780 7798 7792 7791 +2 6 3779 3777 3781 7798 3783 3782 +2 6 3780 3777 1686 1687 1688 3782 +2 6 3781 1688 1689 1691 3783 3780 +2 6 3782 1691 3784 7798 3780 7799 +2 6 3783 1691 1692 3785 7799 7800 +2 6 3784 1692 3786 3787 3788 7800 +1 6 3785 1692 1693 1694 3416 3787 +1 6 3786 3416 3417 3785 3788 3789 +2 6 3785 3787 3789 7800 7801 3790 +1 6 3788 3787 3417 3418 3419 3790 +2 6 3789 3419 3791 7801 3788 7802 +1 6 3790 3419 3420 3792 3793 7802 +1 6 3791 3420 3793 3794 3423 3421 +1 6 3791 3792 3794 7802 7803 7804 +1 6 3793 3792 3423 3795 7804 7805 +1 6 3794 3423 3424 3796 7809 7805 +1 6 3795 3424 3797 3952 7809 7810 +1 6 3796 3424 3425 3798 3952 3953 +1 6 3797 3425 3799 3953 3954 3955 +1 6 3798 3425 3426 3427 3800 3955 +1 6 3799 3427 3428 3801 3955 3956 +1 6 3800 3428 3429 3802 3956 3957 +1 6 3801 3429 3432 3442 3803 3957 +1 6 3802 3442 3804 3957 4100 4239 +1 6 3803 3442 3443 3805 4100 4101 +1 6 3804 3443 3806 4101 4102 4103 +1 6 3805 3443 3444 3807 4103 4104 +1 6 3806 3444 3445 3808 4104 4105 +1 6 3807 3445 3447 4105 4106 4107 +2 6 3550 3551 3810 3833 3834 3835 +2 6 3809 3551 3552 3811 3835 3836 +2 6 3810 3552 3553 3812 3836 3837 +2 6 3811 3553 3554 3813 3837 3838 +2 6 3812 3554 3555 3814 3838 3839 +2 6 3813 3555 3815 3839 3840 3841 +2 6 3814 3555 3556 3816 3841 3842 +2 6 3815 3556 3557 3558 3817 3842 +2 6 3816 3558 3559 3818 3842 3843 +2 6 3817 3559 3560 3562 3819 3843 +2 6 3818 3562 3820 3843 3844 3845 +2 6 3819 3562 3563 3821 3845 3846 +2 6 3820 3563 3822 3846 3847 3848 +2 6 3821 3563 3564 3823 3848 3849 +2 6 3822 3564 3566 3849 3850 3567 +2 6 2986 3545 3825 3826 3277 2985 +2 6 3824 3545 3826 3827 3828 3829 +2 6 3824 3825 3827 4069 4065 3277 +2 6 3826 3825 3828 4756 4069 4763 +2 6 3827 3825 3829 4763 4764 4765 +2 6 3828 3825 3545 3546 3830 4765 +2 6 3829 3546 3547 3831 4765 4766 +2 6 3830 3547 3548 3832 4766 4767 +2 6 3831 3548 3549 3833 4770 4767 +2 6 3832 3549 3550 3809 3834 4770 +2 6 3833 3809 3835 5016 4770 5024 +2 6 3834 3809 3810 3836 5024 5025 +2 6 3835 3810 3811 3837 5025 5026 +2 6 3836 3811 3812 3838 4405 5026 +2 6 3837 3812 3813 3839 3864 4405 +2 6 3838 3813 3814 3840 3864 3865 +2 6 3839 3814 3841 3865 3866 3867 +2 6 3840 3814 3815 3842 3853 3867 +2 6 3841 3815 3816 3817 3843 3853 +2 6 3842 3817 3818 3819 3844 3853 +2 6 3843 3819 3845 3853 3854 3855 +2 6 3844 3819 3820 3846 3855 3856 +2 6 3845 3820 3821 3847 3856 3857 +2 6 3846 3821 3848 3860 3857 3876 +2 6 3847 3821 3822 3849 3876 3877 +2 6 3848 3822 3823 3850 3877 3878 +2 6 3849 3823 3567 3878 3879 3568 +1 6 2181 2199 2179 3852 2201 3129 +1 6 2179 3851 27 26 3129 9781 +2 6 3841 3842 3843 3844 3854 3867 +2 6 3853 3844 3855 3867 3868 3869 +2 6 3854 3844 3845 3856 3869 3870 +2 6 3855 3845 3846 3857 3858 3870 +2 6 3856 3846 3858 3859 3860 3847 +2 6 3856 3857 3859 3870 3871 3872 +2 6 3858 3857 3860 3872 3873 3874 +2 6 3859 3857 3847 3874 3875 3876 +1 6 3343 3344 3346 3862 6717 3342 +1 6 3861 3346 3863 6716 6715 6717 +1 7 3862 3346 6532 6531 3347 6533 6716 +2 6 3838 3839 3865 4405 4406 4407 +2 6 3864 3839 3840 3866 4407 4408 +2 6 3865 3840 3867 4408 4409 3868 +2 6 3866 3840 3841 3853 3854 3868 +2 6 3867 3854 3869 4409 3866 4420 +2 6 3868 3854 3855 3870 4420 4421 +2 6 3869 3855 3856 3858 3871 4421 +2 6 3870 3858 3872 4421 4422 4423 +2 6 3871 3858 3859 3873 4423 4424 +2 6 3872 3859 3874 4424 4425 4426 +2 6 3873 3859 3860 3875 4426 4427 +2 6 3874 3860 3876 4427 4428 3888 +2 6 3875 3860 3847 3848 3877 3888 +2 6 3876 3848 3849 3878 3888 3889 +2 6 3877 3849 3850 3879 3889 3890 +2 6 3878 3850 3568 3890 3891 3569 +1 6 2507 3330 2509 3881 3331 3332 +1 6 2509 3880 3334 6499 2511 3332 +1 6 3337 3339 3127 1171 414 3128 +1 6 3127 3339 3122 3884 3885 3340 +1 6 3122 3883 3885 3886 3887 3121 +1 6 3884 3883 3886 3342 6717 3340 +1 6 3884 3885 3887 6538 6715 6717 +1 6 3884 3886 3121 6713 6714 6538 +2 6 3876 3877 3889 4428 3875 4251 +2 6 3888 3877 3878 3890 4236 4251 +2 6 3889 3878 3879 3891 4236 4237 +2 6 3890 3879 3569 4237 3571 3570 +1 6 3397 3398 3893 4746 4744 4743 +1 6 3892 3398 3894 4743 4748 4749 +1 6 3893 3398 3399 3895 4752 4749 +1 6 3894 3399 3896 4661 4758 4752 +1 6 3895 3399 3400 3401 3897 4661 +1 6 3896 3401 3402 3898 4661 4662 +1 6 3897 3402 3899 4662 4663 4664 +1 6 3898 3402 3403 3900 4664 4665 +1 6 3899 3403 3404 3679 3901 4665 +1 6 3900 3679 3680 3682 3902 4665 +1 5 3901 3682 3473 4665 3685 +1 6 3634 3635 3904 4194 4195 4196 +1 6 3903 3635 3636 3637 3905 4196 +1 6 3904 3637 3906 4196 4197 4198 +1 6 3905 3637 3638 3639 3907 4198 +1 6 3906 3639 3640 3908 4198 4199 +1 6 3907 3640 3642 3927 4199 4200 +1 5 3643 3644 3910 3927 3928 +1 7 3909 3644 3061 3062 3911 3928 3929 +1 7 3910 3062 3063 3912 3929 3930 3931 +1 6 3911 3063 3069 3913 3931 3932 +1 6 3912 3069 3070 3914 3932 3933 +1 6 3913 3070 3071 3915 3933 3934 +1 6 3914 3071 3072 3916 3934 3935 +1 6 3915 3072 3073 3917 3935 3936 +1 6 3916 3073 3918 3349 3919 3936 +1 6 3917 3073 3074 3075 3076 3349 +1 6 3917 3349 3350 3351 3920 3936 +1 6 3919 3351 3921 3936 3937 3938 +1 6 3920 3351 3352 3922 3938 3939 +1 6 3921 3352 3353 3923 3939 3940 +1 6 3922 3353 3354 3924 3940 3941 +1 6 3923 3354 3355 3925 3941 3942 +1 6 3924 3355 3374 3942 3943 3375 +1 6 3085 2482 2483 2484 3150 3152 +1 6 3908 3642 3643 3909 3928 4200 +1 6 3927 3909 3910 3929 4200 4201 +1 6 3928 3910 3911 3930 4201 4202 +1 6 3929 3911 3931 4202 4203 4204 +1 5 3930 3911 3912 3932 4204 +1 6 3931 3912 3913 3933 4204 4205 +1 6 3932 3913 3914 3934 4205 4206 +1 6 3933 3914 3915 3935 4206 4207 +1 6 3934 3915 3916 3936 4207 3937 +1 6 3935 3916 3917 3919 3920 3937 +1 6 3936 3920 3938 4207 3935 4335 +1 6 3937 3920 3921 3939 4335 4336 +1 6 3938 3921 3922 3940 4336 4337 +1 6 3939 3922 3923 3941 4337 4338 +1 6 3940 3923 3924 3942 4338 4339 +1 6 3941 3924 3925 3943 4339 4340 +1 6 3942 3925 3375 4340 4341 4342 +1 6 3673 3674 3676 3945 3950 3947 +1 6 3944 3676 3158 3159 3946 3947 +1 6 3945 3159 3947 3948 5922 3962 +1 6 3945 3946 3948 3949 3950 3944 +1 6 3947 3946 3949 5920 5921 5922 +1 6 3947 3948 3950 3951 5919 5920 +1 6 3947 3949 3951 3672 3673 3944 +1 6 3950 3949 3672 5918 3671 5919 +1 6 3796 3797 3953 7810 7811 7812 +1 6 3952 3797 3798 3954 7812 7813 +1 6 3953 3798 3955 7813 7814 7815 +1 6 3954 3798 3799 3800 3956 7815 +1 6 3955 3800 3801 3957 4238 7815 +1 6 3956 3801 3802 3803 4238 4239 +2 6 3187 3188 3959 3960 7588 7586 +2 6 3958 3188 3960 3961 2890 2888 +2 6 3958 3959 3961 7588 7589 7590 +2 6 3960 3959 2890 7590 7591 7592 +1 6 3159 3160 3963 5922 3946 5923 +1 6 3962 3160 3964 3965 5923 5924 +1 6 3963 3160 3965 3966 3967 3161 +1 6 3963 3964 3966 5924 5942 5943 +1 6 3965 3964 3967 5943 5948 5947 +1 6 3966 3964 3161 5948 2488 2487 +1 6 3485 3489 3969 6556 4038 4039 +1 6 3968 3489 3490 3970 1597 6556 +1 6 3969 3490 3971 6358 1595 1597 +1 6 3970 3490 3491 6555 6357 6358 +1 6 3698 3699 3973 4699 4700 4701 +1 6 3972 3699 3700 3701 3974 4701 +1 6 3973 3701 3975 4701 4702 4703 +1 6 3974 3701 3702 3976 4703 4704 +1 6 3975 3702 3703 3977 4704 4705 +1 6 3976 3703 3704 3978 4705 4706 +1 6 3977 3704 3705 3979 4706 4707 +1 6 3978 3705 3706 3980 4707 4708 +1 6 3979 3706 3707 3981 4708 4709 +1 6 3980 3707 3708 3982 4709 4710 +1 6 3981 3708 3709 3983 4710 4711 +1 6 3982 3709 3710 3984 4711 4712 +1 6 3983 3710 3711 3985 4712 4713 +1 6 3984 3711 3712 3986 4713 4714 +1 6 3985 3712 3713 3987 4714 4715 +1 6 3986 3713 3714 3988 4715 4716 +1 6 3987 3714 3715 3989 4716 4717 +1 6 3988 3715 3716 3990 4717 4718 +1 6 3989 3716 3717 3991 4718 4719 +1 6 3990 3717 3718 3992 4719 4720 +1 6 3991 3718 3719 3993 4720 4721 +1 6 3992 3719 3720 3994 4439 4721 +1 6 3993 3720 3721 3995 4439 4440 +1 6 3994 3721 3722 3996 4440 4441 +1 6 3995 3722 3723 3997 4441 4442 +1 6 3996 3723 3724 3998 4442 4443 +1 6 3997 3724 3725 3999 4443 4444 +1 6 3998 3725 3726 4000 4444 4445 +1 6 3999 3726 3727 4001 4445 4446 +1 6 4000 3727 3728 4002 4070 4446 +1 6 4001 3728 3729 4003 4008 4070 +1 6 4002 3729 3730 4004 4008 4009 +1 6 4003 3730 3731 4005 4009 4010 +1 6 4004 3731 3732 3733 4006 4010 +1 6 4005 3733 3734 3735 4007 4010 +1 6 4006 3735 3737 4010 4011 4012 +1 6 4002 4003 4009 4070 4071 4072 +1 6 4008 4003 4004 4010 4072 4011 +1 6 4009 4004 4005 4006 4007 4011 +1 6 4010 4007 4012 4072 4009 4073 +1 6 4011 4007 3737 3738 4013 4073 +1 6 4012 3738 3739 4014 4073 4074 +1 7 4013 3739 3740 4015 4074 4075 4076 +1 6 4014 3740 3741 4016 4076 4077 +1 6 4015 3741 3742 4017 4077 4078 +1 6 4016 3742 3743 4018 4078 4079 +1 6 4017 3743 3744 4019 4079 4080 +1 6 4018 3744 3745 4020 4080 4081 +1 6 4019 3745 3746 4021 4081 4082 +1 6 4020 3746 4022 4030 4082 4083 +1 6 4021 3746 3747 3748 4023 4030 +1 6 4022 3748 4024 4030 4031 4032 +1 6 4023 3748 3749 3750 4025 4032 +1 6 4024 3750 3751 4026 4027 4032 +1 6 4025 3751 4027 4028 4029 3752 +1 6 4025 4026 4028 4032 4033 4034 +1 6 4027 4026 4029 4034 4035 4036 +1 6 4028 4026 3752 4036 4037 3753 +1 6 4021 4022 4023 4031 4083 4084 +1 6 4030 4023 4032 4084 4085 4033 +1 6 4031 4023 4024 4025 4027 4033 +1 6 4032 4027 4034 4085 4031 4462 +1 6 4033 4027 4028 4035 4041 4462 +1 6 4034 4028 4036 4041 4042 4043 +1 6 4035 4028 4029 4037 4043 4044 +1 6 4036 4029 3753 4044 4045 4046 +1 6 3764 3765 4039 6556 6557 3968 +1 6 4038 3765 4040 3968 3485 3484 +1 6 4039 3765 3763 3217 3484 3218 +1 6 4034 4035 4042 4462 4463 4464 +1 6 4041 4035 4043 4464 4465 4466 +1 6 4042 4035 4036 4044 4466 4467 +1 6 4043 4036 4037 4045 4467 4468 +1 6 4044 4037 4046 4468 4469 4047 +1 6 4045 4037 3753 3755 3756 4047 +1 6 4046 3756 3757 4048 4469 4045 +1 6 4047 3757 3758 4049 4469 4470 +1 6 4048 3758 3759 4050 4470 4209 +1 6 4049 3759 4051 4052 4208 4209 +1 6 4050 3759 4052 4053 4054 3265 +1 6 4050 4051 4053 4208 4221 4222 +1 6 4052 4051 4054 3268 4055 4222 +1 6 4053 4051 3265 3266 3267 3268 +1 5 4053 3268 3269 4056 4222 +1 7 4055 3269 3270 4057 4222 4223 4224 +2 7 4056 3270 3271 4058 4224 4225 4226 +2 6 4057 3271 3272 4059 4226 4227 +2 6 4058 3272 3273 4060 4227 4228 +2 6 4059 3273 3274 4061 4062 4228 +2 6 4060 3274 4062 4063 4064 3275 +2 6 4060 4061 4063 4230 4228 4502 +2 6 4062 4061 4064 4066 4067 4502 +2 6 4063 4061 3275 3276 4065 4066 +2 6 4064 3276 4066 4069 3826 3277 +2 6 4064 4065 4063 4067 4068 4069 +2 6 4063 4066 4068 4513 4502 4754 +2 6 4067 4066 4069 4754 4755 4756 +2 6 4068 4066 4065 3826 4756 3827 +1 6 4001 4002 4008 4071 4446 4447 +1 6 4070 4008 4072 4447 4448 4449 +1 6 4071 4008 4009 4011 4073 4449 +1 6 4072 4011 4012 4013 4074 4449 +1 6 4073 4013 4014 4075 4449 4450 +1 6 4074 4014 4076 4450 4451 4452 +1 5 4075 4014 4015 4077 4452 +1 6 4076 4015 4016 4078 4452 4453 +1 6 4077 4016 4017 4079 4453 4454 +1 6 4078 4017 4018 4080 4454 4455 +1 6 4079 4018 4019 4081 4455 4456 +1 6 4080 4019 4020 4082 4456 4457 +1 6 4081 4020 4021 4083 4457 4458 +1 6 4082 4021 4030 4084 4458 4459 +1 6 4083 4030 4031 4085 4459 4460 +1 6 4084 4031 4033 4460 4461 4462 +2 6 2880 2881 4087 4089 7599 7600 +2 6 4086 2881 2882 2883 4088 4089 +2 6 4087 2883 4089 4090 4091 4092 +2 7 4087 4088 4090 7598 7599 4086 7751 +2 6 4089 4088 4091 7751 7753 4379 +2 6 4090 4088 4092 4094 4378 4379 +2 6 4091 4088 2883 2498 4093 4094 +2 6 4092 2498 4094 4095 2809 2499 +2 6 4092 4093 4095 4091 4378 4387 +2 6 4094 4093 2809 4387 4386 4388 +2 6 3542 3543 4097 4098 4099 3544 +2 6 3542 4096 4098 4365 4372 3541 +2 6 4097 4096 4099 4365 4366 4367 +2 6 4098 4096 3544 4367 3094 3093 +1 6 3803 3804 4101 4239 4240 4241 +1 6 4100 3804 3805 4102 4241 4242 +1 6 4101 3805 4103 4242 4243 4244 +1 6 4102 3805 3806 4104 4111 4244 +1 6 4103 3806 3807 4105 4111 4112 +1 6 4104 3807 3808 4106 4112 4113 +1 6 4105 3808 4107 4108 4109 4113 +1 6 4106 3808 3447 3448 3454 4108 +1 6 4107 3454 4106 4109 4110 3456 +1 6 4106 4108 4110 4113 4114 4115 +1 6 4109 4108 3456 4115 4394 3464 +1 6 4103 4104 4112 4244 4245 4246 +1 6 4111 4104 4105 4113 4249 4246 +1 6 4112 4105 4106 4109 4114 4249 +1 6 4113 4109 4115 4249 4391 4392 +1 6 4114 4109 4110 4392 4393 4394 +2 7 3522 3525 4117 4530 4531 3521 4119 +2 5 4116 3525 3526 4118 4119 +2 6 4117 3526 4119 4120 3529 9786 +2 7 4117 4118 4120 4121 9784 4530 4116 +2 6 4119 4118 4121 4122 9786 9789 +2 6 4119 4120 4122 4123 4395 9784 +2 6 4121 4120 4123 4124 9789 7172 +2 6 4121 4122 4124 4125 4126 4395 +2 6 4123 4122 4125 7171 4140 7172 +2 6 4123 4124 4126 4127 4128 4140 +2 6 4123 4125 4127 4395 4396 4397 +1 6 4126 4125 4128 4129 4130 4397 +1 6 4127 4125 4129 4136 4139 4140 +1 6 4127 4128 4130 4131 4135 4136 +1 6 4127 4129 4131 4132 4397 4398 +1 6 4130 4129 4132 4133 4134 4135 +1 6 4130 4131 4133 4401 4398 4410 +1 6 4132 4131 4134 4410 4411 4412 +1 6 4133 4131 4135 4412 4413 7164 +1 6 4134 4131 4129 4136 4137 7164 +1 6 4135 4129 4128 4137 4138 4139 +1 6 4135 4136 4138 7163 7161 7164 +1 6 4137 4136 4139 7168 7163 7169 +1 6 4138 4136 4128 4140 7169 7170 +2 6 4139 4128 4125 7170 7171 4124 +1 6 3580 3581 4142 4268 4269 4270 +1 6 4141 3581 3582 4143 4270 4271 +1 6 4142 3582 3583 4144 4271 4272 +1 6 4143 3583 3584 4145 4272 4273 +1 6 4144 3584 3585 4146 4273 4274 +1 6 4145 3585 3586 4147 4274 4275 +1 6 4146 3586 3587 4148 4275 4276 +1 6 4147 3587 3588 3589 4149 4276 +1 6 4148 3589 4150 4276 4277 4278 +1 6 4149 3589 3590 4151 4278 4279 +1 6 4150 3590 3591 4152 4279 4280 +1 6 4151 3591 3592 4153 4280 4281 +1 6 4152 3592 3593 4154 4281 4282 +1 6 4153 3593 3594 4155 4282 4283 +1 6 4154 3594 3595 4156 4283 4284 +1 6 4155 3595 3596 4157 4284 4285 +1 6 4156 3596 3597 4158 4285 4286 +1 6 4157 3597 3598 4159 4286 4287 +1 6 4158 3598 3599 4160 4287 4288 +1 6 4159 3599 3600 4161 4288 4289 +1 6 4160 3600 3601 3602 4162 4289 +1 6 4161 3602 4163 4289 4290 4291 +1 6 4162 3602 3603 4164 4291 4292 +1 6 4163 3603 3604 4165 4292 4293 +1 6 4164 3604 3605 4166 4293 4294 +1 6 4165 3605 3606 4167 4294 4295 +1 6 4166 3606 3607 4168 4295 4296 +1 6 4167 3607 3608 3609 4169 4296 +1 6 4168 3609 4170 4296 4297 4298 +1 6 4169 3609 3610 4171 4298 4299 +1 6 4170 3610 3611 4172 4299 4300 +1 6 4171 3611 3612 4173 4300 4301 +1 6 4172 3612 3613 4174 4301 4302 +1 6 4173 3613 3614 4175 4302 4303 +1 6 4174 3614 3615 4176 4303 4304 +1 6 4175 3615 3616 4177 4304 4305 +1 6 4176 3616 3617 4178 4305 4306 +1 6 4177 3617 3618 4179 4306 4307 +1 6 4178 3618 3619 4180 4307 4308 +1 6 4179 3619 3620 4181 4308 4309 +1 6 4180 3620 3621 4182 4309 4310 +1 6 4181 3621 3622 4183 4310 4311 +1 6 4182 3622 3623 4184 4311 4312 +1 6 4183 3623 3624 4185 4312 4313 +1 6 4184 3624 3625 4186 4313 4314 +1 6 4185 3625 3626 4187 4314 4315 +1 6 4186 3626 3627 4188 4315 4316 +1 6 4187 3627 3628 4189 4316 4317 +1 6 4188 3628 3629 4190 4317 4318 +1 6 4189 3629 3630 4191 4318 4319 +1 6 4190 3630 3631 4192 4319 4320 +1 6 4191 3631 3632 4193 4320 4321 +1 6 4192 3632 3633 3634 4194 4321 +1 6 4193 3634 3903 4195 4321 4322 +1 6 4194 3903 4196 4322 4323 4324 +1 6 4195 3903 3904 3905 4197 4324 +1 6 4196 3905 4198 4324 4325 4326 +1 6 4197 3905 3906 3907 4199 4326 +1 6 4198 3907 3908 4200 4326 4327 +1 6 4199 3908 3927 3928 4201 4327 +1 6 4200 3928 3929 4202 4327 4328 +1 6 4201 3929 3930 4203 4328 4329 +1 6 4202 3930 4204 4329 4330 4331 +1 6 4203 3930 3931 3932 4205 4331 +1 6 4204 3932 3933 4206 4331 4332 +1 6 4205 3933 3934 4207 4332 4333 +1 7 4206 3934 3935 3937 4333 4334 4335 +1 6 4050 4052 4209 4210 4211 4221 +1 6 4050 4208 4210 4470 4049 4477 +1 6 4209 4208 4211 4212 4477 4478 +1 6 4210 4208 4212 4213 4220 4221 +1 6 4210 4211 4213 4214 4478 4479 +1 6 4212 4211 4214 4215 4216 4220 +1 6 4212 4213 4215 4479 4480 4481 +1 6 4214 4213 4216 4217 4481 4482 +1 6 4215 4213 4217 4218 4219 4220 +1 6 4215 4216 4218 4232 4482 4483 +1 6 4217 4216 4219 4232 4233 4234 +1 6 4218 4216 4220 4224 4234 4223 +1 6 4219 4216 4213 4211 4221 4223 +1 6 4220 4211 4208 4052 4222 4223 +1 6 4221 4052 4053 4055 4056 4223 +1 6 4222 4056 4224 4221 4220 4219 +2 6 4223 4056 4057 4225 4234 4219 +2 6 4224 4057 4226 4235 4234 4488 +2 5 4225 4057 4058 4227 4488 +2 7 4226 4058 4059 4228 4229 4487 4488 +2 6 4227 4059 4229 4230 4062 4060 +2 6 4227 4228 4230 4489 4487 4500 +2 6 4229 4228 4062 4500 4501 4502 +2 6 3147 3412 3146 3145 9791 3413 +1 6 4217 4218 4233 4483 4484 4485 +2 6 4232 4218 4234 4235 4485 4486 +2 6 4233 4218 4235 4225 4224 4219 +2 6 4233 4234 4225 4486 4487 4488 +2 6 3889 3890 4237 4251 4252 4256 +2 6 4236 3890 3891 3571 4256 4257 +1 6 3956 3957 4239 7815 7816 4503 +1 6 4238 3957 3803 4100 4240 4503 +1 6 4239 4100 4241 4503 4504 4505 +1 6 4240 4100 4101 4242 4505 4506 +1 6 4241 4101 4102 4243 4416 4506 +1 6 4242 4102 4244 4416 4417 4418 +1 6 4243 4102 4103 4111 4245 4418 +1 6 4244 4111 4246 4247 4418 4419 +1 6 4245 4111 4247 4248 4249 4112 +1 6 4245 4246 4248 4419 7829 7830 +1 6 4247 4246 4249 4391 4739 7830 +1 6 4248 4246 4112 4113 4114 4391 +1 6 3341 3338 1524 1525 2205 2206 +2 6 3889 4236 4252 4253 4428 3888 +2 6 4251 4236 4253 4254 4255 4256 +2 6 4251 4252 4254 4647 4428 6892 +2 6 4253 4252 4255 4729 4730 6892 +2 6 4254 4252 4256 4729 4261 4260 +2 6 4255 4252 4236 4237 4257 4260 +2 6 4256 4237 3571 3572 4258 4260 +2 6 4257 3572 3573 3574 4259 4260 +2 6 4258 3574 4260 4261 4262 4263 +2 6 4258 4259 4261 4256 4257 4255 +2 6 4260 4259 4262 4732 4729 4255 +2 6 4261 4259 4263 6901 4732 6902 +1 6 4262 4259 3574 3575 4264 6902 +1 6 4263 3575 3576 4265 5231 6902 +1 6 4264 3576 3577 4266 5231 5232 +1 6 4265 3577 3578 4267 5232 5233 +1 6 4266 3578 4268 5233 5234 4269 +1 6 4267 3578 3579 3580 4141 4269 +1 6 4268 4141 4270 5234 4267 5451 +1 6 4269 4141 4142 4271 5451 5452 +1 6 4270 4142 4143 4272 5452 5453 +1 6 4271 4143 4144 4273 5453 5454 +1 6 4272 4144 4145 4274 5457 5454 +1 6 4273 4145 4146 4275 5469 5457 +1 6 4274 4146 4147 4276 5469 5470 +1 6 4275 4147 4148 4149 4277 5470 +1 6 4276 4149 4278 5470 5471 5472 +1 6 4277 4149 4150 4279 5472 5473 +1 6 4278 4150 4151 4280 5473 5474 +1 6 4279 4151 4152 4281 5046 5474 +1 6 4280 4152 4153 4282 5046 5047 +1 6 4281 4153 4154 4283 5047 5048 +1 6 4282 4154 4155 4284 5048 5049 +1 6 4283 4155 4156 4285 5049 5050 +1 6 4284 4156 4157 4286 5050 5051 +1 6 4285 4157 4158 4287 5051 5052 +1 6 4286 4158 4159 4288 4923 5052 +1 6 4287 4159 4160 4289 4923 4924 +1 6 4288 4160 4161 4162 4290 4924 +1 6 4289 4162 4291 4924 4925 4926 +1 6 4290 4162 4163 4292 4926 4927 +1 6 4291 4163 4164 4293 4927 4928 +1 6 4292 4164 4165 4294 4928 4929 +1 6 4293 4165 4166 4295 4929 4930 +1 6 4294 4166 4167 4296 4930 4931 +1 6 4295 4167 4168 4169 4297 4931 +1 6 4296 4169 4298 4771 4931 4932 +1 6 4297 4169 4170 4299 4771 4772 +1 6 4298 4170 4171 4300 4772 4773 +1 6 4299 4171 4172 4301 4773 4774 +1 6 4300 4172 4173 4302 4774 4775 +1 6 4301 4173 4174 4303 4775 4776 +1 6 4302 4174 4175 4304 4776 4777 +1 6 4303 4175 4176 4305 4777 4778 +1 6 4304 4176 4177 4306 4778 4779 +1 6 4305 4177 4178 4307 4779 4780 +1 6 4306 4178 4179 4308 4780 4781 +1 6 4307 4179 4180 4309 4781 4782 +1 6 4308 4180 4181 4310 4566 4782 +1 6 4309 4181 4182 4311 4566 4567 +1 6 4310 4182 4183 4312 4567 4568 +1 6 4311 4183 4184 4313 4568 4569 +1 6 4312 4184 4185 4314 4569 4570 +1 6 4313 4185 4186 4315 4570 4571 +1 6 4314 4186 4187 4316 4571 4572 +1 6 4315 4187 4188 4317 4572 4573 +1 6 4316 4188 4189 4318 4573 4574 +1 6 4317 4189 4190 4319 4574 4575 +1 6 4318 4190 4191 4320 4575 4576 +1 6 4319 4191 4192 4321 4576 4577 +1 6 4320 4192 4193 4194 4322 4577 +1 6 4321 4194 4195 4323 4577 4578 +1 6 4322 4195 4324 4578 4579 4580 +1 6 4323 4195 4196 4197 4325 4580 +1 6 4324 4197 4326 4580 4581 4582 +1 6 4325 4197 4198 4199 4327 4582 +1 6 4326 4199 4200 4201 4328 4582 +1 6 4327 4201 4202 4329 4582 4583 +1 6 4328 4202 4203 4330 4583 4584 +1 6 4329 4203 4331 4584 4585 4589 +1 7 4330 4203 4204 4205 4332 4589 4590 +1 6 4331 4205 4206 4333 4590 4591 +1 6 4332 4206 4207 4334 4591 4592 +1 6 4333 4207 4335 4336 4429 4592 +1 5 4334 4207 3937 3938 4336 +1 6 4335 3938 3939 4337 4334 4429 +1 6 4336 3939 3940 4338 4429 4430 +1 6 4337 3940 3941 4339 4430 4431 +1 6 4338 3941 3942 4340 4431 4432 +1 6 4339 3942 3943 4341 4432 4433 +1 6 4340 3943 4342 4433 4434 4435 +1 6 4341 3943 3375 3376 4343 4435 +1 6 4342 3376 3377 4344 4345 4435 +1 6 4343 3377 4345 4346 4347 3378 +1 6 4343 4344 4346 4435 4436 4437 +1 6 4345 4344 4347 4437 4438 4348 +1 6 4346 4344 3378 3645 3646 4348 +1 6 4347 3646 4349 4350 4438 4346 +1 6 4348 3646 4350 4351 4352 3647 +1 6 4348 4349 4351 4601 4438 4602 +1 6 4350 4349 4352 4602 4603 4604 +1 6 4351 4349 3647 3648 4353 4604 +1 6 4352 3648 3657 4354 4355 4604 +1 6 4353 3657 4355 4356 4357 4358 +1 6 4353 4354 4356 4604 4605 4606 +1 6 4355 4354 4357 4361 4362 4606 +1 6 4356 4354 4358 4359 4360 4361 +1 6 4357 4354 4359 4371 3658 3657 +1 6 4357 4358 4360 4368 4369 4371 +1 6 4357 4359 4361 4364 4368 4614 +1 6 4357 4360 4356 4362 4363 4364 +1 6 4356 4361 4363 4606 4607 4608 +1 6 4362 4361 4364 4611 4608 4612 +1 6 4363 4361 4360 4612 4613 4614 +2 6 4097 4098 4366 4372 4373 4374 +2 6 4365 4098 4367 4374 4375 4376 +2 7 4366 4098 4099 3094 4376 1626 1624 +1 6 4360 4359 4369 4370 4614 4615 +1 6 4368 4359 4370 4371 9794 9793 +1 6 4368 4369 9794 4642 4637 4615 +1 6 4369 4359 4358 3658 9793 3659 +2 6 4097 4365 4373 7212 3540 3541 +2 6 4372 4365 4374 7212 7210 7209 +2 6 4373 4365 4366 4375 7209 7213 +2 6 4374 4366 4376 4377 7213 7214 +2 6 4375 4366 4367 4377 1627 1626 +2 5 4375 4376 1627 7214 7215 +2 6 4091 4094 4379 4380 4381 4387 +2 7 4091 4378 4380 7753 4090 7752 7754 +2 6 4379 4378 4381 4382 7754 7755 +2 6 4380 4378 4382 4383 4384 4387 +2 6 4380 4381 4383 7755 7756 7764 +2 6 4382 4381 4384 4385 4389 7764 +2 6 4383 4381 4385 3140 4386 4387 +2 6 4383 4384 3140 4389 4390 3141 +2 6 3140 4384 4387 4095 4388 3139 +2 6 4386 4384 4381 4378 4094 4095 +2 6 4386 4095 2809 2810 2813 3139 +2 6 4383 4385 4390 7764 7765 7766 +2 6 4389 4385 3141 7766 7767 3142 +1 6 4249 4114 4392 4248 4739 4740 +1 6 4391 4114 4115 4393 4402 4740 +1 6 4392 4115 4394 4402 4403 4404 +1 6 4393 4115 4110 3464 4404 3465 +2 5 4121 4123 4126 4396 9784 +2 7 4395 4126 4397 4399 4528 4529 9784 +1 6 4396 4126 4127 4130 4398 4399 +1 6 4397 4130 4399 4400 4401 4132 +1 6 4397 4398 4400 4525 4528 4396 +1 5 4399 4398 4401 4527 4525 +1 7 4400 4398 4132 4410 4534 4527 4535 +1 6 4392 4393 4403 4740 4741 4742 +1 6 4402 4393 4404 4742 4743 4744 +1 6 4403 4393 4394 3465 4744 4745 +2 6 3837 3838 3864 4406 5026 5027 +2 6 4405 3864 4407 5027 5028 5029 +2 6 4406 3864 3865 4408 5029 5030 +2 6 4407 3865 3866 4409 5030 5031 +2 6 4408 3866 3868 4420 5031 5032 +1 6 4401 4132 4133 4411 4535 4536 +1 6 4410 4133 4412 4545 4539 4536 +1 6 4411 4133 4134 4413 4414 4545 +1 6 4412 4134 4414 4415 7164 7165 +1 6 4412 4413 4415 4545 4544 4648 +1 6 4414 4413 4649 4648 7165 7166 +1 6 4242 4243 4417 4506 4507 4508 +1 6 4416 4243 4418 4508 4509 4510 +1 6 4417 4243 4244 4245 4419 4510 +1 6 4418 4245 4247 7828 4510 7829 +2 6 4409 3868 3869 4421 5032 5033 +2 6 4420 3869 3870 3871 4422 5033 +2 6 4421 3871 4423 5033 5034 5035 +2 6 4422 3871 3872 4424 5035 5036 +2 6 4423 3872 3873 4425 4643 5036 +2 6 4424 3873 4426 4643 4644 4645 +2 6 4425 3873 3874 4427 4645 4646 +2 6 4426 3874 3875 4428 4646 4647 +2 6 4427 3875 3888 4647 4253 4251 +1 6 4334 4336 4337 4430 4592 4593 +1 6 4429 4337 4338 4431 4593 4594 +1 6 4430 4338 4339 4432 4594 4595 +1 6 4431 4339 4340 4433 4595 4596 +1 6 4432 4340 4341 4434 4596 4597 +1 6 4433 4341 4435 4597 4598 4436 +1 6 4434 4341 4342 4343 4345 4436 +1 6 4435 4345 4437 4598 4434 4599 +1 6 4436 4345 4346 4438 4599 4600 +1 6 4437 4346 4348 4600 4601 4350 +1 6 3993 3994 4440 4721 4722 4723 +1 6 4439 3994 3995 4441 4723 4724 +1 6 4440 3995 3996 4442 4724 4725 +1 6 4441 3996 3997 4443 4725 4726 +1 6 4442 3997 3998 4444 4726 4727 +1 6 4443 3998 3999 4445 4727 4728 +1 6 4444 3999 4000 4446 4728 4658 +1 6 4445 4000 4001 4070 4447 4658 +1 6 4446 4070 4071 4448 4658 4659 +1 6 4447 4071 4449 4659 4660 4450 +1 6 4448 4071 4072 4073 4074 4450 +1 6 4449 4074 4075 4451 4660 4448 +1 6 4450 4075 4452 4669 4738 4660 +1 6 4451 4075 4076 4077 4453 4669 +1 6 4452 4077 4078 4454 4669 4670 +1 6 4453 4078 4079 4455 4670 4671 +1 6 4454 4079 4080 4456 4671 4672 +1 6 4455 4080 4081 4457 4672 4673 +1 6 4456 4081 4082 4458 4673 4674 +1 6 4457 4082 4083 4459 4674 4675 +1 6 4458 4083 4084 4460 4675 4676 +1 6 4459 4084 4085 4461 4676 4677 +1 6 4460 4085 4462 4677 4678 4679 +1 7 4461 4085 4033 4034 4041 4463 4679 +1 5 4462 4041 4464 4679 4680 +1 6 4463 4041 4042 4465 4471 4680 +1 6 4464 4042 4466 4471 4472 4473 +1 6 4465 4042 4043 4467 4473 4474 +1 6 4466 4043 4044 4468 4474 4475 +1 6 4467 4044 4045 4469 4475 4476 +1 6 4468 4045 4047 4048 4470 4476 +1 6 4469 4048 4049 4209 4476 4477 +1 6 4464 4465 4472 4680 4681 4682 +1 6 4471 4465 4473 4682 4683 4684 +1 6 4472 4465 4466 4474 4684 4685 +1 6 4473 4466 4467 4475 4685 4686 +1 6 4474 4467 4468 4476 4686 4687 +1 6 4475 4468 4469 4470 4477 4687 +1 6 4476 4470 4209 4210 4478 4687 +1 6 4477 4210 4212 4479 4687 5213 +1 6 4478 4212 4214 4480 5213 5214 +1 6 4479 4214 4481 5214 5215 5216 +1 6 4480 4214 4215 4482 4490 5216 +1 6 4481 4215 4217 4483 4490 4491 +1 6 4482 4217 4232 4484 4491 4492 +1 6 4483 4232 4485 4492 4493 4494 +2 6 4484 4232 4233 4486 4494 4495 +2 6 4485 4233 4235 4487 4489 4495 +2 6 4486 4235 4488 4227 4489 4229 +2 5 4487 4235 4227 4226 4225 +2 6 4486 4487 4229 4495 4496 4500 +1 6 4481 4482 4491 4981 4989 5216 +1 6 4490 4482 4483 4492 4981 4982 +1 6 4491 4483 4484 4493 4982 4983 +1 6 4492 4484 4494 4983 4984 4985 +2 6 4493 4484 4485 4495 4985 4497 +2 6 4494 4485 4486 4489 4496 4497 +2 6 4495 4489 4497 4498 4499 4500 +2 6 4495 4496 4498 4985 4494 4986 +2 6 4497 4496 4499 4986 4987 4988 +2 5 4498 4496 4500 4988 4511 +2 7 4499 4496 4489 4229 4230 4501 4511 +2 6 4500 4230 4502 4511 4512 4513 +2 6 4501 4230 4062 4513 4067 4063 +1 6 4239 4240 4504 7816 4238 7817 +1 6 4503 4240 4505 7817 7818 7819 +1 6 4504 4240 4241 4506 7819 7820 +1 6 4505 4241 4242 4416 4507 7820 +1 6 4506 4416 4508 7820 7821 7822 +1 6 4507 4416 4417 4509 7822 7823 +1 6 4508 4417 4510 7823 7824 7825 +1 6 4509 4417 4418 7825 7828 4419 +2 7 4500 4501 4512 4988 4499 5002 4999 +2 6 4511 4501 4513 4754 4759 5002 +2 5 4512 4501 4502 4067 4754 +1 6 426 411 4515 4516 5611 5612 +1 6 4514 411 4516 4517 4521 410 +1 6 4514 4515 4517 4518 5611 5615 +1 6 4516 4515 4518 4519 4520 4521 +1 6 4516 4517 4519 9734 7508 5615 +1 6 4518 4517 4520 5235 9734 9678 +1 6 4519 4517 4521 5235 5236 5237 +1 6 4520 4517 4515 410 5237 421 +1 7 3507 3510 3770 4523 6693 6695 6704 +1 6 4522 3770 4524 6694 6693 4532 +1 6 4523 3770 3771 4525 4526 4532 +1 7 4524 3771 4526 4527 4400 4399 4528 +1 6 4524 4525 4527 4532 4533 4534 +1 5 4526 4525 4400 4534 4401 +1 6 4399 4525 3771 3772 4529 4396 +2 6 4528 3772 3773 4530 4396 9784 +2 6 4529 3773 4531 4116 4119 9784 +2 5 4530 3773 4116 3521 3520 +1 6 4524 4526 4533 5156 4523 6694 +1 6 4532 4526 4534 5156 5157 4666 +1 6 4533 4526 4527 4401 4535 4666 +1 6 4534 4401 4410 4536 4537 4666 +1 6 4535 4410 4537 4538 4539 4411 +1 6 4535 4536 4538 4666 4667 4668 +1 6 4537 4536 4539 4540 4546 4668 +1 6 4538 4536 4540 4541 4545 4411 +1 6 4538 4539 4541 4542 4546 4547 +1 6 4540 4539 4542 4543 4544 4545 +1 6 4540 4541 4543 4550 4547 4551 +1 6 4542 4541 4544 4551 4552 4553 +1 6 4543 4541 4545 4414 4648 4553 +1 6 4544 4541 4539 4411 4412 4414 +1 6 4538 4540 4547 4548 9762 4668 +1 6 4546 4540 4548 4549 4550 4542 +1 6 4546 4547 4549 4557 4560 9762 +1 6 4548 4547 4550 4557 4558 4559 +1 6 4549 4547 4542 4551 6763 4559 +1 6 4550 4542 4543 4552 7144 6763 +1 6 4551 4543 4553 4554 7145 7144 +1 6 4552 4543 4554 4555 4544 4648 +1 6 4552 4553 4555 4556 7145 7146 +1 6 4554 4553 4556 4648 4649 7153 +1 6 4554 4555 7146 7148 7149 7153 +1 6 4548 4549 4558 4560 4561 4562 +1 6 4557 4549 4559 4565 4562 6764 +1 6 4558 4549 6763 6762 6764 4550 +1 7 4548 4557 4561 9762 9761 6675 9792 +1 6 4560 4557 4562 4563 6674 6675 +1 6 4561 4557 4563 4564 4565 4558 +1 6 4561 4562 4564 6665 6666 6674 +1 6 4563 4562 4565 6673 6665 6790 +1 6 4564 4562 4558 6764 6765 6790 +1 6 4309 4310 4567 4782 4783 4784 +1 6 4566 4310 4311 4568 4784 4785 +1 6 4567 4311 4312 4569 4785 4786 +1 6 4568 4312 4313 4570 4786 4787 +1 6 4569 4313 4314 4571 4787 4788 +1 6 4570 4314 4315 4572 4788 4789 +1 6 4571 4315 4316 4573 4789 4790 +1 6 4572 4316 4317 4574 4790 4791 +1 6 4573 4317 4318 4575 4791 4792 +1 6 4574 4318 4319 4576 4792 4793 +1 6 4575 4319 4320 4577 4793 4794 +1 6 4576 4320 4321 4322 4578 4794 +1 6 4577 4322 4323 4579 4794 4795 +1 6 4578 4323 4580 4795 4796 4797 +1 6 4579 4323 4324 4325 4581 4797 +1 6 4580 4325 4582 4797 4798 4583 +1 6 4581 4325 4326 4327 4328 4583 +1 6 4582 4328 4329 4584 4798 4581 +1 7 4583 4329 4330 4585 4586 4804 4798 +1 6 4584 4330 4586 4587 4588 4589 +1 5 4584 4585 4587 4804 4805 +1 6 4586 4585 4588 4805 4806 4807 +1 6 4587 4585 4589 4807 4808 4809 +1 6 4588 4585 4330 4331 4590 4809 +1 5 4589 4331 4332 4591 4809 +1 6 4590 4332 4333 4592 4809 4810 +1 6 4591 4333 4334 4429 4593 4810 +1 6 4592 4429 4430 4594 4810 4811 +1 6 4593 4430 4431 4595 4811 4812 +1 6 4594 4431 4432 4596 4812 4813 +1 6 4595 4432 4433 4597 4813 4814 +1 6 4596 4433 4434 4598 4814 4815 +1 6 4597 4434 4436 4599 4815 4816 +1 6 4598 4436 4437 4600 4816 4817 +1 6 4599 4437 4438 4601 4817 4818 +1 6 4600 4438 4350 4602 4821 4818 +1 6 4601 4350 4351 4603 4821 4822 +1 6 4602 4351 4604 4825 4822 4826 +1 7 4603 4351 4352 4353 4355 4605 4826 +1 5 4604 4355 4606 4826 4827 +1 6 4605 4355 4356 4362 4607 4827 +1 5 4606 4362 4608 4609 4827 +1 6 4607 4362 4609 4610 4611 4363 +1 7 4607 4608 4610 4827 4828 4829 4830 +1 6 4609 4608 4611 4830 4831 4832 +1 6 4610 4608 4363 4612 4832 4834 +1 6 4611 4363 4364 4613 4837 4834 +1 6 4612 4364 4614 4616 4617 4837 +1 6 4613 4364 4360 4368 4615 4616 +1 7 4614 4368 4616 4637 4634 4619 4370 +1 6 4614 4615 4613 4617 4618 4619 +1 6 4613 4616 4618 4837 4622 4838 +1 6 4617 4616 4619 4620 4621 4622 +1 6 4618 4616 4620 4633 4634 4615 +1 6 4618 4619 4621 4628 4629 4633 +1 6 4618 4620 4622 4623 4624 4628 +1 6 4618 4621 4623 4840 4838 4617 +1 6 4622 4621 4624 4625 4840 4841 +1 6 4623 4621 4625 4626 4627 4628 +1 6 4623 4624 4626 4841 4860 4853 +1 6 4625 4624 4627 4860 4861 4862 +1 6 4626 4624 4628 4862 4863 4630 +1 6 4627 4624 4621 4620 4629 4630 +1 6 4628 4620 4630 4631 4632 4633 +1 6 4628 4629 4631 4863 4627 4864 +1 6 4630 4629 4632 4638 4868 4864 +1 6 4631 4629 4633 4638 4639 4635 +1 6 4632 4629 4620 4619 4634 4635 +1 6 4633 4619 4635 4636 4637 4615 +1 6 4633 4634 4636 4639 4632 4640 +1 6 4635 4634 4637 4640 4641 4642 +1 5 4636 4634 4615 4642 4370 +1 6 4631 4632 4639 4868 4912 9760 +1 6 4638 4632 4635 4640 4912 4913 +1 6 4639 4635 4636 4641 4916 4913 +1 6 4640 4636 4642 4910 4916 4909 +1 7 4641 4636 4637 4908 4909 9794 4370 +2 6 4424 4425 4644 5036 5037 5044 +2 6 4643 4425 4645 5045 5044 6889 +2 6 4644 4425 4426 4646 6890 6889 +2 6 4645 4426 4427 4647 6890 6891 +2 6 4646 4427 4428 4253 6891 6892 +1 6 4544 4414 4553 4555 4649 4415 +1 6 4555 4648 4415 7166 7154 7153 +1 6 422 52 53 4651 4652 9684 +1 6 4650 53 4652 4653 4657 54 +1 6 4650 4651 4653 4654 9683 9684 +1 6 4652 4651 4654 4655 4656 4657 +1 6 4652 4653 4655 9682 9680 9683 +1 6 4654 4653 4656 9682 9685 9686 +1 7 4655 4653 4657 5380 9688 9686 9689 +1 6 4656 4653 4651 54 5380 55 +1 6 4446 4447 4659 4728 4445 4736 +1 6 4658 4447 4448 4660 4736 4737 +1 6 4659 4448 4450 4737 4738 4451 +1 6 3895 3896 3897 4662 7841 4758 +1 6 4661 3897 3898 4663 7841 7842 +1 6 4662 3898 4664 7842 4689 4688 +1 6 4663 3898 3899 4665 3685 4688 +1 6 4664 3899 3900 3901 3902 3685 +1 6 4534 4535 4537 4667 5157 4533 +1 6 4666 4537 4668 9750 5157 9761 +1 6 4667 4537 4538 9761 9762 4546 +1 7 4451 4452 4453 4670 4980 4738 5194 +1 6 4669 4453 4454 4671 5194 5195 +1 6 4670 4454 4455 4672 5195 5196 +1 6 4671 4455 4456 4673 5196 5197 +1 6 4672 4456 4457 4674 5197 5198 +1 6 4673 4457 4458 4675 5198 5199 +1 6 4674 4458 4459 4676 5199 5200 +1 6 4675 4459 4460 4677 5200 5201 +1 6 4676 4460 4461 4678 5201 5202 +1 6 4677 4461 4679 5202 5203 5204 +1 6 4678 4461 4462 4463 4680 5204 +1 7 4679 4463 4464 4471 4681 5204 5205 +1 5 4680 4471 4682 5205 5206 +1 7 4681 4471 4472 4683 5206 5207 5208 +1 5 4682 4472 4684 5208 5209 +1 7 4683 4472 4473 4685 5209 5210 5211 +1 6 4684 4473 4474 4686 5211 5212 +1 6 4685 4474 4475 4687 5212 5213 +1 6 4686 4475 4476 4477 4478 5213 +1 6 4664 3685 3686 3687 4689 4663 +1 6 4688 3687 4690 7842 4663 7843 +1 6 4689 3687 3688 4691 7843 7844 +1 6 4690 3688 3689 4692 5158 7844 +1 6 4691 3689 3690 3692 4693 5158 +1 6 4692 3692 4694 5158 5159 5160 +1 6 4693 3692 3693 4695 5160 5161 +1 6 4694 3693 4696 5161 5162 5163 +1 6 4695 3693 3694 3695 4697 5163 +1 6 4696 3695 4698 5163 5164 5165 +1 6 4697 3695 3696 4699 5165 4700 +1 6 4698 3696 3697 3698 3972 4700 +1 6 4699 3972 4701 5165 4698 7854 +1 6 4700 3972 3973 3974 4702 7854 +1 6 4701 3974 4703 7308 7854 7855 +1 6 4702 3974 3975 4704 7308 7309 +1 6 4703 3975 3976 4705 7309 7310 +1 6 4704 3976 3977 4706 7310 7311 +1 6 4705 3977 3978 4707 7311 7312 +1 6 4706 3978 3979 4708 5170 7312 +1 6 4707 3979 3980 4709 5170 5171 +1 6 4708 3980 3981 4710 5171 5172 +1 6 4709 3981 3982 4711 5172 5173 +1 6 4710 3982 3983 4712 5173 5174 +1 6 4711 3983 3984 4713 5174 5175 +1 6 4712 3984 3985 4714 5175 5176 +1 6 4713 3985 3986 4715 5176 5177 +1 6 4714 3986 3987 4716 4965 5177 +1 6 4715 3987 3988 4717 4965 4966 +1 6 4716 3988 3989 4718 4966 4967 +1 6 4717 3989 3990 4719 4967 4968 +1 6 4718 3990 3991 4720 4968 4969 +1 6 4719 3991 3992 4721 4969 4970 +1 6 4720 3992 3993 4439 4722 4970 +1 6 4721 4439 4723 4970 4971 4972 +1 6 4722 4439 4440 4724 4972 4973 +1 6 4723 4440 4441 4725 4973 4974 +1 6 4724 4441 4442 4726 4733 4974 +1 6 4725 4442 4443 4727 4733 4734 +1 6 4726 4443 4444 4728 4734 4735 +1 6 4727 4444 4445 4658 4735 4736 +2 6 4254 4255 4730 4731 4732 4261 +2 6 4254 4729 4731 6892 6893 6894 +2 6 4730 4729 4732 6894 6895 6896 +2 6 4731 4729 4261 6896 6901 4262 +1 6 4725 4726 4734 4974 4975 4976 +1 6 4733 4726 4727 4735 4976 4977 +1 6 4734 4727 4728 4736 4977 4978 +1 6 4735 4728 4658 4659 4737 4978 +1 6 4736 4659 4660 4738 4978 4979 +1 6 4737 4660 4451 4979 4980 4669 +1 6 4248 4391 4740 5003 7830 7831 +1 6 4739 4391 4392 4402 4741 5003 +1 6 4740 4402 4742 4753 5003 5004 +1 6 4741 4402 4403 4743 4753 4748 +1 6 4742 4403 4744 3892 3893 4748 +1 6 4743 4403 4404 4745 4746 3892 +1 6 4744 4404 3465 3466 3468 4746 +1 6 4745 3468 4747 3397 3892 4744 +1 6 4746 3468 2172 2173 3395 3397 +1 6 4743 3893 4749 4750 4753 4742 +1 6 4748 3893 4750 4751 4752 3894 +1 6 4748 4749 4751 5005 4753 7837 +1 6 4750 4749 4752 4757 7837 7838 +1 6 4751 4749 3894 4757 4758 3895 +1 6 4741 4742 4748 5004 5005 4750 +2 7 4513 4067 4068 4755 4512 4759 4760 +2 5 4754 4068 4756 4760 4761 +2 7 4755 4068 4069 3827 4761 4762 4763 +1 6 4751 4752 4758 7838 7839 7840 +1 6 4757 4752 3895 7840 7841 4661 +2 6 4512 4754 4760 5006 5002 5001 +2 5 4759 4754 4755 4761 5006 +2 7 4760 4755 4756 4762 5006 5007 5008 +2 6 4761 4756 4763 5008 5009 5010 +2 6 4762 4756 3827 3828 4764 5010 +2 6 4763 3828 4765 5010 5011 5012 +2 6 4764 3828 3829 3830 4766 5012 +2 6 4765 3830 3831 4767 4768 5012 +2 6 4766 3831 4768 4769 4770 3832 +2 7 4766 4767 4769 5012 5011 5013 5014 +2 6 4768 4767 4770 5014 5015 5016 +2 6 4769 4767 3832 5016 3834 3833 +1 6 4297 4298 4772 4932 4933 4934 +1 6 4771 4298 4299 4773 4934 4935 +1 6 4772 4299 4300 4774 4935 4936 +1 6 4773 4300 4301 4775 4936 4937 +1 6 4774 4301 4302 4776 4937 4938 +1 6 4775 4302 4303 4777 4938 4939 +1 6 4776 4303 4304 4778 4939 4940 +1 6 4777 4304 4305 4779 4940 4941 +1 6 4778 4305 4306 4780 4941 4942 +1 6 4779 4306 4307 4781 4942 4943 +1 6 4780 4307 4308 4782 4943 4944 +1 6 4781 4308 4309 4566 4783 4944 +1 6 4782 4566 4784 4944 4945 4946 +1 6 4783 4566 4567 4785 4946 4947 +1 6 4784 4567 4568 4786 4947 4948 +1 6 4785 4568 4569 4787 4948 4949 +1 6 4786 4569 4570 4788 4949 4950 +1 6 4787 4570 4571 4789 4950 4951 +1 6 4788 4571 4572 4790 4951 4952 +1 6 4789 4572 4573 4791 4952 4953 +1 6 4790 4573 4574 4792 4953 4954 +1 6 4791 4574 4575 4793 4799 4954 +1 6 4792 4575 4576 4794 4799 4800 +1 6 4793 4576 4577 4578 4795 4800 +1 6 4794 4578 4579 4796 4800 4801 +1 6 4795 4579 4797 4801 4802 4803 +1 6 4796 4579 4580 4581 4798 4803 +1 6 4797 4581 4583 4803 4804 4584 +1 6 4792 4793 4800 4954 4955 4956 +1 6 4799 4793 4794 4795 4801 4956 +1 6 4800 4795 4796 4802 4956 4957 +1 6 4801 4796 4803 4957 4958 4959 +1 6 4802 4796 4797 4798 4804 4959 +1 6 4803 4798 4584 4586 4805 4959 +1 6 4804 4586 4587 4806 4918 4959 +1 6 4805 4587 4807 4918 4919 4920 +1 6 4806 4587 4588 4808 4920 4921 +1 6 4807 4588 4809 4921 4922 4810 +1 6 4808 4588 4589 4590 4591 4810 +1 7 4809 4591 4592 4593 4811 4922 4808 +1 5 4810 4593 4594 4812 4922 +1 6 4811 4594 4595 4813 4964 4922 +1 6 4812 4595 4596 4814 5093 4964 +1 6 4813 4596 4597 4815 5093 5094 +1 6 4814 4597 4598 4816 5094 5095 +1 6 4815 4598 4599 4817 5095 5096 +1 6 4816 4599 4600 4818 4819 5096 +1 6 4817 4600 4819 4820 4821 4601 +1 6 4817 4818 4820 5096 5097 5098 +1 6 4819 4818 4821 5098 5099 4823 +1 6 4820 4818 4601 4602 4822 4823 +1 6 4821 4602 4823 4824 4825 4603 +1 6 4821 4822 4824 5099 4820 5100 +1 6 4823 4822 4825 5100 5101 5102 +1 6 4824 4822 4603 4826 5102 5103 +1 6 4825 4603 4604 4605 4827 5103 +1 7 4826 4605 4606 4607 4609 4828 5103 +1 6 4827 4609 4829 5103 5102 5104 +1 6 4828 4609 4830 5104 5105 5106 +1 6 4829 4609 4610 4831 5106 5107 +1 6 4830 4610 4832 4833 5113 5107 +1 5 4831 4610 4611 4833 4834 +1 6 4831 4832 4834 4835 5113 5114 +1 7 4833 4832 4611 4835 4836 4837 4612 +1 6 4833 4834 4836 5114 4845 4844 +1 6 4835 4834 4837 4838 4839 4844 +1 6 4836 4834 4612 4613 4617 4838 +1 6 4836 4837 4839 4840 4622 4617 +1 6 4836 4838 4840 4842 4843 4844 +1 6 4839 4838 4622 4623 4841 4842 +1 6 4840 4623 4842 4625 4852 4853 +1 6 4840 4841 4839 4843 4852 4850 +1 6 4839 4842 4844 4845 4846 4850 +1 5 4839 4843 4845 4835 4836 +1 7 4844 4843 4846 4847 5114 4835 5115 +1 6 4845 4843 4847 4848 4849 4850 +1 6 4845 4846 4848 5117 5115 5118 +1 6 4847 4846 4849 5118 5119 5120 +1 6 4848 4846 4850 4851 5120 5121 +1 6 4849 4846 4851 4852 4842 4843 +1 6 4849 4850 4852 4854 4855 5121 +1 6 4851 4850 4842 4841 4853 4854 +1 6 4852 4841 4854 4857 4860 4625 +1 6 4851 4852 4853 4855 4856 4857 +1 6 4851 4854 4856 5121 5122 5123 +1 6 4855 4854 4857 4858 5123 5124 +1 6 4856 4854 4853 4858 4859 4860 +1 6 4856 4857 4859 5124 5125 5129 +1 6 4858 4857 4860 5129 5130 4861 +1 6 4859 4857 4853 4625 4626 4861 +1 6 4860 4626 4862 5130 4859 5131 +1 6 4861 4626 4627 4863 4865 5131 +1 6 4862 4627 4630 4864 4865 4866 +1 6 4863 4630 4866 4867 4868 4631 +1 6 4862 4863 4866 5131 5132 5136 +1 6 4865 4863 4864 4867 5136 5137 +1 6 4866 4864 4868 4869 4870 5137 +1 6 4867 4864 4631 4638 4869 9760 +1 6 4867 4868 4870 4871 4872 9760 +1 6 4867 4869 4871 5137 5138 5139 +1 6 4870 4869 4872 4873 5150 5139 +1 6 4871 4869 4873 4874 4875 9760 +1 6 4871 4872 4874 5149 5147 5150 +1 6 4873 4872 4875 4876 4877 5149 +1 6 4874 4872 4876 9760 4912 4914 +1 6 4874 4875 4877 4878 4879 4914 +1 6 4874 4876 4878 5155 5149 4882 +1 6 4877 4876 4879 4880 4881 4882 +1 6 4878 4876 4880 4914 4915 9753 +1 7 4878 4879 4881 9753 9754 9756 9757 +1 6 4878 4880 4882 4883 4884 9757 +1 6 4878 4881 4883 5155 4877 5369 +1 6 4882 4881 4884 4885 5369 5370 +1 6 4883 4881 4885 4886 9757 4895 +1 6 4883 4884 4886 4887 4888 5370 +1 6 4885 4884 4887 4894 4891 4895 +1 6 4885 4886 4888 4889 4890 4891 +1 6 4885 4887 4889 5372 5370 5899 +1 6 4888 4887 4890 5898 5896 5899 +1 6 4889 4887 4891 4892 5898 5901 +1 6 4890 4887 4892 4893 4894 4886 +1 6 4890 4891 4893 5901 5902 5903 +1 6 4892 4891 4894 5912 5903 5913 +1 6 4893 4891 4886 4895 4896 5913 +1 7 4894 4886 4896 4897 9757 9756 4884 +1 6 4894 4895 4897 4898 4899 5913 +1 5 4896 4895 4898 9756 9759 +1 6 4896 4897 4899 4900 4901 9759 +1 6 4896 4898 4900 5913 5914 5917 +1 6 4899 4898 4901 4902 5917 5918 +1 6 4900 4898 4902 4903 4904 9759 +1 6 4900 4901 4903 5918 3671 3670 +1 6 4902 4901 4904 4905 3669 3670 +1 6 4903 4901 4905 9754 4911 9759 +1 6 4903 4904 3669 4906 4907 4911 +1 6 3669 4905 4907 4908 3661 3660 +1 6 4906 4905 4908 4909 4910 4911 +1 7 4906 4907 4909 4642 3660 9793 9794 +1 5 4908 4907 4910 4642 4641 +1 6 4909 4907 4911 4917 4916 4641 +1 6 4910 4907 4905 9754 4917 4904 +1 6 4638 4639 4913 4914 9760 4875 +1 6 4912 4639 4914 4915 4916 4640 +1 6 4912 4913 4915 4875 4876 4879 +1 6 4914 4913 4916 4917 9753 4879 +1 6 4915 4913 4917 4910 4641 4640 +1 6 4915 4916 4910 9753 9754 4911 +1 6 4805 4806 4919 4959 4958 4960 +1 6 4918 4806 4920 4960 4961 4962 +1 6 4919 4806 4807 4921 4962 4963 +1 6 4920 4807 4808 4922 4963 4964 +1 6 4921 4808 4810 4964 4812 4811 +1 6 4287 4288 4924 5052 5053 5054 +1 6 4923 4288 4289 4290 4925 5054 +1 6 4924 4290 4926 5054 5055 5056 +1 6 4925 4290 4291 4927 5056 5057 +1 6 4926 4291 4292 4928 5057 5058 +1 6 4927 4292 4293 4929 5058 5059 +1 6 4928 4293 4294 4930 5059 5060 +1 6 4929 4294 4295 4931 5060 5061 +1 6 4930 4295 4296 4297 4932 5061 +1 6 4931 4297 4771 4933 5061 5062 +1 6 4932 4771 4934 5062 5063 5064 +1 6 4933 4771 4772 4935 5064 5065 +1 6 4934 4772 4773 4936 5065 5066 +1 6 4935 4773 4774 4937 5066 5067 +1 6 4936 4774 4775 4938 5067 5068 +1 6 4937 4775 4776 4939 5068 5069 +1 6 4938 4776 4777 4940 5069 5070 +1 6 4939 4777 4778 4941 5070 5071 +1 6 4940 4778 4779 4942 5071 5072 +1 6 4941 4779 4780 4943 5072 5073 +1 6 4942 4780 4781 4944 5073 5074 +1 6 4943 4781 4782 4783 4945 5074 +1 6 4944 4783 4946 5074 5075 5076 +1 6 4945 4783 4784 4947 5076 5077 +1 6 4946 4784 4785 4948 5077 5078 +1 6 4947 4785 4786 4949 5078 5079 +1 6 4948 4786 4787 4950 5079 5080 +1 6 4949 4787 4788 4951 5080 5081 +1 6 4950 4788 4789 4952 5081 5082 +1 6 4951 4789 4790 4953 5082 5083 +1 6 4952 4790 4791 4954 5083 5084 +1 6 4953 4791 4792 4799 4955 5084 +1 6 4954 4799 4956 5084 5085 5086 +1 6 4955 4799 4800 4801 4957 5086 +1 6 4956 4801 4802 4958 5088 5086 +1 6 4957 4802 4959 4918 4960 5088 +1 6 4958 4802 4803 4804 4805 4918 +1 6 4958 4918 4919 4961 5088 5089 +1 6 4960 4919 4962 5089 5090 5091 +1 6 4961 4919 4920 4963 5091 5092 +1 6 4962 4920 4921 4964 5092 5093 +1 6 4963 4921 4922 4812 5093 4813 +1 6 4715 4716 4966 5177 5178 5179 +1 6 4965 4716 4717 4967 5179 5180 +1 6 4966 4717 4718 4968 5180 5181 +1 6 4967 4718 4719 4969 5181 5182 +1 6 4968 4719 4720 4970 5182 5183 +1 6 4969 4720 4721 4722 4971 5183 +1 6 4970 4722 4972 5183 5184 5185 +1 6 4971 4722 4723 4973 5185 5186 +1 6 4972 4723 4724 4974 5186 5187 +1 6 4973 4724 4725 4733 4975 5187 +1 6 4974 4733 4976 5187 5188 5189 +1 6 4975 4733 4734 4977 5189 5190 +1 6 4976 4734 4735 4978 5190 5191 +1 6 4977 4735 4736 4737 4979 5191 +1 6 4978 4737 4738 4980 5191 5192 +1 6 4979 4738 4669 5192 5193 5194 +1 6 4490 4491 4982 4989 4990 4991 +1 6 4981 4491 4492 4983 4991 4992 +1 6 4982 4492 4493 4984 4992 4993 +1 6 4983 4493 4985 4993 4994 4995 +2 6 4984 4493 4494 4497 4986 4995 +2 6 4985 4497 4498 4987 4995 4996 +2 6 4986 4498 4988 4996 4997 4998 +2 6 4987 4498 4499 4511 4998 4999 +1 6 4490 4981 4990 5216 5217 5218 +1 6 4989 4981 4991 5218 5219 5220 +1 6 4990 4981 4982 4992 5220 5221 +1 6 4991 4982 4983 4993 5221 5222 +1 6 4992 4983 4984 4994 5222 5223 +1 6 4993 4984 4995 5223 5224 5225 +2 6 4994 4984 4985 4986 4996 5225 +2 6 4995 4986 4987 4997 5225 5226 +2 6 4996 4987 4998 5226 5227 5228 +2 6 4997 4987 4988 4999 5000 5228 +2 6 4998 4988 5000 5001 5002 4511 +2 6 4998 4999 5001 5228 5229 5230 +2 7 5000 4999 5002 4759 5006 5166 5230 +2 5 5001 4999 4511 4512 4759 +1 6 4739 4740 4741 5004 7831 7834 +1 6 5003 4741 4753 5005 7834 7835 +1 6 5004 4753 4750 7835 7836 7837 +2 7 4759 4760 4761 5007 5021 5001 5166 +2 6 5006 4761 5008 5021 5022 5023 +2 6 5007 4761 4762 5009 5023 5018 +2 6 5008 4762 5010 5011 5017 5018 +2 5 5009 4762 4763 4764 5011 +2 7 5010 4764 5012 4768 5013 5009 5017 +2 5 5011 4764 4765 4766 4768 +2 6 5011 4768 5014 5020 5017 5241 +2 6 5013 4768 4769 5015 5241 5242 +2 6 5014 4769 5016 5242 5243 5024 +2 5 5015 4769 4770 3834 5024 +2 6 5009 5011 5018 5019 5020 5013 +2 7 5009 5017 5019 5023 5008 5238 6833 +2 6 5018 5017 5020 5238 5239 5240 +2 5 5019 5017 5013 5240 5241 +2 5 5006 5007 5022 5166 5167 +2 6 5021 5007 5023 5167 5168 5169 +2 6 5022 5007 5008 5018 5169 6833 +2 7 5016 3834 3835 5025 5243 5015 5244 +2 6 5024 3835 3836 5026 5244 5245 +2 6 5025 3836 3837 4405 5027 5245 +2 6 5026 4405 4406 5028 5245 5246 +2 6 5027 4406 5029 5249 5246 6844 +2 6 5028 4406 4407 5030 6844 6845 +2 6 5029 4407 4408 5031 6845 6846 +2 6 5030 4408 4409 5032 6849 6846 +2 6 5031 4409 4420 5033 6849 6850 +2 6 5032 4420 4421 4422 5034 6850 +2 6 5033 4422 5035 6850 6851 6852 +2 6 5034 4422 4423 5036 6852 5038 +2 6 5035 4423 4424 4643 5037 5038 +2 6 5036 4643 5038 5039 5040 5044 +2 6 5036 5037 5039 6852 5035 6853 +2 6 5038 5037 5040 5041 6856 6853 +2 6 5039 5037 5041 5042 5043 5044 +2 6 5039 5040 5042 6858 6856 6863 +2 6 5041 5040 5043 6878 6879 6863 +2 6 5042 5040 5044 5045 6880 6878 +2 6 5043 5040 5045 4644 4643 5037 +2 6 5043 5044 4644 6880 6881 6889 +1 6 4280 4281 5047 5474 5475 5476 +1 6 5046 4281 4282 5048 5476 5477 +1 6 5047 4282 4283 5049 5477 5478 +1 6 5048 4283 4284 5050 5478 5479 +1 6 5049 4284 4285 5051 5479 5480 +1 6 5050 4285 4286 5052 5480 5481 +1 6 5051 4286 4287 4923 5053 5481 +1 6 5052 4923 5054 5481 5482 5483 +1 6 5053 4923 4924 4925 5055 5483 +1 6 5054 4925 5056 5483 5484 5485 +1 6 5055 4925 4926 5057 5485 5486 +1 6 5056 4926 4927 5058 5486 5487 +1 6 5057 4927 4928 5059 5487 5488 +1 6 5058 4928 4929 5060 5488 5489 +1 6 5059 4929 4930 5061 5489 5490 +1 6 5060 4930 4931 4932 5062 5490 +1 6 5061 4932 4933 5063 5490 5491 +1 6 5062 4933 5064 5250 5491 5492 +1 6 5063 4933 4934 5065 5250 5251 +1 6 5064 4934 4935 5066 5251 5252 +1 6 5065 4935 4936 5067 5252 5253 +1 6 5066 4936 4937 5068 5253 5254 +1 6 5067 4937 4938 5069 5254 5255 +1 6 5068 4938 4939 5070 5255 5256 +1 6 5069 4939 4940 5071 5256 5257 +1 6 5070 4940 4941 5072 5257 5258 +1 6 5071 4941 4942 5073 5258 5259 +1 6 5072 4942 4943 5074 5259 5260 +1 6 5073 4943 4944 4945 5075 5260 +1 6 5074 4945 5076 5260 5261 5262 +1 6 5075 4945 4946 5077 5262 5263 +1 6 5076 4946 4947 5078 5263 5264 +1 6 5077 4947 4948 5079 5264 5265 +1 6 5078 4948 4949 5080 5265 5266 +1 6 5079 4949 4950 5081 5266 5267 +1 6 5080 4950 4951 5082 5267 5268 +1 6 5081 4951 4952 5083 5268 5269 +1 6 5082 4952 4953 5084 5269 5270 +1 6 5083 4953 4954 4955 5085 5270 +1 6 5084 4955 5086 5087 5270 5271 +1 6 5085 4955 4956 5087 5088 4957 +1 6 5085 5086 5088 5271 5272 5089 +1 6 5087 5086 4957 4958 4960 5089 +1 6 5088 4960 4961 5090 5272 5087 +1 6 5089 4961 5091 5272 5273 5274 +1 6 5090 4961 4962 5092 5274 5275 +1 6 5091 4962 4963 5093 5275 5276 +1 7 5092 4963 4964 4813 4814 5094 5276 +1 6 5093 4814 4815 5095 5276 5277 +1 6 5094 4815 4816 5096 5277 5278 +1 6 5095 4816 4817 4819 5097 5278 +1 6 5096 4819 5098 5278 5279 5280 +1 6 5097 4819 4820 5099 5280 5281 +1 6 5098 4820 4823 5100 5281 5282 +1 6 5099 4823 4824 5101 5282 5152 +1 6 5100 4824 5102 5104 5151 5152 +1 6 5101 4824 4825 5103 4828 5104 +1 5 5102 4825 4826 4827 4828 +1 6 5102 4828 4829 5105 5101 5151 +1 7 5104 4829 5106 5154 5151 5287 5288 +1 6 5105 4829 4830 5107 5108 5288 +1 6 5106 4830 5108 5109 5113 4831 +1 6 5106 5107 5109 5110 5288 5289 +1 6 5108 5107 5110 5111 5112 5113 +1 6 5108 5109 5111 5289 5290 5294 +1 6 5110 5109 5112 5294 5295 5116 +1 6 5111 5109 5113 5114 5115 5116 +1 6 5112 5109 5107 4831 4833 5114 +1 6 5113 4833 4835 4845 5115 5112 +1 6 5114 4845 5112 5116 5117 4847 +1 6 5112 5115 5117 5295 5111 5296 +1 6 5116 5115 4847 5118 5299 5296 +1 6 5117 4847 4848 5119 5299 5300 +1 6 5118 4848 5120 5300 5301 5302 +1 5 5119 4848 4849 5121 5302 +1 6 5120 4849 4851 4855 5122 5302 +1 6 5121 4855 5123 5318 5302 5319 +1 6 5122 4855 4856 5124 5321 5319 +1 6 5123 4856 4858 5125 5126 5321 +1 6 5124 4858 5126 5127 5128 5129 +1 6 5124 5125 5127 5322 5321 5323 +1 6 5126 5125 5128 5323 5324 5328 +1 6 5127 5125 5129 5336 5328 5337 +1 6 5128 5125 4858 4859 5130 5337 +1 6 5129 4859 4861 5131 5337 5338 +1 7 5130 4861 4862 4865 5132 5133 5338 +1 6 5131 4865 5133 5134 5135 5136 +1 5 5131 5132 5134 5338 5339 +1 6 5133 5132 5135 5339 5340 5341 +1 6 5134 5132 5136 5346 5344 5341 +1 6 5135 5132 4865 4866 5137 5346 +1 6 5136 4866 4867 4870 5138 5346 +1 6 5137 4870 5139 5140 5344 5346 +1 6 5138 4870 5140 5141 4871 5150 +1 6 5138 5139 5141 5142 5345 5344 +1 6 5140 5139 5142 5143 5144 5150 +1 6 5140 5141 5143 5345 5360 5359 +1 7 5142 5141 5144 5145 5360 5357 5361 +1 6 5143 5141 5145 5146 5147 5150 +1 6 5143 5144 5146 5361 5362 5366 +1 5 5145 5144 5147 5148 5366 +1 6 5146 5144 5148 5149 4873 5150 +1 7 5146 5147 5149 5155 5366 5367 5368 +1 6 5148 5147 4873 5155 4877 4874 +1 6 4873 5147 4871 5139 5141 5144 +1 6 5101 5104 5152 5153 5154 5105 +1 6 5101 5151 5153 5282 5100 5283 +1 6 5152 5151 5154 5283 5284 5285 +1 6 5153 5151 5105 5285 5286 5287 +1 6 5148 5149 4877 4882 5368 5369 +1 7 4532 4533 5157 6682 6683 6684 6694 +1 6 5156 4533 4666 6682 9750 4667 +1 5 4691 4692 4693 5159 7844 +1 7 5158 4693 5160 7844 7845 7846 7847 +1 6 5159 4693 4694 5161 7847 7848 +1 6 5160 4694 4695 5162 7848 7849 +1 6 5161 4695 5163 7849 7850 7851 +1 6 5162 4695 4696 4697 5164 7851 +1 6 5163 4697 5165 7851 7852 7853 +1 6 5164 4697 4698 4700 7853 7854 +2 5 5001 5006 5021 5167 5230 +2 8 5166 5021 5022 5168 5229 5230 6826 6824 +2 6 5167 5022 5169 6826 6827 6830 +2 7 5168 5022 5023 6830 6831 6832 6833 +1 6 4707 4708 5171 7312 7313 7314 +1 6 5170 4708 4709 5172 7314 7315 +1 6 5171 4709 4710 5173 7315 7316 +1 6 5172 4710 4711 5174 7316 7317 +1 6 5173 4711 4712 5175 7317 7318 +1 6 5174 4712 4713 5176 7318 7319 +1 6 5175 4713 4714 5177 7319 7320 +1 6 5176 4714 4715 4965 5178 7320 +1 6 5177 4965 5179 7320 7321 7322 +1 6 5178 4965 4966 5180 7322 7323 +1 6 5179 4966 4967 5181 5411 7323 +1 6 5180 4967 4968 5182 5411 5412 +1 6 5181 4968 4969 5183 5412 5413 +1 6 5182 4969 4970 4971 5184 5413 +1 6 5183 4971 5185 5413 5414 5415 +1 6 5184 4971 4972 5186 5403 5415 +1 6 5185 4972 4973 5187 5403 5404 +1 6 5186 4973 4974 4975 5188 5404 +1 6 5187 4975 5189 5404 5405 5406 +1 6 5188 4975 4976 5190 5406 5407 +1 6 5189 4976 4977 5191 5407 5408 +1 6 5190 4977 4978 4979 5192 5408 +1 6 5191 4979 4980 5193 5408 5409 +1 6 5192 4980 5194 5409 5410 5195 +1 5 5193 4980 4669 4670 5195 +1 6 5194 4670 4671 5196 5410 5193 +1 7 5195 4671 4672 5197 5423 5410 5431 +1 5 5196 4672 4673 5198 5431 +1 7 5197 4673 4674 5199 5431 5432 5433 +1 6 5198 4674 4675 5200 5433 5434 +1 6 5199 4675 4676 5201 5434 5435 +1 6 5200 4676 4677 5202 5435 5436 +1 6 5201 4677 4678 5203 5436 5437 +1 6 5202 4678 5204 5437 5438 5439 +1 6 5203 4678 4679 4680 5205 5439 +1 5 5204 4680 4681 5206 5439 +1 7 5205 4681 4682 5207 5439 5440 5441 +1 6 5206 4682 5208 5441 5442 5443 +1 6 5207 4682 4683 5209 5424 5443 +1 7 5208 4683 4684 5210 5424 5425 5426 +1 5 5209 4684 5211 5426 5427 +1 7 5210 4684 4685 5212 5427 5215 5214 +1 5 5211 4685 4686 5213 5214 +1 6 5212 4686 4687 4478 4479 5214 +1 6 5213 4479 4480 5215 5211 5212 +1 6 5214 4480 5216 5427 5211 5217 +1 6 5215 4480 4481 4490 4989 5217 +1 7 5216 4989 5218 5447 5427 5215 6810 +1 6 5217 4989 4990 5219 6810 6811 +1 6 5218 4990 5220 6811 6812 6813 +1 6 5219 4990 4991 5221 6813 6814 +1 5 5220 4991 4992 5222 6814 +1 7 5221 4992 4993 5223 6814 6815 6816 +1 5 5222 4993 4994 5224 6816 +1 7 5223 4994 5225 6816 6817 6818 6819 +2 6 5224 4994 4995 4996 5226 6819 +2 6 5225 4996 4997 5227 6819 6820 +2 6 5226 4997 5228 6820 6821 6822 +2 6 5227 4997 4998 5000 5229 6822 +2 7 5228 5000 5230 5167 6822 6823 6824 +2 5 5229 5000 5167 5166 5001 +1 6 4264 4265 5232 6902 6903 5458 +1 6 5231 4265 4266 5233 5448 5458 +1 6 5232 4266 4267 5234 5448 5449 +1 6 5233 4267 4269 5449 5450 5451 +1 6 4519 4520 5236 9677 9678 9679 +1 6 5235 4520 5237 9679 9683 9684 +1 6 5236 4520 4521 422 9684 421 +2 6 5018 5019 5239 6832 6833 6834 +2 6 5238 5019 5240 5648 6834 6835 +2 6 5239 5019 5020 5241 5648 5649 +2 7 5240 5020 5013 5014 5242 5649 5650 +2 5 5241 5014 5015 5243 5650 +2 7 5242 5015 5024 5244 5652 5650 5653 +2 6 5243 5024 5025 5245 5653 5247 +2 6 5244 5025 5026 5027 5246 5247 +2 6 5245 5027 5247 5248 5249 5028 +2 6 5245 5246 5248 5653 5244 6840 +2 6 5247 5246 5249 6841 6840 6842 +2 6 5248 5246 5028 6842 6843 6844 +1 6 5063 5064 5251 5492 5493 5494 +1 6 5250 5064 5065 5252 5494 5495 +1 6 5251 5065 5066 5253 5495 5496 +1 6 5252 5066 5067 5254 5496 5497 +1 6 5253 5067 5068 5255 5497 5498 +1 6 5254 5068 5069 5256 5498 5499 +1 6 5255 5069 5070 5257 5499 5500 +1 6 5256 5070 5071 5258 5500 5501 +1 6 5257 5071 5072 5259 5501 5502 +1 6 5258 5072 5073 5260 5502 5503 +1 6 5259 5073 5074 5075 5261 5503 +1 6 5260 5075 5262 5503 5504 5505 +1 6 5261 5075 5076 5263 5505 5506 +1 6 5262 5076 5077 5264 5506 5507 +1 6 5263 5077 5078 5265 5507 5508 +1 6 5264 5078 5079 5266 5508 5509 +1 6 5265 5079 5080 5267 5509 5510 +1 6 5266 5080 5081 5268 5510 5511 +1 6 5267 5081 5082 5269 5511 5512 +1 6 5268 5082 5083 5270 5512 5513 +1 6 5269 5083 5084 5085 5271 5513 +1 6 5270 5085 5087 5272 5513 5514 +1 6 5271 5087 5089 5090 5273 5514 +1 6 5272 5090 5274 5514 5515 5516 +1 6 5273 5090 5091 5275 5519 5516 +1 6 5274 5091 5092 5276 5519 5277 +1 5 5275 5092 5093 5094 5277 +1 6 5276 5094 5095 5278 5519 5275 +1 6 5277 5095 5096 5097 5279 5519 +1 6 5278 5097 5280 5519 5518 5520 +1 6 5279 5097 5098 5281 5520 5377 +1 6 5280 5098 5099 5282 5376 5377 +1 6 5281 5099 5100 5152 5283 5376 +1 6 5282 5152 5153 5284 5379 5376 +1 6 5283 5153 5285 5524 5379 5525 +1 6 5284 5153 5154 5286 5525 5526 +1 6 5285 5154 5287 5526 5527 5291 +1 6 5286 5154 5105 5288 5291 5289 +1 5 5287 5105 5106 5108 5289 +1 6 5288 5108 5110 5290 5291 5287 +1 6 5289 5110 5291 5292 5293 5294 +1 7 5289 5290 5292 5527 5286 5287 5528 +1 6 5291 5290 5293 5528 5529 5533 +1 5 5292 5290 5294 5533 5534 +1 6 5293 5290 5110 5111 5295 5534 +1 6 5294 5111 5116 5296 5297 5534 +1 6 5295 5116 5297 5298 5299 5117 +1 6 5295 5296 5298 5534 5535 5542 +1 6 5297 5296 5299 5542 5543 5544 +1 6 5298 5296 5117 5118 5300 5544 +1 6 5299 5118 5119 5301 5304 5544 +1 6 5300 5119 5302 5303 5304 5305 +1 7 5301 5119 5303 5318 5122 5120 5121 +1 6 5301 5302 5308 5305 5309 5318 +1 6 5300 5301 5305 5306 5543 5544 +1 6 5304 5301 5306 5307 5308 5303 +1 6 5304 5305 5307 5543 5545 5546 +1 6 5306 5305 5308 5311 5312 5546 +1 6 5307 5305 5303 5309 5310 5311 +1 6 5308 5303 5310 5316 5317 5318 +1 6 5308 5309 5311 5314 5315 5316 +1 6 5308 5310 5307 5312 5313 5314 +1 6 5307 5311 5313 5546 5547 5548 +1 6 5312 5311 5314 5548 5549 5550 +1 6 5313 5311 5310 5315 5553 5550 +1 6 5314 5310 5316 5555 5553 5558 +1 6 5315 5310 5309 5317 5558 5559 +1 6 5316 5309 5318 5319 5320 5559 +1 6 5317 5309 5303 5302 5122 5319 +1 6 5318 5122 5317 5320 5321 5123 +1 6 5317 5319 5321 5322 5559 5560 +1 6 5320 5319 5322 5126 5124 5123 +1 6 5320 5321 5126 5323 5560 5561 +1 6 5322 5126 5127 5324 5325 5561 +1 6 5323 5127 5325 5326 5327 5328 +1 6 5323 5324 5326 5561 5562 5563 +1 6 5325 5324 5327 5572 5563 5573 +1 6 5326 5324 5328 5329 5330 5573 +1 6 5327 5324 5329 5336 5128 5127 +1 6 5327 5328 5330 5331 5332 5336 +1 6 5327 5329 5331 5573 5574 5575 +1 6 5330 5329 5332 5333 5575 5576 +1 6 5331 5329 5333 5334 5335 5336 +1 6 5331 5332 5334 5576 5577 5578 +1 6 5333 5332 5335 5578 5340 5339 +1 6 5334 5332 5336 5337 5338 5339 +1 6 5335 5332 5329 5328 5128 5337 +1 6 5336 5128 5129 5130 5335 5338 +1 6 5335 5337 5130 5131 5133 5339 +1 6 5338 5133 5134 5340 5334 5335 +1 6 5339 5134 5341 5342 5578 5334 +1 6 5340 5134 5342 5343 5344 5135 +1 6 5340 5341 5343 5348 5349 5578 +1 6 5342 5341 5344 5345 5347 5348 +1 7 5343 5341 5345 5140 5138 5346 5135 +1 6 5343 5344 5140 5142 5347 5359 +1 5 5138 5344 5135 5136 5137 +1 6 5343 5345 5348 5351 5352 5359 +1 6 5343 5347 5342 5349 5350 5351 +1 6 5342 5348 5350 5578 5577 5579 +1 6 5349 5348 5351 5579 5580 5584 +1 6 5350 5348 5347 5352 5353 5584 +1 6 5351 5347 5353 5354 5355 5359 +1 6 5351 5352 5354 5608 5584 5609 +1 6 5353 5352 5355 5356 5807 5609 +1 6 5354 5352 5356 5357 5359 5360 +1 6 5354 5355 5357 5358 5807 5808 +1 6 5356 5355 5358 5360 5143 5361 +1 7 5356 5357 5808 5809 5810 5363 5361 +1 6 5355 5352 5347 5360 5142 5345 +1 5 5355 5359 5142 5143 5357 +1 6 5357 5143 5145 5362 5363 5358 +1 6 5361 5145 5363 5364 5365 5366 +1 5 5361 5362 5364 5810 5358 +1 6 5363 5362 5365 5810 5811 5402 +1 7 5364 5362 5366 5402 5401 5367 5375 +1 6 5365 5362 5145 5146 5148 5367 +1 6 5366 5148 5368 5374 5365 5375 +1 6 5367 5148 5155 5369 5371 5374 +1 6 5368 5155 4882 4883 5370 5371 +1 6 5369 4883 5371 5372 4888 4885 +1 6 5369 5370 5372 5373 5374 5368 +1 6 5371 5370 5373 4888 5393 5899 +1 6 5371 5372 5374 5375 5392 5393 +1 5 5371 5373 5375 5368 5367 +1 6 5374 5373 5392 5365 5367 5401 +1 6 5281 5282 5377 5378 5379 5283 +1 6 5281 5376 5378 5520 5280 5521 +1 6 5377 5376 5379 5521 5522 5523 +1 6 5378 5376 5283 5523 5524 5284 +1 6 4656 4657 55 9689 430 56 +2 6 1679 1680 1678 5382 5383 1682 +2 6 1678 5381 5383 5384 7779 3415 +2 6 5382 5381 5384 5385 3774 1682 +2 6 5382 5383 5385 5386 7779 7780 +2 6 5384 5383 5386 5387 5391 3774 +2 6 5384 5385 5387 5388 7780 7781 +2 6 5386 5385 5388 5389 5390 5391 +2 6 5386 5387 5389 5616 7781 7782 +2 6 5388 5387 5390 5616 5617 5618 +2 6 5389 5387 5391 5618 5619 5620 +2 6 5390 5387 5385 3774 5620 3775 +1 6 5375 5373 5393 5394 5401 5398 +1 6 5392 5373 5394 5372 5395 5899 +1 6 5392 5393 5395 5396 5397 5398 +1 5 5394 5393 5396 5899 5894 +1 6 5394 5395 5397 5893 5890 5894 +1 6 5394 5396 5398 5399 5889 5890 +1 6 5394 5397 5399 5400 5401 5392 +1 6 5398 5397 5400 5880 5888 5889 +1 7 5398 5399 5401 5402 5887 5881 5880 +1 6 5398 5400 5402 5365 5375 5392 +1 6 5401 5400 5887 5811 5364 5365 +1 6 5185 5186 5404 5415 5416 5417 +1 6 5403 5186 5187 5188 5405 5417 +1 6 5404 5188 5406 5417 5418 5419 +1 6 5405 5188 5189 5407 5419 5420 +1 6 5406 5189 5190 5408 5420 5421 +1 6 5407 5190 5191 5192 5409 5421 +1 6 5408 5192 5193 5410 5421 5422 +1 6 5409 5193 5195 5422 5423 5196 +1 6 5180 5181 5412 7323 7324 7325 +1 6 5411 5181 5182 5413 7325 7326 +1 6 5412 5182 5183 5184 5414 7326 +1 6 5413 5184 5415 7326 7327 7328 +1 6 5414 5184 5185 5403 5416 7328 +1 6 5415 5403 5417 7328 7329 7330 +1 6 5416 5403 5404 5405 5418 7330 +1 6 5417 5405 5419 6791 7330 7331 +1 6 5418 5405 5406 5420 6791 6792 +1 6 5419 5406 5407 5421 5428 6792 +1 6 5420 5407 5408 5409 5422 5428 +1 6 5421 5409 5410 5423 5428 5429 +1 6 5422 5410 5196 5429 5430 5431 +1 6 5208 5209 5425 5443 5444 5445 +1 6 5424 5209 5426 5445 5446 5447 +1 5 5425 5209 5210 5427 5447 +1 6 5426 5210 5211 5215 5447 5217 +1 6 5420 5421 5422 5429 6792 6793 +1 6 5428 5422 5423 5430 6793 6794 +1 6 5429 5423 5431 6794 6795 5432 +1 6 5430 5423 5196 5197 5198 5432 +1 5 5431 5198 5433 6795 5430 +1 6 5432 5198 5199 5434 6795 6796 +1 6 5433 5199 5200 5435 6796 6797 +1 6 5434 5200 5201 5436 6797 6798 +1 6 5435 5201 5202 5437 6798 6799 +1 6 5436 5202 5203 5438 6799 6800 +1 6 5437 5203 5439 6800 6801 6802 +1 7 5438 5203 5204 5205 5206 5440 6802 +1 5 5439 5206 5441 6802 6803 +1 6 5440 5206 5207 5442 6803 6804 +1 6 5441 5207 5443 6804 6805 5444 +1 5 5442 5207 5208 5424 5444 +1 6 5443 5424 5445 6805 5442 6806 +1 6 5444 5424 5425 5446 6806 6807 +1 6 5445 5425 5447 6807 6808 6809 +1 7 5446 5425 5426 5427 5217 6809 6810 +1 6 5232 5233 5449 5458 5459 5460 +1 6 5448 5233 5234 5450 5460 5461 +1 6 5449 5234 5451 5461 5462 5463 +1 6 5450 5234 4269 4270 5452 5463 +1 6 5451 4270 4271 5453 5463 5464 +1 6 5452 4271 4272 5454 5455 5464 +1 6 5453 4272 5455 5456 5457 4273 +1 6 5453 5454 5456 5464 5465 5466 +1 6 5455 5454 5457 5466 5467 5468 +1 6 5456 5454 4273 5468 5469 4274 +1 6 5232 5448 5459 6903 5231 6904 +1 6 5458 5448 5460 6904 6905 6906 +1 6 5459 5448 5449 5461 6906 6907 +1 6 5460 5449 5450 5462 6907 6908 +1 6 5461 5450 5463 6908 6909 6910 +1 6 5462 5450 5451 5452 5464 6910 +1 6 5463 5452 5453 5455 5465 6910 +1 6 5464 5455 5466 6910 6911 6912 +1 6 5465 5455 5456 5467 6912 6913 +1 6 5466 5456 5468 6913 6914 6915 +1 6 5467 5456 5457 5469 6915 6916 +1 6 5468 5457 4274 4275 5470 6916 +1 6 5469 4275 4276 4277 5471 6916 +1 6 5470 4277 5472 6916 6917 6918 +1 6 5471 4277 4278 5473 6918 6919 +1 6 5472 4278 4279 5474 6919 6920 +1 6 5473 4279 4280 5046 5475 6920 +1 6 5474 5046 5476 6920 6921 6922 +1 6 5475 5046 5047 5477 6922 6923 +1 6 5476 5047 5048 5478 6923 6924 +1 6 5477 5048 5049 5479 6924 6925 +1 6 5478 5049 5050 5480 6925 6926 +1 6 5479 5050 5051 5481 5654 6926 +1 6 5480 5051 5052 5053 5482 5654 +1 6 5481 5053 5483 5654 5655 5656 +1 6 5482 5053 5054 5055 5484 5656 +1 6 5483 5055 5485 5656 5657 5658 +1 6 5484 5055 5056 5486 5658 5659 +1 6 5485 5056 5057 5487 5659 5660 +1 6 5486 5057 5058 5488 5660 5661 +1 6 5487 5058 5059 5489 5621 5661 +1 6 5488 5059 5060 5490 5621 5622 +1 6 5489 5060 5061 5062 5491 5622 +1 6 5490 5062 5063 5492 5622 5623 +1 6 5491 5063 5250 5493 5623 5624 +1 6 5492 5250 5494 5624 5625 5626 +1 6 5493 5250 5251 5495 5626 5627 +1 6 5494 5251 5252 5496 5627 5628 +1 6 5495 5252 5253 5497 5628 5629 +1 6 5496 5253 5254 5498 5629 5630 +1 6 5497 5254 5255 5499 5630 5631 +1 6 5498 5255 5256 5500 5631 5632 +1 6 5499 5256 5257 5501 5632 5633 +1 6 5500 5257 5258 5502 5633 5634 +1 6 5501 5258 5259 5503 5634 5635 +1 6 5502 5259 5260 5261 5504 5635 +1 6 5503 5261 5505 5635 5636 5637 +1 6 5504 5261 5262 5506 5637 5638 +1 6 5505 5262 5263 5507 5638 5639 +1 6 5506 5263 5264 5508 5639 5640 +1 6 5507 5264 5265 5509 5640 5641 +1 6 5508 5265 5266 5510 5641 5642 +1 6 5509 5266 5267 5511 5642 5643 +1 6 5510 5267 5268 5512 5643 5644 +1 6 5511 5268 5269 5513 5644 5645 +1 6 5512 5269 5270 5271 5514 5645 +1 6 5513 5271 5272 5273 5515 5645 +1 6 5514 5273 5516 5517 5645 5646 +1 6 5515 5273 5517 5518 5519 5274 +1 6 5515 5516 5518 5646 5647 5520 +1 5 5517 5516 5519 5279 5520 +1 7 5518 5516 5274 5275 5277 5278 5279 +1 7 5518 5279 5280 5377 5521 5647 5517 +1 5 5520 5377 5378 5522 5647 +1 7 5521 5378 5523 5685 5647 5684 5686 +1 6 5522 5378 5379 5524 5687 5686 +1 6 5523 5379 5284 5525 5687 5688 +1 6 5524 5284 5285 5526 5688 5689 +1 6 5525 5285 5286 5527 5689 5690 +1 6 5526 5286 5291 5528 5690 5691 +1 6 5527 5291 5292 5529 5530 5691 +1 6 5528 5292 5530 5531 5532 5533 +1 5 5528 5529 5531 5691 5692 +1 6 5530 5529 5532 5692 5693 5694 +1 7 5531 5529 5533 5694 5695 5538 5536 +1 6 5532 5529 5292 5293 5534 5536 +1 7 5533 5293 5294 5295 5297 5535 5536 +1 6 5534 5297 5536 5537 5541 5542 +1 6 5534 5535 5537 5538 5532 5533 +1 6 5536 5535 5538 5539 5540 5541 +1 6 5536 5537 5539 5695 5532 5696 +1 6 5538 5537 5540 5696 5697 5698 +1 7 5539 5537 5541 5698 5699 5700 9795 +1 5 5540 5537 5535 5542 9795 +1 6 5541 5535 5297 5298 5543 9795 +1 7 5542 5298 5544 5304 5306 5545 9795 +1 5 5543 5298 5304 5300 5299 +1 6 5543 5306 5546 5701 5700 9795 +1 6 5545 5306 5307 5312 5547 5701 +1 6 5546 5312 5548 5701 5702 5703 +1 6 5547 5312 5313 5549 5703 5704 +1 6 5548 5313 5550 5551 5704 5705 +1 6 5549 5313 5551 5552 5553 5314 +1 6 5549 5550 5552 5705 5706 5707 +1 6 5551 5550 5553 5554 5707 5708 +1 6 5552 5550 5314 5554 5555 5315 +1 6 5552 5553 5555 5556 5708 5709 +1 6 5554 5553 5315 5556 5557 5558 +1 6 5554 5555 5557 5709 5710 5711 +1 6 5556 5555 5558 5714 5711 5715 +1 6 5557 5555 5315 5316 5559 5715 +1 6 5558 5316 5317 5320 5560 5715 +1 6 5559 5320 5322 5561 5716 5715 +1 6 5560 5322 5323 5325 5562 5716 +1 6 5561 5325 5563 5564 5717 5716 +1 6 5562 5325 5564 5565 5572 5326 +1 6 5562 5563 5565 5566 5717 5713 +1 6 5564 5563 5566 5567 5571 5572 +1 6 5564 5565 5567 5568 5753 5713 +1 6 5566 5565 5568 5569 5570 5571 +1 6 5566 5567 5569 5752 5753 5754 +1 6 5568 5567 5570 5754 5755 5770 +1 6 5569 5567 5571 5769 5767 5770 +1 6 5570 5567 5565 5572 5769 5771 +1 6 5571 5565 5563 5326 5573 5771 +1 6 5572 5326 5327 5330 5574 5771 +1 6 5573 5330 5575 5771 5772 5773 +1 6 5574 5330 5331 5576 5773 5594 +1 7 5575 5331 5333 5577 5594 5589 5774 +1 6 5576 5333 5578 5349 5579 5774 +1 6 5577 5333 5334 5340 5342 5349 +1 6 5577 5349 5350 5580 5581 5774 +1 6 5579 5350 5581 5582 5583 5584 +1 6 5579 5580 5582 5585 5586 5774 +1 6 5581 5580 5583 5585 5605 5606 +1 6 5582 5580 5584 5606 5607 5608 +1 6 5583 5580 5350 5351 5608 5353 +1 6 5581 5582 5586 5587 5605 5597 +1 6 5581 5585 5587 5588 5589 5774 +1 6 5586 5585 5588 5595 5596 5597 +1 6 5586 5587 5589 5590 5591 5595 +1 6 5586 5588 5590 5594 5576 5774 +1 6 5589 5588 5591 5592 5594 5773 +1 6 5590 5588 5592 5593 5595 5778 +1 6 5590 5591 5593 5773 5772 5775 +1 6 5592 5591 5775 5776 5777 5778 +1 5 5589 5590 5773 5575 5576 +1 6 5591 5588 5587 5596 5778 5779 +1 6 5595 5587 5597 5598 5599 5779 +1 6 5596 5587 5598 5602 5605 5585 +1 6 5596 5597 5599 5600 5601 5602 +1 6 5596 5598 5600 5779 5780 5781 +1 6 5599 5598 5601 5781 5789 5790 +1 6 5600 5598 5602 5603 5790 5791 +1 6 5601 5598 5603 5604 5597 5605 +1 6 5601 5602 5604 5794 5791 5795 +1 6 5603 5602 5795 5796 5606 5605 +1 6 5602 5597 5585 5582 5606 5604 +1 6 5605 5582 5583 5607 5796 5604 +1 6 5606 5583 5608 5610 5798 5796 +1 6 5607 5583 5584 5353 5609 5610 +1 7 5608 5353 5610 5800 5806 5807 5354 +1 5 5608 5609 5607 5800 5798 +1 6 4514 4516 5612 5613 5614 5615 +1 6 4514 5611 5613 427 426 7500 +1 6 5612 5611 5614 7500 7501 7505 +1 6 5613 5611 5615 7505 7506 7507 +1 6 5614 5611 4516 7507 7508 4518 +2 6 5388 5389 5617 7782 7783 7784 +2 6 5616 5389 5618 7784 7785 7786 +2 6 5617 5389 5390 5619 7786 7789 +2 6 5618 5390 5620 7789 7790 7791 +2 6 5619 5390 5391 3775 3778 7791 +1 6 5488 5489 5622 5661 5662 5663 +1 6 5621 5489 5490 5491 5623 5663 +1 6 5622 5491 5492 5624 5663 5664 +1 6 5623 5492 5493 5625 5664 5665 +1 6 5624 5493 5626 5665 5666 5667 +1 6 5625 5493 5494 5627 5667 5668 +1 6 5626 5494 5495 5628 5668 5669 +1 6 5627 5495 5496 5629 5669 5670 +1 6 5628 5496 5497 5630 5670 5671 +1 6 5629 5497 5498 5631 5671 5672 +1 6 5630 5498 5499 5632 5672 5673 +1 6 5631 5499 5500 5633 5673 5674 +1 6 5632 5500 5501 5634 5674 5675 +1 6 5633 5501 5502 5635 5675 5676 +1 6 5634 5502 5503 5504 5636 5676 +1 6 5635 5504 5637 5676 5677 5678 +1 6 5636 5504 5505 5638 5678 5679 +1 6 5637 5505 5506 5639 5679 5680 +1 6 5638 5506 5507 5640 5680 5681 +1 6 5639 5507 5508 5641 5681 5682 +1 6 5640 5508 5509 5642 5682 5683 +1 6 5641 5509 5510 5643 5683 5684 +1 6 5642 5510 5511 5644 5684 5685 +1 6 5643 5511 5512 5645 5685 5646 +1 6 5644 5512 5513 5514 5515 5646 +1 6 5645 5515 5517 5647 5685 5644 +1 6 5646 5517 5520 5685 5522 5521 +2 6 5239 5240 5649 6835 6836 6837 +2 6 5648 5240 5241 5650 5651 6837 +2 6 5649 5241 5651 5652 5243 5242 +2 6 5649 5650 5652 6837 6838 6839 +2 6 5651 5650 5243 5653 6839 6840 +2 5 5652 5243 5244 5247 6840 +1 6 5480 5481 5482 5655 6926 6927 +1 6 5654 5482 5656 6927 6928 6929 +1 6 5655 5482 5483 5484 5657 6929 +1 6 5656 5484 5658 6929 6930 6931 +1 6 5657 5484 5485 5659 5831 6931 +1 6 5658 5485 5486 5660 5831 5832 +1 6 5659 5486 5487 5661 5832 5833 +1 6 5660 5487 5488 5621 5662 5833 +1 6 5661 5621 5663 5833 5834 5835 +1 6 5662 5621 5622 5623 5664 5835 +1 6 5663 5623 5624 5665 5835 5813 +1 6 5664 5624 5625 5666 5812 5813 +1 6 5665 5625 5667 5812 5816 5817 +1 6 5666 5625 5626 5668 5859 5817 +1 6 5667 5626 5627 5669 5859 5860 +1 6 5668 5627 5628 5670 5860 5861 +1 6 5669 5628 5629 5671 5861 5862 +1 6 5670 5629 5630 5672 5862 5863 +1 6 5671 5630 5631 5673 5863 5864 +1 6 5672 5631 5632 5674 5864 5865 +1 6 5673 5632 5633 5675 5865 5866 +1 6 5674 5633 5634 5676 5866 5867 +1 6 5675 5634 5635 5636 5677 5867 +1 6 5676 5636 5678 5867 5868 5693 +1 6 5677 5636 5637 5679 5693 5869 +1 6 5678 5637 5638 5680 5869 5870 +1 6 5679 5638 5639 5681 5870 5871 +1 6 5680 5639 5640 5682 5871 5688 +1 6 5681 5640 5641 5683 5688 5687 +1 6 5682 5641 5642 5684 5686 5687 +1 6 5683 5642 5643 5685 5522 5686 +1 6 5684 5643 5644 5646 5647 5522 +1 5 5684 5522 5683 5687 5523 +1 6 5683 5686 5523 5524 5688 5682 +1 7 5687 5524 5525 5689 5871 5681 5682 +1 5 5688 5525 5526 5690 5871 +1 7 5689 5526 5527 5691 5871 5870 5692 +1 5 5690 5527 5528 5530 5692 +1 7 5691 5530 5531 5693 5870 5690 5869 +1 7 5692 5531 5694 5868 5677 5678 5869 +1 6 5693 5531 5532 5695 9698 5868 +1 6 5694 5532 5538 5696 9699 9698 +1 6 5695 5538 5539 5697 5718 9699 +1 6 5696 5539 5698 5718 5719 5720 +1 6 5697 5539 5540 5699 5720 5721 +1 6 5698 5540 5700 5701 5721 5722 +1 5 5699 5540 5701 5545 9795 +1 7 5699 5700 5545 5546 5547 5702 5722 +1 6 5701 5547 5703 5722 5723 5727 +1 6 5702 5547 5548 5704 5727 5728 +1 6 5703 5548 5549 5705 5728 5729 +1 6 5704 5549 5551 5706 5732 5729 +1 6 5705 5551 5707 5732 5733 5734 +1 6 5706 5551 5552 5708 5737 5734 +1 6 5707 5552 5554 5709 5737 5738 +1 6 5708 5554 5556 5710 5747 5738 +1 6 5709 5556 5711 5712 5747 5748 +1 6 5710 5556 5712 5713 5714 5557 +1 6 5710 5711 5713 5748 5749 5753 +1 7 5712 5711 5714 5717 5564 5753 5566 +1 6 5713 5711 5557 5715 5716 5717 +1 6 5714 5557 5716 5560 5559 5558 +1 6 5714 5715 5717 5562 5561 5560 +1 5 5714 5716 5562 5564 5713 +1 7 5696 5697 5719 9696 5865 9697 9699 +1 6 5718 5697 5720 9696 9695 9700 +1 6 5719 5697 5698 5721 9700 9701 +1 7 5720 5698 5699 5722 5723 5724 9701 +1 5 5721 5699 5701 5702 5723 +1 7 5722 5702 5721 5724 5725 5726 5727 +1 6 5721 5723 5725 6095 9701 9702 +1 6 5724 5723 5726 6095 6096 6097 +1 6 5725 5723 5727 6097 5730 5728 +1 5 5726 5723 5702 5703 5728 +1 6 5727 5703 5704 5729 5730 5726 +1 6 5728 5704 5730 5731 5732 5705 +1 7 5728 5729 5731 6097 5726 6098 6099 +1 6 5730 5729 5732 6099 6100 6101 +1 6 5731 5729 5705 5706 5733 6101 +1 6 5732 5706 5734 5735 6101 6102 +1 6 5733 5706 5735 5736 5737 5707 +1 6 5733 5734 5736 6105 6102 6106 +1 6 5735 5734 5737 6106 6107 5739 +1 6 5736 5734 5707 5708 5738 5739 +1 6 5737 5708 5739 5740 5747 5709 +1 6 5737 5738 5740 5741 6107 5736 +1 6 5739 5738 5741 5742 5746 5747 +1 6 5739 5740 5742 5743 6107 6108 +1 6 5741 5740 5743 5744 5745 5746 +1 6 5741 5742 5744 6111 6108 6112 +1 6 5743 5742 5745 6112 6113 6114 +1 6 5744 5742 5746 5750 6121 6114 +1 6 5745 5742 5740 5747 5748 5750 +1 6 5746 5740 5738 5709 5710 5748 +1 6 5747 5710 5712 5749 5746 5750 +1 6 5748 5712 5750 5751 5752 5753 +1 6 5746 5748 5745 5749 5751 6121 +1 5 5750 5749 5752 6121 5949 +1 6 5751 5749 5753 5568 5754 5949 +1 6 5752 5749 5712 5713 5568 5566 +1 6 5752 5568 5569 5755 5756 5949 +1 6 5754 5569 5756 5757 5758 5770 +1 6 5754 5755 5757 5949 5950 5951 +1 6 5756 5755 5758 5759 5951 5952 +1 6 5757 5755 5759 5760 5761 5770 +1 6 5757 5758 5760 5952 5953 5957 +1 6 5759 5758 5761 5762 5763 5957 +1 6 5760 5758 5762 5766 5767 5770 +1 6 5760 5761 5763 5764 5765 5766 +1 6 5760 5762 5764 5957 5958 5988 +1 6 5763 5762 5765 5989 5988 5990 +1 6 5764 5762 5766 5990 5991 5776 +1 6 5765 5762 5761 5767 5768 5776 +1 6 5766 5761 5768 5769 5570 5770 +1 6 5766 5767 5769 5772 5775 5776 +1 6 5768 5767 5570 5571 5771 5772 +1 6 5570 5767 5569 5761 5755 5758 +1 6 5769 5571 5572 5573 5574 5772 +1 7 5771 5574 5773 5592 5775 5769 5768 +1 6 5772 5574 5575 5594 5590 5592 +1 6 5589 5576 5586 5581 5579 5577 +1 5 5772 5592 5593 5776 5768 +1 7 5775 5593 5777 5991 5765 5768 5766 +1 6 5776 5593 5778 5992 5991 5782 +1 6 5777 5593 5591 5595 5779 5782 +1 6 5778 5595 5596 5599 5780 5782 +1 6 5779 5599 5781 5782 5783 5784 +1 6 5780 5599 5600 5784 5785 5789 +1 6 5779 5780 5783 5992 5777 5778 +1 6 5782 5780 5784 5993 5992 5996 +1 7 5783 5780 5781 5785 5786 5996 5997 +1 6 5784 5781 5786 5787 5788 5789 +1 6 5784 5785 5787 5997 5998 5999 +1 6 5786 5785 5788 6002 5999 6003 +1 6 5787 5785 5789 6009 6003 6199 +1 6 5788 5785 5781 5600 5790 6199 +1 6 5789 5600 5601 5791 5792 6199 +1 6 5790 5601 5792 5793 5794 5603 +1 6 5790 5791 5793 6198 6199 6197 +1 6 5792 5791 5794 6197 6200 6221 +1 6 5793 5791 5603 5795 6221 6219 +1 6 5794 5603 5604 5796 5797 6219 +1 6 5795 5604 5797 5798 5607 5606 +1 6 5795 5796 5798 5799 6218 6219 +1 6 5797 5796 5607 5799 5800 5610 +1 6 5797 5798 5800 5801 5802 6218 +1 7 5799 5798 5610 5609 5801 5805 5806 +1 6 5799 5800 5802 5803 5804 5805 +1 6 5799 5801 5803 6217 6209 6218 +1 6 5802 5801 5804 5823 5824 6217 +1 6 5803 5801 5805 5823 5830 5839 +1 6 5804 5801 5800 5806 5808 5839 +1 5 5805 5800 5609 5807 5808 +1 5 5806 5609 5354 5356 5808 +1 7 5807 5356 5358 5809 5839 5805 5806 +1 6 5808 5358 5810 5838 5839 5886 +1 7 5809 5358 5363 5364 5811 5885 5886 +1 6 5810 5364 5884 5885 5887 5402 +1 6 5665 5666 5813 5814 5815 5816 +1 6 5665 5812 5814 5835 5664 5842 +1 6 5813 5812 5815 5842 5843 5844 +1 6 5814 5812 5816 5819 5820 5844 +1 6 5815 5812 5666 5817 5818 5819 +1 6 5816 5666 5818 5859 5857 5667 +1 6 5816 5817 5819 5822 5857 5854 +1 6 5816 5818 5815 5820 5821 5822 +1 6 5815 5819 5821 5844 5845 5846 +1 6 5820 5819 5822 5852 5849 5846 +1 6 5821 5819 5818 5852 5853 5854 +1 6 5803 5804 5824 5825 5826 5830 +1 5 5803 5823 5825 6216 6217 +1 7 5824 5823 5826 5827 6216 6215 6021 +1 6 5825 5823 5827 5828 5829 5830 +1 6 5825 5826 5828 6019 6020 6021 +1 6 5827 5826 5829 5836 5872 6019 +1 6 5828 5826 5830 5836 5837 5838 +1 6 5829 5826 5823 5804 5838 5839 +1 6 5658 5659 5832 6931 6932 6933 +1 6 5831 5659 5660 5833 5840 6933 +1 6 5832 5660 5661 5662 5834 5840 +1 6 5833 5662 5835 5840 5841 5842 +1 6 5834 5662 5663 5664 5813 5842 +1 6 5828 5829 5837 5872 5873 5883 +1 6 5836 5829 5838 5885 5883 5886 +1 6 5837 5829 5830 5839 5809 5886 +1 6 5838 5830 5809 5808 5805 5804 +1 6 5832 5833 5834 5841 6933 6934 +1 6 5840 5834 5842 6934 6935 5843 +1 6 5841 5834 5835 5813 5814 5843 +1 6 5842 5814 5844 6018 6935 5841 +1 6 5843 5814 5815 5820 5845 6018 +1 6 5844 5820 5846 5847 6018 6940 +1 6 5845 5820 5847 5848 5849 5821 +1 6 5845 5846 5848 6940 6941 6942 +1 6 5847 5846 5849 5850 6945 6942 +1 6 5848 5846 5850 5851 5852 5821 +1 5 5848 5849 5851 6945 6385 +1 6 5850 5849 5852 6103 6104 6385 +1 6 5851 5849 5821 5822 5853 6103 +1 6 5852 5822 5854 5855 6100 6103 +1 6 5853 5822 5855 5856 5857 5818 +1 6 5853 5854 5856 6098 6099 6100 +1 6 5855 5854 5857 5858 6384 6098 +1 6 5856 5854 5858 5859 5817 5818 +1 6 5856 5857 5859 5860 6383 6384 +1 6 5858 5857 5817 5667 5668 5860 +1 6 5859 5668 5669 5861 6383 5858 +1 6 5860 5669 5670 5862 9703 6383 +1 6 5861 5670 5671 5863 9694 9703 +1 6 5862 5671 5672 5864 9694 9695 +1 6 5863 5672 5673 5865 9695 9696 +1 7 5864 5673 5674 5866 9696 5718 9697 +1 5 5865 5674 5675 5867 9697 +1 7 5866 5675 5676 5677 5868 9697 9698 +1 5 5867 5677 5693 5694 9698 +1 5 5693 5678 5679 5870 5692 +1 6 5869 5679 5680 5871 5690 5692 +1 6 5870 5680 5681 5688 5689 5690 +1 6 5828 5836 5873 5874 9736 6019 +1 6 5872 5836 5874 5875 5882 5883 +1 6 5872 5873 5875 5876 9736 6041 +1 6 5874 5873 5876 5877 5878 5882 +1 6 5874 5875 5877 6048 6041 6042 +1 6 5876 5875 5878 5879 6049 6048 +1 6 5877 5875 5879 5880 5881 5882 +1 6 5877 5878 5880 6049 6050 5888 +1 6 5879 5878 5881 5400 5399 5888 +1 6 5880 5878 5882 5884 5887 5400 +1 6 5881 5878 5875 5873 5883 5884 +1 6 5882 5873 5836 5884 5885 5837 +1 6 5882 5883 5885 5811 5881 5887 +1 6 5884 5883 5837 5811 5810 5886 +1 5 5810 5885 5837 5838 5809 +1 5 5881 5884 5811 5402 5400 +1 6 5880 5399 5889 6053 6050 5879 +1 6 5888 5399 5397 5890 5891 6053 +1 6 5889 5397 5891 5892 5893 5396 +1 6 5889 5890 5892 6056 6053 6057 +1 6 5891 5890 5893 6057 6058 6059 +1 6 5892 5890 5396 5894 5895 6059 +1 6 5893 5396 5895 5896 5899 5395 +1 6 5893 5894 5896 5897 6059 6061 +1 6 5895 5894 5897 5898 4889 5899 +1 6 5895 5896 5898 5900 6061 6062 +1 6 5897 5896 4889 4890 5900 5901 +1 7 4889 5896 5894 5395 5393 5372 4888 +1 6 5897 5898 5901 6065 6062 6066 +1 6 5900 5898 4890 4892 5902 6066 +1 6 5901 4892 5903 5904 5905 6066 +1 6 5902 4892 5904 5911 5912 4893 +1 6 5902 5903 5905 5906 5907 5911 +1 6 5902 5904 5906 6066 6070 6067 +1 7 5905 5904 5907 5908 6075 6072 6070 +1 6 5906 5904 5908 5909 5910 5911 +1 5 5906 5907 5909 5934 6075 +1 7 5908 5907 5910 5932 5929 5933 5934 +1 6 5909 5907 5911 5932 9752 5915 +1 6 5910 5907 5904 5903 5912 5915 +1 6 5911 5903 4893 5913 5914 5915 +1 6 5912 4893 4894 4896 4899 5914 +1 6 5913 4899 5912 5915 5916 5917 +1 6 5912 5914 5916 5911 9752 5910 +1 6 5915 5914 5917 9752 9755 9758 +1 6 5916 5914 4899 4900 5918 9758 +1 7 5917 4900 4902 3671 3951 5919 9758 +1 6 5918 3951 3949 5920 9755 9758 +1 5 5919 3949 3948 5921 9755 +1 6 5920 3948 5922 5930 5931 9755 +1 6 5921 3948 3946 3962 5923 5930 +1 6 5922 3962 3963 5924 5925 5930 +1 6 5923 3963 3965 5925 5926 5942 +1 6 5923 5924 5926 5927 5929 5930 +1 6 5925 5924 5927 5928 5941 5942 +1 5 5925 5926 5928 5929 5933 +1 7 5927 5926 5935 5933 5936 5940 5941 +1 7 5925 5927 5930 5931 5932 5909 5933 +1 6 5925 5929 5931 5923 5922 5921 +1 6 5930 5929 5921 5932 9752 9755 +1 5 5931 5929 5909 5910 9752 +1 6 5909 5929 5934 5935 5928 5927 +1 6 5909 5933 5935 6074 6075 5908 +1 6 5934 5933 5928 5936 5937 6074 +1 6 5935 5928 5937 5938 5939 5940 +1 5 5935 5936 5938 6074 6076 +1 6 5937 5936 5939 6076 6077 6086 +1 6 5938 5936 5940 6087 6086 6091 +1 7 5939 5936 5928 5941 5944 6091 5946 +1 5 5940 5928 5926 5942 5944 +1 6 5941 5926 5924 3965 5943 5944 +1 7 5942 3965 3966 5944 5945 3135 5947 +1 6 5942 5943 5941 5940 5945 5946 +1 5 5944 5943 5946 3134 3135 +1 6 5944 5945 3134 6091 5940 3136 +1 6 3135 5943 2093 2092 5948 3966 +1 6 2092 5947 3966 3967 2488 2489 +1 6 5754 5756 5950 5752 5751 6121 +1 6 5949 5756 5951 6166 6120 6121 +1 6 5950 5756 5757 5952 6166 6164 +1 6 5951 5757 5759 5953 5954 6164 +1 6 5952 5759 5954 5955 5956 5957 +1 6 5952 5953 5955 6162 6161 6164 +1 6 5954 5953 5956 5960 5967 6162 +1 6 5955 5953 5957 5958 5959 5960 +1 6 5956 5953 5759 5760 5763 5958 +1 6 5957 5763 5956 5959 5963 5988 +1 6 5956 5958 5960 5961 5962 5963 +1 6 5956 5959 5961 5964 5967 5955 +1 6 5960 5959 5962 5964 5965 5982 +1 6 5961 5959 5963 5983 5982 5984 +1 6 5962 5959 5958 5987 5984 5988 +1 6 5960 5961 5965 5966 5967 5968 +1 6 5964 5961 5966 5982 5980 5971 +1 6 5964 5965 5968 5969 5970 5971 +1 6 5960 5964 5955 5968 6163 6162 +1 7 5967 5964 5966 5969 6156 6157 6163 +1 6 5968 5966 5970 6447 6445 6156 +1 6 5969 5966 5971 5972 6447 6448 +1 6 5970 5966 5972 5973 5965 5980 +1 6 5970 5971 5973 5974 5975 6448 +1 6 5972 5971 5974 5978 5979 5980 +1 6 5972 5973 5975 5976 5977 5978 +1 6 5972 5974 5976 6448 6449 6450 +1 6 5975 5974 5977 6450 6608 6609 +1 6 5976 5974 5978 6609 6612 6613 +1 6 5977 5974 5973 5979 6613 6614 +1 6 5978 5973 5980 5981 6640 6614 +1 6 5979 5973 5981 5982 5965 5971 +1 6 5979 5980 5982 5983 6640 6641 +1 6 5981 5980 5983 5962 5961 5965 +1 6 5981 5982 5962 5984 5985 6641 +1 6 5983 5962 5985 5986 5987 5963 +1 6 5983 5984 5986 6643 6641 6168 +1 6 5985 5984 5987 5994 6167 6168 +1 6 5986 5984 5963 5988 5989 5994 +1 6 5987 5963 5958 5989 5764 5763 +1 6 5987 5988 5764 5990 5993 5994 +1 6 5989 5764 5765 5991 5992 5993 +1 5 5990 5765 5992 5777 5776 +1 6 5990 5991 5777 5993 5783 5782 +1 7 5990 5992 5783 5989 5994 5995 5996 +1 6 5989 5993 5995 5986 5987 6167 +1 6 5994 5993 5996 5997 5998 6167 +1 5 5995 5993 5783 5784 5997 +1 5 5995 5996 5998 5784 5786 +1 7 5995 5997 5786 5999 6000 6169 6167 +1 6 5998 5786 6000 6001 6002 5787 +1 5 5998 5999 6001 6169 6170 +1 6 6000 5999 6002 6170 6171 6005 +1 6 6001 5999 5787 6003 6004 6005 +1 6 6002 5787 6004 6008 6009 5788 +1 6 6002 6003 6005 6006 6007 6008 +1 6 6002 6004 6006 6171 6001 6172 +1 6 6005 6004 6007 6010 6172 6173 +1 6 6006 6004 6008 6010 6011 6015 +1 6 6007 6004 6003 6009 6017 6015 +1 6 6008 6003 5788 6198 6017 6199 +1 6 6006 6007 6011 6012 6179 6173 +1 6 6010 6007 6012 6013 6014 6015 +1 6 6010 6011 6013 6180 6179 6186 +1 6 6012 6011 6014 6190 6187 6186 +1 6 6013 6011 6015 6016 6190 6191 +1 6 6014 6011 6016 6017 6008 6007 +1 6 6014 6015 6017 6191 6194 6195 +1 6 6016 6015 6008 6198 6195 6009 +1 6 5843 5844 5845 6937 6935 6940 +1 6 5827 5828 6020 9736 6038 5872 +1 6 5827 6019 6021 6022 6023 6038 +1 6 5827 6020 6022 6215 5825 6222 +1 6 6021 6020 6023 6024 6025 6222 +1 6 6022 6020 6024 6037 6028 6038 +1 6 6022 6023 6025 6026 6027 6028 +1 6 6022 6024 6026 6222 6225 6223 +1 6 6025 6024 6027 6225 6226 6032 +1 6 6026 6024 6028 6029 6031 6032 +1 6 6027 6024 6029 6030 6037 6023 +1 6 6027 6028 6030 6031 6033 6034 +1 6 6029 6028 6034 6035 6036 6037 +1 6 6027 6029 6032 6033 6247 6239 +1 6 6027 6031 6226 6026 6227 6239 +1 6 6031 6029 6034 6247 6246 6248 +1 6 6033 6029 6030 6035 6248 6249 +1 6 6034 6030 6036 6249 6263 6264 +1 6 6035 6030 6037 6039 6040 6264 +1 6 6036 6030 6028 6023 6038 6039 +1 6 6037 6023 6039 9736 6019 6020 +1 6 6037 6038 6036 6040 6041 9736 +1 7 6036 6039 6041 6042 6043 6265 6264 +1 6 6040 6039 6042 9736 5874 5876 +1 6 6040 6041 6043 6044 6048 5876 +1 5 6040 6042 6044 6045 6265 +1 6 6043 6042 6045 6046 6047 6048 +1 7 6043 6044 6046 6262 6265 6261 6266 +1 6 6045 6044 6047 6269 6266 6280 +1 6 6046 6044 6048 6049 6051 6280 +1 6 6047 6044 6042 6049 5877 5876 +1 6 6047 6048 5877 5879 6050 6051 +1 6 6049 5879 6051 6052 6053 5888 +1 6 6049 6050 6052 6054 6280 6047 +1 6 6051 6050 6053 6054 6055 6056 +1 6 6052 6050 5888 5889 6056 5891 +1 7 6051 6052 6055 6279 6280 6278 6281 +1 6 6054 6052 6056 6283 6281 6284 +1 6 6055 6052 6053 5891 6057 6284 +1 6 6056 5891 5892 6058 6060 6284 +1 6 6057 5892 6059 6060 6287 6288 +1 6 6058 5892 5893 5895 6061 6288 +1 6 6057 6058 6284 6285 6286 6287 +1 6 6059 5895 5897 6062 6063 6288 +1 6 6061 5897 6063 6064 6065 5900 +1 7 6061 6062 6064 6288 6291 6289 6292 +1 5 6063 6062 6065 6292 6068 +1 6 6064 6062 5900 6066 6067 6068 +1 6 6065 5900 5901 5902 5905 6067 +1 6 6065 6066 6068 6069 6070 5905 +1 7 6065 6067 6069 6292 6064 6293 6294 +1 5 6068 6067 6070 6071 6294 +1 6 6069 6067 5905 6071 6072 5906 +1 7 6069 6070 6072 6073 6296 6294 6297 +1 6 6071 6070 6073 6074 6075 5906 +1 6 6071 6072 6074 6297 6078 6076 +1 7 6073 6072 6075 5934 5935 5937 6076 +1 5 6074 6072 5934 5908 5906 +1 6 6074 5937 5938 6077 6078 6073 +1 6 6076 5938 6078 6079 6086 6083 +1 6 6076 6077 6079 6080 6297 6073 +1 6 6078 6077 6080 6081 6082 6083 +1 6 6078 6079 6081 6297 6298 6301 +1 6 6080 6079 6082 6301 6302 6314 +1 6 6081 6079 6083 6084 6313 6314 +1 6 6082 6079 6084 6085 6086 6077 +1 7 6082 6083 6085 6088 6313 6315 6318 +1 6 6084 6083 6086 6087 6088 6089 +1 6 6085 6083 6087 5939 5938 6077 +1 6 6085 6086 5939 6089 6090 6091 +1 6 6084 6085 6089 6094 3769 6318 +1 7 6088 6085 6087 6090 3137 6092 6094 +1 5 6089 6087 6091 3136 3137 +1 6 6090 6087 5939 5940 5946 3136 +1 6 6089 3137 3138 6093 3768 6094 +1 7 6092 3138 3768 3766 2085 2084 9776 +1 5 6092 3768 3769 6088 6089 +1 6 5724 5725 6096 6383 9702 9703 +1 6 6095 5725 6097 6098 6383 6384 +1 5 6096 5725 5726 5730 6098 +1 7 6096 6097 5730 6099 6384 5856 5855 +1 5 6098 5730 5731 6100 5855 +1 7 6099 5731 6101 6102 6103 5855 5853 +1 5 6100 5731 5732 5733 6102 +1 7 6101 5733 6100 6103 6104 6105 5735 +1 6 6100 6102 6104 5853 5852 5851 +1 6 6103 6102 6105 5851 6385 6386 +1 5 6104 6102 5735 6106 6386 +1 7 6105 5735 5736 6107 6386 6387 6109 +1 6 6106 5736 5739 5741 6108 6109 +1 6 6107 5741 6109 6110 6111 5743 +1 6 6107 6108 6110 6387 6106 6388 +1 6 6109 6108 6111 6388 6389 6390 +1 6 6110 6108 5743 6112 6393 6390 +1 6 6111 5743 5744 6113 6115 6393 +1 6 6112 5744 6114 6115 6116 6117 +1 6 6113 5744 6120 6117 6121 5745 +1 6 6112 6113 6116 6393 9737 9738 +1 6 6115 6113 6117 6118 6122 9738 +1 6 6116 6113 6118 6119 6120 6114 +1 6 6116 6117 6119 6122 6123 6165 +1 5 6118 6117 6120 6166 6165 +1 6 6119 6117 6114 6121 6166 5950 +1 7 6120 6114 5745 5750 5751 5949 5950 +1 6 6116 6118 6123 6124 6131 9738 +1 6 6122 6118 6124 6125 6165 6160 +1 6 6122 6123 6125 6126 6127 6131 +1 6 6124 6123 6126 6152 6160 6158 +1 6 6124 6125 6127 6128 6151 6152 +1 6 6124 6126 6128 6129 6130 6131 +1 6 6127 6126 6129 6150 6149 6151 +1 6 6127 6128 6130 6150 6137 6134 +1 6 6127 6129 6131 6132 6133 6134 +1 6 6127 6130 6132 9738 6122 6124 +1 6 6131 6130 6133 6398 9737 9738 +1 6 6132 6130 6134 6135 6397 6398 +1 6 6133 6130 6135 6136 6137 6129 +1 6 6133 6134 6136 6397 6399 6400 +1 6 6135 6134 6137 6138 6400 6401 +1 6 6136 6134 6138 6139 6150 6129 +1 6 6136 6137 6139 6140 6401 6402 +1 6 6138 6137 6140 6141 6148 6150 +1 6 6138 6139 6141 6142 6402 6403 +1 6 6140 6139 6142 6143 6144 6148 +1 6 6140 6141 6143 6403 6404 6405 +1 6 6142 6141 6144 6145 6405 6436 +1 6 6143 6141 6145 6146 6147 6148 +1 6 6143 6144 6146 6437 6436 6438 +1 6 6145 6144 6147 6438 6439 6440 +1 6 6146 6144 6148 6149 6440 6441 +1 6 6147 6144 6141 6139 6149 6150 +1 6 6147 6148 6150 6128 6151 6441 +1 6 6149 6148 6139 6137 6129 6128 +1 6 6149 6128 6126 6152 6153 6441 +1 6 6151 6126 6125 6153 6154 6158 +1 6 6151 6152 6154 6155 6441 6442 +1 6 6153 6152 6155 6156 6157 6158 +1 6 6153 6154 6156 6444 6442 6445 +1 6 6155 6154 6157 5969 6445 5968 +1 6 6156 6154 6158 6159 5968 6163 +1 6 6157 6154 6152 6159 6160 6125 +1 6 6157 6158 6160 6161 6162 6163 +1 6 6159 6158 6125 6161 6123 6165 +1 6 6159 6160 6162 5954 6164 6165 +1 6 6159 6161 6163 5967 5955 5954 +1 5 6159 6162 5967 6157 5968 +1 6 5954 6161 6165 6166 5951 5952 +1 7 6164 6161 6166 6119 6118 6123 6160 +1 6 6164 6165 6119 6120 5950 5951 +1 6 5994 5995 5986 6168 6169 5998 +1 6 5986 6167 6169 6643 5985 9783 +1 6 6168 6167 5998 6000 6170 9783 +1 7 6169 6000 6001 6171 6789 9783 9782 +1 7 6170 6001 6005 6172 6788 6786 6789 +1 6 6171 6005 6006 6173 6174 6788 +1 6 6172 6006 6174 6175 6010 6179 +1 6 6172 6173 6175 6176 6784 6788 +1 6 6174 6173 6176 6177 6178 6179 +1 6 6174 6175 6177 6782 6781 6784 +1 6 6176 6175 6178 9796 6782 9797 +1 6 6177 6175 6179 6180 6181 9796 +1 6 6178 6175 6180 6012 6010 6173 +1 6 6178 6179 6181 6182 6186 6012 +1 6 6178 6180 6182 6183 9796 9799 +1 6 6181 6180 6183 6184 6185 6186 +1 6 6181 6182 6184 6362 6645 9799 +1 6 6183 6182 6185 6362 6363 6367 +1 6 6184 6182 6186 6187 6188 6367 +1 6 6185 6182 6180 6187 6012 6013 +1 6 6185 6186 6188 6189 6190 6013 +1 6 6185 6187 6189 6367 6368 6369 +1 6 6188 6187 6190 6369 6372 6192 +1 6 6189 6187 6013 6014 6191 6192 +1 6 6190 6014 6016 6192 6193 6194 +1 6 6190 6191 6193 6372 6189 6373 +1 6 6192 6191 6194 6382 6373 6203 +1 6 6193 6191 6016 6195 6196 6203 +1 6 6194 6016 6196 6197 6198 6017 +1 6 6194 6195 6197 6200 6201 6203 +1 6 6196 6195 6198 5792 5793 6200 +1 6 6197 6195 6017 6009 6199 5792 +1 6 6198 6009 5792 5790 5789 5788 +1 6 6197 5793 6196 6201 6202 6221 +1 6 6196 6200 6202 6203 6204 6205 +1 6 6201 6200 6205 6206 6220 6221 +1 6 6196 6201 6204 6382 6193 6194 +1 6 6203 6201 6205 6382 6459 6381 +1 6 6204 6201 6202 6206 6207 6459 +1 6 6205 6202 6207 6208 6209 6220 +1 6 6205 6206 6208 6210 6211 6459 +1 6 6207 6206 6209 6210 6214 6217 +1 6 6208 6206 5802 6217 6218 6220 +1 6 6207 6208 6211 6212 6213 6214 +1 6 6207 6210 6212 6456 6458 6459 +1 7 6211 6210 6213 6223 6224 6454 6456 +1 5 6212 6210 6214 6215 6223 +1 6 6213 6210 6208 6215 6216 6217 +1 7 6213 6214 6216 5825 6021 6222 6223 +1 5 6215 6214 6217 5824 5825 +1 7 6216 6214 5824 5803 5802 6209 6208 +1 6 5802 6209 5799 5797 6219 6220 +1 6 5797 6218 6220 6221 5794 5795 +1 6 6219 6218 6209 6206 6202 6221 +1 6 6219 6220 6202 6200 5793 5794 +1 5 6215 6021 6022 6025 6223 +1 7 6215 6222 6213 6212 6224 6225 6025 +1 7 6212 6223 6225 6454 6231 6226 6228 +1 5 6224 6223 6025 6026 6226 +1 6 6225 6026 6032 6227 6228 6224 +1 6 6226 6032 6228 6229 6238 6239 +1 6 6226 6227 6229 6230 6231 6224 +1 6 6228 6227 6230 6237 6234 6238 +1 6 6228 6229 6231 6232 6233 6234 +1 6 6228 6230 6232 6454 6224 6455 +1 6 6231 6230 6233 6455 6460 6461 +1 6 6232 6230 6234 6235 6461 6462 +1 6 6233 6230 6235 6236 6237 6229 +1 6 6233 6234 6236 6462 6463 6471 +1 6 6235 6234 6237 6473 6471 6476 +1 6 6236 6234 6229 6238 6476 6241 +1 6 6237 6229 6227 6239 6240 6241 +1 6 6238 6227 6240 6247 6031 6032 +1 6 6238 6239 6241 6242 6243 6247 +1 6 6238 6240 6242 6476 6237 6477 +1 6 6241 6240 6243 6244 6477 6479 +1 6 6242 6240 6244 6245 6246 6247 +1 6 6242 6243 6245 6481 6479 6482 +1 6 6244 6243 6246 6482 6253 6251 +1 6 6245 6243 6247 6033 6248 6251 +1 6 6246 6243 6240 6239 6031 6033 +1 6 6246 6033 6034 6249 6250 6251 +1 6 6248 6034 6035 6250 6263 6255 +1 6 6248 6249 6251 6252 6254 6255 +1 6 6248 6250 6252 6253 6245 6246 +1 6 6251 6250 6253 6254 6484 6485 +1 6 6251 6252 6482 6245 6483 6484 +1 6 6252 6250 6255 6256 6257 6485 +1 6 6254 6250 6256 6263 6260 6249 +1 6 6254 6255 6257 6258 6259 6260 +1 6 6254 6256 6258 6485 6493 6494 +1 6 6257 6256 6259 6494 6495 6496 +1 7 6258 6256 6260 6261 6496 6273 6267 +1 6 6259 6256 6261 6262 6263 6255 +1 6 6259 6260 6262 6045 6266 6267 +1 6 6261 6260 6263 6264 6265 6045 +1 6 6262 6260 6264 6255 6249 6035 +1 6 6262 6263 6265 6035 6040 6036 +1 5 6262 6264 6045 6043 6040 +1 6 6045 6261 6267 6268 6269 6046 +1 6 6261 6266 6268 6272 6273 6259 +1 6 6267 6266 6269 6270 6271 6272 +1 6 6268 6266 6046 6270 6279 6280 +1 6 6268 6269 6271 6277 6278 6279 +1 6 6268 6270 6272 6275 6276 6277 +1 6 6268 6271 6267 6273 6274 6275 +1 6 6267 6272 6274 6496 6259 6497 +1 6 6273 6272 6275 6500 6497 6501 +1 6 6274 6272 6271 6276 6501 6502 +1 6 6275 6271 6277 6502 6503 6504 +1 6 6276 6271 6270 6278 6504 6505 +1 7 6277 6270 6279 6054 6281 6282 6505 +1 5 6278 6270 6269 6280 6054 +1 6 6279 6269 6046 6054 6051 6047 +1 5 6278 6054 6282 6283 6055 +1 6 6278 6281 6283 6506 6505 6507 +1 6 6282 6281 6055 6284 6507 6285 +1 6 6283 6055 6056 6057 6060 6285 +1 6 6284 6060 6286 6507 6283 6508 +1 7 6285 6060 6287 6508 6328 6511 6290 +1 6 6286 6060 6058 6288 6289 6290 +1 6 6287 6058 6059 6061 6063 6289 +1 5 6287 6288 6290 6291 6063 +1 5 6287 6289 6291 6328 6286 +1 7 6290 6289 6063 6292 6326 6327 6328 +1 6 6291 6063 6064 6068 6293 6326 +1 6 6292 6068 6294 6295 6325 6326 +1 6 6293 6068 6069 6295 6296 6071 +1 6 6293 6294 6296 6299 6324 6325 +1 6 6295 6294 6071 6297 6298 6299 +1 6 6296 6071 6073 6078 6080 6298 +1 6 6297 6080 6296 6299 6300 6301 +1 5 6296 6298 6300 6324 6295 +1 6 6299 6298 6301 6303 6323 6324 +1 6 6300 6298 6080 6081 6302 6303 +1 6 6301 6081 6303 6304 6308 6314 +1 6 6301 6302 6304 6305 6323 6300 +1 6 6303 6302 6305 6306 6307 6308 +1 6 6303 6304 6306 6323 6337 6338 +1 6 6305 6304 6307 6338 6341 6342 +1 6 6306 6304 6308 6309 6342 6343 +1 6 6307 6304 6302 6309 6310 6314 +1 6 6307 6308 6310 6311 6343 6346 +1 6 6309 6308 6311 6312 6313 6314 +1 6 6309 6310 6312 6321 6322 6346 +1 6 6311 6310 6313 6315 6316 6321 +1 6 6312 6310 6314 6082 6084 6315 +1 6 6313 6310 6082 6081 6302 6308 +1 6 6313 6084 6312 6316 6317 6318 +1 6 6312 6315 6317 6319 6320 6321 +1 6 6316 6315 6318 3769 1571 6319 +1 5 6317 6315 3769 6084 6088 +1 5 6317 1571 1572 6320 6316 +1 7 6319 1572 1573 6316 6321 6322 6360 +1 5 6316 6320 6322 6312 6311 +1 7 6321 6320 6311 6347 6346 6348 6360 +1 6 6303 6305 6300 6324 6335 6337 +1 7 6300 6323 6299 6295 6325 6336 6335 +1 6 6295 6324 6293 6326 6336 6331 +1 6 6293 6325 6292 6291 6327 6331 +1 6 6291 6326 6328 6329 6330 6331 +1 6 6291 6327 6329 6511 6286 6290 +1 6 6328 6327 6330 6510 6511 6519 +1 7 6329 6327 6331 6332 6333 6519 6518 +1 6 6330 6327 6332 6336 6325 6326 +1 6 6330 6331 6333 6334 6335 6336 +1 5 6330 6332 6334 6518 6520 +1 6 6333 6332 6335 6520 6528 6529 +1 7 6334 6332 6336 6324 6323 6337 6529 +1 5 6335 6332 6331 6325 6324 +1 6 6335 6323 6305 6338 6339 6529 +1 6 6337 6305 6306 6339 6340 6341 +1 6 6337 6338 6340 6530 6527 6529 +1 5 6339 6338 6341 6545 6530 +1 6 6340 6338 6306 6342 6546 6545 +1 6 6341 6306 6307 6343 6344 6546 +1 6 6342 6307 6344 6345 6346 6309 +1 6 6342 6343 6345 6546 6543 6547 +1 6 6344 6343 6346 6347 6549 6547 +1 6 6345 6343 6347 6322 6311 6309 +1 6 6345 6346 6322 6348 6349 6549 +1 6 6347 6322 6349 6350 6359 6360 +1 6 6347 6348 6350 6351 6550 6549 +1 6 6349 6348 6351 6352 6353 6359 +1 6 6349 6350 6352 6552 6550 6553 +1 6 6351 6350 6353 6354 6355 6553 +1 6 6352 6350 6354 1589 2476 6359 +1 7 6352 6353 6355 6356 1594 1590 1589 +1 6 6352 6354 6356 6357 6553 6554 +1 5 6355 6354 6357 6358 1594 +1 6 6355 6356 6358 6554 6555 3971 +1 6 6357 6356 1594 3971 3970 1595 +1 6 2476 6353 6350 6348 6360 6361 +1 6 6359 6348 6361 1573 6320 6322 +1 5 6359 6360 1573 2475 2476 +1 6 6183 6184 6363 6364 6644 6645 +1 6 6362 6184 6364 6365 6366 6367 +1 6 6362 6363 6365 6644 6648 6649 +1 6 6364 6363 6366 9727 9673 6649 +1 6 6365 6363 6367 9727 9728 6368 +1 6 6366 6363 6184 6185 6188 6368 +1 6 6367 6188 6369 6370 9728 6366 +1 6 6368 6188 6189 6370 6371 6372 +1 6 6368 6369 6371 9728 9729 9730 +1 6 6370 6369 6372 6374 6375 9730 +1 6 6371 6369 6189 6192 6373 6374 +1 6 6372 6192 6374 6382 6380 6193 +1 6 6372 6373 6371 6375 6376 6380 +1 6 6371 6374 6376 6377 6467 9730 +1 6 6375 6374 6377 6378 6379 6380 +1 5 6375 6376 6378 9693 6467 +1 7 6377 6376 6379 6457 6455 6460 9693 +1 6 6378 6376 6380 6381 6457 6458 +1 6 6379 6376 6381 6382 6373 6374 +1 6 6379 6380 6382 6459 6458 6204 +1 6 6381 6380 6373 6193 6203 6204 +1 7 6095 6096 6384 9703 5861 5860 5858 +1 5 6383 6096 6098 5856 5858 +1 6 5851 6104 6386 6945 5850 6946 +1 7 6385 6104 6105 6106 6387 6946 6947 +1 5 6386 6106 6109 6388 6947 +1 6 6387 6109 6110 6389 6947 6948 +1 6 6388 6110 6390 6391 6948 6949 +1 6 6389 6110 6391 6392 6393 6111 +1 6 6389 6390 6392 6394 6395 6949 +1 6 6391 6390 6393 6394 9737 6398 +1 6 6392 6390 6111 6112 6115 9737 +1 6 6391 6392 6395 6396 6397 6398 +1 6 6391 6394 6396 6949 6950 6951 +1 6 6395 6394 6397 6951 6952 6399 +1 6 6396 6394 6398 6133 6135 6399 +1 6 6397 6394 6133 6132 9737 6392 +1 6 6397 6135 6400 6952 6396 6953 +1 6 6399 6135 6136 6401 6953 6954 +1 6 6400 6136 6138 6402 6954 6960 +1 6 6401 6138 6140 6403 6960 6410 +1 6 6402 6140 6142 6404 6408 6410 +1 6 6403 6142 6405 6406 6407 6408 +1 6 6404 6142 6143 6406 6436 6434 +1 6 6404 6405 6407 6431 6429 6434 +1 6 6404 6406 6408 6409 6428 6429 +1 6 6404 6407 6409 6403 6410 6411 +1 6 6408 6407 6411 6412 6413 6428 +1 6 6403 6408 6411 6959 6960 6402 +1 6 6410 6408 6409 6412 6959 6961 +1 6 6411 6409 6413 6414 6963 6961 +1 6 6412 6409 6414 6415 6427 6428 +1 6 6412 6413 6415 6416 6963 6964 +1 6 6414 6413 6416 6417 6418 6427 +1 6 6414 6415 6417 6558 6559 6964 +1 6 6416 6415 6418 6419 6558 6565 +1 6 6417 6415 6419 6420 6427 6424 +1 6 6417 6418 6420 6421 6573 6565 +1 6 6419 6418 6421 6422 6423 6424 +1 6 6419 6420 6422 6573 6572 6574 +1 6 6421 6420 6423 6580 6577 6574 +1 6 6422 6420 6424 6425 6580 6581 +1 6 6423 6420 6425 6426 6427 6418 +1 6 6423 6424 6426 6584 6581 6430 +1 6 6425 6424 6427 6428 6429 6430 +1 6 6426 6424 6418 6415 6413 6428 +1 6 6427 6413 6409 6407 6426 6429 +1 6 6426 6428 6407 6430 6431 6406 +1 6 6426 6429 6431 6432 6584 6425 +1 6 6430 6429 6406 6432 6433 6434 +1 6 6430 6431 6433 6584 6585 6586 +1 6 6432 6431 6434 6435 6589 6586 +1 6 6433 6431 6435 6436 6405 6406 +1 6 6433 6434 6436 6437 6589 6590 +1 6 6435 6434 6405 6437 6145 6143 +1 6 6435 6436 6145 6438 6590 6591 +1 6 6437 6145 6146 6439 6591 6592 +1 6 6438 6146 6440 6595 6592 6443 +1 6 6439 6146 6147 6441 6442 6443 +1 6 6440 6147 6149 6151 6153 6442 +1 6 6441 6153 6440 6443 6444 6155 +1 6 6440 6442 6444 6595 6439 6453 +1 6 6443 6442 6155 6445 6446 6453 +1 6 6444 6155 6446 6447 5969 6156 +1 6 6444 6445 6447 6449 6452 6453 +1 6 6446 6445 5969 5970 6448 6449 +1 5 6447 5970 5972 5975 6449 +1 7 6448 5975 6447 6450 6451 6452 6446 +1 7 6449 5975 5976 6451 6607 6598 6608 +1 6 6449 6450 6452 6596 6597 6598 +1 5 6449 6451 6446 6453 6596 +1 6 6446 6452 6595 6443 6444 6596 +1 5 6212 6224 6231 6455 6456 +1 7 6454 6231 6456 6457 6378 6232 6460 +1 6 6454 6455 6457 6458 6211 6212 +1 5 6456 6455 6378 6379 6458 +1 6 6457 6379 6456 6211 6459 6381 +1 6 6211 6458 6207 6381 6204 6205 +1 5 6455 6232 6461 9693 6378 +1 6 6460 6232 6233 6462 6465 9693 +1 6 6461 6233 6235 6463 6464 6465 +1 6 6462 6235 6464 6469 6470 6471 +1 6 6462 6463 6465 6466 6468 6469 +1 6 6462 6464 6461 6466 6467 9693 +1 6 6465 6464 6467 6468 9731 9732 +1 7 6465 6466 9693 6377 6375 9730 9731 +1 6 6466 6464 6469 7509 7510 9732 +1 7 6468 6464 6463 6470 7507 7509 7506 +1 6 6469 6463 6471 6472 7506 7505 +1 6 6470 6463 6235 6472 6473 6236 +1 6 6470 6471 6473 6474 7504 7505 +1 6 6472 6471 6236 6474 6475 6476 +1 7 6472 6473 6475 7503 7504 9692 9780 +1 6 6474 6473 6476 6477 6478 9692 +1 6 6475 6473 6236 6237 6241 6477 +1 6 6476 6241 6242 6475 6478 6479 +1 7 6475 6477 6479 6480 9692 9778 9779 +1 6 6478 6477 6242 6480 6481 6244 +1 6 6478 6479 6481 6487 9705 9778 +1 6 6480 6479 6244 6482 6486 6487 +1 6 6481 6244 6245 6253 6483 6486 +1 5 6482 6253 6484 6486 6489 +1 7 6483 6253 6252 6485 6489 6490 6491 +1 7 6484 6252 6254 6257 6491 6492 6493 +1 6 6482 6483 6481 6487 6488 6489 +1 5 6481 6486 6488 9705 6480 +1 7 6487 6486 6489 9704 2194 2195 9705 +1 6 6488 6486 6483 6484 6490 9704 +1 6 6489 6484 6491 2251 2252 9704 +1 6 6490 6484 6485 6492 2251 9706 +1 6 6491 6485 6493 9706 3335 9707 +1 5 6492 6485 6257 6494 9707 +1 6 6493 6257 6258 6495 9707 6499 +1 6 6494 6258 6496 6497 6498 6499 +1 5 6495 6258 6259 6273 6497 +1 6 6496 6273 6495 6498 6500 6274 +1 6 6495 6497 6499 2511 2512 6500 +1 7 6495 6498 2511 3334 9707 3881 6494 +1 6 2512 6498 6497 6274 6501 9710 +1 6 6500 6274 6275 6502 9709 9710 +1 6 6501 6275 6276 6503 9708 9709 +1 6 6502 6276 6504 6512 9708 9711 +1 6 6503 6276 6277 6505 6506 6512 +1 5 6504 6277 6506 6282 6278 +1 7 6504 6505 6282 6507 6512 6513 6509 +1 6 6506 6282 6283 6285 6508 6509 +1 6 6507 6285 6286 6509 6510 6511 +1 6 6507 6508 6510 6513 6506 6514 +1 7 6509 6508 6511 6329 6514 6515 6519 +1 5 6510 6508 6329 6328 6286 +1 6 6503 6504 6506 6513 9711 9717 +1 5 6512 6506 6509 6514 9717 +1 7 6513 6509 6510 6515 6516 9717 9718 +1 6 6514 6510 6516 6517 6518 6519 +1 6 6514 6515 6517 9718 9719 6522 +1 6 6516 6515 6518 6520 6521 6522 +1 6 6517 6515 6519 6330 6333 6520 +1 5 6518 6515 6510 6329 6330 +1 7 6518 6333 6334 6517 6521 6525 6528 +1 6 6517 6520 6522 6523 6524 6525 +1 7 6517 6521 6523 2214 9719 6516 2213 +1 5 6522 6521 6524 2213 3348 +1 7 6523 6521 6525 6526 3348 3347 6532 +1 6 6524 6521 6520 6526 6527 6528 +1 6 6524 6525 6527 6530 6531 6532 +1 6 6526 6525 6528 6530 6339 6529 +1 5 6527 6525 6520 6334 6529 +1 6 6528 6334 6335 6339 6527 6337 +1 7 6526 6527 6531 6340 6545 6339 6534 +1 6 6526 6530 6532 3863 6533 6534 +1 5 6526 6531 3863 3347 6524 +1 6 3863 6531 6534 6535 6536 6716 +1 6 6533 6531 6535 6544 6545 6530 +1 6 6533 6534 6536 6537 6544 6541 +1 6 6533 6535 6537 6538 6715 6716 +1 6 6536 6535 6538 6539 6540 6541 +1 7 6536 6537 6539 6714 3887 3886 6715 +1 6 6538 6537 6540 6714 6718 6719 +1 6 6539 6537 6541 6542 6719 6708 +1 6 6540 6537 6542 6543 6544 6535 +1 6 6540 6541 6543 6547 6548 6708 +1 6 6542 6541 6544 6546 6344 6547 +1 6 6543 6541 6535 6534 6545 6546 +1 6 6544 6534 6546 6341 6340 6530 +1 6 6544 6545 6543 6341 6342 6344 +1 6 6543 6344 6542 6548 6549 6345 +1 6 6542 6547 6549 6550 6551 6708 +1 6 6548 6547 6345 6347 6550 6349 +1 6 6548 6549 6551 6552 6351 6349 +1 6 6548 6550 6552 6705 6707 6708 +1 6 6551 6550 6351 6553 6554 6705 +1 5 6552 6351 6352 6355 6554 +1 6 6553 6355 6357 6555 6552 6705 +1 7 6554 6357 3971 6705 6706 9747 3491 +1 6 3969 1597 1598 6557 4038 3968 +1 6 6556 1598 4038 3764 612 611 +1 6 6416 6417 6559 6560 6564 6565 +1 6 6416 6558 6560 6561 6964 6965 +1 6 6559 6558 6561 6562 6563 6564 +1 6 6559 6560 6562 6965 6966 6967 +1 6 6561 6560 6563 6985 6983 6967 +1 6 6562 6560 6564 6985 6986 6567 +1 6 6563 6560 6558 6565 6566 6567 +1 6 6564 6558 6417 6566 6573 6419 +1 6 6564 6565 6567 6568 6569 6573 +1 6 6564 6566 6568 6986 6563 6987 +1 6 6567 6566 6569 6570 6990 6987 +1 6 6568 6566 6570 6571 6572 6573 +1 6 6568 6569 6571 6997 6990 6998 +1 6 6570 6569 6572 6575 7001 6998 +1 6 6571 6569 6573 6421 6574 6575 +1 6 6572 6569 6566 6565 6419 6421 +1 6 6572 6421 6575 6576 6577 6422 +1 6 6572 6574 6576 7003 7001 6571 +1 6 6575 6574 6577 6578 7003 7004 +1 6 6576 6574 6578 6579 6580 6422 +1 6 6576 6577 6579 7004 7005 7006 +1 6 6578 6577 6580 7006 7007 6582 +1 6 6579 6577 6422 6423 6581 6582 +1 6 6580 6423 6582 6583 6584 6425 +1 6 6580 6581 6583 7007 6579 7008 +1 6 6582 6581 6584 6720 7008 6585 +1 6 6583 6581 6425 6430 6432 6585 +1 6 6584 6432 6586 6587 6720 6583 +1 6 6585 6432 6587 6588 6589 6433 +1 6 6585 6586 6588 6720 6721 6728 +1 6 6587 6586 6589 6728 6729 6730 +1 6 6588 6586 6433 6435 6590 6730 +1 6 6589 6435 6437 6591 6730 6731 +1 6 6590 6437 6438 6592 6593 6731 +1 6 6591 6438 6593 6594 6595 6439 +1 6 6591 6592 6594 6731 6732 6733 +1 7 6593 6592 6595 6600 6733 6597 6596 +1 6 6594 6592 6439 6443 6453 6596 +1 6 6595 6453 6452 6451 6597 6594 +1 6 6596 6451 6598 6599 6600 6594 +1 6 6597 6451 6599 6606 6607 6450 +1 6 6597 6598 6600 6601 6602 6606 +1 5 6597 6599 6601 6733 6594 +1 6 6600 6599 6602 6603 6734 6733 +1 6 6601 6599 6603 6604 6605 6606 +1 7 6601 6602 6604 6734 6735 6736 6737 +1 5 6603 6602 6605 6737 6738 +1 7 6604 6602 6606 6738 6739 6748 6745 +1 6 6605 6602 6599 6598 6607 6748 +1 6 6606 6598 6450 6608 6747 6748 +1 6 6607 6450 5976 6609 6610 6747 +1 6 6608 5976 5977 6610 6611 6612 +1 6 6608 6609 6611 6747 6746 6749 +1 6 6610 6609 6612 6619 6620 6749 +1 6 6611 6609 5977 6613 6616 6619 +1 6 6612 5977 5978 6614 6615 6616 +1 6 6613 5978 6615 6639 6640 5979 +1 6 6613 6614 6616 6617 6638 6639 +1 6 6613 6615 6617 6618 6619 6612 +1 6 6616 6615 6618 6636 6637 6638 +1 6 6616 6617 6619 6621 6622 6636 +1 6 6616 6618 6612 6611 6620 6621 +1 6 6611 6619 6621 6750 6749 6626 +1 6 6620 6619 6618 6622 6623 6626 +1 6 6621 6618 6623 6624 6635 6636 +1 6 6621 6622 6624 6625 6626 6627 +1 6 6623 6622 6625 6633 6634 6635 +1 6 6623 6624 6627 6628 6632 6633 +1 6 6621 6623 6627 6750 6620 6751 +1 6 6626 6623 6625 6628 6629 6751 +1 6 6627 6625 6629 6630 6631 6632 +1 6 6627 6628 6630 6756 6753 6751 +1 6 6629 6628 6631 6756 6757 6758 +1 6 6630 6628 6632 6758 6766 6767 +1 6 6631 6628 6625 6633 6767 6768 +1 6 6632 6625 6624 6634 6768 6769 +1 6 6633 6624 6635 6769 6770 6771 +1 6 6634 6624 6622 6636 9785 6771 +1 6 6635 6622 6618 6617 6637 9785 +1 6 6636 6617 6638 6785 6783 9785 +1 6 6637 6617 6615 6639 9777 6785 +1 6 6638 6615 6614 6640 9777 6642 +1 6 6639 6614 5979 5981 6641 6642 +1 6 6640 5981 5983 6642 6643 5985 +1 7 6640 6641 6643 9777 6639 6787 9782 +1 6 6642 6641 5985 6168 9782 9783 +1 6 6362 6364 6645 6646 6647 6648 +1 6 6362 6644 6183 6646 9724 9799 +1 6 6645 6644 6647 9723 9724 6655 +1 6 6646 6644 6648 6652 6654 6655 +1 6 6647 6644 6364 6649 6650 6652 +1 6 6648 6364 6650 6651 9673 6365 +1 6 6648 6649 6651 6652 6653 9670 +1 6 6650 6649 9670 9671 9672 9673 +1 6 6648 6650 6653 6647 6654 3173 +1 6 6652 6650 9670 9691 3172 3173 +1 6 6647 6652 3173 6655 3450 3175 +1 6 6647 6654 3450 6656 9723 6646 +1 6 6655 3450 6657 6658 9721 9723 +1 6 6656 3450 6658 3179 6659 6667 +1 6 6656 6657 6667 6668 6669 9721 +1 6 6657 3179 6660 6663 6664 6667 +1 6 6659 3179 3178 6661 6662 6663 +1 6 6660 3178 3180 2858 2859 6662 +1 5 6660 6661 6663 6666 2859 +1 6 6660 6662 6659 6664 6665 6666 +1 6 6659 6663 6665 6667 6668 6672 +1 7 6664 6663 6666 6672 6673 4564 4563 +1 6 6665 6663 6662 4563 6674 2859 +1 5 6659 6664 6668 6658 6657 +1 7 6667 6664 6658 6669 6670 6671 6672 +1 6 6658 6668 6670 6774 6775 9721 +1 6 6669 6668 6671 6773 6772 6774 +1 6 6670 6668 6672 6673 6790 6773 +1 5 6671 6668 6664 6665 6673 +1 5 6672 6665 4564 6671 6790 +1 6 4563 6666 4561 6675 2860 2859 +1 6 4561 6674 2860 6676 4560 9792 +1 6 6675 2860 2853 2854 6677 9792 +1 6 6676 2854 6678 6679 6681 9792 +1 5 6677 2854 6679 6680 2855 +1 6 6677 6678 6680 6681 6682 6683 +1 6 6679 6678 6685 6683 6686 2855 +1 6 6677 6679 6682 9750 9761 9792 +1 6 6681 6679 6683 5156 5157 9750 +1 6 6682 6679 5156 6684 6685 6680 +1 6 5156 6683 6685 6692 6693 6694 +1 6 6684 6683 6680 6686 6687 6692 +1 6 6685 6680 6687 6688 6689 2855 +1 6 6685 6686 6688 6692 6696 6699 +1 6 6687 6686 6689 6690 6699 6700 +1 6 6688 6686 6690 6691 2856 2855 +1 6 6688 6689 6691 6700 6702 2551 +1 5 6690 6689 2856 2550 2551 +1 6 6685 6687 6684 6693 6695 6696 +1 6 6684 6692 6694 4523 4522 6695 +1 5 6684 6693 4523 4532 5156 +1 6 4522 6693 6692 6696 6697 6704 +1 6 6695 6692 6687 6697 6698 6699 +1 7 6695 6696 6698 6703 3505 3506 6704 +1 6 6697 6696 6699 6700 6701 6703 +1 5 6698 6696 6687 6688 6700 +1 7 6699 6688 6690 6698 6701 2222 6702 +1 6 6698 6700 2222 64 65 6703 +1 5 2222 6700 6690 2551 2221 +1 6 6698 6701 65 66 6697 3505 +1 5 6697 3506 3507 4522 6695 +1 7 6552 6554 6555 6706 6551 6707 9749 +1 6 6705 6555 9747 3502 9748 9749 +1 6 6551 6705 6708 6709 6710 9749 +1 7 6551 6707 6709 6719 6540 6548 6542 +1 6 6708 6707 6710 6711 6718 6719 +1 7 6709 6707 6711 6712 3503 9748 9749 +1 7 6709 6710 6712 3117 3119 6713 6718 +1 6 6711 6710 3503 3504 3116 3117 +1 6 6711 3119 3121 3887 6714 6718 +1 5 6713 3887 6538 6539 6718 +1 6 6538 3886 6536 6716 3862 6717 +1 5 6536 6715 6533 3863 3862 +1 6 3862 6715 3861 3342 3885 3886 +1 6 6714 6539 6713 6711 6709 6719 +1 5 6718 6539 6540 6709 6708 +1 6 6585 6587 6721 6722 7008 6583 +1 6 6720 6587 6722 6723 6727 6728 +1 6 6720 6721 6723 6724 7009 7008 +1 6 6722 6721 6724 6725 6726 6727 +1 6 6722 6723 6725 7009 7010 7011 +1 6 6724 6723 6726 7022 7011 7023 +1 6 6725 6723 6727 7023 7026 7027 +1 6 6726 6723 6721 6728 7027 7030 +1 6 6727 6721 6587 6588 6729 7030 +1 6 6728 6588 6730 7030 7031 7032 +1 6 6729 6588 6589 6590 6731 7032 +1 6 6730 6590 6591 6593 6732 7032 +1 6 6731 6593 6733 6734 7032 7033 +1 6 6732 6593 6734 6601 6600 6594 +1 6 6732 6733 6601 6603 6735 7033 +1 6 6734 6603 6736 7033 7034 7035 +1 6 6735 6603 6737 6740 7035 7036 +1 5 6736 6603 6604 6738 6740 +1 7 6737 6604 6605 6739 6740 6741 6742 +1 6 6738 6605 6742 6743 6744 6745 +1 6 6736 6737 6738 6741 7036 7037 +1 6 6740 6738 6742 7037 7038 7039 +1 6 6741 6738 6739 6743 7039 7040 +1 7 6742 6739 6744 7040 7041 6754 7042 +1 5 6743 6739 6745 6746 7042 +1 6 6744 6739 6746 6747 6748 6605 +1 7 6744 6745 6747 6610 6749 6750 7042 +1 6 6746 6745 6748 6607 6608 6610 +1 5 6747 6745 6607 6605 6606 +1 5 6746 6610 6750 6620 6611 +1 7 6746 6749 6620 6626 6751 6752 7042 +1 6 6750 6626 6752 6753 6629 6627 +1 5 6750 6751 6753 6754 7042 +1 6 6752 6751 6754 6755 6756 6629 +1 7 6752 6753 6755 7041 6743 7042 7141 +1 5 6754 6753 6756 7141 6759 +1 6 6755 6753 6629 6630 6757 6759 +1 6 6756 6630 6758 6759 6760 6761 +1 6 6757 6630 6631 6761 6762 6766 +1 6 6756 6757 6760 7141 6755 7142 +1 6 6759 6757 6761 7142 7143 7144 +1 6 6760 6757 6758 6762 6763 7144 +1 6 6761 6758 6763 4559 6764 6766 +1 6 6761 6762 4559 4551 7144 4550 +1 6 4559 6762 4558 4565 6765 6766 +1 5 4565 6764 6766 6790 6767 +1 6 6765 6764 6762 6758 6631 6767 +1 6 6766 6631 6632 6768 6790 6765 +1 6 6767 6632 6633 6769 6773 6790 +1 6 6768 6633 6634 6770 6772 6773 +1 6 6769 6634 6771 6772 6777 6778 +1 6 6770 6634 6778 6779 6635 9785 +1 6 6769 6770 6773 6670 6774 6777 +1 6 6769 6772 6670 6671 6790 6768 +1 6 6670 6772 6669 6775 6776 6777 +1 6 6669 6774 6776 9721 9722 9798 +1 7 6775 6774 6777 6778 6780 9797 9798 +1 5 6776 6774 6772 6770 6778 +1 6 6777 6770 6771 6779 6780 6776 +1 6 6778 6771 6780 6781 6783 9785 +1 6 6778 6779 6781 6782 6776 9797 +1 6 6780 6779 6782 6176 6783 6784 +1 5 6780 6781 6176 6177 9797 +1 6 6781 6779 6784 6785 6637 9785 +1 7 6781 6783 6176 6174 6785 6786 6788 +1 7 6784 6783 6786 6787 9777 6638 6637 +1 6 6784 6785 6787 6788 6171 6789 +1 6 6786 6785 9777 6642 9782 6789 +1 5 6784 6786 6171 6172 6174 +1 5 6171 6786 6170 6787 9782 +1 8 6671 6673 6773 4564 4565 6765 6768 6767 +1 6 5418 5419 6792 7331 7332 7333 +1 6 6791 5419 5420 5428 6793 7333 +1 6 6792 5428 5429 6794 7333 7334 +1 6 6793 5429 5430 6795 7334 7335 +1 6 6794 5430 5432 5433 6796 7335 +1 6 6795 5433 5434 6797 7335 7336 +1 6 6796 5434 5435 6798 7336 7337 +1 6 6797 5435 5436 6799 7337 7338 +1 6 6798 5436 5437 6800 7338 7339 +1 6 6799 5437 5438 6801 7339 7340 +1 6 6800 5438 6802 7340 7341 7342 +1 6 6801 5438 5439 5440 6803 7342 +1 6 6802 5440 5441 6804 7342 7343 +1 6 6803 5441 5442 6805 7343 7344 +1 6 6804 5442 5444 6806 7344 7345 +1 6 6805 5444 5445 6807 7345 7346 +1 6 6806 5445 5446 6808 7346 7347 +1 6 6807 5446 6809 7347 7348 7349 +1 6 6808 5446 5447 6810 7349 6811 +1 5 6809 5447 5217 5218 6811 +1 6 6810 5218 5219 6812 7349 6809 +1 5 6811 5219 6813 7349 7350 +1 6 6812 5219 5220 6814 7350 7351 +1 7 6813 5220 5221 5222 6815 7351 7352 +1 5 6814 5222 6816 7352 7353 +1 7 6815 5222 5223 5224 6817 7353 7354 +1 5 6816 5224 6818 7354 7355 +2 6 6817 5224 6819 7355 7356 7357 +2 6 6818 5224 5225 5226 6820 7357 +2 5 6819 5226 5227 6821 7357 +2 6 6820 5227 6822 7357 7358 7359 +2 7 6821 5227 5228 5229 6823 7359 7360 +2 5 6822 5229 6824 6825 7360 +2 5 6823 5229 6825 6826 5167 +2 7 6823 6824 6826 6827 6828 7362 7360 +2 5 6825 6824 5167 5168 6827 +2 6 6826 5168 6825 6828 6829 6830 +2 6 6825 6827 6829 7362 7363 7364 +2 6 6828 6827 6830 7364 7365 7366 +2 6 6829 6827 5168 5169 6831 7366 +2 7 6830 5169 6832 7366 7367 7368 6834 +2 5 6831 5169 6833 5238 6834 +2 5 6832 5169 5238 5018 5023 +2 6 6832 5238 5239 6835 7368 6831 +2 6 6834 5239 5648 6836 7375 7368 +2 7 6835 5648 6837 7375 7374 7376 7377 +2 6 6836 5648 5649 5651 6838 7377 +2 6 6837 5651 6839 7377 7378 7379 +2 6 6838 5651 5652 6840 6841 7379 +2 6 6839 5652 5653 5247 6841 5248 +2 6 6839 6840 5248 6842 7379 7380 +2 6 6841 5248 5249 6843 7380 7381 +2 6 6842 5249 6844 7381 7382 7383 +2 6 6843 5249 5028 5029 6845 7383 +2 6 6844 5029 5030 6846 6847 7383 +2 6 6845 5030 6847 6848 6849 5031 +2 6 6845 6846 6848 7384 7383 7385 +2 6 6847 6846 6849 7385 7386 7387 +2 6 6848 6846 5031 5032 6850 7387 +2 6 6849 5032 5033 5034 6851 7387 +2 6 6850 5034 6852 7387 7388 6854 +2 6 6851 5034 5035 5038 6853 6854 +2 6 6852 5038 6854 6855 6856 5039 +2 6 6852 6853 6855 7388 6851 7389 +2 6 6854 6853 6856 6857 6859 7389 +2 6 6855 6853 5039 6857 6858 5041 +2 6 6855 6856 6858 6859 6860 6861 +2 6 6857 6856 5041 6861 6862 6863 +2 6 6855 6857 6860 7389 7390 7397 +2 6 6859 6857 6861 7397 7398 7399 +2 6 6860 6857 6858 6862 7399 7400 +2 6 6861 6858 6863 6864 6865 7400 +2 6 6862 6858 6864 5042 6879 5041 +2 6 6862 6863 6865 6866 6879 6873 +2 6 6862 6864 6866 6867 7400 7401 +2 6 6865 6864 6867 6868 6872 6873 +2 6 6865 6866 6868 6869 7401 7402 +2 6 6867 6866 6869 6870 6871 6872 +2 6 6867 6868 6870 7405 7402 7406 +2 6 6869 6868 6871 7412 7406 7413 +2 6 6870 6868 6872 7419 7416 7413 +2 6 6871 6868 6866 6873 6874 7419 +2 6 6872 6866 6874 6875 6864 6879 +2 6 6872 6873 6875 6876 7419 7418 +2 6 6874 6873 6876 6877 6878 6879 +2 6 6874 6875 6877 6883 6884 7418 +2 6 6876 6875 6878 6880 6882 6883 +2 6 6877 6875 6879 6880 5043 5042 +2 6 6878 6875 5042 6863 6864 6873 +2 6 6877 6878 5043 5045 6881 6882 +2 6 6880 5045 6882 6887 6888 6889 +2 6 6880 6881 6877 6883 6886 6887 +2 6 6877 6882 6876 6884 6885 6886 +2 6 6876 6883 6885 7418 7420 7426 +2 6 6884 6883 6886 7426 7427 7428 +2 6 6885 6883 6882 6887 7428 7429 +2 6 6886 6882 6881 6888 7429 7430 +2 6 6887 6881 6889 6890 7430 7433 +2 6 6888 6881 5045 6890 4645 4644 +2 6 6888 6889 4645 4646 6891 7433 +2 6 6890 4646 4647 6892 7433 6893 +2 6 6891 4647 4253 4254 4730 6893 +2 6 6892 4730 6894 7433 6891 7432 +2 6 6893 4730 4731 6895 6897 7432 +2 6 6894 4731 6896 6897 6898 6899 +2 6 6895 4731 4732 6899 6900 6901 +2 6 6894 6895 6898 7432 7431 7434 +2 6 6897 6895 6899 7434 7435 7436 +2 6 6898 6895 6896 6900 7436 7437 +1 6 6899 6896 6901 7437 6904 6903 +2 6 6900 6896 4732 4262 6902 6903 +1 6 6901 4262 4263 4264 5231 6903 +1 6 6902 5231 5458 6904 6900 6901 +1 6 6903 5458 5459 6905 7437 6900 +1 6 6904 5459 6906 7437 7438 7439 +1 6 6905 5459 5460 6907 7439 7440 +1 6 6906 5460 5461 6908 7262 7440 +1 6 6907 5461 5462 6909 7262 7263 +1 6 6908 5462 6910 7263 7264 6911 +1 6 6909 5462 5463 5464 5465 6911 +1 6 6910 5465 6912 7264 6909 7265 +1 6 6911 5465 5466 6913 7265 7266 +1 6 6912 5466 5467 6914 7266 7267 +1 6 6913 5467 6915 7267 7268 7269 +1 6 6914 5467 5468 6916 6917 7269 +1 6 6915 5468 5469 5470 5471 6917 +1 6 6915 6916 5471 6918 7269 7270 +1 6 6917 5471 5472 6919 7270 7271 +1 6 6918 5472 5473 6920 7271 7272 +1 6 6919 5473 5474 5475 6921 7272 +1 6 6920 5475 6922 7274 7272 7275 +1 6 6921 5475 5476 6923 7275 7276 +1 6 6922 5476 5477 6924 7276 7277 +1 6 6923 5477 5478 6925 7277 7278 +1 6 6924 5478 5479 6926 7278 7279 +1 6 6925 5479 5480 5654 6927 7279 +1 6 6926 5654 5655 6928 7281 7279 +1 6 6927 5655 6929 7281 7282 7283 +1 6 6928 5655 5656 5657 6930 7283 +1 6 6929 5657 6931 7283 7284 7285 +1 6 6930 5657 5658 5831 6932 7285 +1 6 6931 5831 6933 7285 7286 7287 +1 6 6932 5831 5832 5840 6934 7287 +1 6 6933 5840 5841 6935 6936 7287 +1 6 6934 5841 5843 6936 6937 6018 +1 6 6934 6935 6937 6938 7287 7288 +1 6 6936 6935 6018 6938 6939 6940 +1 6 6936 6937 6939 7288 7289 7290 +1 6 6938 6937 6940 7290 7291 6941 +1 6 6939 6937 6018 5845 5847 6941 +1 6 6940 5847 6942 6943 7291 6939 +1 6 6941 5847 6943 6944 6945 5848 +1 6 6941 6942 6944 7291 7292 7293 +1 6 6943 6942 6945 7293 7294 7295 +1 7 6944 6942 5848 5850 6385 6946 7295 +1 6 6945 6385 6386 6947 7295 7296 +1 6 6946 6386 6387 6388 6948 7296 +1 6 6947 6388 6389 6949 7296 7297 +1 7 6948 6389 6391 6395 6950 7297 7298 +1 6 6949 6395 6951 7298 7300 7301 +1 6 6950 6395 6396 6952 7043 7301 +1 6 6951 6396 6399 6953 7043 7044 +1 6 6952 6399 6400 6954 6955 7044 +1 6 6953 6400 6401 6955 6956 6960 +1 6 6953 6954 6956 6957 7044 7045 +1 6 6955 6954 6957 6958 6959 6960 +1 6 6955 6956 6958 7045 7048 7049 +1 6 6957 6956 6959 6961 6962 7049 +1 6 6958 6956 6960 6410 6411 6961 +1 6 6959 6956 6954 6401 6402 6410 +1 6 6959 6411 6958 6962 6963 6412 +1 6 6958 6961 6963 7051 7049 7052 +1 6 6962 6961 6412 6414 6964 7052 +1 6 6963 6414 6416 6559 6965 7052 +1 6 6964 6559 6561 6966 7052 6971 +1 6 6965 6561 6967 6968 6970 6971 +1 6 6966 6561 6968 6969 6562 6983 +1 6 6966 6967 6969 6970 6974 6975 +1 6 6968 6967 6981 6975 6982 6983 +1 6 6966 6968 6971 6972 6973 6974 +1 6 6966 6970 6972 7052 6965 7051 +1 6 6971 6970 6973 7051 7050 7053 +1 6 6972 6970 6974 7062 7053 7063 +1 6 6973 6970 6968 6975 6976 7063 +1 6 6974 6968 6976 6977 6981 6969 +1 6 6974 6975 6977 6978 7063 7064 +1 6 6976 6975 6978 6979 6980 6981 +1 6 6976 6977 6979 7064 7065 7066 +1 6 6978 6977 6980 7066 7067 7071 +1 6 6979 6977 6981 7071 7072 7073 +1 6 6980 6977 6975 6969 6982 7073 +1 6 6981 6969 6983 6984 7073 7074 +1 6 6982 6969 6984 6985 6562 6967 +1 6 6982 6983 6985 7074 7075 7076 +1 6 6984 6983 6562 6563 6986 7076 +1 6 6985 6563 6567 6987 6988 7076 +1 6 6986 6567 6988 6989 6990 6568 +1 6 6986 6987 6989 6991 7076 7077 +1 6 6988 6987 6990 6991 6992 6996 +1 6 6989 6987 6996 6997 6570 6568 +1 6 6988 6989 6992 6993 7077 7078 +1 6 6991 6989 6993 6994 6995 6996 +1 6 6991 6992 6994 7078 7081 7082 +1 6 6993 6992 6995 7082 7085 7086 +1 6 6994 6992 6996 7086 7087 7088 +1 6 6995 6992 6989 6990 6997 7088 +1 6 6996 6990 6570 6998 6999 7088 +1 6 6997 6570 6999 7000 7001 6571 +1 6 6997 6998 7000 7088 7089 7092 +1 6 6999 6998 7001 7002 7092 7093 +1 6 7000 6998 7002 7003 6575 6571 +1 6 7000 7001 7003 7093 7094 7095 +1 6 7002 7001 6575 6576 7004 7095 +1 6 7003 6576 6578 7005 7095 7096 +1 6 7004 6578 7006 7096 7097 7098 +1 6 7005 6578 6579 7007 7012 7098 +1 6 7006 6579 6582 7008 7009 7012 +1 6 7007 6582 7009 6722 6720 6583 +1 6 7007 7008 6722 6724 7010 7012 +1 6 7009 6724 7011 7012 7013 7014 +1 6 7010 6724 7022 7020 7014 6725 +1 6 7009 7010 7007 7006 7013 7098 +1 6 7012 7010 7014 7015 7098 7099 +1 6 7013 7010 7015 7016 7020 7011 +1 6 7013 7014 7016 7017 7099 7100 +1 6 7015 7014 7017 7018 7019 7020 +1 6 7015 7016 7018 7107 7100 7113 +1 6 7017 7016 7019 7114 7113 7115 +1 6 7018 7016 7020 7021 7115 7116 +1 6 7019 7016 7014 7021 7022 7011 +1 6 7019 7020 7022 7024 7116 7117 +1 6 7021 7020 7011 6725 7023 7024 +1 6 7022 6725 6726 7024 7025 7026 +1 6 7021 7022 7023 7025 7117 7118 +1 6 7024 7023 7026 7118 7119 7120 +1 6 7025 7023 6726 7027 7028 7120 +1 6 7026 6726 6727 7028 7029 7030 +1 6 7026 7027 7029 7122 7120 7123 +1 6 7028 7027 7030 7123 7034 7031 +1 6 7029 7027 6727 6728 6729 7031 +1 6 7030 6729 7032 7034 7029 7033 +1 6 7031 6729 6730 6731 6732 7033 +1 6 7032 6732 6734 6735 7034 7031 +1 6 7033 6735 7035 7123 7029 7031 +1 5 7034 6735 6736 7036 7123 +1 6 7035 6736 6740 7037 7123 7122 +1 7 7036 6740 6741 7038 7122 7124 7125 +1 6 7037 6741 7039 7135 7125 7136 +1 6 7038 6741 6742 7040 7136 7137 +1 6 7039 6742 6743 7041 7137 7138 +1 5 7040 6743 6754 7141 7138 +1 6 6754 6743 6744 6746 6750 6752 +1 6 6951 6952 7044 7301 7302 7046 +1 6 7043 6952 6953 6955 7045 7046 +1 6 7044 6955 6957 7046 7047 7048 +1 6 7044 7045 7047 7302 7043 7303 +1 6 7046 7045 7048 7303 7056 7054 +1 6 7047 7045 6957 7049 7050 7054 +1 6 7048 6957 7050 7051 6962 6958 +1 6 7048 7049 7051 6972 7053 7054 +1 6 7050 7049 6962 7052 6971 6972 +1 6 7051 6962 6963 6964 6965 6971 +1 6 7050 6972 7054 7055 7062 6973 +1 6 7050 7053 7055 7056 7047 7048 +1 6 7054 7053 7056 7057 7058 7062 +1 6 7054 7055 7057 7303 7047 7304 +1 6 7056 7055 7058 7059 7307 7304 +1 6 7057 7055 7059 7060 7061 7062 +1 6 7057 7058 7060 7307 7476 7477 +1 6 7059 7058 7061 7477 7478 7479 +1 6 7060 7058 7062 7063 7064 7479 +1 6 7061 7058 7055 7053 6973 7063 +1 6 7062 6973 6974 6976 7061 7064 +1 6 7061 7063 6976 6978 7065 7479 +1 6 7064 6978 7066 7479 7480 7481 +1 6 7065 6978 6979 7067 7068 7481 +1 6 7066 6979 7068 7069 7070 7071 +1 6 7066 7067 7069 7483 7481 7462 +1 6 7068 7067 7070 7462 7484 7485 +1 6 7069 7067 7071 7485 7486 7487 +1 6 7070 7067 6979 6980 7072 7487 +1 6 7071 6980 7073 7487 7488 7492 +1 6 7072 6980 6981 6982 7074 7492 +1 6 7073 6982 6984 7075 7493 7492 +1 6 7074 6984 7076 7493 7079 7077 +1 6 7075 6984 6985 6986 6988 7077 +1 6 7076 6988 6991 7078 7079 7075 +1 6 7077 6991 6993 7079 7080 7081 +1 6 7077 7078 7080 7691 7493 7075 +1 6 7079 7078 7081 7223 7224 7691 +1 6 7080 7078 6993 7082 7083 7223 +1 6 7081 6993 6994 7083 7084 7085 +1 6 7081 7082 7084 7226 7223 7227 +1 6 7083 7082 7085 7227 7228 7229 +1 6 7084 7082 6994 7086 7232 7229 +1 6 7085 6994 6995 7087 7232 7233 +1 6 7086 6995 7088 7089 7090 7233 +1 6 7087 6995 6996 6997 6999 7089 +1 6 7088 6999 7087 7090 7091 7092 +1 6 7087 7089 7091 7233 7234 7235 +1 6 7090 7089 7092 7235 7236 7237 +1 6 7091 7089 6999 7000 7093 7237 +1 6 7092 7000 7002 7094 7237 7238 +1 6 7093 7002 7095 7238 7239 7103 +1 6 7094 7002 7003 7004 7096 7103 +1 6 7095 7004 7005 7097 7102 7103 +1 6 7096 7005 7098 7099 7101 7102 +1 6 7097 7005 7006 7012 7013 7099 +1 6 7098 7013 7015 7100 7101 7097 +1 6 7099 7015 7101 7106 7107 7017 +1 6 7099 7100 7097 7102 7105 7106 +1 6 7097 7101 7096 7103 7104 7105 +1 6 7096 7102 7104 7239 7094 7095 +1 6 7103 7102 7105 7241 7239 7242 +1 6 7104 7102 7101 7106 7242 7243 +1 6 7105 7101 7100 7107 7108 7243 +1 6 7106 7100 7017 7108 7109 7113 +1 6 7106 7107 7109 7110 7243 7244 +1 6 7108 7107 7110 7111 7112 7113 +1 6 7108 7109 7111 7247 7244 7248 +1 6 7110 7109 7112 7248 7249 7250 +1 6 7111 7109 7113 7114 7250 7251 +1 6 7112 7109 7114 7018 7017 7107 +1 6 7112 7113 7018 7115 7251 7254 +1 6 7114 7018 7019 7116 7254 7255 +1 6 7115 7019 7021 7117 7258 7255 +1 6 7116 7021 7024 7118 7258 7259 +1 6 7117 7024 7025 7119 7259 7128 +1 6 7118 7025 7120 7121 7127 7128 +1 6 7119 7025 7121 7122 7028 7026 +1 6 7119 7120 7122 7124 7126 7127 +1 7 7121 7120 7028 7123 7036 7037 7124 +1 6 7122 7028 7029 7034 7035 7036 +1 5 7122 7037 7125 7126 7121 +1 5 7124 7037 7126 7135 7038 +1 7 7124 7125 7121 7127 7130 7131 7135 +1 6 7121 7126 7119 7128 7129 7130 +1 6 7119 7127 7129 7261 7259 7118 +1 6 7128 7127 7130 7261 7532 7530 +1 6 7129 7127 7126 7131 7132 7532 +1 6 7130 7126 7132 7133 7134 7135 +1 6 7130 7131 7133 7532 7531 7533 +1 6 7132 7131 7134 7533 7534 7535 +1 6 7133 7131 7135 7535 7536 7136 +1 6 7134 7131 7126 7125 7038 7136 +1 6 7135 7038 7039 7137 7536 7134 +1 6 7136 7039 7040 7138 7139 7536 +1 6 7137 7040 7139 7140 7141 7041 +1 6 7137 7138 7140 7148 7150 7536 +1 6 7139 7138 7141 7142 7147 7148 +1 7 7140 7138 7041 6754 6755 6759 7142 +1 6 7140 7141 6759 6760 7143 7147 +1 6 7142 6760 7144 7145 7146 7147 +1 7 7143 6760 7145 4552 4551 6763 6761 +1 5 7143 7144 4552 4554 7146 +1 6 7145 4554 4556 7143 7147 7148 +1 5 7143 7146 7148 7140 7142 +1 7 7147 7146 4556 7140 7139 7149 7150 +1 6 7148 4556 7150 7151 7152 7153 +1 6 7148 7149 7139 7151 7536 7535 +1 6 7150 7149 7152 7535 7534 7537 +1 6 7151 7149 7153 7154 7155 7537 +1 6 7152 7149 7154 4649 4555 4556 +1 6 7152 7153 7155 7156 7166 4649 +1 6 7152 7154 7156 7157 7537 7538 +1 6 7155 7154 7157 7158 7159 7166 +1 6 7155 7156 7158 7538 7539 7554 +1 6 7157 7156 7159 7160 7554 7555 +1 6 7158 7156 7160 7161 7162 7166 +1 6 7158 7159 7161 7163 7167 7555 +1 6 7160 7159 7162 7163 4137 7164 +1 5 7161 7159 7164 7165 7166 +1 6 7160 7161 4137 7167 7168 4138 +1 7 4137 7161 7162 7165 4413 4134 4135 +1 5 7164 7162 4413 4415 7166 +1 7 4415 7165 7162 7159 7156 7154 4649 +1 6 7160 7163 7168 7555 7556 7560 +1 7 7167 7163 4138 7169 7560 7561 7562 +1 5 7168 4138 4139 7170 7562 +2 7 7169 4139 4140 7171 7562 7563 7564 +2 6 7170 4140 4124 7172 7173 7564 +2 6 7171 4124 7173 7174 4122 9789 +2 6 7171 7172 7174 7175 7176 7564 +2 6 7173 7172 7175 9788 9787 9789 +2 6 7173 7174 7176 7177 7178 9788 +2 7 7173 7175 7177 7564 7563 7568 7569 +2 6 7176 7175 7178 7179 7180 7569 +2 6 7177 7175 7179 9788 3535 3537 +2 6 7177 7178 7180 7181 7182 3537 +2 6 7177 7179 7181 7570 7569 7571 +2 6 7180 7179 7182 7571 7572 7573 +2 6 7181 7179 3537 3538 7183 7573 +2 6 7182 3538 7184 7575 7573 7187 +2 6 7183 3538 3539 7185 7186 7187 +2 6 7184 3539 7186 7211 7210 7212 +2 6 7184 7185 7187 7188 7211 7192 +2 6 7184 7186 7188 7189 7575 7183 +2 6 7187 7186 7189 7190 7191 7192 +2 6 7187 7188 7190 7575 7576 7579 +2 6 7189 7188 7191 7193 7579 7580 +2 6 7190 7188 7192 7193 7194 7198 +2 6 7191 7188 7198 7199 7211 7186 +2 6 7190 7191 7194 7195 7580 7581 +2 6 7193 7191 7195 7196 7197 7198 +2 6 7193 7194 7196 7581 7582 7583 +2 6 7195 7194 7197 7583 3196 3195 +2 6 7196 7194 7198 3195 7200 7203 +2 6 7197 7194 7191 7192 7199 7200 +2 6 7198 7192 7200 7201 7211 7208 +2 6 7198 7199 7201 7202 7203 7197 +2 6 7200 7199 7202 7206 7207 7208 +2 6 7200 7201 7203 7204 7205 7206 +2 6 7200 7202 7204 3194 3195 7197 +2 6 7203 7202 7205 7220 7221 3194 +2 6 7204 7202 7206 9745 7218 7220 +2 6 7205 7202 7201 7207 9745 9746 +2 6 7206 7201 7208 7209 9746 7213 +2 6 7207 7201 7209 7210 7211 7199 +2 6 7207 7208 7210 4373 4374 7213 +2 6 7209 7208 7211 7185 7212 4373 +2 6 7210 7208 7199 7192 7186 7185 +2 6 7210 7185 3539 3540 4372 4373 +2 6 7209 4374 4375 7214 9746 7207 +2 6 7213 4375 4377 7215 7216 9746 +2 6 7214 4377 7216 2863 1627 2862 +2 6 7214 7215 2863 7217 9745 9746 +2 6 7216 2863 2864 2865 7218 9745 +2 6 7217 2865 7219 7220 7205 9745 +2 5 7218 2865 7220 3214 2866 +2 6 7218 7219 3214 7221 7205 7204 +2 6 7220 3214 3215 7222 3194 7204 +2 5 7221 3215 3216 3193 3194 +1 6 7080 7081 7224 7225 7226 7083 +1 6 7080 7223 7225 7691 7690 7692 +1 6 7224 7223 7226 7692 7693 7674 +1 6 7225 7223 7083 7227 7674 7694 +1 6 7226 7083 7084 7228 7694 7695 +1 6 7227 7084 7229 7230 7695 7696 +1 6 7228 7084 7230 7231 7232 7085 +1 6 7228 7229 7231 7696 7697 7701 +1 6 7230 7229 7232 7701 7702 7703 +1 6 7231 7229 7085 7086 7233 7703 +1 6 7232 7086 7087 7090 7234 7703 +1 6 7233 7090 7235 7718 7704 7703 +1 6 7234 7090 7091 7236 7718 7717 +1 6 7235 7091 7237 7717 7719 7720 +1 6 7236 7091 7092 7093 7238 7720 +1 6 7237 7093 7094 7239 7240 7720 +1 6 7238 7094 7103 7240 7241 7104 +1 6 7238 7239 7241 7720 7721 7722 +1 6 7240 7239 7104 7242 7722 7725 +1 6 7241 7104 7105 7243 7245 7725 +1 6 7242 7105 7106 7108 7244 7245 +1 6 7243 7108 7245 7246 7247 7110 +1 6 7243 7244 7246 7728 7725 7242 +1 6 7245 7244 7247 7964 7728 7965 +1 6 7246 7244 7110 7248 7965 7966 +1 6 7247 7110 7111 7249 7966 7967 +1 6 7248 7111 7250 7511 7967 7968 +1 6 7249 7111 7112 7251 7252 7511 +1 6 7250 7112 7114 7252 7253 7254 +1 6 7250 7251 7253 7511 7512 7516 +1 6 7252 7251 7254 7256 9775 7516 +1 6 7253 7251 7114 7115 7255 7256 +1 6 7254 7115 7256 7257 7258 7116 +1 6 7254 7255 7257 7523 7253 9775 +1 6 7256 7255 7258 7260 7524 7523 +1 6 7257 7255 7116 7117 7259 7260 +1 6 7258 7117 7118 7260 7261 7128 +1 6 7258 7259 7261 7529 7524 7257 +1 6 7260 7259 7128 7129 7530 7529 +1 6 6907 6908 7263 7440 7442 7443 +1 6 7262 6908 6909 7264 7443 7444 +1 6 7263 6909 6911 7265 7444 7445 +1 6 7264 6911 6912 7266 7445 7446 +1 6 7265 6912 6913 7267 7449 7446 +1 6 7266 6913 6914 7268 7449 7450 +1 6 7267 6914 7269 7450 7451 7452 +1 6 7268 6914 6915 6917 7270 7452 +1 6 7269 6917 6918 7271 7452 7453 +1 6 7270 6918 6919 7272 7273 7453 +1 6 7271 6919 7273 7274 6921 6920 +1 6 7271 7272 7274 7453 7454 7455 +1 6 7273 7272 6921 7275 7455 7456 +1 6 7274 6921 6922 7276 7456 7457 +1 6 7275 6922 6923 7277 7457 7458 +1 6 7276 6923 6924 7278 7458 7459 +1 6 7277 6924 6925 7279 7280 7459 +1 6 7278 6925 7280 7281 6927 6926 +1 6 7278 7279 7281 7459 7460 7464 +1 6 7280 7279 6927 6928 7282 7464 +1 6 7281 6928 7283 7464 7465 7466 +1 6 7282 6928 6929 6930 7284 7466 +1 6 7283 6930 7285 7466 7467 7468 +1 6 7284 6930 6931 6932 7286 7468 +1 6 7285 6932 7287 7468 7469 7288 +1 6 7286 6932 6933 6934 6936 7288 +1 6 7287 6936 6938 7289 7469 7286 +1 6 7288 6938 7290 7469 7470 7471 +1 6 7289 6938 6939 7291 7471 7472 +1 6 7290 6939 6941 6943 7292 7472 +1 6 7291 6943 7293 7472 7473 7474 +1 6 7292 6943 6944 7294 7474 7299 +1 6 7293 6944 7295 7297 7298 7299 +1 6 7294 6944 6945 6946 7296 7297 +1 5 7295 6946 6947 6948 7297 +1 6 7296 6948 6949 7295 7294 7298 +1 6 7294 7297 6949 6950 7299 7300 +1 5 7294 7298 7300 7474 7293 +1 7 7299 7298 6950 7301 7474 7305 7302 +1 5 7300 6950 6951 7043 7302 +1 6 7301 7043 7046 7303 7305 7300 +1 6 7302 7046 7047 7056 7304 7305 +1 6 7303 7056 7305 7306 7307 7057 +1 6 7303 7304 7306 7474 7300 7302 +1 6 7305 7304 7307 7474 7473 7475 +1 6 7306 7304 7057 7059 7475 7476 +1 5 4702 4703 7309 7855 7856 +1 6 7308 4703 4704 7310 7856 7857 +1 6 7309 4704 4705 7311 7857 7858 +1 6 7310 4705 4706 7312 7858 7859 +1 6 7311 4706 4707 5170 7313 7859 +1 6 7312 5170 7314 7859 7860 7861 +1 6 7313 5170 5171 7315 7861 7862 +1 6 7314 5171 5172 7316 7862 7863 +1 6 7315 5172 5173 7317 7863 7864 +1 6 7316 5173 5174 7318 7864 7865 +1 6 7317 5174 5175 7319 7865 7866 +1 6 7318 5175 5176 7320 7866 7867 +1 6 7319 5176 5177 5178 7321 7867 +1 6 7320 5178 7322 7867 7868 7869 +1 6 7321 5178 5179 7323 7869 7870 +1 6 7322 5179 5180 5411 7324 7870 +1 6 7323 5411 7325 7870 7871 7872 +1 6 7324 5411 5412 7326 7872 7873 +1 6 7325 5412 5413 5414 7327 7873 +1 6 7326 5414 7328 7873 7874 7875 +1 6 7327 5414 5415 5416 7329 7875 +1 6 7328 5416 7330 7875 7876 7877 +1 6 7329 5416 5417 5418 7331 7877 +1 6 7330 5418 6791 7332 7877 7878 +1 6 7331 6791 7333 7878 7879 7880 +1 6 7332 6791 6792 6793 7334 7880 +1 6 7333 6793 6794 7335 7880 7881 +1 6 7334 6794 6795 6796 7336 7881 +1 6 7335 6796 6797 7337 7881 7882 +1 6 7336 6797 6798 7338 7882 7883 +1 6 7337 6798 6799 7339 7883 7884 +1 6 7338 6799 6800 7340 7884 7885 +1 6 7339 6800 6801 7341 7885 7886 +1 6 7340 6801 7342 7886 7887 7888 +1 6 7341 6801 6802 6803 7343 7888 +1 6 7342 6803 6804 7344 7888 7889 +1 6 7343 6804 6805 7345 7889 7890 +1 6 7344 6805 6806 7346 7890 7891 +1 6 7345 6806 6807 7347 7891 7892 +1 6 7346 6807 6808 7348 7892 7893 +1 6 7347 6808 7349 7893 7894 7895 +1 7 7348 6808 6809 6811 6812 7350 7895 +1 6 7349 6812 6813 7351 7895 7896 +1 6 7350 6813 6814 7352 7896 7897 +1 5 7351 6814 6815 7353 7897 +1 7 7352 6815 6816 7354 7897 7898 7899 +1 5 7353 6816 6817 7355 7899 +2 7 7354 6817 6818 7356 7899 7900 7901 +2 6 7355 6818 7357 7901 7902 7903 +2 7 7356 6818 6819 6820 6821 7358 7903 +2 6 7357 6821 7359 7903 7904 7905 +2 6 7358 6821 6822 7360 7361 7905 +2 6 7359 6822 6823 7361 7362 6825 +2 6 7359 7360 7362 7905 7906 7907 +2 6 7361 7360 6825 6828 7363 7907 +2 6 7362 6828 7364 7907 7908 7909 +2 5 7363 6828 6829 7365 7909 +2 7 7364 6829 7366 7369 7371 7909 7910 +2 6 7365 6829 6830 6831 7367 7369 +2 6 7366 6831 7368 7369 7370 7375 +2 5 7367 6831 7375 6835 6834 +2 6 7366 7367 7370 7365 7371 7372 +2 6 7369 7367 7372 7373 7374 7375 +2 6 7365 7369 7372 7910 7911 7912 +2 6 7371 7369 7370 7373 7912 7913 +2 6 7372 7370 7374 7913 7914 7915 +2 6 7373 7370 7375 6836 7376 7915 +2 6 7374 7370 7367 7368 6835 6836 +2 6 7374 6836 7377 7915 7916 7917 +2 6 7376 6836 6837 6838 7378 7917 +2 5 7377 6838 7379 7601 7917 +2 6 7378 6838 6839 6841 7380 7601 +2 6 7379 6841 6842 7381 7601 7602 +2 6 7380 6842 6843 7382 7605 7602 +2 6 7381 6843 7383 7384 7605 7606 +2 6 7382 6843 7384 6847 6845 6844 +2 6 7382 7383 6847 7385 7606 7607 +2 6 7384 6847 6848 7386 7607 7392 +2 6 7385 6848 7387 7388 7391 7392 +2 6 7386 6848 6849 6850 6851 7388 +2 6 7387 6851 6854 7389 7391 7386 +2 6 7388 6854 6855 6859 7390 7391 +2 6 7389 6859 7391 7396 7393 7397 +2 6 7389 7390 7388 7386 7392 7393 +2 6 7386 7391 7393 7394 7607 7385 +2 6 7392 7391 7394 7395 7396 7390 +2 6 7392 7393 7395 7607 7608 7611 +2 6 7394 7393 7396 7611 7612 7622 +2 6 7395 7393 7390 7397 7622 7623 +2 6 7396 7390 6859 6860 7398 7623 +2 5 7397 6860 7399 7623 7624 +2 6 7398 6860 6861 7400 7624 7625 +2 7 7399 6861 6862 6865 7401 7625 7626 +2 6 7400 6865 6867 7402 7403 7626 +2 6 7401 6867 7403 7404 7405 6869 +2 6 7401 7402 7404 7626 7627 7628 +2 6 7403 7402 7405 7408 7628 7629 +2 6 7404 7402 6869 7406 7407 7408 +2 6 7405 6869 7407 7411 7412 6870 +2 6 7405 7406 7408 7409 7410 7411 +2 6 7405 7407 7404 7409 7632 7629 +2 6 7408 7407 7410 7632 7633 7634 +2 6 7409 7407 7411 7634 7635 7642 +2 6 7410 7407 7406 7412 7642 7643 +2 6 7411 7406 6870 7413 7414 7643 +2 6 7412 6870 7414 7415 7416 6871 +2 6 7412 7413 7415 7643 7644 7645 +2 6 7414 7413 7416 7417 7645 7646 +2 6 7415 7413 7417 7418 7419 6871 +2 6 7415 7416 7418 7420 7421 7646 +2 7 7417 7416 7419 6874 6876 6884 7420 +2 5 7418 7416 6871 6872 6874 +2 6 7418 6884 7417 7421 7422 7426 +2 6 7417 7420 7422 7423 7646 7647 +2 6 7421 7420 7423 7424 7425 7426 +1 6 7421 7422 7424 7647 7648 7649 +1 6 7423 7422 7425 7649 7650 7651 +2 6 7424 7422 7426 7651 7652 7427 +2 6 7425 7422 7420 6884 6885 7427 +2 6 7426 6885 7428 7652 7425 7653 +2 6 7427 6885 6886 7429 7653 7654 +2 6 7428 6886 6887 7430 7431 7654 +2 6 7429 6887 6888 7431 7432 7433 +2 6 7429 7430 7432 6897 7434 7654 +2 6 7431 7430 7433 6893 6894 6897 +2 6 7432 7430 6888 6890 6891 6893 +2 6 7431 6897 6898 7435 7655 7654 +2 6 7434 6898 7436 7655 7656 7660 +1 6 7435 6898 6899 7437 7660 7438 +1 6 7436 6899 6900 6904 6905 7438 +1 6 7437 6905 7439 7660 7436 7661 +1 6 7438 6905 6906 7440 7441 7661 +1 6 7439 6906 6907 7262 7441 7442 +1 6 7439 7440 7442 7661 7662 7663 +1 6 7441 7440 7262 7443 7663 7664 +1 6 7442 7262 7263 7444 7664 7665 +1 6 7443 7263 7264 7445 7665 7666 +1 6 7444 7264 7265 7446 7447 7666 +1 6 7445 7265 7447 7448 7449 7266 +1 6 7445 7446 7448 7668 7666 7671 +1 6 7447 7446 7449 7671 7676 7673 +1 6 7448 7446 7266 7267 7450 7676 +1 6 7449 7267 7268 7451 7676 7677 +1 6 7450 7268 7452 7677 7678 7682 +1 6 7451 7268 7269 7270 7453 7682 +1 6 7452 7270 7271 7273 7454 7682 +1 6 7453 7273 7455 7682 7681 7683 +1 6 7454 7273 7274 7456 7686 7683 +1 6 7455 7274 7275 7457 7686 7687 +1 6 7456 7275 7276 7458 7687 7688 +1 6 7457 7276 7277 7459 7688 7461 +1 6 7458 7277 7278 7280 7460 7461 +1 6 7459 7280 7461 7462 7463 7464 +1 6 7459 7460 7462 7688 7458 7484 +1 7 7461 7460 7463 7483 7068 7069 7484 +1 6 7462 7460 7464 7483 7482 7465 +1 6 7463 7460 7280 7281 7282 7465 +1 6 7464 7282 7466 7482 7463 7494 +1 6 7465 7282 7283 7284 7467 7494 +1 6 7466 7284 7468 7494 7495 7496 +1 6 7467 7284 7285 7286 7469 7496 +1 6 7468 7286 7288 7289 7470 7496 +1 6 7469 7289 7471 7496 7497 7498 +1 6 7470 7289 7290 7472 7498 7475 +1 6 7471 7290 7291 7292 7473 7475 +1 5 7472 7292 7474 7306 7475 +1 7 7473 7292 7293 7299 7300 7305 7306 +1 7 7473 7306 7307 7476 7498 7471 7472 +1 5 7475 7307 7059 7477 7498 +1 6 7476 7059 7060 7478 7497 7498 +1 7 7477 7060 7479 7480 7497 7495 7499 +1 6 7478 7060 7061 7064 7065 7480 +1 6 7478 7479 7065 7481 7482 7499 +1 6 7480 7065 7482 7483 7068 7066 +1 7 7480 7481 7483 7463 7465 7494 7499 +1 5 7482 7481 7068 7462 7463 +1 5 7462 7069 7485 7688 7461 +1 6 7484 7069 7070 7486 7687 7688 +1 6 7485 7070 7487 7686 7687 7685 +1 7 7486 7070 7071 7072 7488 7489 7685 +1 6 7487 7072 7489 7490 7491 7492 +1 5 7487 7488 7490 7685 7684 +1 6 7489 7488 7491 7684 7689 7690 +1 6 7490 7488 7492 7493 7690 7691 +1 6 7491 7488 7493 7074 7073 7072 +1 6 7491 7492 7074 7075 7691 7079 +1 6 7482 7465 7466 7467 7495 7499 +1 6 7494 7467 7496 7497 7478 7499 +1 6 7495 7467 7468 7469 7470 7497 +1 6 7496 7470 7498 7477 7478 7495 +1 6 7497 7470 7471 7477 7476 7475 +1 5 7495 7478 7480 7482 7494 +1 6 427 5612 5613 7501 7502 9768 +1 6 7500 5613 7502 7503 7504 7505 +1 6 7500 7501 7503 9768 9769 9770 +1 6 7502 7501 7504 6474 9770 9780 +1 5 7503 7501 6474 6472 7505 +1 7 6472 7504 7501 5613 5614 7506 6470 +1 5 7505 5614 7507 6469 6470 +1 6 7506 5614 5615 7508 7509 6469 +1 6 7507 5615 7509 7510 9734 4518 +1 5 7507 7508 7510 6469 6468 +1 6 7509 7508 6468 9732 9733 9734 +1 6 7249 7250 7252 7512 7513 7968 +1 6 7511 7252 7513 7514 7515 7516 +1 6 7511 7512 7514 7968 7969 7970 +1 6 7513 7512 7515 7970 7971 7972 +1 6 7514 7512 7516 7517 7518 7972 +1 6 7515 7512 7252 7517 9775 7253 +1 6 7515 7516 7518 7519 7520 9775 +1 6 7515 7517 7519 7972 7973 7977 +1 6 7518 7517 7520 7521 7977 7978 +1 6 7519 7517 7521 7522 7523 9775 +1 6 7519 7520 7522 7989 7978 7526 +1 6 7521 7520 7523 7524 7525 7526 +1 6 7522 7520 7524 7256 7257 9775 +1 6 7522 7523 7525 7260 7529 7257 +1 6 7522 7524 7526 7527 7528 7529 +1 6 7522 7525 7527 7989 7521 7990 +1 6 7526 7525 7528 7990 7546 7545 +1 6 7527 7525 7529 7530 7531 7545 +1 6 7528 7525 7530 7261 7260 7524 +1 6 7528 7529 7261 7531 7532 7129 +1 7 7528 7530 7532 7132 7533 7543 7545 +1 5 7531 7530 7129 7130 7132 +1 6 7531 7132 7133 7534 7544 7543 +1 6 7533 7133 7535 7151 7537 7544 +1 6 7534 7133 7134 7536 7150 7151 +1 6 7535 7134 7136 7137 7139 7150 +1 6 7534 7151 7152 7155 7538 7544 +1 6 7537 7155 7157 7539 7540 7544 +1 6 7538 7157 7540 7541 7553 7554 +1 6 7538 7539 7541 7542 7543 7544 +1 6 7540 7539 7542 7547 7553 7550 +1 6 7540 7541 7543 7545 7546 7547 +1 6 7540 7542 7544 7533 7531 7545 +1 6 7540 7543 7533 7534 7537 7538 +1 6 7531 7543 7542 7546 7527 7528 +1 6 7545 7542 7547 7548 7990 7527 +1 6 7546 7542 7541 7548 7549 7550 +1 6 7546 7547 7549 7990 7989 7991 +1 6 7548 7547 7550 7551 7991 7992 +1 6 7549 7547 7551 7552 7553 7541 +1 6 7549 7550 7552 7992 7994 7995 +1 7 7551 7550 7553 7557 7556 7558 7995 +1 6 7552 7550 7541 7539 7554 7557 +1 6 7553 7539 7157 7158 7555 7557 +1 6 7554 7158 7160 7167 7556 7557 +1 7 7555 7167 7557 7552 7558 7559 7560 +1 5 7555 7556 7554 7553 7552 +2 5 7552 7556 7559 7995 7996 +2 7 7558 7556 7560 7996 7999 7566 7561 +1 5 7559 7556 7167 7168 7561 +2 6 7560 7168 7562 7565 7566 7559 +2 6 7561 7168 7169 7170 7563 7565 +2 6 7562 7170 7564 7176 7565 7568 +2 5 7563 7170 7171 7173 7176 +2 6 7562 7563 7561 7566 7567 7568 +2 6 7561 7565 7567 7999 7559 8000 +2 6 7566 7565 7568 7569 7570 8000 +2 5 7567 7565 7563 7176 7569 +2 6 7568 7176 7567 7570 7180 7177 +2 6 7567 7569 7180 7571 8000 8001 +2 6 7570 7180 7181 7572 8001 8002 +2 6 7571 7181 7573 7574 8002 8003 +2 6 7572 7181 7574 7575 7183 7182 +2 6 7572 7573 7575 7576 7577 8003 +2 6 7574 7573 7183 7187 7189 7576 +2 6 7575 7189 7574 7577 7578 7579 +2 6 7574 7576 7578 8003 8004 8005 +2 6 7577 7576 7579 8005 8006 8007 +2 6 7578 7576 7189 7190 7580 8007 +2 6 7579 7190 7193 7581 8007 8008 +2 6 7580 7193 7195 7582 8008 8009 +2 6 7581 7195 7583 7585 8012 8009 +2 6 7582 7195 7196 3196 7584 7585 +2 6 7583 3196 3186 7585 7586 3187 +2 6 7583 7584 7586 7587 7582 8012 +2 6 7585 7584 7587 7588 3958 3187 +2 6 7585 7586 7588 7729 8013 8012 +2 6 7587 7586 3958 3960 7589 7729 +2 6 7588 3960 7590 7729 7730 7731 +2 6 7589 3960 3961 7591 7731 7732 +2 6 7590 3961 7592 7738 7732 7739 +2 6 7591 3961 2890 2891 7593 7739 +2 6 7592 2891 7594 7595 7739 7740 +2 6 7593 2891 7595 7596 7597 2892 +2 6 7593 7594 7596 7740 7741 7745 +2 6 7595 7594 7597 7598 7745 7746 +2 6 7596 7594 7598 7599 7600 2892 +2 6 7596 7597 7599 4089 7746 7751 +2 5 7598 7597 7600 4089 4086 +2 6 7599 7597 4086 2880 2879 2892 +2 7 7378 7379 7380 7602 7603 7917 7918 +2 6 7601 7380 7603 7604 7605 7381 +2 6 7601 7602 7604 7926 7920 7918 +2 5 7603 7602 7605 7926 7927 +2 7 7604 7602 7381 7382 7606 7609 7927 +2 6 7605 7382 7384 7607 7608 7609 +2 6 7606 7384 7385 7392 7394 7608 +2 6 7607 7394 7606 7609 7610 7611 +2 6 7606 7608 7610 7929 7927 7605 +2 6 7609 7608 7611 7613 7616 7929 +2 6 7610 7608 7394 7395 7612 7613 +2 6 7611 7395 7613 7614 7621 7622 +2 6 7611 7612 7614 7615 7616 7610 +2 6 7613 7612 7615 7619 7620 7621 +2 6 7613 7614 7616 7617 7618 7619 +2 6 7613 7615 7617 8157 7929 7610 +2 6 7616 7615 7618 8155 8157 8156 +2 6 7617 7615 7619 8156 8158 8159 +2 6 7618 7615 7614 7620 8159 8160 +2 6 7619 7614 7621 8160 8161 8162 +2 6 7620 7614 7612 7622 8162 8163 +2 6 7621 7612 7395 7396 7623 8163 +2 6 7622 7396 7397 7398 7624 8163 +2 6 7623 7398 7399 7625 8163 8164 +2 6 7624 7399 7400 7626 8164 7627 +2 5 7625 7400 7401 7403 7627 +2 6 7626 7403 7628 8164 7625 8165 +2 6 7627 7403 7404 7629 7630 8165 +2 6 7628 7404 7630 7631 7632 7408 +2 6 7628 7629 7631 8165 8166 8167 +2 6 7630 7629 7632 8170 8167 8171 +2 6 7631 7629 7408 7409 7633 8171 +2 6 7632 7409 7634 8173 8171 8174 +2 6 7633 7409 7410 7635 7636 8174 +2 6 7634 7410 7636 7637 7641 7642 +2 6 7634 7635 7637 7638 8174 8175 +2 6 7636 7635 7638 7639 7640 7641 +2 6 7636 7637 7639 8175 8176 8177 +2 6 7638 7637 7640 8177 8178 8179 +2 6 7639 7637 7641 8179 8180 8181 +2 6 7640 7637 7635 7642 8181 8182 +2 6 7641 7635 7410 7411 7643 8182 +2 6 7642 7411 7412 7414 7644 8182 +2 6 7643 7414 7645 8183 8182 8184 +2 6 7644 7414 7415 7646 8184 8185 +2 6 7645 7415 7417 7421 7647 8185 +1 6 7646 7421 7423 7648 8185 8186 +1 6 7647 7423 7649 8186 8187 8188 +1 6 7648 7423 7424 7650 8188 8189 +1 6 7649 7424 7651 8189 8190 8191 +1 6 7650 7424 7425 7652 8191 8192 +2 6 7651 7425 7427 7653 8192 7657 +2 6 7652 7427 7428 7654 7655 7657 +2 6 7653 7428 7429 7655 7434 7431 +2 6 7653 7654 7434 7435 7656 7657 +2 6 7655 7435 7657 7658 7659 7660 +2 6 7655 7656 7658 8192 7652 7653 +1 6 7657 7656 7659 8192 8193 8194 +1 6 7658 7656 7660 8194 7662 7661 +1 6 7659 7656 7435 7436 7438 7661 +1 6 7660 7438 7439 7441 7662 7659 +1 6 7661 7441 7663 8194 7659 8195 +1 6 7662 7441 7442 7664 8208 8195 +1 6 7663 7442 7443 7665 8208 8207 +1 6 7664 7443 7444 7666 7667 8207 +1 6 7665 7444 7667 7668 7447 7445 +1 6 7665 7666 7668 7669 8206 8207 +1 6 7667 7666 7447 7669 7670 7671 +1 6 7667 7668 7670 7698 8206 9790 +1 6 7669 7668 7671 7672 7695 9790 +1 6 7670 7668 7447 7448 7672 7673 +1 6 7670 7671 7673 7674 7695 7694 +1 6 7672 7671 7674 7675 7676 7448 +1 7 7672 7673 7675 7693 7225 7226 7694 +1 6 7674 7673 7676 7677 7679 7693 +1 6 7675 7673 7448 7449 7450 7677 +1 6 7676 7450 7451 7678 7679 7675 +1 6 7677 7451 7679 7680 7681 7682 +1 7 7677 7678 7680 7675 7693 7692 7689 +1 5 7679 7678 7681 7689 7684 +1 6 7680 7678 7682 7454 7683 7684 +1 6 7681 7678 7451 7452 7453 7454 +1 6 7681 7454 7684 7685 7686 7455 +1 7 7681 7683 7685 7489 7490 7689 7680 +1 6 7684 7683 7686 7486 7487 7489 +1 6 7685 7683 7455 7456 7687 7486 +1 6 7686 7456 7457 7486 7485 7688 +1 6 7485 7687 7457 7458 7461 7484 +1 6 7684 7490 7690 7692 7679 7680 +1 6 7689 7490 7491 7691 7224 7692 +1 6 7690 7491 7493 7079 7080 7224 +1 6 7690 7224 7225 7693 7679 7689 +1 5 7692 7225 7674 7675 7679 +1 5 7674 7226 7227 7695 7672 +1 7 7694 7227 7228 7696 7670 7672 9790 +1 6 7695 7228 7230 7697 7698 9790 +1 6 7696 7230 7698 7699 7700 7701 +1 6 7696 7697 7699 8206 7669 9790 +1 6 7698 7697 7700 8205 8203 8206 +1 6 7699 7697 7701 8318 8205 7707 +1 6 7700 7697 7230 7231 7702 7707 +1 6 7701 7231 7703 7704 7705 7707 +1 6 7702 7231 7704 7234 7233 7232 +1 6 7702 7703 7705 7706 7718 7234 +1 6 7702 7704 7706 7707 7708 7709 +1 6 7705 7704 7709 7710 7711 7718 +1 6 7702 7705 7708 8318 7700 7701 +1 6 7707 7705 7709 8318 8481 8317 +1 6 7708 7705 7706 7710 8481 8482 +1 6 7709 7706 7711 7712 7713 8482 +1 6 7710 7706 7712 7716 7717 7718 +1 6 7710 7711 7713 7714 7715 7716 +1 6 7710 7712 7714 8482 8483 8484 +1 6 7713 7712 7715 8484 9765 8486 +1 6 7714 7712 7716 9765 7723 9767 +1 6 7715 7712 7711 7717 9767 7719 +1 6 7716 7711 7718 7235 7236 7719 +1 6 7717 7711 7706 7704 7234 7235 +1 6 7717 7236 7720 9767 7716 7721 +1 6 7719 7236 7237 7238 7240 7721 +1 6 7720 7240 7722 7723 9767 7719 +1 6 7721 7240 7241 7723 7724 7725 +1 7 7721 7722 7724 7726 9765 7715 9767 +1 6 7723 7722 7725 7726 7727 7728 +1 6 7724 7722 7728 7245 7242 7241 +1 6 7723 7724 7727 7962 9765 9764 +1 6 7726 7724 7728 7962 7963 7964 +1 6 7727 7724 7725 7245 7964 7246 +2 6 7587 7588 7589 7730 8013 8014 +2 6 7729 7589 7731 8014 8015 7734 +2 6 7730 7589 7590 7732 7733 7734 +2 6 7731 7590 7733 7737 7738 7591 +2 6 7731 7732 7734 7735 7736 7737 +2 6 7731 7733 7735 8015 7730 8016 +2 6 7734 7733 7736 8016 8017 8018 +2 6 7735 7733 7737 8018 8019 8020 +2 6 7736 7733 7732 7738 8020 8021 +2 6 7737 7732 7591 7739 9766 8021 +2 6 7738 7591 7592 7593 7740 9766 +2 6 7739 7593 7595 7741 7742 9766 +2 6 7740 7595 7742 7743 7744 7745 +2 6 7740 7741 7743 8025 8023 9766 +2 6 7742 7741 7744 8025 8026 8027 +2 6 7743 7741 7745 7747 7748 8027 +2 6 7744 7741 7595 7596 7746 7747 +2 6 7745 7596 7598 7747 7750 7751 +2 6 7745 7746 7744 7748 7749 7750 +2 6 7744 7747 7749 8027 8031 8032 +2 6 7748 7747 7750 8032 8036 7759 +2 6 7749 7747 7746 7751 7752 7759 +2 7 7750 7746 7598 4089 4090 7752 7753 +2 7 7750 7751 7753 4379 7754 7758 7759 +2 4 7752 7751 4090 4379 +2 5 7752 4379 4380 7755 7758 +2 6 7754 4380 4382 7756 7757 7758 +2 6 7755 4382 7757 7762 7763 7764 +2 6 7755 7756 7758 7760 7761 7762 +2 6 7755 7757 7754 7752 7759 7760 +2 6 7752 7758 7760 8036 7749 7750 +2 5 7759 7758 7757 7761 8036 +2 7 7760 7757 7762 8036 8640 8635 8035 +2 7 7761 7757 7756 7763 8852 8639 8640 +2 6 7762 7756 7764 7765 8852 8853 +2 6 7763 7756 4382 4383 4389 7765 +2 6 7763 7764 4389 7766 8319 8853 +2 6 7765 4389 4390 7767 8319 8320 +2 6 7766 4390 3142 7768 7769 8320 +2 6 7767 3142 7769 7770 7774 3143 +2 6 7767 7768 7770 7771 8322 8320 +2 6 7769 7768 7771 7772 7773 7774 +2 6 7769 7770 7772 8322 8323 8324 +2 6 7771 7770 7773 8324 8325 7777 +2 6 7772 7770 7774 7775 7776 7777 +2 6 7773 7770 7768 3143 3144 7775 +2 6 7774 3144 7773 7776 3145 9791 +2 6 7773 7775 7777 7778 3414 9791 +2 6 7773 7776 7778 8325 7772 8326 +2 6 7777 7776 3414 3415 7779 8326 +2 6 7778 3415 5382 5384 7780 8326 +2 6 7779 5384 5386 7781 8326 8327 +2 6 7780 5386 5388 7782 8329 8327 +2 6 7781 5388 5616 7783 8329 8330 +2 6 7782 5616 7784 8330 8331 8332 +2 6 7783 5616 5617 7785 8037 8332 +2 6 7784 5617 7786 7787 8037 8038 +2 6 7785 5617 5618 7787 7788 7789 +2 6 7785 7786 7788 8038 8039 8040 +2 6 7787 7786 7789 8045 8040 7794 +2 6 7788 7786 5618 5619 7790 7794 +2 6 7789 5619 7791 7792 7793 7794 +2 6 7790 5619 7792 3779 3778 5620 +2 6 7790 7791 7793 7797 7798 3779 +2 6 7790 7792 7794 7795 7796 7797 +2 6 7790 7793 7795 8045 7788 7789 +2 6 7794 7793 7796 8045 8046 8047 +2 6 7795 7793 7797 8048 8047 8049 +2 6 7796 7793 7792 7798 8049 7799 +2 6 7797 7792 3779 3780 3783 7799 +2 6 7798 3783 3784 7800 8049 7797 +2 6 7799 3784 3785 3788 7801 8049 +2 6 7800 3788 3790 7802 8048 8049 +2 6 7801 3790 3791 3793 7803 8048 +2 6 7802 3793 7804 7806 8047 8048 +2 6 7803 3793 3794 7805 7806 7807 +2 6 7804 3794 7807 7808 7809 3795 +2 6 7803 7804 7807 8046 8047 8343 +2 6 7806 7804 7805 7808 8344 8343 +2 6 7807 7805 7809 8344 8345 7930 +2 6 7808 7805 3795 3796 7810 7930 +1 6 7809 3796 3952 7811 7930 7931 +1 6 7810 3952 7812 7931 7932 7936 +1 6 7811 3952 3953 7813 7936 7937 +1 6 7812 3953 3954 7814 7937 7938 +1 6 7813 3954 7815 7938 7939 7816 +1 6 7814 3954 3955 3956 4238 7816 +1 6 7815 4238 4503 7817 7939 7814 +1 6 7816 4503 4504 7818 7939 7940 +1 6 7817 4504 7819 7940 7941 7942 +1 6 7818 4504 4505 7820 7942 7943 +1 6 7819 4505 4506 4507 7821 7943 +1 6 7820 4507 7822 7943 7944 7945 +1 6 7821 4507 4508 7823 7945 7946 +1 6 7822 4508 4509 7824 7946 7947 +1 6 7823 4509 7825 7826 7947 7948 +1 6 7824 4509 4510 7826 7827 7828 +1 6 7824 7825 7827 7948 7949 7950 +1 6 7826 7825 7828 7950 7951 7952 +1 6 7827 7825 4510 4419 7829 7952 +1 6 7828 4419 4247 7830 7952 7832 +1 6 7829 4247 4248 4739 7831 7832 +1 6 7830 4739 5003 7832 7833 7834 +1 6 7830 7831 7833 7952 7829 7953 +1 6 7832 7831 7834 7953 7954 7955 +1 6 7833 7831 5003 5004 7835 7955 +1 6 7834 5004 5005 7836 7955 7956 +1 6 7835 5005 7837 7956 7957 7958 +1 6 7836 5005 4750 4751 7838 7958 +1 6 7837 4751 4757 7839 7958 7959 +1 6 7838 4757 7840 7959 7960 7846 +1 6 7839 4757 4758 7841 7846 7961 +1 6 7840 4758 4661 4662 7842 7961 +1 6 7841 4662 4663 4689 7843 7961 +1 6 7842 4689 4690 7844 7961 7845 +1 6 7843 4690 4691 5158 5159 7845 +1 5 7844 5159 7846 7961 7843 +1 7 7845 5159 7847 7960 7839 7840 7961 +1 6 7846 5159 5160 7848 8082 7960 +1 6 7847 5160 5161 7849 8082 8083 +1 6 7848 5161 5162 7850 8083 8084 +1 6 7849 5162 7851 8084 8085 8086 +1 6 7850 5162 5163 5164 7852 8086 +1 6 7851 5164 7853 8086 8087 8088 +1 6 7852 5164 5165 7854 8088 8089 +1 7 7853 5165 4700 4701 4702 7855 8089 +1 5 7854 4702 7308 7856 8089 +1 7 7855 7308 7309 7857 8089 8090 8091 +1 7 7856 7309 7310 7858 8091 8092 8093 +1 6 7857 7310 7311 7859 8093 8094 +1 6 7858 7311 7312 7313 7860 8094 +1 6 7859 7313 7861 8094 8095 8096 +1 6 7860 7313 7314 7862 8096 8097 +1 6 7861 7314 7315 7863 8097 8098 +1 6 7862 7315 7316 7864 8098 8099 +1 6 7863 7316 7317 7865 8099 8100 +1 6 7864 7317 7318 7866 8100 8101 +1 6 7865 7318 7319 7867 8101 8102 +1 6 7866 7319 7320 7321 7868 8102 +1 6 7867 7321 7869 8102 8103 8104 +1 6 7868 7321 7322 7870 8104 8105 +1 6 7869 7322 7323 7324 7871 8105 +1 6 7870 7324 7872 8105 8106 8107 +1 6 7871 7324 7325 7873 8107 8108 +1 6 7872 7325 7326 7327 7874 8108 +1 6 7873 7327 7875 8108 8109 8110 +1 6 7874 7327 7328 7329 7876 8110 +1 6 7875 7329 7877 8110 8111 8112 +1 6 7876 7329 7330 7331 7878 8112 +1 6 7877 7331 7332 7879 8112 8113 +1 6 7878 7332 7880 8113 8114 8115 +1 6 7879 7332 7333 7334 7881 8115 +1 6 7880 7334 7335 7336 7882 8115 +1 6 7881 7336 7337 7883 8115 8116 +1 7 7882 7337 7338 7884 8116 8117 8118 +1 6 7883 7338 7339 7885 8118 8119 +1 6 7884 7339 7340 7886 8119 8120 +1 6 7885 7340 7341 7887 8120 8121 +1 6 7886 7341 7888 8121 8122 8123 +1 6 7887 7341 7342 7343 7889 8123 +1 6 7888 7343 7344 7890 8123 8124 +1 6 7889 7344 7345 7891 8124 8125 +1 6 7890 7345 7346 7892 8125 8126 +1 6 7891 7346 7347 7893 8126 8127 +1 6 7892 7347 7348 7894 8127 8128 +1 6 7893 7348 7895 8128 8129 8130 +1 6 7894 7348 7349 7350 7896 8130 +1 6 7895 7350 7351 7897 8130 8131 +1 7 7896 7351 7352 7353 7898 8131 8132 +1 5 7897 7353 7899 8132 8133 +1 7 7898 7353 7354 7355 7900 8133 8134 +2 6 7899 7355 7901 8134 8135 8136 +2 5 7900 7355 7356 7902 8136 +2 7 7901 7356 7903 8136 8137 8138 7904 +2 5 7902 7356 7357 7358 7904 +2 6 7903 7358 7905 8138 7902 8139 +2 6 7904 7358 7359 7361 7906 8139 +2 6 7905 7361 7907 8139 8140 8141 +2 6 7906 7361 7362 7363 7908 8141 +2 6 7907 7363 7909 8141 8142 8143 +2 6 7908 7363 7364 7365 7910 8143 +2 6 7909 7365 7371 7911 8143 8144 +2 6 7910 7371 7912 8144 8145 8146 +2 5 7911 7371 7372 7913 8146 +2 7 7912 7372 7373 7914 8146 8147 8148 +2 6 7913 7373 7915 8148 8149 8150 +2 6 7914 7373 7374 7376 7916 8150 +2 6 7915 7376 7917 7918 7919 8150 +2 6 7916 7376 7377 7378 7601 7918 +2 6 7917 7601 7916 7919 7920 7603 +2 6 7916 7918 7920 7921 7922 8150 +2 6 7919 7918 7921 7925 7926 7603 +2 6 7919 7920 7922 7923 7924 7925 +2 6 7919 7921 7923 8150 8151 8149 +2 6 7922 7921 7924 8151 8152 8153 +2 6 7923 7921 7925 8153 8154 8155 +2 6 7924 7921 7920 7926 8155 7928 +2 6 7925 7920 7603 7604 7927 7928 +2 6 7926 7604 7928 7929 7609 7605 +2 6 7926 7927 7929 8155 7925 8157 +2 6 7928 7927 7609 8157 7616 7610 +2 6 7809 7810 7931 8050 8345 7808 +1 6 7930 7810 7811 7932 7933 8050 +1 6 7931 7811 7933 7934 7935 7936 +1 6 7931 7932 7934 8050 8051 8052 +1 6 7933 7932 7935 8052 8053 8057 +1 6 7934 7932 7936 8059 8057 8060 +1 6 7935 7932 7811 7812 7937 8060 +1 6 7936 7812 7813 7938 8060 8061 +1 6 7937 7813 7814 7939 8061 8062 +1 6 7938 7814 7816 7817 7940 8062 +1 6 7939 7817 7818 7941 8062 8063 +1 6 7940 7818 7942 8063 8064 8065 +1 6 7941 7818 7819 7943 8065 8066 +1 6 7942 7819 7820 7821 7944 8066 +1 6 7943 7821 7945 8066 8067 8068 +1 6 7944 7821 7822 7946 8068 8069 +1 6 7945 7822 7823 7947 8069 8070 +1 6 7946 7823 7824 7948 8070 8071 +1 6 7947 7824 7826 7949 8071 8072 +1 6 7948 7826 7950 8072 8073 8074 +1 6 7949 7826 7827 7951 8074 8075 +1 6 7950 7827 7952 8075 8076 7953 +1 6 7951 7827 7828 7829 7832 7953 +1 6 7952 7832 7833 7954 8076 7951 +1 6 7953 7833 7955 8076 8077 8078 +1 6 7954 7833 7834 7835 7956 8078 +1 6 7955 7835 7836 7957 8078 8079 +1 6 7956 7836 7958 8079 8080 8081 +1 6 7957 7836 7837 7838 7959 8081 +1 6 7958 7838 7839 7960 8081 8082 +1 5 7959 7839 7846 8082 7847 +1 6 7846 7840 7841 7842 7843 7845 +1 6 7726 7727 7963 8466 8468 9764 +1 6 7962 7727 7964 8466 8487 8488 +1 6 7963 7727 7728 7246 7965 8488 +1 6 7964 7246 7247 7966 8488 8489 +1 6 7965 7247 7248 7967 8489 8490 +1 6 7966 7248 7249 7968 8490 8491 +1 6 7967 7249 7511 7513 7969 8491 +2 6 7968 7513 7970 8493 8491 8494 +2 6 7969 7513 7514 7971 8494 8495 +2 6 7970 7514 7972 8495 8496 7974 +1 6 7971 7514 7515 7518 7973 7974 +1 6 7972 7518 7974 7975 7976 7977 +2 6 7972 7973 7975 8496 7971 8497 +2 6 7974 7973 7976 8500 8497 7981 +2 6 7975 7973 7977 7979 7980 7981 +1 6 7976 7973 7518 7519 7978 7979 +1 6 7977 7519 7979 7988 7989 7521 +1 6 7977 7978 7976 7980 7987 7988 +2 6 7976 7979 7981 7982 7986 7987 +2 6 7976 7980 7982 7983 8500 7975 +2 6 7981 7980 7983 7984 7985 7986 +2 6 7981 7982 7984 8500 8501 8502 +2 6 7983 7982 7985 8502 8503 8504 +2 6 7984 7982 7986 8504 8505 8506 +2 6 7985 7982 7980 7987 8506 7993 +1 7 7986 7980 7979 7988 7991 7992 7993 +1 5 7987 7979 7978 7989 7991 +1 7 7988 7978 7521 7526 7990 7548 7991 +1 5 7989 7526 7527 7546 7548 +1 6 7989 7548 7549 7992 7987 7988 +1 6 7991 7549 7551 7987 7993 7994 +2 6 7987 7992 7994 8506 7986 8507 +2 6 7993 7992 7551 8507 7997 7995 +2 6 7551 7552 7558 7996 7997 7994 +2 6 7995 7558 7559 7997 7998 7999 +2 6 7995 7996 7998 8507 7994 8508 +2 6 7997 7996 7999 8508 8509 8510 +2 6 7998 7996 7559 7566 8000 8510 +2 6 7999 7566 7567 7570 8001 8510 +2 7 8000 7570 7571 8002 8510 8522 8511 +2 6 8001 7571 7572 8003 8522 8523 +2 7 8002 7572 7574 7577 8004 8520 8523 +2 7 8003 7577 8005 8519 8517 8520 8541 +2 5 8004 7577 7578 8006 8541 +2 6 8005 7578 8007 8610 8540 8541 +2 6 8006 7578 7579 7580 8008 8610 +2 6 8007 7580 7581 8009 8010 8610 +2 6 8008 7581 8010 8011 8012 7582 +2 8 8008 8009 8011 8609 8537 8538 8540 8610 +2 5 8010 8009 8012 8013 8609 +2 6 8011 8009 8013 7587 7582 7585 +2 7 8011 8012 7587 7729 8014 8608 8609 +2 6 8013 7729 7730 8015 8607 8608 +2 6 8014 7730 7734 8016 8611 8607 +2 6 8015 7734 7735 8017 8611 8612 +2 6 8016 7735 8018 8612 8613 8614 +2 6 8017 7735 7736 8019 8614 8615 +2 6 8018 7736 8020 8615 8618 8619 +2 6 8019 7736 7737 8021 8022 8619 +2 6 8020 7737 8022 8023 9766 7738 +2 6 8020 8021 8023 8024 8619 8620 +2 6 8022 8021 8024 8025 7742 9766 +2 6 8022 8023 8025 8620 8621 8028 +2 6 8024 8023 7742 7743 8026 8028 +2 6 8025 7743 8027 8028 8029 8030 +2 6 8026 7743 7744 7748 8030 8031 +2 6 8025 8026 8029 8621 8024 8622 +2 6 8028 8026 8030 8628 8622 8629 +2 6 8029 8026 8027 8031 8033 8629 +2 6 8030 8027 7748 8032 8033 8034 +2 6 8031 7748 7749 8034 8035 8036 +2 6 8030 8031 8034 8629 8630 8631 +2 6 8033 8031 8032 8035 8631 8632 +2 6 8034 8032 8036 7761 8635 8632 +2 6 8035 8032 7749 7759 7760 7761 +2 6 7784 7785 8038 8332 8333 8334 +2 6 8037 7785 7787 8039 8041 8334 +2 6 8038 7787 8040 8041 8042 8043 +2 6 8039 7787 8043 8044 8045 7788 +2 6 8038 8039 8042 8334 8335 8336 +2 6 8041 8039 8043 8336 8337 8341 +2 6 8042 8039 8040 8044 8341 8342 +2 6 8043 8040 8045 8342 8343 8046 +2 6 8044 8040 7788 7794 7795 8046 +2 6 8045 7795 8047 7806 8343 8044 +2 6 8046 7795 7806 7803 8048 7796 +2 6 7803 8047 7796 7802 7801 8049 +2 6 7801 8048 7796 7797 7799 7800 +2 6 7930 7931 7933 8051 8345 8346 +2 6 8050 7933 8052 8346 8347 8348 +1 6 8051 7933 7934 8053 8054 8348 +1 6 8052 7934 8054 8055 8056 8057 +2 6 8052 8053 8055 8348 8349 8350 +2 6 8054 8053 8056 8350 8351 8352 +1 6 8055 8053 8057 8058 8352 8353 +1 6 8056 8053 8058 8059 7935 7934 +1 6 8056 8057 8059 8353 8354 8355 +1 6 8058 8057 7935 8060 8355 8356 +1 6 8059 7935 7936 7937 8061 8356 +1 6 8060 7937 7938 8062 8356 8358 +1 6 8061 7938 7939 7940 8063 8358 +1 6 8062 7940 7941 8064 8359 8358 +1 6 8063 7941 8065 8359 8360 8361 +1 6 8064 7941 7942 8066 8361 8362 +1 6 8065 7942 7943 7944 8067 8362 +1 6 8066 7944 8068 8362 8363 8364 +1 6 8067 7944 7945 8069 8364 8365 +1 6 8068 7945 7946 8070 8365 8366 +1 6 8069 7946 7947 8071 8366 8367 +1 6 8070 7947 7948 8072 8367 8368 +1 6 8071 7948 7949 8073 8368 8369 +1 6 8072 7949 8074 8369 8370 8371 +1 6 8073 7949 7950 8075 8371 8372 +1 6 8074 7950 7951 8076 8372 8373 +1 6 8075 7951 7953 7954 8077 8373 +1 6 8076 7954 8078 8375 8373 8376 +1 6 8077 7954 7955 7956 8079 8376 +1 6 8078 7956 7957 8080 8376 8377 +1 6 8079 7957 8081 8209 8377 8378 +1 6 8080 7957 7958 7959 8082 8209 +1 7 8081 7959 7960 7847 7848 8083 8209 +1 6 8082 7848 7849 8084 8209 8210 +1 6 8083 7849 7850 8085 8210 8211 +1 6 8084 7850 8086 8211 8212 8213 +1 6 8085 7850 7851 7852 8087 8213 +1 6 8086 7852 8088 8213 8214 8215 +1 6 8087 7852 7853 8089 8215 8090 +1 6 8088 7853 7854 7855 7856 8090 +1 5 8089 7856 8091 8215 8088 +1 7 8090 7856 7857 8092 8215 8216 8217 +1 5 8091 7857 8093 8217 8218 +1 6 8092 7857 7858 8094 8218 8219 +1 6 8093 7858 7859 7860 8095 8219 +1 6 8094 7860 8096 8219 8220 8221 +1 6 8095 7860 7861 8097 8221 8222 +1 6 8096 7861 7862 8098 8222 8223 +1 6 8097 7862 7863 8099 8223 8224 +1 6 8098 7863 7864 8100 8224 8225 +1 6 8099 7864 7865 8101 8225 8226 +1 6 8100 7865 7866 8102 8226 8227 +1 6 8101 7866 7867 7868 8103 8227 +1 6 8102 7868 8104 8227 8228 8229 +1 6 8103 7868 7869 8105 8229 8230 +1 6 8104 7869 7870 7871 8106 8230 +1 6 8105 7871 8107 8230 8231 8232 +1 6 8106 7871 7872 8108 8232 8233 +1 6 8107 7872 7873 7874 8109 8233 +1 6 8108 7874 8110 8233 8234 8235 +1 6 8109 7874 7875 7876 8111 8235 +1 6 8110 7876 8112 8235 8236 8237 +1 6 8111 7876 7877 7878 8113 8237 +1 6 8112 7878 7879 8114 8237 8238 +1 6 8113 7879 8115 8238 8239 8116 +1 6 8114 7879 7880 7881 7882 8116 +1 6 8115 7882 7883 8117 8239 8114 +1 6 8116 7883 8118 8239 8240 8241 +1 5 8117 7883 7884 8119 8241 +1 6 8118 7884 7885 8120 8241 8242 +1 6 8119 7885 7886 8121 8242 8243 +1 6 8120 7886 7887 8122 8243 8244 +1 6 8121 7887 8123 8244 8245 8246 +1 6 8122 7887 7888 7889 8124 8246 +1 6 8123 7889 7890 8125 8246 8247 +1 6 8124 7890 7891 8126 8247 8248 +1 6 8125 7891 7892 8127 8248 8249 +1 6 8126 7892 7893 8128 8249 8250 +1 6 8127 7893 7894 8129 8250 8251 +1 6 8128 7894 8130 8251 8252 8253 +1 6 8129 7894 7895 7896 8131 8253 +1 6 8130 7896 7897 8132 8253 8254 +1 5 8131 7897 7898 8133 8254 +1 7 8132 7898 7899 8134 8254 8255 8256 +2 5 8133 7899 7900 8135 8256 +2 7 8134 7900 8136 8256 8257 8258 8259 +2 6 8135 7900 7901 7902 8137 8259 +2 6 8136 7902 8138 8259 8260 8261 +2 6 8137 7902 7904 8139 8261 8262 +2 6 8138 7904 7905 7906 8140 8262 +2 6 8139 7906 8141 8262 8263 8264 +2 6 8140 7906 7907 7908 8142 8264 +2 6 8141 7908 8143 8264 8265 8266 +2 6 8142 7908 7909 7910 8144 8266 +2 6 8143 7910 7911 8145 8266 8267 +2 6 8144 7911 8146 8267 8268 8269 +2 6 8145 7911 7912 7913 8147 8269 +2 6 8146 7913 8148 8269 8270 8271 +2 6 8147 7913 7914 8149 8151 8271 +2 5 8148 7914 8150 8151 7922 +2 6 8149 7914 7915 7916 7919 7922 +2 7 8148 8149 7922 7923 8152 8271 8272 +2 5 8151 7923 8153 8272 8273 +2 7 8152 7923 7924 8154 8273 8274 8275 +2 6 8153 7924 8155 8156 8275 8276 +2 7 8154 7924 8156 7925 7928 8157 7617 +2 6 8154 8155 7617 7618 8158 8276 +2 5 8155 7928 7929 7616 7617 +2 6 8156 7618 8159 8276 8277 8278 +2 6 8158 7618 7619 8160 8278 8279 +2 7 8159 7619 7620 8161 8279 8280 8281 +2 5 8160 7620 8162 8281 8282 +2 7 8161 7620 7621 8163 8282 8283 8164 +2 6 8162 7621 7622 7623 7624 8164 +2 7 8163 7624 7625 7627 8165 8283 8162 +2 6 8164 7627 7628 7630 8166 8283 +2 6 8165 7630 8167 8168 8283 8282 +2 6 8166 7630 8168 8169 8170 7631 +2 6 8166 8167 8169 8282 8284 8285 +2 6 8168 8167 8170 8285 8286 8287 +2 6 8169 8167 7631 8171 8172 8287 +2 6 8170 7631 8172 8173 7633 7632 +2 6 8170 8171 8173 8287 8288 8289 +2 6 8172 8171 7633 8174 8289 8290 +2 6 8173 7633 7634 7636 8175 8290 +2 6 8174 7636 7638 8176 8290 8291 +2 6 8175 7638 8177 8291 8292 8293 +2 6 8176 7638 7639 8178 8293 8294 +2 6 8177 7639 8179 8294 8295 8296 +2 6 8178 7639 7640 8180 8296 8297 +2 6 8179 7640 8181 8307 8297 8308 +2 6 8180 7640 7641 8182 8183 8308 +2 6 8181 7641 8183 7644 7643 7642 +2 6 8181 8182 7644 8184 8308 8309 +2 6 8183 7644 7645 8185 8309 8310 +2 7 8184 7645 7646 7647 8186 8310 8311 +1 6 8185 7647 7648 8187 8311 8312 +1 6 8186 7648 8188 8312 8313 8314 +1 6 8187 7648 7649 8189 8314 8315 +1 6 8188 7649 7650 8190 8315 8200 +1 6 8189 7650 8191 8197 8199 8200 +1 6 8190 7650 7651 8192 8197 8193 +1 6 8191 7651 7652 7657 7658 8193 +1 6 8192 7658 8194 8196 8197 8191 +1 6 8193 7658 7659 7662 8195 8196 +1 6 8194 7662 8196 8208 8204 7663 +1 6 8194 8195 8193 8197 8198 8204 +1 6 8193 8196 8198 8199 8190 8191 +1 6 8197 8196 8199 8202 8203 8204 +1 6 8197 8198 8190 8200 8201 8202 +1 6 8190 8199 8201 8315 8189 8316 +1 6 8200 8199 8202 8316 8317 8318 +1 6 8201 8199 8198 8203 8205 8318 +1 6 8202 8198 8204 8205 7699 8206 +1 7 8203 8198 8206 8207 8208 8195 8196 +1 5 8202 8203 7699 8318 7700 +1 7 7699 8203 8204 7698 7669 7667 8207 +1 6 7667 8206 8204 8208 7664 7665 +1 5 8207 8204 8195 7663 7664 +1 6 8080 8081 8082 8083 8210 8378 +1 5 8209 8083 8084 8211 8378 +1 6 8210 8084 8085 8212 8378 8379 +1 6 8211 8085 8213 8379 8380 8381 +1 6 8212 8085 8086 8087 8214 8381 +1 6 8213 8087 8215 8381 8382 8216 +1 6 8214 8087 8088 8090 8091 8216 +1 6 8215 8091 8217 8382 8214 8383 +1 6 8216 8091 8092 8218 8383 8384 +1 6 8217 8092 8093 8219 8384 8385 +1 6 8218 8093 8094 8095 8220 8385 +1 5 8219 8095 8221 8385 8386 +1 6 8220 8095 8096 8222 8386 8387 +1 6 8221 8096 8097 8223 8387 8388 +1 6 8222 8097 8098 8224 8388 8389 +1 6 8223 8098 8099 8225 8389 8390 +1 6 8224 8099 8100 8226 8390 8391 +1 6 8225 8100 8101 8227 8391 8392 +1 6 8226 8101 8102 8103 8228 8392 +1 6 8227 8103 8229 8392 8393 8394 +1 6 8228 8103 8104 8230 8394 8395 +1 6 8229 8104 8105 8106 8231 8395 +1 6 8230 8106 8232 8395 8396 8397 +1 6 8231 8106 8107 8233 8397 8398 +1 6 8232 8107 8108 8109 8234 8398 +1 6 8233 8109 8235 8398 8399 8400 +1 6 8234 8109 8110 8111 8236 8400 +1 6 8235 8111 8237 8400 8401 8402 +1 6 8236 8111 8112 8113 8238 8402 +1 6 8237 8113 8114 8239 8402 8403 +1 6 8238 8114 8116 8117 8240 8403 +1 6 8239 8117 8241 8403 8404 8405 +1 6 8240 8117 8118 8119 8242 8405 +1 6 8241 8119 8120 8243 8405 8406 +1 6 8242 8120 8121 8244 8406 8407 +1 6 8243 8121 8122 8245 8407 8408 +1 6 8244 8122 8246 8408 8409 8410 +1 6 8245 8122 8123 8124 8247 8410 +1 6 8246 8124 8125 8248 8410 8411 +1 6 8247 8125 8126 8249 8411 8412 +1 6 8248 8126 8127 8250 8412 8413 +1 6 8249 8127 8128 8251 8413 8414 +1 6 8250 8128 8129 8252 8414 8415 +1 6 8251 8129 8253 8415 8416 8417 +1 6 8252 8129 8130 8131 8254 8417 +1 7 8253 8131 8132 8133 8255 8417 8418 +1 5 8254 8133 8256 8418 8419 +2 7 8255 8133 8134 8135 8257 8419 8420 +2 5 8256 8135 8258 8420 8421 +2 6 8257 8135 8259 8421 8422 8260 +2 5 8258 8135 8136 8137 8260 +2 6 8259 8137 8261 8422 8258 8423 +2 6 8260 8137 8138 8262 8423 8424 +2 6 8261 8138 8139 8140 8263 8424 +2 6 8262 8140 8264 8424 8425 8426 +2 6 8263 8140 8141 8142 8265 8426 +2 6 8264 8142 8266 8426 8427 8428 +2 7 8265 8142 8143 8144 8267 8428 8429 +2 6 8266 8144 8145 8268 8429 8430 +2 6 8267 8145 8269 8430 8431 8432 +2 6 8268 8145 8146 8147 8270 8432 +2 6 8269 8147 8271 8432 8433 8434 +2 6 8270 8147 8148 8151 8272 8434 +2 5 8271 8151 8152 8273 8434 +2 7 8272 8152 8153 8274 8434 8435 8436 +2 6 8273 8153 8275 8436 8437 8438 +2 6 8274 8153 8154 8276 8438 8277 +2 5 8275 8154 8156 8158 8277 +2 6 8276 8158 8278 8438 8275 8439 +2 6 8277 8158 8159 8279 8439 8440 +2 7 8278 8159 8160 8280 8440 8441 8445 +2 6 8279 8160 8281 8445 8446 8284 +2 5 8280 8160 8161 8282 8284 +2 7 8281 8161 8162 8283 8166 8168 8284 +2 5 8282 8162 8164 8165 8166 +2 6 8282 8168 8285 8446 8280 8281 +2 6 8284 8168 8169 8286 8446 8447 +2 6 8285 8169 8287 8447 8449 8450 +2 6 8286 8169 8170 8172 8288 8450 +2 6 8287 8172 8289 8450 8451 8452 +2 6 8288 8172 8173 8290 8452 8453 +2 6 8289 8173 8174 8175 8291 8453 +2 6 8290 8175 8176 8292 8453 8454 +2 6 8291 8176 8293 8454 8455 8456 +2 6 8292 8176 8177 8294 8456 8457 +2 6 8293 8177 8178 8295 8457 8458 +2 6 8294 8178 8296 8461 8458 8299 +2 6 8295 8178 8179 8297 8298 8299 +2 6 8296 8179 8298 8307 8305 8180 +2 6 8296 8297 8299 8300 8301 8305 +2 6 8296 8298 8300 8461 8295 8462 +2 6 8299 8298 8301 8302 8462 8463 +2 6 8300 8298 8302 8303 8304 8305 +2 6 8300 8301 8303 8463 8464 8465 +2 6 8302 8301 8304 8465 8466 8467 +2 6 8303 8301 8305 8306 8470 8467 +2 6 8304 8301 8298 8306 8307 8297 +2 6 8304 8305 8307 8470 8471 8472 +2 6 8306 8305 8297 8180 8308 8472 +2 6 8307 8180 8181 8183 8309 8472 +2 6 8308 8183 8184 8310 8472 8473 +2 6 8309 8184 8185 8311 8473 8474 +1 5 8310 8185 8186 8312 8474 +1 6 8311 8186 8187 8313 8474 8475 +1 6 8312 8187 8314 8478 8475 8479 +1 6 8313 8187 8188 8315 8479 8480 +1 6 8314 8188 8189 8200 8316 8480 +1 5 8315 8200 8201 8317 8480 +1 6 8316 8201 8318 8480 8481 7708 +1 7 8317 8201 8202 8205 7700 7707 7708 +2 6 7765 7766 8320 8321 8853 8854 +2 6 8319 7766 7767 8321 8322 7769 +2 7 8319 8320 8322 8854 8855 8856 8323 +2 5 8321 8320 7769 7771 8323 +2 6 8322 7771 8324 8856 8321 8857 +2 6 8323 7771 7772 8325 8857 8328 +2 6 8324 7772 7777 8326 8327 8328 +2 6 8325 7777 7778 7779 7780 8327 +2 6 8326 7780 8325 8328 8329 7781 +2 6 8325 8327 8329 8857 8324 8858 +2 6 8328 8327 7781 7782 8330 8858 +2 6 8329 7782 7783 8331 8858 8859 +2 6 8330 7783 8332 8865 8862 8859 +2 6 8331 7783 7784 8037 8333 8865 +2 6 8332 8037 8334 8866 8865 8867 +2 6 8333 8037 8038 8041 8335 8867 +2 6 8334 8041 8336 8867 8868 8869 +2 6 8335 8041 8042 8337 8338 8869 +2 6 8336 8042 8338 8339 8340 8341 +2 6 8336 8337 8339 8869 8870 8874 +2 6 8338 8337 8340 8874 8875 8347 +2 6 8339 8337 8341 8347 8346 8876 +2 6 8340 8337 8042 8043 8342 8876 +2 6 8341 8043 8044 8343 8344 8876 +2 6 8342 8044 8344 7807 7806 8046 +2 6 8342 8343 7807 7808 8345 8876 +2 6 8344 7808 7930 8050 8346 8876 +2 6 8345 8050 8051 8347 8340 8876 +2 6 8346 8051 8348 8875 8339 8340 +2 6 8347 8051 8052 8054 8349 8875 +2 6 8348 8054 8350 8902 8875 8901 +2 6 8349 8054 8055 8351 8901 8903 +2 6 8350 8055 8352 8903 8904 8905 +1 6 8351 8055 8056 8353 8905 8906 +1 6 8352 8056 8058 8354 8906 8907 +1 6 8353 8058 8355 8907 8908 8909 +1 6 8354 8058 8059 8356 8357 8909 +1 6 8355 8059 8060 8061 8357 8358 +1 6 8355 8356 8358 8359 8909 8910 +1 6 8357 8356 8061 8062 8359 8063 +1 6 8357 8358 8063 8064 8360 8910 +1 6 8359 8064 8361 8912 8910 8913 +1 6 8360 8064 8065 8362 8913 8914 +1 6 8361 8065 8066 8067 8363 8914 +1 6 8362 8067 8364 8916 8914 8917 +1 6 8363 8067 8068 8365 8917 8918 +1 6 8364 8068 8069 8366 8918 8919 +1 6 8365 8069 8070 8367 8919 8920 +1 6 8366 8070 8071 8368 8920 8921 +1 6 8367 8071 8072 8369 8921 8922 +1 6 8368 8072 8073 8370 8922 8923 +1 6 8369 8073 8371 8923 8924 8925 +1 6 8370 8073 8074 8372 8925 8926 +1 6 8371 8074 8075 8373 8374 8926 +1 6 8372 8075 8076 8374 8375 8077 +1 6 8372 8373 8375 8926 8927 8928 +1 6 8374 8373 8077 8376 8928 8929 +1 6 8375 8077 8078 8079 8377 8929 +1 6 8376 8079 8080 8378 8929 8379 +1 6 8377 8080 8209 8210 8211 8379 +1 7 8378 8211 8212 8380 8929 8377 8930 +1 5 8379 8212 8381 8930 8931 +1 7 8380 8212 8213 8214 8382 8743 8931 +1 6 8381 8214 8216 8383 8641 8743 +1 6 8382 8216 8217 8384 8641 8642 +1 6 8383 8217 8218 8385 8642 8643 +1 6 8384 8218 8219 8220 8386 8643 +1 7 8385 8220 8221 8387 8643 8644 8645 +1 6 8386 8221 8222 8388 8645 8646 +1 6 8387 8222 8223 8389 8646 8647 +1 6 8388 8223 8224 8390 8647 8648 +1 7 8389 8224 8225 8391 8648 8649 8650 +1 6 8390 8225 8226 8392 8650 8651 +1 6 8391 8226 8227 8228 8393 8651 +1 6 8392 8228 8394 8651 8652 8653 +1 6 8393 8228 8229 8395 8653 8654 +1 6 8394 8229 8230 8231 8396 8654 +1 5 8395 8231 8397 8654 8655 +1 6 8396 8231 8232 8398 8655 8656 +1 7 8397 8232 8233 8234 8399 8656 8657 +1 5 8398 8234 8400 8657 8658 +1 7 8399 8234 8235 8236 8401 8658 8659 +1 5 8400 8236 8402 8659 8660 +1 6 8401 8236 8237 8238 8403 8660 +1 6 8402 8238 8239 8240 8404 8660 +1 6 8403 8240 8405 8660 8661 8662 +1 6 8404 8240 8241 8242 8406 8662 +1 6 8405 8242 8243 8407 8662 8663 +1 7 8406 8243 8244 8408 8663 8664 8665 +1 6 8407 8244 8245 8409 8665 8666 +1 6 8408 8245 8410 8666 8667 8668 +1 6 8409 8245 8246 8247 8411 8668 +1 6 8410 8247 8248 8412 8668 8669 +1 6 8411 8248 8249 8413 8669 8670 +1 6 8412 8249 8250 8414 8670 8671 +1 6 8413 8250 8251 8415 8671 8672 +1 6 8414 8251 8252 8416 8672 8673 +1 6 8415 8252 8417 8673 8674 8675 +1 6 8416 8252 8253 8254 8418 8675 +1 6 8417 8254 8255 8419 8675 8676 +2 6 8418 8255 8256 8420 8676 8677 +2 6 8419 8256 8257 8421 8677 8678 +2 6 8420 8257 8258 8422 8678 8679 +2 6 8421 8258 8260 8423 8679 8680 +2 7 8422 8260 8261 8424 8680 8681 8682 +2 6 8423 8261 8262 8263 8425 8682 +2 6 8424 8263 8426 8682 8683 8687 +2 6 8425 8263 8264 8265 8427 8687 +2 6 8426 8265 8428 8687 8688 8689 +2 6 8427 8265 8266 8429 8689 8690 +2 5 8428 8266 8267 8430 8690 +2 6 8429 8267 8268 8431 8542 8690 +2 6 8430 8268 8432 8542 8543 8544 +2 6 8431 8268 8269 8270 8433 8544 +2 6 8432 8270 8434 8544 8545 8546 +2 7 8433 8270 8271 8272 8273 8435 8546 +2 6 8434 8273 8436 8546 8547 8548 +2 6 8435 8273 8274 8437 8548 8549 +2 6 8436 8274 8438 8549 8550 8439 +2 5 8437 8274 8275 8277 8439 +2 7 8438 8277 8278 8440 8550 8437 8551 +2 6 8439 8278 8279 8441 8442 8551 +2 6 8440 8279 8442 8443 8444 8445 +2 6 8440 8441 8443 8551 8552 8553 +2 6 8442 8441 8444 8553 8554 8555 +2 7 8443 8441 8445 8446 8447 8448 8555 +2 5 8444 8441 8279 8280 8446 +2 6 8445 8280 8284 8285 8447 8444 +2 6 8446 8285 8286 8444 8448 8449 +2 5 8444 8447 8449 8555 8556 +2 6 8448 8447 8286 8450 8556 8557 +2 7 8449 8286 8287 8288 8451 8557 8558 +2 6 8450 8288 8452 8558 8559 8560 +2 6 8451 8288 8289 8453 8560 8561 +2 6 8452 8289 8290 8291 8454 8561 +2 6 8453 8291 8292 8455 8561 8562 +2 6 8454 8292 8456 8562 8563 8564 +2 6 8455 8292 8293 8457 8564 8565 +2 6 8456 8293 8294 8458 8459 8565 +2 6 8457 8294 8459 8460 8461 8295 +2 6 8457 8458 8460 8565 8566 8567 +2 6 8459 8458 8461 8567 8568 8569 +2 6 8460 8458 8295 8299 8462 8569 +2 6 8461 8299 8300 8463 8569 8570 +2 6 8462 8300 8302 8464 8570 8571 +2 6 8463 8302 8465 8571 8572 8573 +2 6 8464 8302 8303 8466 8573 8487 +2 7 8465 8303 8467 8468 7962 7963 8487 +2 6 8466 8303 8468 8469 8470 8304 +1 6 8466 8467 8469 7962 9763 9764 +1 7 8468 8467 8470 9094 8485 9763 8486 +2 6 8469 8467 8304 8306 8471 9094 +2 6 8470 8306 8472 8476 9094 8473 +2 6 8471 8306 8307 8308 8309 8473 +2 6 8472 8309 8310 8474 8476 8471 +1 6 8473 8310 8311 8312 8475 8476 +1 6 8474 8312 8476 8477 8478 8313 +1 7 8474 8475 8477 8485 9094 8471 8473 +1 6 8476 8475 8478 8483 8484 8485 +1 6 8477 8475 8313 8479 8483 8482 +1 6 8478 8313 8314 8480 8482 8481 +1 6 8479 8314 8315 8316 8317 8481 +1 6 8480 8317 7708 7709 8482 8479 +1 7 8481 7709 7710 7713 8483 8478 8479 +1 5 8482 7713 8484 8477 8478 +1 6 8483 7713 7714 8477 8485 8486 +1 6 8477 8484 8486 8469 9094 8476 +1 6 8485 8484 9765 9763 8469 7714 +2 5 8466 7963 8488 8573 8465 +2 7 8487 7963 7964 7965 8489 8573 8574 +2 5 8488 7965 7966 8490 8574 +2 7 8489 7966 7967 8491 8492 8574 8575 +2 6 8490 7967 8492 8493 7969 7968 +2 5 8490 8491 8493 8575 8576 +2 6 8492 8491 7969 8494 8576 8577 +2 6 8493 7969 7970 8495 8577 8578 +2 6 8494 7970 7971 8496 8578 8579 +2 6 8495 7971 7974 8497 8498 8579 +2 6 8496 7974 8498 8499 8500 7975 +2 6 8496 8497 8499 8579 8580 8581 +2 6 8498 8497 8500 8581 8582 8501 +2 6 8499 8497 7975 7981 7983 8501 +2 6 8500 7983 8502 8582 8499 8583 +2 6 8501 7983 7984 8503 8586 8583 +2 6 8502 7984 8504 8527 8586 8526 +2 6 8503 7984 7985 8505 8526 8588 +2 6 8504 7985 8506 8588 8513 8589 +2 6 8505 7985 7986 7993 8507 8589 +2 6 8506 7993 7994 7997 8508 8589 +2 6 8507 7997 7998 8509 8513 8589 +2 6 8508 7998 8510 8511 8512 8513 +2 6 8509 7998 7999 8000 8001 8511 +2 6 8509 8510 8512 8521 8522 8001 +2 6 8509 8511 8513 8514 8515 8521 +2 7 8509 8512 8514 8588 8505 8589 8508 +2 6 8513 8512 8515 8516 8526 8588 +2 6 8514 8512 8516 8517 8520 8521 +2 6 8514 8515 8517 8518 8524 8526 +2 6 8516 8515 8518 8519 8004 8520 +2 6 8516 8517 8519 8524 8525 8531 +2 6 8518 8517 8004 8541 8539 8531 +2 6 8004 8517 8003 8515 8521 8523 +2 6 8520 8515 8512 8511 8522 8523 +2 5 8521 8511 8001 8002 8523 +2 5 8522 8002 8521 8520 8003 +2 6 8516 8518 8525 8526 8527 8528 +2 6 8524 8518 8528 8529 8530 8531 +2 7 8516 8524 8527 8503 8504 8588 8514 +2 5 8526 8524 8528 8586 8503 +2 6 8527 8524 8525 8529 8587 8586 +2 6 8528 8525 8530 8602 8587 8603 +2 6 8529 8525 8531 8532 8533 8603 +2 6 8530 8525 8532 8519 8539 8518 +2 6 8530 8531 8533 8534 8538 8539 +2 6 8530 8532 8534 8535 8603 8604 +2 6 8533 8532 8535 8536 8537 8538 +2 6 8533 8534 8536 8604 8605 8606 +2 6 8535 8534 8537 8606 8607 8608 +2 6 8536 8534 8538 8608 8609 8010 +2 6 8537 8534 8532 8539 8540 8010 +2 6 8538 8532 8540 8541 8519 8531 +2 6 8538 8539 8541 8010 8610 8006 +2 6 8540 8539 8519 8006 8005 8004 +2 6 8430 8431 8543 8690 8691 8692 +2 6 8542 8431 8544 8692 8693 8694 +2 6 8543 8431 8432 8433 8545 8694 +2 6 8544 8433 8546 8694 8695 8547 +2 5 8545 8433 8434 8435 8547 +2 6 8546 8435 8548 8695 8545 8696 +2 6 8547 8435 8436 8549 8696 8697 +2 6 8548 8436 8437 8550 8697 8698 +2 6 8549 8437 8439 8551 8698 8552 +2 5 8550 8439 8440 8442 8552 +2 7 8551 8442 8553 8698 8550 8699 8700 +2 6 8552 8442 8443 8554 8700 8701 +2 6 8553 8443 8555 8701 8702 8703 +2 6 8554 8443 8444 8448 8556 8703 +2 6 8555 8448 8449 8557 8703 8704 +2 6 8556 8449 8450 8558 8704 8705 +2 6 8557 8450 8451 8559 8705 8706 +2 6 8558 8451 8560 8706 8707 8708 +2 5 8559 8451 8452 8561 8708 +2 6 8560 8452 8453 8454 8562 8708 +2 6 8561 8454 8455 8563 8708 8709 +2 6 8562 8455 8564 8709 8710 8711 +2 6 8563 8455 8456 8565 8711 8712 +2 7 8564 8456 8457 8459 8566 8712 8713 +2 5 8565 8459 8567 8713 8714 +2 6 8566 8459 8460 8568 8714 8715 +2 6 8567 8460 8569 8715 8716 8717 +2 6 8568 8460 8461 8462 8570 8717 +2 7 8569 8462 8463 8571 8590 8592 8717 +2 5 8570 8463 8464 8572 8590 +2 7 8571 8464 8573 8574 8575 8576 8590 +2 6 8572 8464 8465 8487 8488 8574 +2 6 8573 8488 8489 8490 8575 8572 +2 5 8574 8490 8492 8576 8572 +2 7 8575 8492 8493 8577 8572 8590 8591 +2 6 8576 8493 8494 8578 8594 8591 +2 6 8577 8494 8495 8579 8594 8595 +2 6 8578 8495 8496 8498 8580 8595 +2 6 8579 8498 8581 8595 8596 8597 +2 6 8580 8498 8499 8582 8597 8598 +2 6 8581 8499 8501 8583 8584 8598 +2 6 8582 8501 8584 8585 8586 8502 +2 6 8582 8583 8585 8598 8599 8600 +2 6 8584 8583 8586 8587 8600 8601 +2 7 8585 8583 8587 8528 8527 8503 8502 +2 6 8585 8586 8528 8601 8602 8529 +2 5 8526 8504 8505 8513 8514 +2 5 8513 8505 8506 8508 8507 +2 6 8572 8576 8591 8571 8570 8592 +2 6 8590 8576 8592 8593 8594 8577 +2 5 8570 8590 8591 8593 8717 +2 7 8592 8591 8594 8717 8716 8718 8719 +2 6 8593 8591 8577 8578 8595 8719 +2 7 8594 8578 8579 8580 8596 8719 8720 +2 6 8595 8580 8597 8720 8721 8722 +2 6 8596 8580 8581 8598 8722 8723 +2 6 8597 8581 8582 8584 8599 8723 +2 6 8598 8584 8600 8723 8724 8725 +2 6 8599 8584 8585 8601 8725 8726 +2 6 8600 8585 8587 8602 8726 8727 +2 5 8601 8587 8529 8603 8727 +2 6 8602 8529 8530 8533 8604 8727 +2 6 8603 8533 8535 8605 8727 8728 +2 6 8604 8535 8606 8728 8731 8732 +2 6 8605 8535 8536 8607 8611 8732 +2 6 8606 8536 8608 8611 8015 8014 +2 6 8607 8536 8537 8609 8014 8013 +2 5 8608 8537 8010 8013 8011 +2 5 8010 8540 8008 8007 8006 +2 6 8606 8607 8015 8016 8612 8732 +2 6 8611 8016 8017 8613 8732 8733 +2 6 8612 8017 8614 8733 8734 8735 +2 6 8613 8017 8018 8615 8616 8735 +2 6 8614 8018 8019 8616 8617 8618 +2 6 8614 8615 8617 8735 8736 8737 +2 6 8616 8615 8618 8737 8738 8739 +2 6 8617 8615 8019 8619 8739 8742 +2 6 8618 8019 8020 8022 8620 8742 +2 6 8619 8022 8024 8621 8624 8742 +2 6 8620 8024 8028 8622 8623 8624 +2 6 8621 8028 8623 8627 8628 8029 +2 6 8621 8622 8624 8625 8626 8627 +2 6 8621 8623 8625 8741 8742 8620 +2 6 8624 8623 8626 8837 8741 8838 +2 6 8625 8623 8627 8838 8839 8840 +2 6 8626 8623 8622 8628 8840 8841 +2 6 8627 8622 8029 8629 8841 8842 +2 6 8628 8029 8030 8033 8630 8842 +2 6 8629 8033 8631 8842 8843 8844 +2 6 8630 8033 8034 8632 8633 8844 +2 6 8631 8034 8633 8634 8635 8035 +2 6 8631 8632 8634 8844 8845 8846 +2 6 8633 8632 8635 8636 8637 8846 +2 6 8634 8632 8636 8640 7761 8035 +2 6 8634 8635 8637 8638 8639 8640 +2 6 8634 8636 8638 8846 8848 8849 +2 6 8637 8636 8639 8849 8850 8851 +2 6 8638 8636 8640 8851 8852 7762 +2 5 8639 8636 8635 7761 7762 +1 6 8382 8383 8642 8743 8744 8745 +1 6 8641 8383 8384 8643 8745 8746 +1 6 8642 8384 8385 8386 8644 8746 +1 6 8643 8386 8645 8746 8747 8748 +1 6 8644 8386 8387 8646 8748 8749 +1 6 8645 8387 8388 8647 8749 8750 +1 6 8646 8388 8389 8648 8750 8751 +1 6 8647 8389 8390 8649 8751 8752 +1 6 8648 8390 8650 8752 8753 8754 +1 5 8649 8390 8391 8651 8754 +1 6 8650 8391 8392 8393 8652 8754 +1 6 8651 8393 8653 8754 8755 8756 +1 6 8652 8393 8394 8654 8756 8757 +1 6 8653 8394 8395 8396 8655 8757 +1 6 8654 8396 8397 8656 8757 8758 +1 7 8655 8397 8398 8657 8758 8759 8760 +1 5 8656 8398 8399 8658 8760 +1 7 8657 8399 8400 8659 8760 8761 8762 +1 5 8658 8400 8401 8660 8762 +1 8 8659 8401 8402 8403 8404 8661 8762 8763 +1 5 8660 8404 8662 8763 8764 +1 6 8661 8404 8405 8406 8663 8764 +1 6 8662 8406 8407 8664 8764 8765 +1 6 8663 8407 8665 8765 8766 8767 +1 5 8664 8407 8408 8666 8767 +1 6 8665 8408 8409 8667 8767 8768 +1 6 8666 8409 8668 8768 8769 8770 +1 6 8667 8409 8410 8411 8669 8770 +1 6 8668 8411 8412 8670 8770 8771 +1 6 8669 8412 8413 8671 8771 8772 +1 6 8670 8413 8414 8672 8772 8773 +1 6 8671 8414 8415 8673 8773 8774 +1 6 8672 8415 8416 8674 8774 8775 +1 6 8673 8416 8675 8775 8776 8777 +1 6 8674 8416 8417 8418 8676 8777 +1 6 8675 8418 8419 8677 8777 8778 +2 6 8676 8419 8420 8678 8778 8779 +2 6 8677 8420 8421 8679 8779 8780 +2 6 8678 8421 8422 8680 8780 8781 +2 6 8679 8422 8423 8681 8781 8782 +2 6 8680 8423 8682 8782 8783 8684 +2 6 8681 8423 8424 8425 8683 8684 +2 6 8682 8425 8684 8685 8686 8687 +2 5 8682 8683 8685 8783 8681 +2 6 8684 8683 8686 8783 8784 8785 +2 6 8685 8683 8687 8785 8786 8787 +2 7 8686 8683 8425 8426 8427 8688 8787 +2 5 8687 8427 8689 8787 8788 +2 6 8688 8427 8428 8690 8788 8789 +2 7 8689 8428 8429 8430 8542 8691 8789 +2 6 8690 8542 8692 8789 8790 8791 +2 5 8691 8542 8543 8693 8791 +2 7 8692 8543 8694 8791 8792 8793 8794 +2 6 8693 8543 8544 8545 8695 8794 +2 6 8694 8545 8547 8696 8794 8795 +2 7 8695 8547 8548 8697 8795 8796 8797 +2 6 8696 8548 8549 8698 8797 8798 +2 6 8697 8549 8550 8552 8699 8798 +2 6 8698 8552 8700 8798 8799 8800 +2 6 8699 8552 8553 8701 8800 8803 +2 6 8700 8553 8554 8702 8803 8804 +2 6 8701 8554 8703 8804 8805 8806 +2 6 8702 8554 8555 8556 8704 8806 +2 6 8703 8556 8557 8705 8806 8807 +2 6 8704 8557 8558 8706 8807 8808 +2 6 8705 8558 8559 8707 8808 8809 +2 6 8706 8559 8708 8809 8810 8811 +2 7 8707 8559 8560 8561 8562 8709 8811 +2 5 8708 8562 8563 8710 8811 +2 7 8709 8563 8711 8811 8812 8813 8814 +2 6 8710 8563 8564 8712 8814 8815 +2 6 8711 8564 8565 8713 8815 8816 +2 5 8712 8565 8566 8714 8816 +2 7 8713 8566 8567 8715 8816 8817 8818 +2 6 8714 8567 8568 8716 8818 8819 +2 6 8715 8568 8717 8593 8718 8819 +2 6 8716 8568 8569 8570 8592 8593 +2 6 8716 8593 8719 8819 8820 8720 +2 5 8718 8593 8594 8595 8720 +2 6 8719 8595 8596 8721 8820 8718 +2 6 8720 8596 8722 8820 8821 8822 +2 5 8721 8596 8597 8723 8822 +2 6 8722 8597 8598 8599 8724 8822 +2 6 8723 8599 8725 8822 8823 8824 +2 6 8724 8599 8600 8726 8824 8825 +2 6 8725 8600 8601 8727 8825 8729 +2 7 8726 8601 8602 8603 8604 8728 8729 +2 6 8727 8604 8605 8729 8730 8731 +2 5 8727 8728 8730 8825 8726 +2 6 8729 8728 8731 8825 8827 8828 +2 6 8730 8728 8605 8732 8828 8829 +2 7 8731 8605 8606 8611 8612 8733 8829 +2 6 8732 8612 8613 8734 8830 8829 +2 6 8733 8613 8735 8830 8831 8736 +2 5 8734 8613 8614 8616 8736 +2 6 8735 8616 8737 8831 8734 8832 +2 6 8736 8616 8617 8738 8832 8833 +2 6 8737 8617 8739 8740 8833 8834 +2 6 8738 8617 8618 8740 8741 8742 +2 6 8738 8739 8741 8834 8835 8836 +2 7 8740 8739 8742 8624 8836 8837 8625 +2 6 8741 8739 8624 8620 8619 8618 +1 6 8381 8382 8641 8744 8931 8932 +1 5 8743 8641 8745 8932 8933 +1 6 8744 8641 8642 8746 8933 8934 +1 6 8745 8642 8643 8644 8747 8934 +1 6 8746 8644 8748 8934 8935 8936 +1 6 8747 8644 8645 8749 8936 8937 +1 6 8748 8645 8646 8750 8937 8938 +1 6 8749 8646 8647 8751 8938 8939 +1 6 8750 8647 8648 8752 8939 8940 +1 6 8751 8648 8649 8753 8940 8941 +1 6 8752 8649 8754 8941 8942 8943 +1 7 8753 8649 8650 8651 8652 8755 8943 +1 5 8754 8652 8756 8943 8944 +1 6 8755 8652 8653 8757 8944 8945 +1 6 8756 8653 8654 8655 8758 8945 +1 7 8757 8655 8656 8759 8945 8946 8947 +1 5 8758 8656 8760 8947 8948 +1 6 8759 8656 8657 8658 8761 8948 +1 6 8760 8658 8762 8948 8949 8950 +1 6 8761 8658 8659 8660 8763 8950 +1 5 8762 8660 8661 8764 8950 +1 7 8763 8661 8662 8663 8765 8950 8951 +1 6 8764 8663 8664 8766 8951 8952 +1 6 8765 8664 8767 8952 8953 8954 +1 6 8766 8664 8665 8666 8768 8954 +1 6 8767 8666 8667 8769 8954 8955 +1 6 8768 8667 8770 8955 8956 8957 +1 6 8769 8667 8668 8669 8771 8957 +1 6 8770 8669 8670 8772 8957 8958 +1 6 8771 8670 8671 8773 8958 8959 +1 6 8772 8671 8672 8774 8959 8960 +1 6 8773 8672 8673 8775 8960 8961 +1 6 8774 8673 8674 8776 8961 8962 +1 6 8775 8674 8777 8962 8963 8964 +1 6 8776 8674 8675 8676 8778 8964 +1 6 8777 8676 8677 8779 8964 8965 +2 6 8778 8677 8678 8780 8965 8966 +2 6 8779 8678 8679 8781 8966 8967 +2 6 8780 8679 8680 8782 8967 8968 +2 6 8781 8680 8681 8783 8968 8969 +2 6 8782 8681 8684 8685 8784 8969 +2 6 8783 8685 8785 8969 8970 8971 +2 6 8784 8685 8686 8786 8971 8972 +2 6 8785 8686 8787 8972 8973 8974 +2 6 8786 8686 8687 8688 8788 8974 +2 6 8787 8688 8689 8789 8974 8975 +2 6 8788 8689 8690 8691 8790 8975 +2 6 8789 8691 8791 8975 8976 8977 +2 6 8790 8691 8692 8693 8792 8977 +2 6 8791 8693 8793 8977 8978 8979 +2 6 8792 8693 8794 8979 8980 8795 +2 5 8793 8693 8694 8695 8795 +2 6 8794 8695 8696 8796 8980 8793 +2 6 8795 8696 8797 8980 8981 8982 +2 6 8796 8696 8697 8798 8982 8799 +2 5 8797 8697 8698 8699 8799 +2 6 8798 8699 8800 8801 8982 8797 +2 6 8799 8699 8700 8801 8802 8803 +2 6 8799 8800 8802 8982 8983 8984 +2 6 8801 8800 8803 8984 8985 8986 +2 6 8802 8800 8700 8701 8804 8986 +2 6 8803 8701 8702 8805 8986 8987 +2 6 8804 8702 8806 8987 8988 8989 +2 6 8805 8702 8703 8704 8807 8989 +2 6 8806 8704 8705 8808 8989 8990 +2 7 8807 8705 8706 8809 8992 8990 8993 +2 5 8808 8706 8707 8810 8993 +2 6 8809 8707 8811 8993 8994 8812 +2 6 8810 8707 8708 8709 8710 8812 +2 6 8811 8710 8813 8994 8810 8995 +2 6 8812 8710 8814 8995 8996 8997 +2 6 8813 8710 8711 8815 8997 8998 +2 5 8814 8711 8712 8816 8998 +2 7 8815 8712 8713 8714 8817 8998 8999 +2 6 8816 8714 8818 8999 9000 9001 +2 6 8817 8714 8715 8819 9001 9002 +2 6 8818 8715 8716 8718 8820 9002 +2 6 8819 8718 8720 8721 8821 9002 +2 6 8820 8721 8822 9002 9003 8823 +2 6 8821 8721 8722 8723 8724 8823 +2 6 8822 8724 8824 9003 8821 9004 +2 6 8823 8724 8725 8825 8826 9004 +2 7 8824 8725 8726 8729 8730 8826 8827 +2 6 8824 8825 8827 9004 9005 9006 +2 6 8826 8825 8730 8828 9012 9006 +2 6 8827 8730 8731 8829 8830 9012 +2 5 8828 8731 8830 8733 8732 +2 7 8828 8829 8733 8734 8831 9011 9012 +2 6 8830 8734 8736 8832 9013 9011 +2 7 8831 8736 8737 8833 9013 9014 9015 +2 6 8832 8737 8738 8834 9015 9016 +2 6 8833 8738 8740 8835 9016 9017 +2 6 8834 8740 8836 9017 9018 9019 +2 6 8835 8740 8741 8837 9019 9020 +2 5 8836 8741 8625 8838 9020 +2 6 8837 8625 8626 8839 9020 9021 +2 6 8838 8626 8840 9021 9022 9023 +2 6 8839 8626 8627 8841 9023 9024 +2 6 8840 8627 8628 8842 9024 9025 +2 6 8841 8628 8629 8630 8843 9025 +2 6 8842 8630 8844 9025 9026 9030 +2 6 8843 8630 8631 8633 8845 9030 +2 6 8844 8633 8846 8847 9031 9030 +2 6 8845 8633 8634 8637 8847 8848 +2 6 8845 8846 8848 9031 9032 9033 +2 6 8847 8846 8637 8849 9042 9033 +2 6 8848 8637 8638 8850 9043 9042 +2 6 8849 8638 8851 9043 9044 9045 +2 6 8850 8638 8639 8852 9045 9048 +2 6 8851 8639 7762 7763 8853 9048 +2 6 8852 7763 7765 8319 8854 9048 +2 6 8853 8319 8321 8855 9047 9048 +2 6 8854 8321 8856 9047 9049 9050 +2 5 8855 8321 8323 8857 9050 +2 7 8856 8323 8324 8328 8858 9050 8860 +2 6 8857 8328 8329 8330 8859 8860 +2 6 8858 8330 8860 8861 8862 8331 +2 6 8858 8859 8861 9050 8857 9051 +2 6 8860 8859 8862 8863 9051 9052 +2 6 8861 8859 8863 8864 8865 8331 +2 6 8861 8862 8864 8877 9058 9052 +2 6 8863 8862 8865 8866 8877 8878 +2 6 8864 8862 8866 8333 8332 8331 +2 6 8864 8865 8333 8867 8878 8879 +2 6 8866 8333 8334 8335 8868 8879 +2 6 8867 8335 8869 8879 8880 8871 +2 6 8868 8335 8336 8338 8870 8871 +2 6 8869 8338 8871 8872 8873 8874 +2 6 8869 8870 8872 8894 8880 8868 +2 6 8871 8870 8873 8896 8894 8897 +2 6 8872 8870 8874 8897 8898 8902 +2 6 8873 8870 8338 8339 8875 8902 +2 6 8874 8339 8347 8902 8349 8348 +2 6 8346 8340 8341 8342 8344 8345 +2 5 8863 8864 8878 9058 8882 +2 6 8877 8864 8866 8879 8881 8882 +2 6 8878 8866 8867 8868 8880 8881 +2 6 8879 8868 8881 8893 8894 8871 +2 6 8879 8880 8878 8882 8883 8893 +2 6 8878 8881 8883 8884 9058 8877 +2 6 8882 8881 8884 8885 8892 8893 +2 6 8882 8883 8885 8886 8887 9058 +2 6 8884 8883 8886 8890 8891 8892 +2 6 8884 8885 8887 8888 8889 8890 +2 6 8884 8886 8888 9058 9057 9059 +2 6 8887 8886 8889 9059 9060 9061 +2 6 8888 8886 8890 9061 9062 9063 +2 6 8889 8886 8885 8891 9063 9064 +2 6 8890 8885 8892 9064 9065 9066 +2 6 8891 8885 8883 8893 9066 8895 +2 6 8892 8883 8881 8880 8894 8895 +2 6 8893 8880 8895 8896 8872 8871 +2 6 8893 8894 8896 9066 8892 9067 +2 6 8895 8894 8872 8897 9067 9068 +2 6 8896 8872 8873 8898 8899 9068 +2 6 8897 8873 8899 8900 8901 8902 +2 6 8897 8898 8900 9068 9069 9070 +2 6 8899 8898 8901 9070 9071 8903 +2 6 8900 8898 8902 8349 8350 8903 +2 6 8901 8898 8873 8874 8875 8349 +2 6 8901 8350 8351 8904 9071 8900 +2 6 8903 8351 8905 9071 9072 9073 +1 6 8904 8351 8352 8906 9073 9074 +1 6 8905 8352 8353 8907 9074 9075 +1 6 8906 8353 8354 8908 9075 9076 +1 6 8907 8354 8909 9076 9077 8911 +1 6 8908 8354 8355 8357 8910 8911 +1 6 8909 8357 8911 8912 8360 8359 +1 6 8909 8910 8912 9077 8908 9078 +1 6 8911 8910 8360 8913 9078 9079 +1 6 8912 8360 8361 8914 8915 9079 +1 6 8913 8361 8362 8915 8916 8363 +1 6 8913 8914 8916 9079 9080 9081 +1 6 8915 8914 8363 8917 9081 9082 +1 6 8916 8363 8364 8918 9082 9083 +1 6 8917 8364 8365 8919 9083 9084 +1 6 8918 8365 8366 8920 9093 9084 +1 6 8919 8366 8367 8921 9093 9100 +1 6 8920 8367 8368 8922 9100 9101 +1 6 8921 8368 8369 8923 9101 9102 +1 6 8922 8369 8370 8924 9102 9103 +1 6 8923 8370 8925 9103 9104 9105 +1 6 8924 8370 8371 8926 9105 9106 +1 6 8925 8371 8372 8374 8927 9106 +1 6 8926 8374 8928 9106 9107 8931 +1 6 8927 8374 8375 8929 8931 8930 +1 6 8928 8375 8376 8377 8379 8930 +1 5 8929 8379 8380 8931 8928 +1 8 8930 8380 8381 8743 8932 9107 8927 8928 +1 5 8931 8743 8744 8933 9107 +1 8 8932 8744 8745 8934 9107 9106 9105 9108 +1 6 8933 8745 8746 8747 8935 9108 +1 6 8934 8747 8936 9108 9109 9110 +1 6 8935 8747 8748 8937 9110 9111 +1 6 8936 8748 8749 8938 9111 9112 +1 6 8937 8749 8750 8939 9112 9113 +1 6 8938 8750 8751 8940 9113 9114 +1 6 8939 8751 8752 8941 9114 9115 +1 6 8940 8752 8753 8942 9115 9116 +1 6 8941 8753 8943 9116 9117 8944 +1 5 8942 8753 8754 8755 8944 +1 7 8943 8755 8756 8945 9117 8942 9118 +1 7 8944 8756 8757 8758 8946 9118 9119 +1 5 8945 8758 8947 9119 9120 +1 6 8946 8758 8759 8948 9120 9121 +1 7 8947 8759 8760 8761 8949 9121 9122 +1 6 8948 8761 8950 9122 9123 8951 +1 6 8949 8761 8762 8763 8764 8951 +1 6 8950 8764 8765 8952 9123 8949 +1 6 8951 8765 8766 8953 9123 9124 +1 6 8952 8766 8954 9124 9125 9126 +1 6 8953 8766 8767 8768 8955 9126 +1 6 8954 8768 8769 8956 9126 9127 +1 6 8955 8769 8957 9127 9128 9129 +1 6 8956 8769 8770 8771 8958 9129 +1 6 8957 8771 8772 8959 9129 9130 +1 6 8958 8772 8773 8960 9130 9131 +1 6 8959 8773 8774 8961 9131 9132 +1 6 8960 8774 8775 8962 9132 9133 +1 6 8961 8775 8776 8963 9133 9134 +1 6 8962 8776 8964 9134 9135 9136 +1 6 8963 8776 8777 8778 8965 9136 +1 6 8964 8778 8779 8966 9136 9137 +2 6 8965 8779 8780 8967 9137 9138 +2 6 8966 8780 8781 8968 9138 9139 +2 6 8967 8781 8782 8969 9139 9140 +2 7 8968 8782 8783 8784 8970 9140 9141 +2 5 8969 8784 8971 9141 9142 +2 7 8970 8784 8785 8972 9142 9143 9144 +2 6 8971 8785 8786 8973 9144 9145 +2 6 8972 8786 8974 9145 9146 9147 +2 6 8973 8786 8787 8788 8975 9147 +2 6 8974 8788 8789 8790 8976 9147 +2 6 8975 8790 8977 9147 9148 9149 +2 6 8976 8790 8791 8792 8978 9149 +2 6 8977 8792 8979 9149 9150 9151 +2 6 8978 8792 8793 8980 9151 9152 +2 6 8979 8793 8795 8796 8981 9152 +2 6 8980 8796 8982 9152 9153 8983 +2 6 8981 8796 8797 8799 8801 8983 +2 6 8982 8801 8984 9153 8981 9154 +2 6 8983 8801 8802 8985 9154 9155 +2 6 8984 8802 8986 9155 9156 9157 +2 7 8985 8802 8803 8804 8987 9157 9158 +2 5 8986 8804 8805 8988 9158 +2 7 8987 8805 8989 8990 8991 9158 9159 +2 5 8988 8805 8806 8807 8990 +2 6 8989 8807 8988 8991 8992 8808 +2 6 8988 8990 8992 9159 9160 9161 +2 6 8991 8990 8808 8993 9164 9161 +2 6 8992 8808 8809 8810 8994 9164 +2 6 8993 8810 8812 8995 9164 9165 +2 7 8994 8812 8813 8996 9165 9167 9168 +2 5 8995 8813 8997 9168 9169 +2 6 8996 8813 8814 8998 9169 9170 +2 7 8997 8814 8815 8816 8999 9170 9171 +2 5 8998 8816 8817 9000 9171 +2 6 8999 8817 9001 9171 9172 9173 +2 6 9000 8817 8818 9002 9173 9003 +2 6 9001 8818 8819 8820 8821 9003 +2 6 9002 8821 8823 9004 9173 9001 +2 6 9003 8823 8824 8826 9005 9173 +2 6 9004 8826 9006 9007 9008 9173 +2 6 9005 8826 9007 9011 9012 8827 +2 6 9005 9006 9008 9009 9010 9011 +2 6 9005 9007 9009 9173 9172 9174 +2 5 9008 9007 9010 9174 9177 +2 6 9009 9007 9011 9013 9177 9014 +2 7 9010 9007 9006 9012 9013 8831 8830 +2 5 9011 9006 8830 8828 8827 +2 5 9010 9011 8831 8832 9014 +2 6 9013 8832 9015 9177 9010 9178 +2 6 9014 8832 8833 9016 9181 9178 +2 5 9015 8833 8834 9017 9181 +2 7 9016 8834 8835 9018 9181 9182 9188 +2 6 9017 8835 9019 9188 9189 9190 +2 6 9018 8835 8836 9020 9190 9191 +2 6 9019 8836 8837 8838 9021 9191 +2 6 9020 8838 8839 9022 9191 9192 +2 6 9021 8839 9023 9192 9195 9196 +2 6 9022 8839 8840 9024 9196 9197 +2 6 9023 8840 8841 9025 9197 9027 +2 6 9024 8841 8842 8843 9026 9027 +2 6 9025 8843 9027 9028 9029 9030 +2 6 9025 9026 9028 9197 9024 9198 +2 6 9027 9026 9029 9198 9199 9203 +2 5 9028 9026 9030 9031 9203 +2 6 9029 9026 8843 9031 8845 8844 +2 7 9029 9030 8845 8847 9032 9203 9204 +2 6 9031 8847 9033 9034 9204 9205 +2 6 9032 8847 9034 9035 9042 8848 +2 6 9032 9033 9035 9036 9037 9205 +2 6 9034 9033 9036 9040 9041 9042 +2 6 9034 9035 9037 9038 9039 9040 +2 6 9034 9036 9038 9205 9206 9207 +2 6 9037 9036 9039 9207 9208 9209 +2 6 9038 9036 9040 9209 9062 9061 +2 6 9039 9036 9035 9041 9061 9060 +2 6 9040 9035 9042 9043 9060 9210 +2 6 9041 9035 9033 8848 9043 8849 +2 6 9041 9042 8849 8850 9044 9210 +2 7 9043 8850 9045 9046 9055 9056 9210 +2 6 9044 8850 8851 9046 9047 9048 +2 6 9044 9045 9047 9053 9055 9049 +2 6 9046 9045 9048 8854 8855 9049 +2 6 9047 9045 8851 8854 8853 8852 +2 6 9047 8855 9050 9051 9053 9046 +2 6 9049 8855 8856 8857 8860 9051 +2 6 9050 8860 8861 9052 9053 9049 +2 6 9051 8861 9053 9054 9058 8863 +2 6 9051 9052 9054 9055 9046 9049 +2 6 9053 9052 9055 9056 9057 9058 +2 5 9053 9054 9046 9044 9056 +2 6 9044 9055 9054 9057 9059 9210 +2 5 9056 9054 9058 8887 9059 +2 8 9057 9054 9052 8863 8877 8882 8884 8887 +2 6 9057 8887 8888 9060 9210 9056 +2 6 9059 8888 9061 9040 9041 9210 +2 6 9060 8888 8889 9062 9039 9040 +2 6 9061 8889 9063 9209 9039 9211 +2 6 9062 8889 8890 9064 9211 9212 +2 6 9063 8890 8891 9065 9212 9213 +2 6 9064 8891 9066 9213 9214 9215 +2 6 9065 8891 8892 8895 9067 9215 +2 6 9066 8895 8896 9068 9215 9216 +2 6 9067 8896 8897 8899 9069 9216 +2 6 9068 8899 9070 9216 9217 9218 +2 6 9069 8899 8900 9071 9218 9219 +2 7 9070 8900 8903 8904 9072 9219 9220 +2 5 9071 8904 9073 9220 9221 +1 7 9072 8904 8905 9074 9221 9222 9223 +1 6 9073 8905 8906 9075 9223 9225 +1 6 9074 8906 8907 9076 9225 9226 +1 5 9075 8907 8908 9077 9226 +1 7 9076 8908 8911 9078 9226 9227 9228 +1 5 9077 8911 8912 9079 9228 +1 6 9078 8912 8913 8915 9080 9228 +1 6 9079 8915 9081 9228 9229 9230 +1 6 9080 8915 8916 9082 9230 9231 +1 6 9081 8916 8917 9083 9231 9232 +1 6 9082 8917 8918 9084 9085 9232 +1 6 9083 8918 9085 9086 9093 8919 +1 6 9083 9084 9086 9087 9232 9233 +1 6 9085 9084 9087 9088 9092 9093 +1 6 9085 9086 9088 9089 9233 9234 +1 6 9087 9086 9089 9090 9091 9092 +1 6 9087 9088 9090 9095 9234 9235 +1 6 9089 9088 9091 9095 9096 9097 +1 6 9090 9088 9092 9097 9098 9099 +1 6 9091 9088 9086 9093 9099 9100 +1 6 9092 9086 9084 8919 8920 9100 +1 5 8469 8470 8485 8476 8471 +1 6 9089 9090 9096 9235 9236 9237 +1 6 9095 9090 9097 9237 9238 9239 +1 6 9096 9090 9091 9098 9239 9240 +1 6 9097 9091 9099 9240 9241 9242 +1 6 9098 9091 9092 9100 9242 9101 +1 6 9099 9092 9093 8920 8921 9101 +1 6 9100 8921 8922 9102 9242 9099 +1 6 9101 8922 8923 9103 9242 9243 +1 6 9102 8923 8924 9104 9243 9244 +1 6 9103 8924 9105 9109 9244 9108 +1 6 9104 8924 8925 9106 8933 9108 +1 6 9105 8925 8926 8927 9107 8933 +1 5 9106 8927 8931 8932 8933 +1 6 9105 8933 8934 8935 9109 9104 +1 5 9108 8935 9110 9244 9104 +1 7 9109 8935 8936 9111 9245 9244 9348 +1 6 9110 8936 8937 9112 9350 9348 +1 5 9111 8937 8938 9113 9350 +1 6 9112 8938 8939 9114 9350 9351 +1 6 9113 8939 8940 9115 9351 9352 +1 6 9114 8940 8941 9116 9352 9353 +1 6 9115 8941 8942 9117 9246 9353 +1 6 9116 8942 8944 9118 9246 9247 +1 6 9117 8944 8945 9119 9247 9248 +1 5 9118 8945 8946 9120 9248 +1 7 9119 8946 8947 9121 9248 9249 9250 +1 6 9120 8947 8948 9122 9250 9251 +1 5 9121 8948 8949 9123 9251 +1 6 9122 8949 8951 8952 9124 9251 +1 6 9123 8952 8953 9125 9251 9252 +1 6 9124 8953 9126 9252 9253 9254 +1 6 9125 8953 8954 8955 9127 9254 +1 6 9126 8955 8956 9128 9254 9255 +1 6 9127 8956 9129 9255 9256 9257 +1 6 9128 8956 8957 8958 9130 9257 +1 6 9129 8958 8959 9131 9257 9258 +1 6 9130 8959 8960 9132 9258 9259 +1 6 9131 8960 8961 9133 9259 9260 +1 6 9132 8961 8962 9134 9260 9261 +1 6 9133 8962 8963 9135 9261 9262 +1 6 9134 8963 9136 9262 9263 9264 +1 6 9135 8963 8964 8965 9137 9264 +1 6 9136 8965 8966 9138 9264 9265 +2 6 9137 8966 8967 9139 9265 9266 +2 6 9138 8967 8968 9140 9266 9267 +2 6 9139 8968 8969 9141 9267 9268 +2 5 9140 8969 8970 9142 9268 +2 7 9141 8970 8971 9143 9268 9269 9270 +2 6 9142 8971 9144 9270 9271 9272 +2 5 9143 8971 8972 9145 9272 +2 6 9144 8972 8973 9146 9272 9273 +2 6 9145 8973 9147 9273 9274 9148 +2 6 9146 8973 8974 8975 8976 9148 +2 6 9147 8976 9149 9274 9146 9275 +2 6 9148 8976 8977 8978 9150 9275 +2 6 9149 8978 9151 9275 9276 9277 +2 6 9150 8978 8979 9152 9277 9278 +2 7 9151 8979 8980 8981 9153 9278 9279 +2 6 9152 8981 8983 9154 9279 9280 +2 6 9153 8983 8984 9155 9280 9281 +2 6 9154 8984 8985 9156 9281 9282 +2 6 9155 8985 9157 9282 9283 9284 +2 6 9156 8985 8986 9158 9284 9285 +2 6 9157 8986 8987 8988 9159 9285 +2 6 9158 8988 8991 9160 9285 9286 +2 6 9159 8991 9161 9162 9286 9287 +2 6 9160 8991 9162 9163 9164 8992 +2 6 9160 9161 9163 9287 9288 9289 +2 6 9162 9161 9164 9165 9166 9289 +2 6 9163 9161 8992 8993 8994 9165 +2 6 9164 8994 8995 9163 9166 9167 +2 6 9163 9165 9167 9289 9290 9186 +2 6 9166 9165 8995 9168 9186 9185 +2 6 9167 8995 8996 9169 9185 9184 +2 7 9168 8996 8997 9170 9184 9179 9176 +2 6 9169 8997 8998 9171 9176 9175 +2 6 9170 8998 8999 9000 9172 9175 +2 6 9171 9000 9173 9008 9174 9175 +2 7 9172 9000 9001 9003 9004 9005 9008 +2 6 9172 9008 9009 9175 9176 9177 +2 5 9172 9174 9176 9170 9171 +2 6 9175 9174 9177 9179 9169 9170 +2 7 9176 9174 9009 9010 9014 9178 9179 +2 6 9177 9014 9179 9180 9181 9015 +2 6 9177 9178 9180 9184 9169 9176 +2 6 9179 9178 9181 9182 9183 9184 +2 6 9180 9178 9015 9016 9017 9182 +2 6 9181 9017 9180 9183 9187 9188 +2 6 9180 9182 9184 9185 9186 9187 +2 6 9180 9183 9185 9168 9169 9179 +2 5 9184 9183 9186 9167 9168 +2 6 9185 9183 9187 9290 9166 9167 +2 6 9186 9183 9182 9188 9290 9291 +2 6 9187 9182 9017 9018 9189 9291 +2 5 9188 9018 9190 9291 9292 +2 6 9189 9018 9019 9191 9292 9193 +2 6 9190 9019 9020 9021 9192 9193 +2 6 9191 9021 9022 9193 9194 9195 +2 6 9191 9192 9194 9292 9190 9293 +2 6 9193 9192 9195 9293 9294 9295 +2 6 9194 9192 9022 9196 9295 9296 +2 6 9195 9022 9023 9197 9302 9296 +2 7 9196 9023 9024 9027 9198 9302 9303 +2 6 9197 9027 9028 9199 9200 9303 +2 6 9198 9028 9200 9201 9202 9203 +2 6 9198 9199 9201 9303 9301 9304 +2 6 9200 9199 9202 9304 9305 9306 +2 6 9201 9199 9203 9306 9307 9204 +2 6 9202 9199 9028 9029 9031 9204 +2 7 9203 9031 9032 9205 9307 9202 9206 +2 5 9204 9032 9034 9037 9206 +2 6 9205 9037 9207 9307 9204 9308 +2 6 9206 9037 9038 9208 9308 9309 +2 6 9207 9038 9209 9309 9310 9314 +2 6 9208 9038 9039 9062 9211 9314 +2 6 9060 9041 9043 9059 9056 9044 +2 6 9209 9062 9063 9212 9314 9315 +2 6 9211 9063 9064 9213 9315 9316 +2 6 9212 9064 9065 9214 9319 9316 +2 6 9213 9065 9215 9319 9320 9321 +2 6 9214 9065 9066 9067 9216 9321 +2 6 9215 9067 9068 9069 9217 9321 +2 7 9216 9069 9218 9321 9320 9322 9323 +2 5 9217 9069 9070 9219 9323 +2 7 9218 9070 9071 9220 9323 9324 9325 +2 5 9219 9071 9072 9221 9325 +2 7 9220 9072 9073 9222 9325 9326 9327 +1 6 9221 9073 9223 9224 9327 9328 +1 5 9222 9073 9074 9224 9225 +1 6 9222 9223 9225 9328 9329 9330 +1 6 9224 9223 9074 9075 9226 9330 +1 7 9225 9075 9076 9077 9227 9330 9331 +1 6 9226 9077 9228 9331 9332 9229 +1 6 9227 9077 9078 9079 9080 9229 +1 7 9228 9080 9230 9332 9227 9333 9334 +1 6 9229 9080 9081 9231 9334 9335 +1 6 9230 9081 9082 9232 9335 9336 +1 7 9231 9082 9083 9085 9233 9336 9337 +1 5 9232 9085 9087 9234 9337 +1 7 9233 9087 9089 9235 9337 9338 9339 +1 5 9234 9089 9095 9236 9339 +1 7 9235 9095 9237 9339 9340 9341 9342 +1 6 9236 9095 9096 9238 9342 9343 +1 6 9237 9096 9239 9343 9344 9345 +1 6 9238 9096 9097 9240 9345 9346 +1 6 9239 9097 9098 9241 9346 9347 +1 6 9240 9098 9242 9347 9245 9243 +1 6 9241 9098 9099 9101 9102 9243 +1 6 9242 9102 9103 9244 9245 9241 +1 6 9243 9103 9245 9110 9109 9104 +1 6 9243 9244 9110 9347 9241 9348 +1 6 9116 9117 9247 9353 9354 9355 +1 6 9246 9117 9118 9248 9355 9356 +1 6 9247 9118 9119 9120 9249 9356 +1 6 9248 9120 9250 9356 9357 9358 +1 6 9249 9120 9121 9251 9358 9252 +1 6 9250 9121 9122 9123 9124 9252 +1 7 9251 9124 9125 9253 9358 9250 9359 +1 5 9252 9125 9254 9359 9360 +1 7 9253 9125 9126 9127 9255 9360 9361 +1 6 9254 9127 9128 9256 9361 9362 +1 6 9255 9128 9257 9362 9363 9364 +1 6 9256 9128 9129 9130 9258 9364 +1 7 9257 9130 9131 9259 9364 9365 9366 +1 6 9258 9131 9132 9260 9366 9367 +1 6 9259 9132 9133 9261 9367 9368 +1 6 9260 9133 9134 9262 9368 9369 +1 6 9261 9134 9135 9263 9369 9370 +1 6 9262 9135 9264 9370 9371 9372 +1 6 9263 9135 9136 9137 9265 9372 +1 6 9264 9137 9138 9266 9372 9373 +2 6 9265 9138 9139 9267 9373 9374 +2 6 9266 9139 9140 9268 9374 9375 +2 7 9267 9140 9141 9142 9269 9375 9376 +2 5 9268 9142 9270 9376 9377 +2 6 9269 9142 9143 9271 9377 9381 +2 6 9270 9143 9272 9381 9382 9383 +2 6 9271 9143 9144 9145 9273 9383 +2 6 9272 9145 9146 9274 9383 9384 +2 6 9273 9146 9148 9275 9384 9385 +2 7 9274 9148 9149 9150 9276 9385 9386 +2 5 9275 9150 9277 9386 9388 +2 6 9276 9150 9151 9278 9388 9389 +2 6 9277 9151 9152 9279 9389 9390 +2 6 9278 9152 9153 9280 9390 9391 +2 5 9279 9153 9154 9281 9391 +2 6 9280 9154 9155 9282 9393 9391 +2 6 9281 9155 9156 9283 9393 9394 +2 6 9282 9156 9284 9394 9395 9396 +2 6 9283 9156 9157 9285 9396 9397 +2 6 9284 9157 9158 9159 9286 9397 +2 6 9285 9159 9160 9287 9397 9398 +2 5 9286 9160 9162 9288 9398 +2 7 9287 9162 9289 9398 9399 9400 9401 +2 6 9288 9162 9163 9166 9290 9401 +2 7 9289 9166 9186 9187 9291 9402 9401 +2 6 9290 9187 9188 9189 9292 9402 +2 7 9291 9189 9190 9193 9293 9402 9400 +2 6 9292 9193 9194 9294 9400 9403 +2 6 9293 9194 9295 9403 9404 9405 +2 6 9294 9194 9195 9296 9297 9405 +2 6 9295 9195 9297 9298 9302 9196 +2 6 9295 9296 9298 9299 9405 9406 +2 6 9297 9296 9299 9300 9301 9302 +2 6 9297 9298 9300 9409 9406 9410 +2 6 9299 9298 9301 9410 9411 9412 +2 7 9300 9298 9302 9303 9200 9304 9412 +2 6 9301 9298 9296 9196 9197 9303 +2 5 9302 9197 9198 9200 9301 +2 5 9301 9200 9201 9305 9412 +2 7 9304 9201 9306 9412 9413 9414 9418 +2 5 9305 9201 9202 9307 9418 +2 6 9306 9202 9204 9206 9308 9418 +2 6 9307 9206 9207 9309 9417 9418 +2 6 9308 9207 9208 9310 9311 9417 +2 6 9309 9208 9311 9312 9313 9314 +2 6 9309 9310 9312 9416 9417 9419 +2 6 9311 9310 9313 9419 9420 9424 +2 7 9312 9310 9314 9424 9425 9317 9315 +2 6 9313 9310 9208 9209 9211 9315 +2 6 9314 9211 9212 9316 9317 9313 +2 6 9315 9212 9317 9318 9319 9213 +2 6 9315 9316 9318 9425 9313 9426 +2 6 9317 9316 9319 9426 9427 9428 +2 6 9318 9316 9213 9214 9320 9428 +2 6 9319 9214 9321 9217 9322 9428 +2 5 9320 9214 9215 9216 9217 +2 6 9320 9217 9323 9428 9429 9430 +2 6 9322 9217 9218 9219 9324 9430 +2 6 9323 9219 9325 9430 9431 9432 +2 6 9324 9219 9220 9221 9326 9432 +2 6 9325 9221 9327 9432 9433 9434 +2 6 9326 9221 9222 9328 9434 9435 +1 5 9327 9222 9224 9329 9435 +1 7 9328 9224 9330 9435 9436 9437 9438 +1 6 9329 9224 9225 9226 9331 9438 +1 6 9330 9226 9227 9332 9438 9439 +1 6 9331 9227 9229 9333 9442 9439 +1 6 9332 9229 9334 9442 9443 9446 +1 5 9333 9229 9230 9335 9446 +1 6 9334 9230 9231 9336 9446 9447 +1 6 9335 9231 9232 9337 9447 9448 +1 6 9336 9232 9233 9234 9338 9448 +1 6 9337 9234 9339 9448 9449 9450 +1 6 9338 9234 9235 9236 9340 9450 +1 6 9339 9236 9341 9450 9451 9452 +1 6 9340 9236 9342 9452 9453 9454 +1 6 9341 9236 9237 9343 9454 9455 +1 5 9342 9237 9238 9344 9455 +1 7 9343 9238 9345 9455 9456 9457 9458 +1 6 9344 9238 9239 9346 9458 9349 +1 5 9345 9239 9240 9347 9349 +1 6 9346 9240 9241 9245 9348 9349 +1 6 9347 9245 9349 9350 9111 9110 +1 7 9347 9348 9350 9458 9345 9346 9351 +1 6 9349 9348 9111 9112 9113 9351 +1 7 9350 9113 9114 9352 9458 9349 9459 +1 6 9351 9114 9115 9353 9459 9460 +1 6 9352 9115 9116 9246 9354 9460 +1 6 9353 9246 9355 9460 9461 9462 +1 6 9354 9246 9247 9356 9462 9463 +1 6 9355 9247 9248 9249 9357 9463 +1 6 9356 9249 9358 9463 9464 9465 +1 6 9357 9249 9250 9252 9359 9465 +1 5 9358 9252 9253 9360 9465 +1 7 9359 9253 9254 9361 9465 9466 9467 +1 5 9360 9254 9255 9362 9467 +1 6 9361 9255 9256 9363 9467 9468 +1 6 9362 9256 9364 9468 9469 9470 +1 6 9363 9256 9257 9258 9365 9470 +1 6 9364 9258 9366 9470 9471 9472 +1 5 9365 9258 9259 9367 9472 +1 6 9366 9259 9260 9368 9472 9473 +1 6 9367 9260 9261 9369 9473 9474 +1 6 9368 9261 9262 9370 9474 9475 +1 6 9369 9262 9263 9371 9475 9476 +1 6 9370 9263 9372 9476 9477 9478 +1 6 9371 9263 9264 9265 9373 9478 +1 6 9372 9265 9266 9374 9478 9479 +2 6 9373 9266 9267 9375 9479 9480 +2 6 9374 9267 9268 9376 9480 9481 +2 6 9375 9268 9269 9377 9378 9481 +2 7 9376 9269 9270 9378 9379 9380 9381 +2 5 9376 9377 9379 9481 9482 +2 6 9378 9377 9380 9482 9483 9484 +2 6 9379 9377 9381 9484 9485 9382 +2 5 9380 9377 9270 9271 9382 +2 6 9381 9271 9383 9485 9380 9486 +2 7 9382 9271 9272 9273 9384 9486 9487 +2 6 9383 9273 9274 9385 9487 9488 +2 6 9384 9274 9275 9386 9387 9488 +2 5 9385 9275 9276 9387 9388 +2 6 9385 9386 9388 9488 9489 9490 +2 7 9387 9386 9276 9277 9389 9490 9491 +2 6 9388 9277 9278 9390 9491 9492 +2 6 9389 9278 9279 9391 9392 9492 +2 6 9390 9279 9392 9393 9281 9280 +2 6 9390 9391 9393 9492 9493 9494 +2 6 9392 9391 9281 9282 9394 9494 +2 6 9393 9282 9283 9395 9494 9495 +2 6 9394 9283 9396 9495 9496 9497 +2 6 9395 9283 9284 9397 9498 9497 +2 6 9396 9284 9285 9286 9398 9498 +2 6 9397 9286 9287 9288 9399 9498 +2 6 9398 9288 9400 9498 9404 9403 +2 7 9399 9288 9401 9402 9292 9293 9403 +2 5 9400 9288 9402 9290 9289 +2 5 9400 9401 9290 9291 9292 +2 5 9400 9293 9294 9404 9399 +2 6 9403 9294 9405 9498 9399 9407 +2 6 9404 9294 9295 9297 9406 9407 +2 6 9405 9297 9407 9408 9409 9299 +2 6 9405 9406 9408 9497 9498 9404 +2 6 9407 9406 9409 9496 9497 9499 +2 6 9408 9406 9299 9410 9499 9500 +2 6 9409 9299 9300 9411 9500 9501 +2 6 9410 9300 9412 9501 9502 9413 +2 6 9411 9300 9301 9304 9305 9413 +2 6 9412 9305 9414 9415 9502 9411 +2 6 9413 9305 9415 9416 9417 9418 +2 6 9413 9414 9416 9502 9503 9504 +2 6 9415 9414 9417 9311 9419 9504 +2 6 9416 9414 9418 9308 9309 9311 +2 6 9417 9414 9308 9307 9306 9305 +2 6 9416 9311 9312 9420 9421 9504 +2 6 9419 9312 9421 9422 9423 9424 +2 6 9419 9420 9422 9504 9505 9506 +2 6 9421 9420 9423 9506 9507 9508 +2 6 9422 9420 9424 9511 9508 9512 +2 6 9423 9420 9312 9313 9425 9512 +2 5 9424 9313 9317 9426 9512 +2 6 9425 9317 9318 9427 9512 9513 +2 6 9426 9318 9428 9513 9514 9429 +2 6 9427 9318 9319 9320 9322 9429 +2 6 9428 9322 9430 9517 9514 9427 +2 6 9429 9322 9323 9324 9431 9517 +2 6 9430 9324 9432 9524 9517 9525 +2 6 9431 9324 9325 9326 9433 9525 +2 6 9432 9326 9434 9525 9526 9527 +2 6 9433 9326 9327 9435 9527 9528 +2 6 9434 9327 9328 9329 9436 9528 +2 6 9435 9329 9437 9528 9530 9531 +1 6 9436 9329 9438 9531 9532 9440 +1 6 9437 9329 9330 9331 9439 9440 +1 6 9438 9331 9440 9441 9442 9332 +1 5 9438 9439 9441 9532 9437 +1 7 9440 9439 9442 9443 9444 9532 9533 +1 5 9441 9439 9332 9333 9443 +1 6 9442 9333 9441 9444 9445 9446 +1 5 9441 9443 9445 9533 9534 +1 6 9444 9443 9446 9534 9535 9536 +1 7 9445 9443 9333 9334 9335 9447 9536 +1 6 9446 9335 9336 9448 9536 9537 +1 6 9447 9336 9337 9338 9449 9537 +1 6 9448 9338 9450 9537 9538 9451 +1 5 9449 9338 9339 9340 9451 +1 7 9450 9340 9452 9538 9449 9539 9540 +1 6 9451 9340 9341 9453 9540 9541 +1 6 9452 9341 9454 9541 9542 9543 +1 6 9453 9341 9342 9455 9543 9544 +1 6 9454 9342 9343 9344 9456 9544 +1 6 9455 9344 9457 9544 9545 9461 +1 6 9456 9344 9458 9461 9460 9459 +1 6 9457 9344 9345 9349 9351 9459 +1 5 9458 9351 9352 9460 9457 +1 6 9459 9352 9353 9354 9461 9457 +1 6 9460 9354 9462 9545 9456 9457 +1 5 9461 9354 9355 9463 9545 +1 7 9462 9355 9356 9357 9464 9545 9546 +1 6 9463 9357 9465 9546 9547 9548 +1 7 9464 9357 9358 9359 9360 9466 9548 +1 6 9465 9360 9467 9548 9549 9550 +1 6 9466 9360 9361 9362 9468 9550 +1 6 9467 9362 9363 9469 9550 9551 +1 6 9468 9363 9470 9551 9552 9553 +1 6 9469 9363 9364 9365 9471 9553 +1 6 9470 9365 9472 9553 9554 9555 +1 6 9471 9365 9366 9367 9473 9555 +1 6 9472 9367 9368 9474 9555 9556 +1 6 9473 9368 9369 9475 9556 9557 +1 6 9474 9369 9370 9476 9557 9558 +1 6 9475 9370 9371 9477 9558 9559 +1 6 9476 9371 9478 9559 9560 9561 +1 6 9477 9371 9372 9373 9479 9561 +1 6 9478 9373 9374 9480 9561 9562 +2 6 9479 9374 9375 9481 9562 9563 +2 6 9480 9375 9376 9378 9482 9563 +2 6 9481 9378 9379 9483 9563 9564 +2 6 9482 9379 9484 9564 9565 9566 +2 6 9483 9379 9380 9485 9566 9567 +2 6 9484 9380 9382 9486 9567 9568 +2 6 9485 9382 9383 9487 9568 9569 +2 6 9486 9383 9384 9488 9569 9570 +2 6 9487 9384 9385 9387 9489 9570 +2 6 9488 9387 9490 9570 9571 9572 +2 6 9489 9387 9388 9491 9572 9573 +2 6 9490 9388 9389 9492 9573 9574 +2 6 9491 9389 9390 9392 9493 9574 +2 6 9492 9392 9494 9574 9575 9576 +2 6 9493 9392 9393 9394 9495 9576 +2 6 9494 9394 9395 9496 9576 9577 +2 6 9495 9395 9497 9408 9499 9577 +2 6 9496 9395 9408 9407 9498 9396 +2 7 9407 9497 9396 9397 9398 9399 9404 +2 5 9496 9408 9409 9500 9577 +2 7 9499 9409 9410 9501 9577 9578 9579 +2 6 9500 9410 9411 9502 9579 9580 +2 6 9501 9411 9413 9415 9503 9580 +2 6 9502 9415 9504 9580 9581 9582 +2 7 9503 9415 9416 9419 9421 9505 9582 +2 5 9504 9421 9506 9582 9583 +2 6 9505 9421 9422 9507 9583 9584 +2 6 9506 9422 9508 9509 9584 9585 +2 6 9507 9422 9509 9510 9511 9423 +2 6 9507 9508 9510 9585 9586 9587 +2 6 9509 9508 9511 9518 9587 9521 +2 6 9510 9508 9423 9512 9518 9519 +2 7 9511 9423 9424 9425 9426 9513 9519 +2 6 9512 9426 9427 9514 9515 9519 +2 6 9513 9427 9515 9516 9517 9429 +2 6 9513 9514 9516 9519 9518 9520 +2 6 9515 9514 9517 9523 9520 9524 +2 6 9516 9514 9429 9430 9524 9431 +2 6 9510 9511 9519 9515 9520 9521 +2 5 9518 9511 9512 9513 9515 +2 6 9518 9515 9521 9522 9523 9516 +2 6 9518 9520 9522 9587 9510 9588 +2 6 9521 9520 9523 9588 9589 9590 +2 6 9522 9520 9516 9524 9590 9591 +2 6 9523 9516 9517 9431 9525 9591 +2 7 9524 9431 9432 9433 9526 9591 9592 +2 5 9525 9433 9527 9592 9593 +2 6 9526 9433 9434 9528 9529 9593 +2 6 9527 9434 9435 9436 9529 9530 +2 6 9527 9528 9530 9593 9594 9595 +2 6 9529 9528 9436 9531 9595 9596 +2 6 9530 9436 9437 9532 9596 9597 +1 7 9531 9437 9440 9441 9533 9597 9598 +1 5 9532 9441 9444 9534 9598 +1 7 9533 9444 9445 9535 9598 9599 9600 +1 6 9534 9445 9536 9600 9601 9602 +1 7 9535 9445 9446 9447 9537 9602 9603 +1 6 9536 9447 9448 9449 9538 9603 +1 6 9537 9449 9451 9539 9603 9604 +1 6 9538 9451 9540 9604 9605 9606 +1 6 9539 9451 9452 9541 9606 9607 +1 5 9540 9452 9453 9542 9607 +1 7 9541 9453 9543 9607 9608 9609 9610 +1 5 9542 9453 9454 9544 9610 +1 7 9543 9454 9455 9456 9545 9610 9546 +1 6 9544 9456 9461 9462 9463 9546 +1 6 9545 9463 9464 9547 9610 9544 +1 6 9546 9464 9548 9610 9609 9549 +1 5 9547 9464 9465 9466 9549 +1 6 9548 9466 9550 9609 9547 9611 +1 6 9549 9466 9467 9468 9551 9611 +1 6 9550 9468 9469 9552 9611 9612 +1 6 9551 9469 9553 9612 9613 9614 +1 6 9552 9469 9470 9471 9554 9614 +1 6 9553 9471 9555 9614 9615 9616 +1 6 9554 9471 9472 9473 9556 9616 +1 6 9555 9473 9474 9557 9616 9617 +1 6 9556 9474 9475 9558 9617 9618 +1 6 9557 9475 9476 9559 9618 9619 +1 6 9558 9476 9477 9560 9619 9620 +1 6 9559 9477 9561 9620 9621 9622 +1 6 9560 9477 9478 9479 9562 9622 +1 6 9561 9479 9480 9563 9622 9623 +2 6 9562 9480 9481 9482 9564 9623 +2 6 9563 9482 9483 9565 9623 9624 +2 6 9564 9483 9566 9624 9625 9626 +2 6 9565 9483 9484 9567 9626 9627 +2 6 9566 9484 9485 9568 9627 9628 +2 7 9567 9485 9486 9569 9628 9629 9630 +2 6 9568 9486 9487 9570 9630 9631 +2 6 9569 9487 9488 9489 9571 9631 +2 6 9570 9489 9572 9631 9632 9633 +2 6 9571 9489 9490 9573 9633 9634 +2 6 9572 9490 9491 9574 9634 9635 +2 6 9573 9491 9492 9493 9575 9635 +2 6 9574 9493 9576 9635 9636 9578 +2 6 9575 9493 9494 9495 9577 9578 +2 6 9576 9495 9496 9499 9500 9578 +2 6 9577 9500 9579 9636 9575 9576 +2 6 9578 9500 9501 9580 9636 9581 +2 5 9579 9501 9502 9503 9581 +2 6 9580 9503 9582 9636 9579 9637 +2 6 9581 9503 9504 9505 9583 9637 +2 6 9582 9505 9506 9584 9637 9638 +2 6 9583 9506 9507 9585 9638 9633 +2 6 9584 9507 9509 9586 9633 9632 +2 6 9585 9509 9587 9632 9639 9629 +2 6 9586 9509 9510 9521 9588 9629 +2 6 9587 9521 9522 9589 9629 9628 +2 6 9588 9522 9590 9628 9627 9640 +2 6 9589 9522 9523 9591 9640 9641 +2 6 9590 9523 9524 9525 9592 9641 +2 6 9591 9525 9526 9593 9641 9642 +2 7 9592 9526 9527 9529 9594 9642 9643 +2 5 9593 9529 9595 9643 9644 +2 6 9594 9529 9530 9596 9644 9645 +2 6 9595 9530 9531 9597 9645 9646 +1 6 9596 9531 9532 9598 9646 9647 +1 6 9597 9532 9533 9534 9599 9647 +1 5 9598 9534 9600 9647 9648 +1 7 9599 9534 9535 9601 9648 9649 9650 +1 5 9600 9535 9602 9650 9651 +1 6 9601 9535 9536 9603 9651 9604 +1 5 9602 9536 9537 9538 9604 +1 6 9603 9538 9539 9605 9651 9602 +1 6 9604 9539 9606 9651 9652 9653 +1 6 9605 9539 9540 9607 9653 9613 +1 6 9606 9540 9541 9542 9608 9613 +1 6 9607 9542 9609 9613 9612 9611 +1 6 9608 9542 9610 9547 9549 9611 +1 6 9609 9542 9543 9544 9546 9547 +1 6 9609 9549 9550 9551 9612 9608 +1 5 9611 9551 9552 9613 9608 +1 7 9612 9552 9614 9653 9606 9607 9608 +1 6 9613 9552 9553 9554 9615 9653 +1 6 9614 9554 9616 9653 9652 9654 +1 6 9615 9554 9555 9556 9617 9654 +1 6 9616 9556 9557 9618 9654 9655 +1 6 9617 9557 9558 9619 9655 9656 +1 6 9618 9558 9559 9620 9656 9657 +1 6 9619 9559 9560 9621 9657 9658 +1 6 9620 9560 9622 9658 9659 9660 +1 6 9621 9560 9561 9562 9623 9660 +2 6 9622 9562 9563 9564 9624 9660 +2 7 9623 9564 9565 9625 9660 9661 9662 +2 5 9624 9565 9626 9662 9663 +2 7 9625 9565 9566 9627 9663 9664 9640 +2 6 9626 9566 9567 9628 9589 9640 +2 6 9627 9567 9568 9629 9588 9589 +2 7 9628 9568 9630 9639 9586 9587 9588 +2 5 9629 9568 9569 9631 9639 +2 6 9630 9569 9570 9571 9632 9639 +2 6 9631 9571 9633 9585 9586 9639 +2 7 9632 9571 9572 9634 9638 9584 9585 +2 6 9633 9572 9573 9635 9637 9638 +2 6 9634 9573 9574 9575 9636 9637 +2 6 9635 9575 9578 9579 9581 9637 +2 7 9636 9581 9582 9583 9638 9635 9634 +2 5 9637 9583 9584 9633 9634 +2 5 9632 9586 9629 9630 9631 +2 6 9627 9589 9590 9641 9664 9626 +2 6 9640 9590 9591 9592 9642 9664 +2 6 9641 9592 9593 9643 9664 9663 +2 6 9642 9593 9594 9644 9663 9662 +2 7 9643 9594 9595 9645 9662 9661 9665 +2 7 9644 9595 9596 9646 9665 9659 9666 +1 6 9645 9596 9597 9647 9666 9667 +1 6 9646 9597 9598 9599 9648 9667 +1 6 9647 9599 9600 9649 9667 9668 +1 6 9648 9600 9650 9668 9656 9655 +1 6 9649 9600 9601 9651 9655 9669 +1 7 9650 9601 9602 9604 9605 9652 9669 +1 6 9651 9605 9653 9615 9654 9669 +1 6 9652 9605 9606 9613 9614 9615 +1 6 9652 9615 9616 9617 9655 9669 +1 7 9654 9617 9618 9656 9649 9650 9669 +1 6 9655 9618 9619 9657 9668 9649 +1 5 9656 9619 9620 9658 9668 +1 6 9657 9620 9621 9659 9668 9666 +1 6 9658 9621 9660 9665 9645 9666 +2 7 9659 9621 9622 9623 9624 9661 9665 +2 5 9660 9624 9662 9644 9665 +2 6 9661 9624 9625 9663 9643 9644 +2 6 9662 9625 9626 9664 9642 9643 +2 5 9663 9626 9640 9641 9642 +2 5 9661 9644 9645 9659 9660 +1 6 9659 9645 9646 9667 9668 9658 +1 5 9666 9646 9647 9648 9668 +1 7 9667 9648 9649 9656 9657 9658 9666 +1 5 9655 9650 9651 9652 9654 +1 6 6653 6650 6651 9671 9691 9681 +1 6 9670 6651 9672 9676 9680 9681 +1 6 9671 6651 9673 9674 9675 9676 +1 6 9672 6651 9674 6649 9727 6365 +1 6 9672 9673 9675 9725 9726 9727 +1 6 9672 9674 9676 9677 9678 9725 +1 6 9672 9675 9677 9679 9680 9671 +1 5 9676 9675 9678 5235 9679 +1 7 9677 9675 5235 9734 4519 9725 9733 +1 6 9677 5235 5236 9676 9680 9683 +1 7 9676 9679 9671 9681 9682 4654 9683 +1 6 9671 9680 9682 9691 9670 9685 +1 5 9681 9680 4654 4655 9685 +1 6 4654 9680 9679 5236 4652 9684 +1 6 4652 9683 4650 422 5237 5236 +1 6 9682 4655 9686 9687 9691 9681 +1 6 9685 4655 9687 3169 9688 4656 +1 6 9685 9686 3169 3170 9691 3172 +1 7 3169 9686 4656 9689 3168 2843 9690 +1 5 9688 4656 5380 430 9690 +1 6 2843 9688 9689 430 2841 429 +1 6 9685 9687 3172 6653 9670 9681 +1 6 6475 6478 6474 9779 9774 9780 +1 6 6460 6461 6465 6467 6377 6378 +1 6 5862 5863 9695 9702 9703 9700 +1 6 9694 5863 5864 9696 5719 9700 +1 5 9695 5864 5865 5718 5719 +1 6 5718 5865 5866 5867 9698 9699 +1 6 9697 5867 9699 5695 5694 5868 +1 5 9697 9698 5695 5696 5718 +1 6 9695 5719 5720 9701 9702 9694 +1 5 9700 5720 5721 5724 9702 +1 6 9701 5724 6095 9703 9694 9700 +1 6 9702 6095 6383 9694 5862 5861 +1 6 6490 2252 415 2194 6488 6489 +1 7 6488 2195 6487 6480 2196 9773 9778 +1 5 2251 6491 3336 6492 3335 +1 6 3335 6492 3334 6499 6493 6494 +1 6 6502 6503 9709 2189 9711 9712 +1 6 6502 9708 2189 6501 9710 2190 +1 6 6501 9709 6500 2190 2191 2512 +1 7 9708 6503 6512 9712 9715 9716 9717 +1 5 9708 9711 2189 9713 9715 +1 6 2189 9712 2187 2197 9714 9715 +1 6 2197 9713 9715 2215 2216 9720 +1 6 9714 9713 9712 9711 9716 2215 +1 7 9715 9711 9717 9718 9719 2214 2215 +1 6 9716 9711 6512 6513 6514 9718 +1 5 9717 6514 6516 9719 9716 +1 5 9718 6516 9716 2214 6522 +1 6 9714 2216 2217 2200 2198 2197 +1 6 6669 6775 9722 9723 6656 6658 +1 5 9721 6775 9723 9724 9798 +1 6 9721 9722 9724 6646 6656 6655 +1 6 9723 9722 6646 6645 9799 9798 +1 6 9675 9674 9726 9678 9733 9735 +1 6 9725 9674 9727 9729 9735 9728 +1 6 9726 9674 9673 6365 6366 9728 +1 6 9727 6366 6368 6370 9729 9726 +1 6 9728 6370 9730 9731 9735 9726 +1 6 9729 6370 6371 6375 6467 9731 +1 6 9730 6467 6466 9732 9735 9729 +1 6 9731 6466 6468 7510 9733 9735 +1 6 9732 7510 9734 9735 9678 9725 +1 6 9733 7510 7508 4518 4519 9678 +1 6 9732 9733 9731 9729 9726 9725 +1 6 6041 6039 6038 6019 5872 5874 +1 6 6132 6398 6392 6393 6115 9738 +1 6 9737 6115 6116 6132 6131 6122 +1 6 569 571 9740 9744 568 9743 +1 6 9739 571 573 9741 9742 9743 +1 6 9740 573 916 917 9742 918 +1 6 9740 9741 918 9743 921 919 +1 6 9740 9742 921 563 9744 9739 +1 6 9743 563 564 567 568 9739 +2 6 7205 7206 9746 7218 7217 7216 +2 6 9745 7206 7207 7213 7216 7214 +1 6 3491 3492 3496 3502 6706 6555 +1 5 6706 3502 9749 3503 6710 +1 5 6706 9748 6710 6707 6705 +1 5 6682 5157 4667 6681 9761 +1 5 3201 3470 3410 3200 3411 +1 6 5932 5910 5915 5916 9755 5931 +1 5 4915 4917 9754 4880 4879 +1 7 9753 4917 4911 4880 9756 4904 9759 +1 7 9752 5916 5931 5921 5920 5919 9758 +1 6 4880 9754 9757 4895 4897 9759 +1 5 4880 9756 4895 4884 4881 +1 5 5919 9755 5918 5916 5917 +1 6 9754 4904 4901 4898 4897 9756 +1 6 4638 4912 4875 4872 4869 4868 +1 7 6681 9750 4667 4668 9762 4560 9792 +1 5 9761 4668 4546 4548 4560 +1 5 8468 8469 9764 9765 8486 +1 5 8468 9763 9765 7726 7962 +1 7 9764 9763 8486 7714 7715 7723 7726 +2 6 8023 8021 7738 7739 7740 7742 +1 5 7723 7715 7716 7719 7721 +1 6 427 7500 7502 9769 46 45 +1 6 9768 7502 9770 9772 44 45 +1 7 9769 7502 7503 9771 9772 9774 9780 +1 7 2196 43 1 9772 9770 9773 9774 +1 5 9771 1 9770 9769 44 +1 6 2196 9771 9774 9705 9778 9779 +1 6 9773 9771 9770 9779 9692 9780 +1 6 7253 7256 7523 7520 7517 7516 +1 6 2095 2083 2084 6093 3138 3131 +1 5 6638 6639 6642 6787 6785 +1 5 9705 9773 9779 6478 6480 +1 5 9778 9773 9774 9692 6478 +1 5 9692 9774 6474 9770 7503 +1 6 3852 3129 26 25 1526 3130 +1 6 6787 6642 6643 9783 6789 6170 +1 5 9782 6643 6168 6169 6170 +2 6 4396 4529 4395 4121 4119 4530 +1 6 6637 6783 6779 6636 6635 6771 +2 6 4118 3529 3531 9787 9789 4120 +2 6 9786 3531 3533 9788 7174 9789 +2 6 9787 3533 3535 7178 7175 7174 +2 6 9787 7174 9786 4120 4122 7172 +1 5 7670 7695 7696 7698 7669 +2 6 7775 3145 4231 3413 3414 7776 +1 6 4560 6675 6676 6677 6681 9761 +1 6 3659 3660 4908 9794 4369 4371 +1 5 9793 4908 4642 4370 4369 +1 6 5543 5545 5700 5540 5541 5542 +1 6 6177 6178 9797 9798 6181 9799 +1 6 6782 6177 9796 9798 6776 6780 +1 7 9797 9796 6776 9799 9724 9722 6775 +1 6 9796 6181 6183 6645 9724 9798 diff --git a/scotch_6.0.3/src/check/data/bump_old.map b/scotch_6.0.3/src/check/data/bump_old.map new file mode 100644 index 00000000..28738482 --- /dev/null +++ b/scotch_6.0.3/src/check/data/bump_old.map @@ -0,0 +1,9801 @@ +9800 +0 24 +1 18 +2 0 +3 14 +4 11 +5 30 +6 24 +7 24 +8 24 +9 24 +10 24 +11 24 +12 24 +13 24 +14 24 +15 27 +16 27 +17 27 +18 27 +19 27 +20 27 +21 27 +22 27 +23 27 +24 27 +25 27 +26 27 +27 27 +28 27 +29 27 +30 27 +31 27 +32 27 +33 27 +34 27 +35 27 +36 27 +37 18 +38 18 +39 18 +40 18 +41 18 +42 18 +43 18 +44 18 +45 18 +46 18 +47 18 +48 18 +49 18 +50 18 +51 18 +52 16 +53 16 +54 16 +55 16 +56 16 +57 16 +58 16 +59 16 +60 16 +61 16 +62 16 +63 16 +64 16 +65 16 +66 16 +67 16 +68 16 +69 16 +70 0 +71 0 +72 0 +73 0 +74 0 +75 0 +76 0 +77 0 +78 0 +79 0 +80 0 +81 0 +82 0 +83 0 +84 2 +85 2 +86 2 +87 2 +88 2 +89 2 +90 2 +91 2 +92 2 +93 2 +94 2 +95 2 +96 3 +97 3 +98 3 +99 3 +100 3 +101 3 +102 3 +103 3 +104 3 +105 3 +106 3 +107 3 +108 3 +109 3 +110 3 +111 3 +112 3 +113 13 +114 13 +115 13 +116 13 +117 13 +118 13 +119 13 +120 13 +121 13 +122 13 +123 13 +124 14 +125 14 +126 14 +127 14 +128 14 +129 14 +130 14 +131 14 +132 14 +133 14 +134 14 +135 14 +136 14 +137 14 +138 14 +139 14 +140 14 +141 14 +142 14 +143 14 +144 14 +145 14 +146 14 +147 14 +148 14 +149 14 +150 14 +151 14 +152 14 +153 14 +154 14 +155 14 +156 14 +157 15 +158 15 +159 15 +160 15 +161 15 +162 15 +163 15 +164 15 +165 15 +166 15 +167 15 +168 15 +169 15 +170 15 +171 15 +172 15 +173 15 +174 15 +175 15 +176 8 +177 8 +178 8 +179 8 +180 8 +181 8 +182 8 +183 8 +184 8 +185 8 +186 8 +187 8 +188 11 +189 11 +190 11 +191 11 +192 11 +193 11 +194 11 +195 11 +196 11 +197 11 +198 11 +199 11 +200 11 +201 11 +202 11 +203 11 +204 11 +205 11 +206 11 +207 11 +208 11 +209 11 +210 11 +211 11 +212 11 +213 11 +214 11 +215 11 +216 11 +217 11 +218 11 +219 11 +220 11 +221 11 +222 11 +223 11 +224 10 +225 10 +226 10 +227 10 +228 10 +229 10 +230 10 +231 10 +232 10 +233 10 +234 10 +235 10 +236 10 +237 10 +238 10 +239 10 +240 10 +241 10 +242 10 +243 10 +244 10 +245 10 +246 10 +247 4 +248 4 +249 4 +250 4 +251 4 +252 4 +253 4 +254 4 +255 4 +256 4 +257 4 +258 5 +259 5 +260 5 +261 5 +262 5 +263 5 +264 5 +265 5 +266 5 +267 5 +268 5 +269 5 +270 5 +271 5 +272 20 +273 20 +274 20 +275 20 +276 20 +277 20 +278 20 +279 20 +280 20 +281 20 +282 20 +283 20 +284 20 +285 20 +286 20 +287 20 +288 20 +289 22 +290 22 +291 22 +292 22 +293 22 +294 22 +295 22 +296 22 +297 22 +298 22 +299 22 +300 22 +301 22 +302 22 +303 22 +304 22 +305 22 +306 22 +307 22 +308 22 +309 22 +310 22 +311 22 +312 22 +313 22 +314 28 +315 28 +316 28 +317 28 +318 28 +319 28 +320 28 +321 28 +322 28 +323 28 +324 30 +325 30 +326 30 +327 30 +328 30 +329 30 +330 30 +331 30 +332 30 +333 30 +334 30 +335 30 +336 30 +337 30 +338 30 +339 30 +340 30 +341 30 +342 30 +343 30 +344 30 +345 30 +346 30 +347 30 +348 30 +349 30 +350 30 +351 30 +352 30 +353 30 +354 30 +355 30 +356 31 +357 31 +358 31 +359 31 +360 31 +361 31 +362 31 +363 31 +364 31 +365 31 +366 31 +367 31 +368 31 +369 31 +370 31 +371 31 +372 25 +373 25 +374 25 +375 25 +376 25 +377 25 +378 25 +379 25 +380 25 +381 25 +382 25 +383 25 +384 25 +385 25 +386 24 +387 24 +388 24 +389 24 +390 24 +391 24 +392 24 +393 24 +394 24 +395 24 +396 24 +397 24 +398 24 +399 24 +400 24 +401 24 +402 24 +403 24 +404 24 +405 24 +406 24 +407 24 +408 16 +409 0 +410 18 +411 18 +412 24 +413 24 +414 27 +415 18 +416 18 +417 24 +418 24 +419 24 +420 24 +421 18 +422 18 +423 24 +424 24 +425 25 +426 18 +427 18 +428 0 +429 16 +430 16 +431 4 +432 5 +433 5 +434 5 +435 5 +436 5 +437 5 +438 5 +439 5 +440 5 +441 5 +442 5 +443 5 +444 5 +445 5 +446 20 +447 20 +448 20 +449 20 +450 20 +451 20 +452 20 +453 20 +454 20 +455 20 +456 20 +457 20 +458 20 +459 20 +460 20 +461 20 +462 22 +463 22 +464 22 +465 22 +466 22 +467 22 +468 22 +469 22 +470 22 +471 22 +472 22 +473 22 +474 22 +475 22 +476 22 +477 22 +478 22 +479 22 +480 22 +481 22 +482 22 +483 22 +484 22 +485 22 +486 22 +487 28 +488 28 +489 28 +490 28 +491 28 +492 28 +493 28 +494 28 +495 28 +496 28 +497 28 +498 30 +499 30 +500 30 +501 30 +502 30 +503 30 +504 30 +505 30 +506 30 +507 30 +508 30 +509 30 +510 30 +511 30 +512 30 +513 30 +514 30 +515 30 +516 30 +517 30 +518 30 +519 30 +520 30 +521 30 +522 30 +523 30 +524 30 +525 30 +526 30 +527 30 +528 30 +529 31 +530 31 +531 31 +532 31 +533 31 +534 31 +535 31 +536 31 +537 31 +538 31 +539 31 +540 31 +541 31 +542 31 +543 31 +544 31 +545 25 +546 25 +547 25 +548 25 +549 25 +550 25 +551 25 +552 25 +553 25 +554 25 +555 25 +556 25 +557 25 +558 25 +559 25 +560 25 +561 25 +562 25 +563 25 +564 25 +565 25 +566 25 +567 25 +568 25 +569 25 +570 25 +571 25 +572 25 +573 25 +574 25 +575 24 +576 24 +577 24 +578 24 +579 24 +580 24 +581 24 +582 24 +583 24 +584 24 +585 24 +586 24 +587 24 +588 24 +589 24 +590 24 +591 24 +592 24 +593 24 +594 24 +595 24 +596 24 +597 24 +598 24 +599 24 +600 24 +601 24 +602 24 +603 24 +604 24 +605 24 +606 24 +607 24 +608 24 +609 24 +610 24 +611 24 +612 24 +613 24 +614 24 +615 24 +616 24 +617 24 +618 24 +619 24 +620 24 +621 24 +622 24 +623 24 +624 24 +625 24 +626 24 +627 24 +628 24 +629 24 +630 24 +631 24 +632 24 +633 24 +634 24 +635 24 +636 24 +637 24 +638 24 +639 24 +640 24 +641 24 +642 24 +643 24 +644 24 +645 24 +646 24 +647 24 +648 24 +649 24 +650 24 +651 15 +652 15 +653 15 +654 15 +655 15 +656 15 +657 15 +658 15 +659 15 +660 15 +661 15 +662 15 +663 15 +664 8 +665 8 +666 8 +667 8 +668 8 +669 8 +670 8 +671 8 +672 8 +673 8 +674 8 +675 11 +676 11 +677 11 +678 11 +679 11 +680 11 +681 11 +682 11 +683 11 +684 11 +685 11 +686 11 +687 11 +688 11 +689 11 +690 11 +691 11 +692 11 +693 11 +694 11 +695 11 +696 11 +697 11 +698 11 +699 11 +700 11 +701 11 +702 11 +703 11 +704 11 +705 11 +706 11 +707 11 +708 11 +709 10 +710 10 +711 10 +712 10 +713 10 +714 10 +715 10 +716 10 +717 10 +718 10 +719 10 +720 10 +721 10 +722 10 +723 10 +724 10 +725 10 +726 10 +727 10 +728 10 +729 10 +730 10 +731 10 +732 4 +733 4 +734 4 +735 4 +736 4 +737 4 +738 4 +739 4 +740 4 +741 4 +742 4 +743 4 +744 4 +745 5 +746 5 +747 5 +748 5 +749 5 +750 5 +751 5 +752 5 +753 5 +754 5 +755 5 +756 5 +757 5 +758 20 +759 20 +760 20 +761 20 +762 20 +763 20 +764 20 +765 20 +766 20 +767 20 +768 20 +769 20 +770 20 +771 20 +772 20 +773 20 +774 20 +775 22 +776 22 +777 22 +778 22 +779 22 +780 22 +781 22 +782 22 +783 22 +784 22 +785 22 +786 22 +787 22 +788 22 +789 22 +790 22 +791 22 +792 22 +793 22 +794 22 +795 22 +796 22 +797 22 +798 22 +799 28 +800 28 +801 28 +802 28 +803 28 +804 28 +805 28 +806 28 +807 28 +808 28 +809 28 +810 28 +811 30 +812 30 +813 30 +814 30 +815 30 +816 30 +817 30 +818 30 +819 30 +820 30 +821 30 +822 30 +823 30 +824 30 +825 30 +826 30 +827 30 +828 30 +829 30 +830 30 +831 30 +832 30 +833 30 +834 30 +835 30 +836 30 +837 30 +838 30 +839 30 +840 31 +841 31 +842 31 +843 31 +844 31 +845 31 +846 31 +847 31 +848 31 +849 31 +850 31 +851 31 +852 31 +853 31 +854 31 +855 31 +856 31 +857 31 +858 31 +859 25 +860 25 +861 25 +862 25 +863 25 +864 25 +865 25 +866 25 +867 25 +868 25 +869 25 +870 25 +871 25 +872 25 +873 25 +874 25 +875 25 +876 25 +877 25 +878 25 +879 25 +880 25 +881 25 +882 25 +883 25 +884 25 +885 25 +886 25 +887 25 +888 25 +889 25 +890 25 +891 25 +892 25 +893 25 +894 25 +895 24 +896 24 +897 24 +898 25 +899 24 +900 24 +901 25 +902 24 +903 25 +904 24 +905 24 +906 24 +907 24 +908 24 +909 24 +910 24 +911 24 +912 24 +913 24 +914 24 +915 24 +916 25 +917 25 +918 25 +919 25 +920 25 +921 25 +922 25 +923 14 +924 14 +925 14 +926 15 +927 15 +928 15 +929 15 +930 15 +931 15 +932 15 +933 15 +934 15 +935 15 +936 15 +937 15 +938 15 +939 15 +940 15 +941 15 +942 15 +943 15 +944 15 +945 15 +946 8 +947 8 +948 8 +949 8 +950 8 +951 8 +952 8 +953 8 +954 8 +955 8 +956 8 +957 11 +958 11 +959 11 +960 11 +961 11 +962 11 +963 11 +964 11 +965 11 +966 11 +967 11 +968 11 +969 11 +970 11 +971 11 +972 11 +973 11 +974 11 +975 11 +976 11 +977 11 +978 11 +979 11 +980 11 +981 11 +982 11 +983 11 +984 11 +985 11 +986 11 +987 11 +988 10 +989 10 +990 10 +991 10 +992 10 +993 10 +994 10 +995 10 +996 10 +997 10 +998 10 +999 10 +1000 10 +1001 10 +1002 10 +1003 10 +1004 10 +1005 10 +1006 10 +1007 10 +1008 10 +1009 10 +1010 10 +1011 4 +1012 4 +1013 4 +1014 4 +1015 4 +1016 4 +1017 4 +1018 4 +1019 4 +1020 4 +1021 4 +1022 4 +1023 4 +1024 4 +1025 4 +1026 4 +1027 5 +1028 5 +1029 5 +1030 5 +1031 5 +1032 5 +1033 5 +1034 5 +1035 5 +1036 5 +1037 5 +1038 5 +1039 20 +1040 20 +1041 20 +1042 20 +1043 20 +1044 20 +1045 20 +1046 20 +1047 20 +1048 20 +1049 20 +1050 20 +1051 20 +1052 20 +1053 20 +1054 20 +1055 20 +1056 22 +1057 22 +1058 22 +1059 22 +1060 22 +1061 22 +1062 22 +1063 22 +1064 22 +1065 22 +1066 22 +1067 22 +1068 22 +1069 22 +1070 22 +1071 22 +1072 22 +1073 22 +1074 22 +1075 22 +1076 22 +1077 22 +1078 22 +1079 22 +1080 22 +1081 28 +1082 28 +1083 28 +1084 28 +1085 28 +1086 28 +1087 28 +1088 28 +1089 28 +1090 28 +1091 28 +1092 28 +1093 30 +1094 30 +1095 30 +1096 30 +1097 30 +1098 30 +1099 30 +1100 30 +1101 30 +1102 30 +1103 30 +1104 30 +1105 30 +1106 30 +1107 30 +1108 30 +1109 30 +1110 30 +1111 30 +1112 30 +1113 30 +1114 30 +1115 30 +1116 30 +1117 30 +1118 30 +1119 30 +1120 30 +1121 31 +1122 31 +1123 31 +1124 31 +1125 31 +1126 31 +1127 31 +1128 31 +1129 31 +1130 31 +1131 31 +1132 31 +1133 31 +1134 31 +1135 31 +1136 31 +1137 31 +1138 31 +1139 25 +1140 25 +1141 25 +1142 25 +1143 25 +1144 25 +1145 25 +1146 25 +1147 25 +1148 25 +1149 25 +1150 25 +1151 25 +1152 31 +1153 31 +1154 31 +1155 31 +1156 31 +1157 25 +1158 25 +1159 25 +1160 2 +1161 2 +1162 2 +1163 2 +1164 25 +1165 25 +1166 25 +1167 25 +1168 25 +1169 25 +1170 25 +1171 27 +1172 27 +1173 27 +1174 2 +1175 2 +1176 2 +1177 2 +1178 2 +1179 2 +1180 2 +1181 2 +1182 2 +1183 2 +1184 2 +1185 2 +1186 2 +1187 2 +1188 2 +1189 2 +1190 2 +1191 2 +1192 3 +1193 3 +1194 3 +1195 3 +1196 3 +1197 3 +1198 3 +1199 3 +1200 3 +1201 3 +1202 3 +1203 3 +1204 3 +1205 3 +1206 3 +1207 3 +1208 13 +1209 13 +1210 13 +1211 13 +1212 13 +1213 13 +1214 13 +1215 13 +1216 13 +1217 13 +1218 13 +1219 13 +1220 14 +1221 14 +1222 14 +1223 14 +1224 14 +1225 14 +1226 14 +1227 14 +1228 14 +1229 14 +1230 14 +1231 14 +1232 14 +1233 14 +1234 14 +1235 14 +1236 14 +1237 14 +1238 14 +1239 14 +1240 14 +1241 14 +1242 14 +1243 14 +1244 14 +1245 14 +1246 14 +1247 14 +1248 14 +1249 14 +1250 14 +1251 14 +1252 14 +1253 15 +1254 15 +1255 15 +1256 15 +1257 15 +1258 15 +1259 15 +1260 15 +1261 15 +1262 15 +1263 15 +1264 15 +1265 15 +1266 15 +1267 15 +1268 15 +1269 15 +1270 15 +1271 15 +1272 8 +1273 8 +1274 8 +1275 8 +1276 8 +1277 8 +1278 8 +1279 8 +1280 8 +1281 8 +1282 8 +1283 11 +1284 11 +1285 11 +1286 11 +1287 11 +1288 11 +1289 11 +1290 11 +1291 11 +1292 11 +1293 11 +1294 11 +1295 11 +1296 11 +1297 11 +1298 11 +1299 11 +1300 11 +1301 11 +1302 11 +1303 11 +1304 11 +1305 11 +1306 11 +1307 11 +1308 11 +1309 11 +1310 11 +1311 11 +1312 10 +1313 10 +1314 10 +1315 10 +1316 10 +1317 10 +1318 10 +1319 10 +1320 10 +1321 10 +1322 10 +1323 10 +1324 10 +1325 10 +1326 10 +1327 10 +1328 10 +1329 10 +1330 10 +1331 10 +1332 10 +1333 10 +1334 10 +1335 10 +1336 4 +1337 4 +1338 4 +1339 4 +1340 4 +1341 4 +1342 4 +1343 4 +1344 4 +1345 4 +1346 4 +1347 4 +1348 4 +1349 4 +1350 4 +1351 5 +1352 5 +1353 5 +1354 5 +1355 5 +1356 5 +1357 5 +1358 5 +1359 5 +1360 5 +1361 5 +1362 5 +1363 20 +1364 20 +1365 20 +1366 20 +1367 20 +1368 20 +1369 20 +1370 20 +1371 20 +1372 20 +1373 20 +1374 20 +1375 20 +1376 20 +1377 20 +1378 20 +1379 20 +1380 22 +1381 22 +1382 22 +1383 22 +1384 22 +1385 22 +1386 22 +1387 22 +1388 22 +1389 22 +1390 22 +1391 22 +1392 22 +1393 22 +1394 22 +1395 22 +1396 22 +1397 22 +1398 22 +1399 22 +1400 22 +1401 22 +1402 22 +1403 22 +1404 22 +1405 28 +1406 28 +1407 28 +1408 28 +1409 28 +1410 28 +1411 28 +1412 28 +1413 28 +1414 28 +1415 28 +1416 28 +1417 30 +1418 30 +1419 30 +1420 30 +1421 30 +1422 30 +1423 30 +1424 30 +1425 30 +1426 30 +1427 30 +1428 30 +1429 30 +1430 30 +1431 30 +1432 30 +1433 30 +1434 30 +1435 30 +1436 30 +1437 30 +1438 30 +1439 30 +1440 30 +1441 30 +1442 31 +1443 31 +1444 31 +1445 31 +1446 31 +1447 31 +1448 31 +1449 31 +1450 31 +1451 31 +1452 31 +1453 31 +1454 31 +1455 31 +1456 31 +1457 3 +1458 3 +1459 3 +1460 3 +1461 31 +1462 31 +1463 31 +1464 31 +1465 31 +1466 31 +1467 31 +1468 31 +1469 31 +1470 31 +1471 31 +1472 31 +1473 31 +1474 0 +1475 0 +1476 0 +1477 0 +1478 0 +1479 0 +1480 0 +1481 0 +1482 2 +1483 2 +1484 2 +1485 2 +1486 2 +1487 2 +1488 2 +1489 2 +1490 31 +1491 31 +1492 31 +1493 25 +1494 25 +1495 25 +1496 25 +1497 25 +1498 25 +1499 25 +1500 3 +1501 3 +1502 0 +1503 0 +1504 2 +1505 2 +1506 24 +1507 24 +1508 24 +1509 24 +1510 24 +1511 24 +1512 24 +1513 24 +1514 24 +1515 24 +1516 24 +1517 24 +1518 24 +1519 24 +1520 24 +1521 24 +1522 24 +1523 24 +1524 27 +1525 27 +1526 27 +1527 25 +1528 25 +1529 25 +1530 25 +1531 25 +1532 25 +1533 25 +1534 25 +1535 25 +1536 24 +1537 24 +1538 24 +1539 24 +1540 24 +1541 25 +1542 24 +1543 24 +1544 24 +1545 24 +1546 13 +1547 13 +1548 13 +1549 13 +1550 13 +1551 13 +1552 13 +1553 13 +1554 13 +1555 13 +1556 13 +1557 13 +1558 13 +1559 13 +1560 13 +1561 13 +1562 24 +1563 24 +1564 24 +1565 24 +1566 24 +1567 24 +1568 24 +1569 24 +1570 24 +1571 26 +1572 26 +1573 24 +1574 24 +1575 24 +1576 24 +1577 24 +1578 24 +1579 24 +1580 24 +1581 24 +1582 24 +1583 24 +1584 24 +1585 24 +1586 24 +1587 24 +1588 24 +1589 24 +1590 24 +1591 24 +1592 24 +1593 24 +1594 24 +1595 24 +1596 24 +1597 24 +1598 24 +1599 24 +1600 24 +1601 24 +1602 24 +1603 0 +1604 0 +1605 0 +1606 0 +1607 0 +1608 0 +1609 0 +1610 0 +1611 0 +1612 0 +1613 0 +1614 0 +1615 0 +1616 0 +1617 0 +1618 0 +1619 0 +1620 0 +1621 0 +1622 0 +1623 0 +1624 0 +1625 0 +1626 0 +1627 0 +1628 0 +1629 0 +1630 0 +1631 0 +1632 0 +1633 0 +1634 0 +1635 0 +1636 0 +1637 0 +1638 0 +1639 0 +1640 2 +1641 2 +1642 2 +1643 2 +1644 2 +1645 2 +1646 2 +1647 2 +1648 2 +1649 2 +1650 2 +1651 2 +1652 2 +1653 2 +1654 2 +1655 2 +1656 2 +1657 2 +1658 2 +1659 2 +1660 2 +1661 2 +1662 2 +1663 2 +1664 2 +1665 2 +1666 2 +1667 2 +1668 3 +1669 2 +1670 2 +1671 3 +1672 3 +1673 3 +1674 3 +1675 3 +1676 3 +1677 3 +1678 3 +1679 3 +1680 3 +1681 3 +1682 3 +1683 3 +1684 3 +1685 3 +1686 3 +1687 3 +1688 3 +1689 3 +1690 3 +1691 3 +1692 3 +1693 3 +1694 13 +1695 13 +1696 13 +1697 13 +1698 13 +1699 13 +1700 13 +1701 13 +1702 13 +1703 13 +1704 13 +1705 13 +1706 13 +1707 13 +1708 13 +1709 13 +1710 13 +1711 13 +1712 13 +1713 13 +1714 13 +1715 13 +1716 13 +1717 14 +1718 14 +1719 14 +1720 14 +1721 14 +1722 14 +1723 14 +1724 14 +1725 14 +1726 14 +1727 14 +1728 14 +1729 14 +1730 14 +1731 14 +1732 14 +1733 14 +1734 14 +1735 14 +1736 14 +1737 14 +1738 14 +1739 14 +1740 14 +1741 14 +1742 14 +1743 14 +1744 14 +1745 14 +1746 14 +1747 14 +1748 14 +1749 14 +1750 14 +1751 14 +1752 14 +1753 15 +1754 15 +1755 15 +1756 15 +1757 15 +1758 15 +1759 15 +1760 15 +1761 15 +1762 15 +1763 15 +1764 15 +1765 15 +1766 15 +1767 15 +1768 15 +1769 15 +1770 15 +1771 15 +1772 8 +1773 8 +1774 8 +1775 8 +1776 8 +1777 8 +1778 8 +1779 8 +1780 8 +1781 8 +1782 11 +1783 11 +1784 11 +1785 11 +1786 11 +1787 11 +1788 11 +1789 11 +1790 11 +1791 11 +1792 11 +1793 11 +1794 11 +1795 11 +1796 11 +1797 11 +1798 11 +1799 11 +1800 11 +1801 11 +1802 10 +1803 10 +1804 10 +1805 10 +1806 10 +1807 10 +1808 10 +1809 10 +1810 10 +1811 10 +1812 10 +1813 10 +1814 10 +1815 10 +1816 10 +1817 10 +1818 10 +1819 10 +1820 10 +1821 10 +1822 10 +1823 10 +1824 10 +1825 10 +1826 4 +1827 4 +1828 4 +1829 4 +1830 4 +1831 4 +1832 4 +1833 4 +1834 4 +1835 4 +1836 4 +1837 4 +1838 4 +1839 4 +1840 4 +1841 4 +1842 5 +1843 5 +1844 5 +1845 5 +1846 5 +1847 5 +1848 5 +1849 5 +1850 5 +1851 5 +1852 5 +1853 5 +1854 20 +1855 20 +1856 20 +1857 20 +1858 20 +1859 20 +1860 20 +1861 20 +1862 20 +1863 20 +1864 20 +1865 20 +1866 20 +1867 20 +1868 20 +1869 20 +1870 20 +1871 22 +1872 22 +1873 22 +1874 22 +1875 22 +1876 22 +1877 22 +1878 22 +1879 22 +1880 22 +1881 22 +1882 22 +1883 22 +1884 22 +1885 22 +1886 22 +1887 22 +1888 22 +1889 22 +1890 22 +1891 22 +1892 22 +1893 22 +1894 22 +1895 22 +1896 28 +1897 28 +1898 28 +1899 28 +1900 28 +1901 28 +1902 28 +1903 28 +1904 28 +1905 28 +1906 28 +1907 28 +1908 30 +1909 30 +1910 30 +1911 30 +1912 30 +1913 30 +1914 30 +1915 30 +1916 30 +1917 30 +1918 30 +1919 30 +1920 30 +1921 30 +1922 30 +1923 30 +1924 30 +1925 30 +1926 30 +1927 30 +1928 30 +1929 30 +1930 30 +1931 31 +1932 31 +1933 31 +1934 31 +1935 31 +1936 31 +1937 31 +1938 31 +1939 31 +1940 31 +1941 31 +1942 31 +1943 31 +1944 31 +1945 31 +1946 31 +1947 31 +1948 31 +1949 31 +1950 31 +1951 25 +1952 25 +1953 25 +1954 25 +1955 25 +1956 25 +1957 25 +1958 25 +1959 25 +1960 25 +1961 25 +1962 25 +1963 25 +1964 25 +1965 25 +1966 20 +1967 20 +1968 20 +1969 20 +1970 20 +1971 20 +1972 20 +1973 20 +1974 20 +1975 20 +1976 20 +1977 20 +1978 20 +1979 20 +1980 20 +1981 20 +1982 22 +1983 22 +1984 22 +1985 22 +1986 22 +1987 22 +1988 22 +1989 22 +1990 22 +1991 22 +1992 22 +1993 22 +1994 22 +1995 22 +1996 22 +1997 22 +1998 22 +1999 22 +2000 22 +2001 22 +2002 22 +2003 22 +2004 22 +2005 22 +2006 28 +2007 28 +2008 28 +2009 28 +2010 28 +2011 28 +2012 28 +2013 28 +2014 28 +2015 28 +2016 28 +2017 28 +2018 30 +2019 30 +2020 30 +2021 30 +2022 30 +2023 30 +2024 30 +2025 30 +2026 30 +2027 30 +2028 30 +2029 30 +2030 30 +2031 30 +2032 30 +2033 30 +2034 30 +2035 30 +2036 30 +2037 30 +2038 30 +2039 30 +2040 31 +2041 31 +2042 31 +2043 31 +2044 31 +2045 31 +2046 31 +2047 31 +2048 31 +2049 31 +2050 31 +2051 31 +2052 31 +2053 31 +2054 31 +2055 31 +2056 31 +2057 25 +2058 25 +2059 25 +2060 25 +2061 25 +2062 25 +2063 25 +2064 25 +2065 25 +2066 25 +2067 25 +2068 25 +2069 25 +2070 25 +2071 25 +2072 25 +2073 25 +2074 25 +2075 25 +2076 25 +2077 25 +2078 25 +2079 25 +2080 25 +2081 25 +2082 25 +2083 25 +2084 25 +2085 24 +2086 25 +2087 25 +2088 25 +2089 25 +2090 25 +2091 25 +2092 25 +2093 25 +2094 25 +2095 25 +2096 25 +2097 24 +2098 11 +2099 11 +2100 11 +2101 11 +2102 11 +2103 11 +2104 11 +2105 11 +2106 11 +2107 11 +2108 11 +2109 11 +2110 11 +2111 10 +2112 10 +2113 10 +2114 10 +2115 10 +2116 10 +2117 10 +2118 10 +2119 10 +2120 10 +2121 10 +2122 10 +2123 10 +2124 10 +2125 10 +2126 10 +2127 10 +2128 10 +2129 10 +2130 10 +2131 10 +2132 10 +2133 10 +2134 10 +2135 10 +2136 4 +2137 4 +2138 4 +2139 4 +2140 4 +2141 4 +2142 4 +2143 4 +2144 4 +2145 4 +2146 4 +2147 4 +2148 4 +2149 4 +2150 4 +2151 10 +2152 10 +2153 10 +2154 4 +2155 4 +2156 4 +2157 4 +2158 4 +2159 4 +2160 4 +2161 4 +2162 4 +2163 4 +2164 4 +2165 4 +2166 4 +2167 4 +2168 4 +2169 4 +2170 5 +2171 5 +2172 14 +2173 14 +2174 14 +2175 14 +2176 14 +2177 14 +2178 14 +2179 27 +2180 27 +2181 27 +2182 27 +2183 27 +2184 27 +2185 27 +2186 27 +2187 27 +2188 27 +2189 27 +2190 27 +2191 27 +2192 27 +2193 27 +2194 18 +2195 18 +2196 18 +2197 27 +2198 27 +2199 27 +2200 27 +2201 27 +2202 27 +2203 27 +2204 27 +2205 27 +2206 27 +2207 27 +2208 27 +2209 27 +2210 27 +2211 27 +2212 27 +2213 27 +2214 27 +2215 27 +2216 27 +2217 27 +2218 16 +2219 16 +2220 16 +2221 16 +2222 16 +2223 13 +2224 13 +2225 13 +2226 13 +2227 13 +2228 13 +2229 13 +2230 13 +2231 13 +2232 13 +2233 14 +2234 14 +2235 14 +2236 14 +2237 14 +2238 13 +2239 13 +2240 13 +2241 2 +2242 14 +2243 14 +2244 14 +2245 14 +2246 14 +2247 14 +2248 27 +2249 27 +2250 27 +2251 27 +2252 18 +2253 14 +2254 15 +2255 15 +2256 15 +2257 15 +2258 15 +2259 15 +2260 15 +2261 15 +2262 15 +2263 15 +2264 15 +2265 15 +2266 15 +2267 15 +2268 15 +2269 15 +2270 15 +2271 15 +2272 8 +2273 8 +2274 8 +2275 8 +2276 8 +2277 8 +2278 8 +2279 8 +2280 8 +2281 8 +2282 8 +2283 11 +2284 11 +2285 11 +2286 11 +2287 11 +2288 11 +2289 11 +2290 11 +2291 11 +2292 11 +2293 11 +2294 11 +2295 11 +2296 11 +2297 11 +2298 11 +2299 11 +2300 11 +2301 11 +2302 11 +2303 11 +2304 11 +2305 11 +2306 11 +2307 10 +2308 10 +2309 10 +2310 10 +2311 10 +2312 10 +2313 10 +2314 10 +2315 10 +2316 10 +2317 10 +2318 10 +2319 10 +2320 10 +2321 10 +2322 10 +2323 10 +2324 10 +2325 10 +2326 10 +2327 10 +2328 10 +2329 10 +2330 10 +2331 4 +2332 4 +2333 4 +2334 4 +2335 4 +2336 4 +2337 4 +2338 4 +2339 4 +2340 4 +2341 4 +2342 4 +2343 4 +2344 4 +2345 4 +2346 5 +2347 5 +2348 5 +2349 5 +2350 5 +2351 5 +2352 5 +2353 5 +2354 5 +2355 5 +2356 5 +2357 5 +2358 5 +2359 5 +2360 5 +2361 20 +2362 20 +2363 20 +2364 20 +2365 20 +2366 20 +2367 20 +2368 20 +2369 20 +2370 20 +2371 20 +2372 20 +2373 20 +2374 20 +2375 20 +2376 20 +2377 20 +2378 20 +2379 22 +2380 22 +2381 22 +2382 22 +2383 22 +2384 22 +2385 22 +2386 22 +2387 22 +2388 22 +2389 22 +2390 22 +2391 22 +2392 22 +2393 22 +2394 22 +2395 22 +2396 22 +2397 22 +2398 22 +2399 22 +2400 22 +2401 22 +2402 28 +2403 28 +2404 28 +2405 28 +2406 28 +2407 28 +2408 28 +2409 28 +2410 28 +2411 28 +2412 28 +2413 28 +2414 28 +2415 30 +2416 30 +2417 30 +2418 30 +2419 30 +2420 30 +2421 30 +2422 30 +2423 30 +2424 30 +2425 30 +2426 30 +2427 30 +2428 30 +2429 30 +2430 30 +2431 30 +2432 30 +2433 30 +2434 30 +2435 31 +2436 31 +2437 31 +2438 31 +2439 31 +2440 31 +2441 31 +2442 31 +2443 31 +2444 31 +2445 31 +2446 31 +2447 31 +2448 31 +2449 31 +2450 31 +2451 31 +2452 31 +2453 31 +2454 31 +2455 25 +2456 25 +2457 25 +2458 25 +2459 25 +2460 25 +2461 25 +2462 25 +2463 25 +2464 25 +2465 25 +2466 25 +2467 25 +2468 25 +2469 25 +2470 25 +2471 25 +2472 25 +2473 25 +2474 24 +2475 24 +2476 24 +2477 25 +2478 25 +2479 2 +2480 2 +2481 2 +2482 25 +2483 25 +2484 25 +2485 25 +2486 25 +2487 25 +2488 25 +2489 25 +2490 2 +2491 0 +2492 0 +2493 0 +2494 2 +2495 2 +2496 2 +2497 2 +2498 2 +2499 2 +2500 2 +2501 2 +2502 27 +2503 27 +2504 27 +2505 27 +2506 27 +2507 27 +2508 27 +2509 27 +2510 27 +2511 27 +2512 27 +2513 22 +2514 22 +2515 22 +2516 28 +2517 28 +2518 28 +2519 28 +2520 28 +2521 28 +2522 28 +2523 28 +2524 28 +2525 28 +2526 28 +2527 28 +2528 28 +2529 28 +2530 30 +2531 30 +2532 30 +2533 30 +2534 30 +2535 30 +2536 30 +2537 30 +2538 30 +2539 30 +2540 30 +2541 30 +2542 30 +2543 30 +2544 30 +2545 16 +2546 16 +2547 16 +2548 16 +2549 16 +2550 16 +2551 16 +2552 30 +2553 30 +2554 30 +2555 30 +2556 30 +2557 30 +2558 30 +2559 31 +2560 13 +2561 13 +2562 13 +2563 13 +2564 13 +2565 14 +2566 14 +2567 14 +2568 14 +2569 14 +2570 30 +2571 15 +2572 15 +2573 15 +2574 15 +2575 15 +2576 15 +2577 15 +2578 15 +2579 15 +2580 8 +2581 8 +2582 8 +2583 8 +2584 8 +2585 8 +2586 8 +2587 8 +2588 8 +2589 8 +2590 8 +2591 8 +2592 11 +2593 11 +2594 11 +2595 11 +2596 11 +2597 11 +2598 11 +2599 11 +2600 11 +2601 11 +2602 11 +2603 11 +2604 11 +2605 11 +2606 11 +2607 11 +2608 11 +2609 11 +2610 11 +2611 11 +2612 11 +2613 11 +2614 10 +2615 10 +2616 10 +2617 10 +2618 10 +2619 10 +2620 10 +2621 10 +2622 10 +2623 10 +2624 10 +2625 10 +2626 10 +2627 10 +2628 10 +2629 10 +2630 10 +2631 10 +2632 10 +2633 10 +2634 10 +2635 10 +2636 10 +2637 10 +2638 10 +2639 10 +2640 10 +2641 10 +2642 4 +2643 4 +2644 4 +2645 4 +2646 4 +2647 4 +2648 4 +2649 4 +2650 4 +2651 4 +2652 4 +2653 4 +2654 4 +2655 4 +2656 4 +2657 5 +2658 5 +2659 5 +2660 5 +2661 5 +2662 5 +2663 5 +2664 5 +2665 5 +2666 5 +2667 5 +2668 5 +2669 5 +2670 5 +2671 5 +2672 5 +2673 5 +2674 20 +2675 20 +2676 20 +2677 20 +2678 20 +2679 20 +2680 20 +2681 20 +2682 20 +2683 20 +2684 20 +2685 20 +2686 20 +2687 20 +2688 20 +2689 20 +2690 20 +2691 22 +2692 22 +2693 22 +2694 22 +2695 22 +2696 22 +2697 22 +2698 22 +2699 22 +2700 22 +2701 22 +2702 22 +2703 22 +2704 22 +2705 22 +2706 22 +2707 22 +2708 22 +2709 22 +2710 22 +2711 22 +2712 22 +2713 28 +2714 28 +2715 28 +2716 28 +2717 28 +2718 28 +2719 28 +2720 28 +2721 28 +2722 28 +2723 28 +2724 28 +2725 28 +2726 28 +2727 30 +2728 30 +2729 30 +2730 30 +2731 30 +2732 30 +2733 30 +2734 30 +2735 30 +2736 30 +2737 30 +2738 30 +2739 30 +2740 30 +2741 30 +2742 30 +2743 31 +2744 31 +2745 31 +2746 31 +2747 31 +2748 31 +2749 31 +2750 31 +2751 14 +2752 14 +2753 14 +2754 14 +2755 14 +2756 14 +2757 14 +2758 14 +2759 14 +2760 14 +2761 14 +2762 15 +2763 15 +2764 15 +2765 15 +2766 15 +2767 15 +2768 15 +2769 15 +2770 15 +2771 15 +2772 15 +2773 15 +2774 15 +2775 15 +2776 15 +2777 15 +2778 15 +2779 15 +2780 8 +2781 8 +2782 8 +2783 8 +2784 8 +2785 8 +2786 8 +2787 8 +2788 8 +2789 8 +2790 8 +2791 8 +2792 11 +2793 11 +2794 11 +2795 11 +2796 11 +2797 11 +2798 11 +2799 11 +2800 11 +2801 11 +2802 11 +2803 11 +2804 14 +2805 14 +2806 14 +2807 14 +2808 14 +2809 2 +2810 2 +2811 2 +2812 2 +2813 2 +2814 2 +2815 2 +2816 3 +2817 2 +2818 2 +2819 3 +2820 3 +2821 3 +2822 3 +2823 3 +2824 11 +2825 11 +2826 11 +2827 11 +2828 11 +2829 11 +2830 11 +2831 11 +2832 11 +2833 11 +2834 10 +2835 10 +2836 10 +2837 10 +2838 10 +2839 10 +2840 10 +2841 16 +2842 16 +2843 16 +2844 16 +2845 16 +2846 16 +2847 16 +2848 16 +2849 16 +2850 16 +2851 16 +2852 16 +2853 16 +2854 16 +2855 16 +2856 16 +2857 16 +2858 16 +2859 16 +2860 16 +2861 0 +2862 0 +2863 0 +2864 0 +2865 0 +2866 0 +2867 2 +2868 2 +2869 2 +2870 2 +2871 2 +2872 2 +2873 2 +2874 2 +2875 2 +2876 2 +2877 2 +2878 2 +2879 2 +2880 2 +2881 2 +2882 2 +2883 2 +2884 2 +2885 2 +2886 2 +2887 2 +2888 2 +2889 2 +2890 2 +2891 2 +2892 2 +2893 14 +2894 14 +2895 14 +2896 14 +2897 14 +2898 14 +2899 14 +2900 14 +2901 14 +2902 14 +2903 14 +2904 14 +2905 15 +2906 15 +2907 15 +2908 15 +2909 15 +2910 15 +2911 15 +2912 15 +2913 15 +2914 15 +2915 15 +2916 15 +2917 15 +2918 15 +2919 15 +2920 15 +2921 15 +2922 15 +2923 8 +2924 8 +2925 8 +2926 8 +2927 8 +2928 8 +2929 8 +2930 8 +2931 8 +2932 8 +2933 8 +2934 8 +2935 8 +2936 11 +2937 11 +2938 11 +2939 11 +2940 11 +2941 11 +2942 11 +2943 11 +2944 11 +2945 11 +2946 11 +2947 11 +2948 11 +2949 11 +2950 11 +2951 11 +2952 11 +2953 10 +2954 10 +2955 10 +2956 10 +2957 10 +2958 10 +2959 10 +2960 10 +2961 10 +2962 10 +2963 10 +2964 10 +2965 10 +2966 10 +2967 10 +2968 10 +2969 10 +2970 10 +2971 10 +2972 10 +2973 10 +2974 10 +2975 10 +2976 10 +2977 10 +2978 10 +2979 4 +2980 4 +2981 4 +2982 4 +2983 4 +2984 4 +2985 4 +2986 4 +2987 4 +2988 4 +2989 4 +2990 4 +2991 4 +2992 4 +2993 5 +2994 5 +2995 5 +2996 5 +2997 5 +2998 5 +2999 5 +3000 5 +3001 5 +3002 5 +3003 22 +3004 22 +3005 22 +3006 22 +3007 22 +3008 22 +3009 22 +3010 22 +3011 22 +3012 22 +3013 28 +3014 28 +3015 28 +3016 28 +3017 28 +3018 28 +3019 28 +3020 28 +3021 28 +3022 28 +3023 28 +3024 28 +3025 28 +3026 28 +3027 30 +3028 30 +3029 30 +3030 30 +3031 30 +3032 30 +3033 30 +3034 30 +3035 30 +3036 30 +3037 30 +3038 30 +3039 30 +3040 30 +3041 31 +3042 30 +3043 30 +3044 30 +3045 31 +3046 31 +3047 31 +3048 31 +3049 31 +3050 31 +3051 31 +3052 31 +3053 31 +3054 31 +3055 31 +3056 31 +3057 31 +3058 31 +3059 31 +3060 31 +3061 31 +3062 31 +3063 31 +3064 31 +3065 31 +3066 31 +3067 31 +3068 31 +3069 31 +3070 31 +3071 31 +3072 31 +3073 25 +3074 25 +3075 25 +3076 25 +3077 25 +3078 25 +3079 25 +3080 25 +3081 25 +3082 25 +3083 25 +3084 25 +3085 25 +3086 27 +3087 27 +3088 27 +3089 27 +3090 27 +3091 25 +3092 25 +3093 0 +3094 0 +3095 27 +3096 27 +3097 2 +3098 24 +3099 24 +3100 24 +3101 24 +3102 24 +3103 24 +3104 27 +3105 27 +3106 27 +3107 25 +3108 25 +3109 25 +3110 25 +3111 25 +3112 25 +3113 24 +3114 24 +3115 24 +3116 24 +3117 27 +3118 27 +3119 27 +3120 27 +3121 27 +3122 27 +3123 27 +3124 27 +3125 27 +3126 27 +3127 27 +3128 27 +3129 27 +3130 27 +3131 25 +3132 25 +3133 25 +3134 25 +3135 25 +3136 25 +3137 25 +3138 25 +3139 2 +3140 2 +3141 2 +3142 2 +3143 3 +3144 3 +3145 3 +3146 3 +3147 3 +3148 25 +3149 25 +3150 25 +3151 25 +3152 25 +3153 25 +3154 25 +3155 25 +3156 25 +3157 26 +3158 26 +3159 26 +3160 26 +3161 25 +3162 16 +3163 16 +3164 16 +3165 16 +3166 16 +3167 16 +3168 16 +3169 16 +3170 16 +3171 16 +3172 16 +3173 16 +3174 16 +3175 16 +3176 16 +3177 16 +3178 16 +3179 16 +3180 16 +3181 2 +3182 2 +3183 2 +3184 0 +3185 0 +3186 0 +3187 0 +3188 0 +3189 2 +3190 2 +3191 14 +3192 0 +3193 0 +3194 0 +3195 0 +3196 0 +3197 14 +3198 14 +3199 14 +3200 14 +3201 14 +3202 14 +3203 14 +3204 14 +3205 14 +3206 14 +3207 14 +3208 14 +3209 15 +3210 15 +3211 15 +3212 15 +3213 15 +3214 0 +3215 0 +3216 0 +3217 24 +3218 24 +3219 24 +3220 24 +3221 24 +3222 24 +3223 24 +3224 24 +3225 24 +3226 24 +3227 24 +3228 24 +3229 24 +3230 24 +3231 24 +3232 24 +3233 24 +3234 24 +3235 24 +3236 24 +3237 24 +3238 24 +3239 24 +3240 24 +3241 24 +3242 11 +3243 11 +3244 11 +3245 11 +3246 10 +3247 10 +3248 10 +3249 10 +3250 10 +3251 10 +3252 10 +3253 10 +3254 10 +3255 10 +3256 10 +3257 10 +3258 10 +3259 10 +3260 10 +3261 10 +3262 10 +3263 10 +3264 10 +3265 10 +3266 10 +3267 10 +3268 10 +3269 10 +3270 10 +3271 4 +3272 4 +3273 4 +3274 4 +3275 4 +3276 4 +3277 4 +3278 20 +3279 20 +3280 22 +3281 22 +3282 22 +3283 22 +3284 22 +3285 22 +3286 22 +3287 22 +3288 22 +3289 22 +3290 22 +3291 22 +3292 22 +3293 22 +3294 22 +3295 22 +3296 22 +3297 22 +3298 22 +3299 22 +3300 22 +3301 28 +3302 28 +3303 28 +3304 28 +3305 28 +3306 28 +3307 28 +3308 28 +3309 28 +3310 28 +3311 28 +3312 28 +3313 28 +3314 28 +3315 28 +3316 30 +3317 30 +3318 30 +3319 30 +3320 30 +3321 30 +3322 30 +3323 30 +3324 30 +3325 30 +3326 31 +3327 31 +3328 31 +3329 31 +3330 27 +3331 27 +3332 27 +3333 27 +3334 27 +3335 27 +3336 27 +3337 27 +3338 27 +3339 27 +3340 27 +3341 27 +3342 27 +3343 27 +3344 27 +3345 27 +3346 27 +3347 27 +3348 27 +3349 25 +3350 25 +3351 25 +3352 25 +3353 25 +3354 25 +3355 25 +3356 25 +3357 25 +3358 25 +3359 25 +3360 25 +3361 25 +3362 25 +3363 25 +3364 25 +3365 25 +3366 25 +3367 25 +3368 25 +3369 25 +3370 25 +3371 29 +3372 29 +3373 25 +3374 25 +3375 29 +3376 29 +3377 29 +3378 29 +3379 29 +3380 25 +3381 29 +3382 25 +3383 29 +3384 29 +3385 29 +3386 29 +3387 26 +3388 26 +3389 26 +3390 26 +3391 20 +3392 20 +3393 20 +3394 20 +3395 14 +3396 14 +3397 14 +3398 14 +3399 14 +3400 14 +3401 14 +3402 14 +3403 14 +3404 14 +3405 14 +3406 14 +3407 14 +3408 14 +3409 14 +3410 14 +3411 14 +3412 3 +3413 3 +3414 3 +3415 3 +3416 13 +3417 13 +3418 13 +3419 13 +3420 13 +3421 13 +3422 13 +3423 13 +3424 13 +3425 13 +3426 13 +3427 13 +3428 13 +3429 13 +3430 13 +3431 13 +3432 13 +3433 13 +3434 13 +3435 13 +3436 0 +3437 0 +3438 0 +3439 0 +3440 0 +3441 0 +3442 13 +3443 13 +3444 13 +3445 13 +3446 13 +3447 13 +3448 13 +3449 14 +3450 16 +3451 16 +3452 16 +3453 16 +3454 14 +3455 14 +3456 14 +3457 14 +3458 14 +3459 14 +3460 14 +3461 14 +3462 14 +3463 14 +3464 14 +3465 14 +3466 14 +3467 14 +3468 14 +3469 14 +3470 14 +3471 14 +3472 14 +3473 14 +3474 14 +3475 14 +3476 14 +3477 14 +3478 14 +3479 15 +3480 15 +3481 15 +3482 15 +3483 15 +3484 24 +3485 24 +3486 24 +3487 24 +3488 24 +3489 24 +3490 24 +3491 24 +3492 24 +3493 24 +3494 24 +3495 24 +3496 24 +3497 24 +3498 24 +3499 15 +3500 15 +3501 24 +3502 24 +3503 24 +3504 24 +3505 16 +3506 16 +3507 16 +3508 0 +3509 0 +3510 0 +3511 0 +3512 0 +3513 0 +3514 0 +3515 0 +3516 0 +3517 0 +3518 0 +3519 0 +3520 0 +3521 0 +3522 0 +3523 0 +3524 0 +3525 0 +3526 0 +3527 0 +3528 0 +3529 0 +3530 0 +3531 0 +3532 0 +3533 0 +3534 0 +3535 0 +3536 0 +3537 0 +3538 0 +3539 0 +3540 0 +3541 0 +3542 0 +3543 0 +3544 0 +3545 4 +3546 4 +3547 4 +3548 4 +3549 4 +3550 4 +3551 4 +3552 5 +3553 5 +3554 5 +3555 5 +3556 5 +3557 5 +3558 5 +3559 5 +3560 5 +3561 5 +3562 5 +3563 5 +3564 5 +3565 5 +3566 5 +3567 5 +3568 5 +3569 5 +3570 5 +3571 5 +3572 5 +3573 20 +3574 20 +3575 20 +3576 20 +3577 20 +3578 20 +3579 20 +3580 20 +3581 20 +3582 20 +3583 20 +3584 20 +3585 20 +3586 20 +3587 20 +3588 20 +3589 20 +3590 20 +3591 20 +3592 22 +3593 22 +3594 22 +3595 22 +3596 22 +3597 22 +3598 22 +3599 22 +3600 22 +3601 22 +3602 22 +3603 22 +3604 22 +3605 22 +3606 22 +3607 22 +3608 22 +3609 22 +3610 22 +3611 22 +3612 28 +3613 28 +3614 28 +3615 28 +3616 28 +3617 28 +3618 28 +3619 28 +3620 28 +3621 28 +3622 28 +3623 28 +3624 28 +3625 28 +3626 28 +3627 28 +3628 30 +3629 30 +3630 30 +3631 30 +3632 30 +3633 30 +3634 30 +3635 30 +3636 30 +3637 31 +3638 31 +3639 31 +3640 31 +3641 31 +3642 31 +3643 31 +3644 31 +3645 29 +3646 29 +3647 29 +3648 29 +3649 29 +3650 29 +3651 26 +3652 26 +3653 26 +3654 26 +3655 26 +3656 25 +3657 29 +3658 29 +3659 29 +3660 26 +3661 26 +3662 26 +3663 26 +3664 26 +3665 26 +3666 26 +3667 25 +3668 25 +3669 26 +3670 26 +3671 26 +3672 26 +3673 26 +3674 26 +3675 26 +3676 26 +3677 25 +3678 25 +3679 14 +3680 14 +3681 14 +3682 14 +3683 14 +3684 24 +3685 14 +3686 14 +3687 14 +3688 14 +3689 14 +3690 15 +3691 15 +3692 15 +3693 15 +3694 15 +3695 15 +3696 15 +3697 15 +3698 15 +3699 15 +3700 15 +3701 15 +3702 15 +3703 15 +3704 15 +3705 15 +3706 15 +3707 15 +3708 15 +3709 15 +3710 15 +3711 8 +3712 8 +3713 8 +3714 8 +3715 8 +3716 8 +3717 8 +3718 8 +3719 8 +3720 8 +3721 8 +3722 8 +3723 8 +3724 8 +3725 11 +3726 11 +3727 11 +3728 11 +3729 11 +3730 11 +3731 11 +3732 11 +3733 11 +3734 11 +3735 11 +3736 11 +3737 11 +3738 11 +3739 11 +3740 11 +3741 11 +3742 10 +3743 10 +3744 10 +3745 10 +3746 10 +3747 10 +3748 10 +3749 10 +3750 10 +3751 10 +3752 10 +3753 10 +3754 10 +3755 10 +3756 10 +3757 10 +3758 10 +3759 10 +3760 24 +3761 24 +3762 24 +3763 24 +3764 24 +3765 24 +3766 24 +3767 24 +3768 24 +3769 26 +3770 16 +3771 16 +3772 0 +3773 0 +3774 3 +3775 3 +3776 3 +3777 3 +3778 3 +3779 3 +3780 3 +3781 3 +3782 3 +3783 3 +3784 3 +3785 3 +3786 13 +3787 13 +3788 3 +3789 13 +3790 3 +3791 13 +3792 13 +3793 13 +3794 13 +3795 13 +3796 13 +3797 13 +3798 13 +3799 13 +3800 13 +3801 13 +3802 13 +3803 13 +3804 13 +3805 13 +3806 13 +3807 13 +3808 13 +3809 4 +3810 4 +3811 5 +3812 5 +3813 5 +3814 5 +3815 5 +3816 5 +3817 5 +3818 5 +3819 5 +3820 5 +3821 5 +3822 5 +3823 5 +3824 4 +3825 4 +3826 4 +3827 4 +3828 4 +3829 4 +3830 4 +3831 4 +3832 4 +3833 4 +3834 4 +3835 4 +3836 4 +3837 5 +3838 5 +3839 5 +3840 5 +3841 5 +3842 5 +3843 5 +3844 5 +3845 5 +3846 5 +3847 5 +3848 5 +3849 5 +3850 5 +3851 27 +3852 27 +3853 5 +3854 5 +3855 5 +3856 5 +3857 5 +3858 5 +3859 5 +3860 5 +3861 27 +3862 27 +3863 27 +3864 5 +3865 5 +3866 5 +3867 5 +3868 5 +3869 5 +3870 5 +3871 5 +3872 5 +3873 5 +3874 5 +3875 5 +3876 5 +3877 5 +3878 5 +3879 5 +3880 27 +3881 27 +3882 27 +3883 27 +3884 27 +3885 27 +3886 27 +3887 27 +3888 5 +3889 5 +3890 5 +3891 5 +3892 14 +3893 14 +3894 14 +3895 14 +3896 14 +3897 14 +3898 14 +3899 14 +3900 14 +3901 14 +3902 14 +3903 30 +3904 30 +3905 31 +3906 31 +3907 31 +3908 31 +3909 31 +3910 31 +3911 31 +3912 31 +3913 31 +3914 31 +3915 31 +3916 31 +3917 25 +3918 25 +3919 25 +3920 31 +3921 31 +3922 31 +3923 31 +3924 29 +3925 29 +3926 25 +3927 31 +3928 31 +3929 31 +3930 31 +3931 31 +3932 31 +3933 31 +3934 31 +3935 31 +3936 31 +3937 31 +3938 31 +3939 31 +3940 31 +3941 29 +3942 29 +3943 29 +3944 26 +3945 26 +3946 26 +3947 26 +3948 26 +3949 26 +3950 26 +3951 26 +3952 13 +3953 13 +3954 13 +3955 13 +3956 13 +3957 13 +3958 0 +3959 0 +3960 0 +3961 1 +3962 26 +3963 26 +3964 25 +3965 26 +3966 25 +3967 25 +3968 24 +3969 24 +3970 24 +3971 24 +3972 15 +3973 15 +3974 15 +3975 15 +3976 15 +3977 15 +3978 15 +3979 15 +3980 15 +3981 15 +3982 15 +3983 15 +3984 8 +3985 8 +3986 8 +3987 8 +3988 8 +3989 8 +3990 8 +3991 8 +3992 8 +3993 8 +3994 8 +3995 8 +3996 8 +3997 8 +3998 8 +3999 11 +4000 11 +4001 11 +4002 11 +4003 11 +4004 11 +4005 11 +4006 11 +4007 11 +4008 11 +4009 11 +4010 11 +4011 11 +4012 11 +4013 11 +4014 11 +4015 11 +4016 11 +4017 10 +4018 10 +4019 10 +4020 10 +4021 9 +4022 10 +4023 10 +4024 10 +4025 10 +4026 10 +4027 10 +4028 10 +4029 10 +4030 9 +4031 9 +4032 10 +4033 9 +4034 9 +4035 9 +4036 9 +4037 10 +4038 24 +4039 24 +4040 24 +4041 9 +4042 9 +4043 9 +4044 9 +4045 10 +4046 10 +4047 10 +4048 10 +4049 10 +4050 10 +4051 10 +4052 10 +4053 10 +4054 10 +4055 10 +4056 10 +4057 4 +4058 4 +4059 4 +4060 4 +4061 4 +4062 4 +4063 4 +4064 4 +4065 4 +4066 4 +4067 4 +4068 4 +4069 4 +4070 11 +4071 11 +4072 11 +4073 11 +4074 11 +4075 11 +4076 11 +4077 11 +4078 8 +4079 8 +4080 8 +4081 8 +4082 9 +4083 9 +4084 9 +4085 9 +4086 2 +4087 2 +4088 2 +4089 2 +4090 2 +4091 2 +4092 2 +4093 2 +4094 2 +4095 2 +4096 0 +4097 0 +4098 0 +4099 0 +4100 13 +4101 13 +4102 13 +4103 13 +4104 13 +4105 13 +4106 13 +4107 13 +4108 13 +4109 13 +4110 13 +4111 13 +4112 13 +4113 13 +4114 14 +4115 14 +4116 0 +4117 0 +4118 0 +4119 0 +4120 0 +4121 0 +4122 0 +4123 0 +4124 0 +4125 0 +4126 0 +4127 16 +4128 16 +4129 16 +4130 16 +4131 16 +4132 16 +4133 16 +4134 16 +4135 16 +4136 16 +4137 16 +4138 16 +4139 16 +4140 0 +4141 20 +4142 20 +4143 20 +4144 20 +4145 20 +4146 20 +4147 20 +4148 20 +4149 20 +4150 20 +4151 20 +4152 20 +4153 22 +4154 22 +4155 22 +4156 22 +4157 22 +4158 22 +4159 22 +4160 22 +4161 22 +4162 22 +4163 22 +4164 22 +4165 22 +4166 22 +4167 22 +4168 22 +4169 22 +4170 22 +4171 22 +4172 28 +4173 28 +4174 28 +4175 28 +4176 28 +4177 28 +4178 28 +4179 28 +4180 28 +4181 28 +4182 28 +4183 28 +4184 28 +4185 28 +4186 28 +4187 28 +4188 28 +4189 30 +4190 30 +4191 30 +4192 30 +4193 30 +4194 30 +4195 30 +4196 31 +4197 31 +4198 31 +4199 31 +4200 31 +4201 31 +4202 31 +4203 31 +4204 31 +4205 31 +4206 31 +4207 31 +4208 10 +4209 10 +4210 9 +4211 9 +4212 9 +4213 9 +4214 9 +4215 9 +4216 9 +4217 9 +4218 9 +4219 9 +4220 9 +4221 10 +4222 10 +4223 10 +4224 4 +4225 4 +4226 4 +4227 4 +4228 4 +4229 4 +4230 4 +4231 3 +4232 9 +4233 4 +4234 4 +4235 4 +4236 5 +4237 5 +4238 13 +4239 13 +4240 13 +4241 13 +4242 13 +4243 13 +4244 13 +4245 13 +4246 13 +4247 13 +4248 13 +4249 13 +4250 27 +4251 5 +4252 5 +4253 5 +4254 5 +4255 5 +4256 5 +4257 5 +4258 5 +4259 5 +4260 5 +4261 5 +4262 5 +4263 20 +4264 20 +4265 20 +4266 20 +4267 20 +4268 20 +4269 20 +4270 20 +4271 20 +4272 20 +4273 20 +4274 20 +4275 20 +4276 20 +4277 20 +4278 20 +4279 20 +4280 20 +4281 23 +4282 23 +4283 23 +4284 23 +4285 23 +4286 23 +4287 22 +4288 22 +4289 22 +4290 22 +4291 22 +4292 22 +4293 22 +4294 22 +4295 22 +4296 22 +4297 22 +4298 22 +4299 22 +4300 22 +4301 28 +4302 28 +4303 28 +4304 28 +4305 28 +4306 28 +4307 28 +4308 28 +4309 28 +4310 28 +4311 28 +4312 28 +4313 28 +4314 28 +4315 28 +4316 28 +4317 28 +4318 30 +4319 30 +4320 30 +4321 30 +4322 30 +4323 31 +4324 31 +4325 31 +4326 31 +4327 31 +4328 31 +4329 31 +4330 31 +4331 31 +4332 31 +4333 31 +4334 31 +4335 31 +4336 31 +4337 31 +4338 31 +4339 29 +4340 29 +4341 29 +4342 29 +4343 29 +4344 29 +4345 29 +4346 29 +4347 29 +4348 29 +4349 29 +4350 29 +4351 29 +4352 29 +4353 29 +4354 29 +4355 29 +4356 29 +4357 29 +4358 29 +4359 29 +4360 29 +4361 29 +4362 29 +4363 29 +4364 29 +4365 0 +4366 0 +4367 0 +4368 29 +4369 29 +4370 29 +4371 29 +4372 0 +4373 0 +4374 0 +4375 0 +4376 0 +4377 0 +4378 2 +4379 2 +4380 2 +4381 2 +4382 2 +4383 2 +4384 2 +4385 2 +4386 2 +4387 2 +4388 2 +4389 2 +4390 2 +4391 14 +4392 14 +4393 14 +4394 14 +4395 0 +4396 0 +4397 16 +4398 16 +4399 16 +4400 16 +4401 16 +4402 14 +4403 14 +4404 14 +4405 5 +4406 5 +4407 5 +4408 5 +4409 5 +4410 16 +4411 16 +4412 16 +4413 16 +4414 16 +4415 16 +4416 13 +4417 13 +4418 13 +4419 13 +4420 5 +4421 5 +4422 5 +4423 5 +4424 5 +4425 5 +4426 5 +4427 5 +4428 5 +4429 31 +4430 31 +4431 29 +4432 29 +4433 29 +4434 29 +4435 29 +4436 29 +4437 29 +4438 29 +4439 8 +4440 8 +4441 8 +4442 8 +4443 8 +4444 8 +4445 11 +4446 11 +4447 11 +4448 11 +4449 11 +4450 11 +4451 11 +4452 11 +4453 8 +4454 8 +4455 8 +4456 8 +4457 9 +4458 9 +4459 9 +4460 9 +4461 9 +4462 9 +4463 9 +4464 9 +4465 9 +4466 9 +4467 9 +4468 9 +4469 10 +4470 10 +4471 9 +4472 9 +4473 9 +4474 9 +4475 9 +4476 9 +4477 9 +4478 9 +4479 9 +4480 9 +4481 9 +4482 9 +4483 9 +4484 9 +4485 4 +4486 4 +4487 4 +4488 4 +4489 4 +4490 9 +4491 9 +4492 9 +4493 9 +4494 4 +4495 4 +4496 4 +4497 4 +4498 4 +4499 4 +4500 4 +4501 4 +4502 4 +4503 13 +4504 13 +4505 13 +4506 13 +4507 13 +4508 13 +4509 13 +4510 13 +4511 4 +4512 4 +4513 4 +4514 18 +4515 18 +4516 18 +4517 18 +4518 18 +4519 18 +4520 18 +4521 18 +4522 16 +4523 16 +4524 16 +4525 16 +4526 16 +4527 16 +4528 16 +4529 0 +4530 0 +4531 0 +4532 16 +4533 16 +4534 16 +4535 16 +4536 16 +4537 16 +4538 16 +4539 16 +4540 16 +4541 16 +4542 16 +4543 16 +4544 16 +4545 16 +4546 16 +4547 16 +4548 16 +4549 16 +4550 16 +4551 16 +4552 16 +4553 16 +4554 16 +4555 16 +4556 17 +4557 16 +4558 16 +4559 16 +4560 16 +4561 16 +4562 16 +4563 16 +4564 16 +4565 16 +4566 28 +4567 28 +4568 28 +4569 28 +4570 28 +4571 28 +4572 28 +4573 28 +4574 28 +4575 30 +4576 30 +4577 30 +4578 30 +4579 31 +4580 31 +4581 31 +4582 31 +4583 31 +4584 31 +4585 31 +4586 31 +4587 31 +4588 31 +4589 31 +4590 31 +4591 31 +4592 31 +4593 31 +4594 29 +4595 29 +4596 29 +4597 29 +4598 29 +4599 29 +4600 29 +4601 29 +4602 29 +4603 29 +4604 29 +4605 29 +4606 29 +4607 29 +4608 29 +4609 29 +4610 29 +4611 29 +4612 29 +4613 29 +4614 29 +4615 29 +4616 29 +4617 29 +4618 29 +4619 29 +4620 26 +4621 29 +4622 29 +4623 29 +4624 29 +4625 29 +4626 29 +4627 26 +4628 26 +4629 26 +4630 26 +4631 26 +4632 26 +4633 26 +4634 26 +4635 26 +4636 26 +4637 26 +4638 26 +4639 26 +4640 26 +4641 26 +4642 26 +4643 5 +4644 5 +4645 5 +4646 5 +4647 5 +4648 16 +4649 16 +4650 16 +4651 16 +4652 16 +4653 16 +4654 16 +4655 16 +4656 16 +4657 16 +4658 11 +4659 11 +4660 11 +4661 14 +4662 14 +4663 14 +4664 14 +4665 14 +4666 16 +4667 16 +4668 16 +4669 8 +4670 8 +4671 8 +4672 8 +4673 9 +4674 9 +4675 9 +4676 9 +4677 9 +4678 9 +4679 9 +4680 9 +4681 9 +4682 9 +4683 9 +4684 9 +4685 9 +4686 9 +4687 9 +4688 14 +4689 14 +4690 14 +4691 14 +4692 14 +4693 15 +4694 15 +4695 15 +4696 15 +4697 15 +4698 15 +4699 15 +4700 15 +4701 15 +4702 15 +4703 15 +4704 15 +4705 15 +4706 15 +4707 15 +4708 15 +4709 15 +4710 15 +4711 15 +4712 8 +4713 8 +4714 8 +4715 8 +4716 8 +4717 8 +4718 8 +4719 8 +4720 8 +4721 8 +4722 8 +4723 8 +4724 8 +4725 8 +4726 8 +4727 8 +4728 8 +4729 5 +4730 5 +4731 5 +4732 5 +4733 8 +4734 8 +4735 8 +4736 8 +4737 8 +4738 8 +4739 14 +4740 14 +4741 14 +4742 14 +4743 14 +4744 14 +4745 14 +4746 14 +4747 14 +4748 14 +4749 14 +4750 14 +4751 14 +4752 14 +4753 14 +4754 4 +4755 4 +4756 4 +4757 14 +4758 14 +4759 4 +4760 4 +4761 4 +4762 4 +4763 4 +4764 4 +4765 4 +4766 4 +4767 4 +4768 4 +4769 4 +4770 4 +4771 23 +4772 23 +4773 23 +4774 23 +4775 28 +4776 28 +4777 28 +4778 28 +4779 28 +4780 28 +4781 28 +4782 28 +4783 28 +4784 28 +4785 28 +4786 28 +4787 28 +4788 28 +4789 28 +4790 28 +4791 28 +4792 28 +4793 30 +4794 30 +4795 31 +4796 31 +4797 31 +4798 31 +4799 28 +4800 31 +4801 31 +4802 31 +4803 31 +4804 31 +4805 31 +4806 31 +4807 31 +4808 31 +4809 31 +4810 31 +4811 29 +4812 29 +4813 29 +4814 29 +4815 29 +4816 29 +4817 29 +4818 29 +4819 29 +4820 29 +4821 29 +4822 29 +4823 29 +4824 29 +4825 29 +4826 29 +4827 29 +4828 29 +4829 29 +4830 29 +4831 29 +4832 29 +4833 29 +4834 29 +4835 29 +4836 29 +4837 29 +4838 29 +4839 29 +4840 29 +4841 29 +4842 29 +4843 29 +4844 29 +4845 29 +4846 29 +4847 29 +4848 29 +4849 29 +4850 29 +4851 29 +4852 29 +4853 29 +4854 29 +4855 29 +4856 29 +4857 29 +4858 29 +4859 29 +4860 29 +4861 29 +4862 26 +4863 26 +4864 26 +4865 26 +4866 26 +4867 26 +4868 26 +4869 26 +4870 26 +4871 26 +4872 26 +4873 26 +4874 26 +4875 26 +4876 26 +4877 26 +4878 26 +4879 26 +4880 26 +4881 26 +4882 26 +4883 26 +4884 26 +4885 26 +4886 26 +4887 26 +4888 26 +4889 26 +4890 26 +4891 26 +4892 26 +4893 26 +4894 26 +4895 26 +4896 26 +4897 26 +4898 26 +4899 26 +4900 26 +4901 26 +4902 26 +4903 26 +4904 26 +4905 26 +4906 26 +4907 26 +4908 26 +4909 26 +4910 26 +4911 26 +4912 26 +4913 26 +4914 26 +4915 26 +4916 26 +4917 26 +4918 31 +4919 29 +4920 29 +4921 29 +4922 29 +4923 23 +4924 22 +4925 23 +4926 23 +4927 23 +4928 23 +4929 23 +4930 23 +4931 23 +4932 23 +4933 23 +4934 23 +4935 23 +4936 23 +4937 23 +4938 28 +4939 28 +4940 28 +4941 28 +4942 28 +4943 28 +4944 28 +4945 28 +4946 28 +4947 28 +4948 28 +4949 28 +4950 28 +4951 28 +4952 28 +4953 28 +4954 28 +4955 28 +4956 31 +4957 31 +4958 31 +4959 31 +4960 29 +4961 29 +4962 29 +4963 29 +4964 29 +4965 8 +4966 8 +4967 8 +4968 8 +4969 8 +4970 8 +4971 8 +4972 8 +4973 8 +4974 8 +4975 8 +4976 8 +4977 8 +4978 8 +4979 8 +4980 8 +4981 9 +4982 9 +4983 9 +4984 9 +4985 4 +4986 4 +4987 4 +4988 4 +4989 9 +4990 9 +4991 9 +4992 9 +4993 9 +4994 9 +4995 4 +4996 4 +4997 4 +4998 4 +4999 4 +5000 4 +5001 4 +5002 4 +5003 14 +5004 14 +5005 14 +5006 4 +5007 4 +5008 4 +5009 4 +5010 4 +5011 4 +5012 4 +5013 4 +5014 4 +5015 4 +5016 4 +5017 4 +5018 4 +5019 4 +5020 4 +5021 4 +5022 4 +5023 4 +5024 4 +5025 4 +5026 4 +5027 4 +5028 4 +5029 5 +5030 5 +5031 5 +5032 5 +5033 5 +5034 5 +5035 5 +5036 5 +5037 5 +5038 5 +5039 5 +5040 5 +5041 5 +5042 5 +5043 5 +5044 5 +5045 5 +5046 23 +5047 23 +5048 23 +5049 23 +5050 23 +5051 23 +5052 23 +5053 23 +5054 23 +5055 23 +5056 23 +5057 23 +5058 23 +5059 23 +5060 23 +5061 23 +5062 23 +5063 23 +5064 23 +5065 23 +5066 23 +5067 23 +5068 23 +5069 28 +5070 28 +5071 28 +5072 28 +5073 28 +5074 28 +5075 28 +5076 28 +5077 28 +5078 28 +5079 28 +5080 28 +5081 28 +5082 28 +5083 28 +5084 28 +5085 28 +5086 28 +5087 29 +5088 29 +5089 29 +5090 29 +5091 29 +5092 29 +5093 29 +5094 29 +5095 29 +5096 29 +5097 29 +5098 29 +5099 29 +5100 29 +5101 29 +5102 29 +5103 29 +5104 29 +5105 29 +5106 29 +5107 29 +5108 29 +5109 29 +5110 29 +5111 29 +5112 29 +5113 29 +5114 29 +5115 29 +5116 29 +5117 29 +5118 29 +5119 29 +5120 29 +5121 29 +5122 29 +5123 29 +5124 29 +5125 19 +5126 19 +5127 19 +5128 19 +5129 19 +5130 19 +5131 26 +5132 26 +5133 19 +5134 19 +5135 26 +5136 26 +5137 26 +5138 26 +5139 26 +5140 26 +5141 26 +5142 26 +5143 26 +5144 26 +5145 26 +5146 26 +5147 26 +5148 26 +5149 26 +5150 26 +5151 29 +5152 29 +5153 29 +5154 29 +5155 26 +5156 16 +5157 16 +5158 14 +5159 14 +5160 15 +5161 15 +5162 15 +5163 15 +5164 15 +5165 15 +5166 4 +5167 4 +5168 7 +5169 7 +5170 15 +5171 15 +5172 15 +5173 15 +5174 8 +5175 8 +5176 8 +5177 8 +5178 8 +5179 8 +5180 8 +5181 8 +5182 8 +5183 8 +5184 8 +5185 8 +5186 8 +5187 8 +5188 8 +5189 8 +5190 8 +5191 8 +5192 8 +5193 8 +5194 8 +5195 8 +5196 8 +5197 9 +5198 9 +5199 9 +5200 9 +5201 9 +5202 9 +5203 9 +5204 9 +5205 9 +5206 9 +5207 9 +5208 9 +5209 9 +5210 9 +5211 9 +5212 9 +5213 9 +5214 9 +5215 9 +5216 9 +5217 9 +5218 9 +5219 9 +5220 9 +5221 9 +5222 9 +5223 9 +5224 9 +5225 4 +5226 4 +5227 4 +5228 4 +5229 4 +5230 4 +5231 20 +5232 20 +5233 20 +5234 20 +5235 18 +5236 18 +5237 18 +5238 4 +5239 4 +5240 4 +5241 4 +5242 4 +5243 4 +5244 4 +5245 4 +5246 4 +5247 4 +5248 4 +5249 4 +5250 23 +5251 23 +5252 23 +5253 23 +5254 23 +5255 23 +5256 28 +5257 28 +5258 28 +5259 28 +5260 28 +5261 28 +5262 28 +5263 28 +5264 28 +5265 28 +5266 28 +5267 28 +5268 28 +5269 28 +5270 28 +5271 28 +5272 29 +5273 29 +5274 29 +5275 29 +5276 29 +5277 29 +5278 29 +5279 29 +5280 29 +5281 29 +5282 29 +5283 29 +5284 29 +5285 29 +5286 29 +5287 29 +5288 29 +5289 29 +5290 29 +5291 29 +5292 29 +5293 29 +5294 29 +5295 29 +5296 29 +5297 29 +5298 29 +5299 29 +5300 29 +5301 29 +5302 29 +5303 19 +5304 29 +5305 19 +5306 19 +5307 19 +5308 19 +5309 19 +5310 19 +5311 19 +5312 19 +5313 19 +5314 19 +5315 19 +5316 19 +5317 19 +5318 19 +5319 19 +5320 19 +5321 19 +5322 19 +5323 19 +5324 19 +5325 19 +5326 19 +5327 19 +5328 19 +5329 19 +5330 19 +5331 19 +5332 19 +5333 19 +5334 19 +5335 19 +5336 19 +5337 19 +5338 19 +5339 19 +5340 19 +5341 19 +5342 19 +5343 19 +5344 26 +5345 26 +5346 26 +5347 18 +5348 19 +5349 19 +5350 19 +5351 18 +5352 18 +5353 18 +5354 18 +5355 18 +5356 18 +5357 18 +5358 18 +5359 18 +5360 18 +5361 26 +5362 26 +5363 26 +5364 26 +5365 26 +5366 26 +5367 26 +5368 26 +5369 26 +5370 26 +5371 26 +5372 26 +5373 26 +5374 26 +5375 26 +5376 29 +5377 29 +5378 29 +5379 29 +5380 16 +5381 3 +5382 3 +5383 3 +5384 3 +5385 3 +5386 3 +5387 3 +5388 3 +5389 3 +5390 3 +5391 3 +5392 26 +5393 26 +5394 26 +5395 26 +5396 26 +5397 26 +5398 26 +5399 26 +5400 26 +5401 26 +5402 26 +5403 8 +5404 8 +5405 8 +5406 8 +5407 8 +5408 8 +5409 8 +5410 8 +5411 8 +5412 8 +5413 8 +5414 8 +5415 8 +5416 8 +5417 8 +5418 8 +5419 8 +5420 8 +5421 8 +5422 8 +5423 8 +5424 9 +5425 9 +5426 9 +5427 9 +5428 8 +5429 8 +5430 9 +5431 9 +5432 9 +5433 9 +5434 9 +5435 9 +5436 9 +5437 9 +5438 9 +5439 9 +5440 9 +5441 9 +5442 9 +5443 9 +5444 9 +5445 9 +5446 9 +5447 9 +5448 20 +5449 20 +5450 20 +5451 20 +5452 20 +5453 20 +5454 20 +5455 20 +5456 20 +5457 20 +5458 20 +5459 20 +5460 20 +5461 20 +5462 20 +5463 20 +5464 20 +5465 20 +5466 20 +5467 20 +5468 20 +5469 20 +5470 20 +5471 20 +5472 20 +5473 20 +5474 20 +5475 23 +5476 23 +5477 23 +5478 23 +5479 23 +5480 23 +5481 23 +5482 23 +5483 23 +5484 23 +5485 23 +5486 23 +5487 23 +5488 23 +5489 23 +5490 23 +5491 23 +5492 23 +5493 23 +5494 23 +5495 23 +5496 23 +5497 23 +5498 23 +5499 23 +5500 28 +5501 28 +5502 28 +5503 28 +5504 28 +5505 28 +5506 28 +5507 28 +5508 28 +5509 28 +5510 28 +5511 28 +5512 28 +5513 28 +5514 29 +5515 29 +5516 29 +5517 29 +5518 29 +5519 29 +5520 29 +5521 29 +5522 29 +5523 29 +5524 29 +5525 29 +5526 29 +5527 29 +5528 29 +5529 29 +5530 29 +5531 29 +5532 29 +5533 29 +5534 29 +5535 29 +5536 29 +5537 29 +5538 29 +5539 29 +5540 29 +5541 29 +5542 29 +5543 29 +5544 29 +5545 19 +5546 19 +5547 19 +5548 19 +5549 19 +5550 19 +5551 19 +5552 19 +5553 19 +5554 19 +5555 19 +5556 19 +5557 19 +5558 19 +5559 19 +5560 19 +5561 19 +5562 19 +5563 19 +5564 19 +5565 19 +5566 19 +5567 19 +5568 19 +5569 19 +5570 19 +5571 19 +5572 19 +5573 19 +5574 19 +5575 19 +5576 19 +5577 19 +5578 19 +5579 19 +5580 19 +5581 19 +5582 19 +5583 18 +5584 18 +5585 19 +5586 19 +5587 19 +5588 19 +5589 19 +5590 19 +5591 19 +5592 19 +5593 19 +5594 19 +5595 19 +5596 19 +5597 19 +5598 19 +5599 19 +5600 19 +5601 19 +5602 19 +5603 18 +5604 18 +5605 19 +5606 18 +5607 18 +5608 18 +5609 18 +5610 18 +5611 18 +5612 18 +5613 18 +5614 18 +5615 18 +5616 3 +5617 3 +5618 3 +5619 3 +5620 3 +5621 23 +5622 23 +5623 23 +5624 23 +5625 23 +5626 23 +5627 23 +5628 23 +5629 23 +5630 23 +5631 23 +5632 23 +5633 28 +5634 28 +5635 28 +5636 28 +5637 28 +5638 28 +5639 28 +5640 28 +5641 29 +5642 29 +5643 29 +5644 29 +5645 29 +5646 29 +5647 29 +5648 4 +5649 4 +5650 4 +5651 4 +5652 4 +5653 4 +5654 23 +5655 23 +5656 23 +5657 23 +5658 23 +5659 23 +5660 23 +5661 23 +5662 23 +5663 23 +5664 23 +5665 23 +5666 23 +5667 23 +5668 23 +5669 23 +5670 23 +5671 23 +5672 23 +5673 23 +5674 28 +5675 28 +5676 28 +5677 29 +5678 29 +5679 29 +5680 29 +5681 29 +5682 29 +5683 29 +5684 29 +5685 29 +5686 29 +5687 29 +5688 29 +5689 29 +5690 29 +5691 29 +5692 29 +5693 29 +5694 29 +5695 29 +5696 29 +5697 23 +5698 23 +5699 19 +5700 19 +5701 19 +5702 19 +5703 19 +5704 19 +5705 19 +5706 19 +5707 19 +5708 19 +5709 19 +5710 19 +5711 19 +5712 19 +5713 19 +5714 19 +5715 19 +5716 19 +5717 19 +5718 29 +5719 23 +5720 23 +5721 23 +5722 19 +5723 23 +5724 23 +5725 23 +5726 23 +5727 19 +5728 19 +5729 19 +5730 23 +5731 23 +5732 19 +5733 19 +5734 19 +5735 19 +5736 19 +5737 19 +5738 19 +5739 19 +5740 19 +5741 19 +5742 19 +5743 19 +5744 19 +5745 19 +5746 19 +5747 19 +5748 19 +5749 19 +5750 19 +5751 19 +5752 19 +5753 19 +5754 19 +5755 19 +5756 19 +5757 19 +5758 19 +5759 19 +5760 19 +5761 19 +5762 19 +5763 19 +5764 19 +5765 19 +5766 19 +5767 19 +5768 19 +5769 19 +5770 19 +5771 19 +5772 19 +5773 19 +5774 19 +5775 19 +5776 19 +5777 19 +5778 19 +5779 19 +5780 19 +5781 19 +5782 19 +5783 19 +5784 19 +5785 19 +5786 19 +5787 19 +5788 18 +5789 18 +5790 18 +5791 18 +5792 18 +5793 18 +5794 18 +5795 18 +5796 18 +5797 18 +5798 18 +5799 18 +5800 18 +5801 18 +5802 18 +5803 18 +5804 18 +5805 18 +5806 18 +5807 18 +5808 18 +5809 18 +5810 26 +5811 26 +5812 23 +5813 23 +5814 23 +5815 23 +5816 23 +5817 23 +5818 23 +5819 23 +5820 23 +5821 23 +5822 23 +5823 18 +5824 18 +5825 18 +5826 18 +5827 18 +5828 18 +5829 18 +5830 18 +5831 23 +5832 23 +5833 23 +5834 23 +5835 23 +5836 18 +5837 18 +5838 18 +5839 18 +5840 23 +5841 23 +5842 23 +5843 23 +5844 23 +5845 23 +5846 23 +5847 23 +5848 23 +5849 23 +5850 23 +5851 23 +5852 23 +5853 23 +5854 23 +5855 23 +5856 23 +5857 23 +5858 23 +5859 23 +5860 23 +5861 23 +5862 23 +5863 23 +5864 23 +5865 29 +5866 29 +5867 29 +5868 29 +5869 29 +5870 29 +5871 29 +5872 18 +5873 26 +5874 26 +5875 26 +5876 27 +5877 27 +5878 26 +5879 27 +5880 26 +5881 26 +5882 26 +5883 26 +5884 26 +5885 26 +5886 18 +5887 26 +5888 27 +5889 27 +5890 26 +5891 27 +5892 26 +5893 26 +5894 26 +5895 26 +5896 26 +5897 26 +5898 26 +5899 26 +5900 26 +5901 26 +5902 26 +5903 26 +5904 26 +5905 26 +5906 26 +5907 26 +5908 26 +5909 26 +5910 26 +5911 26 +5912 26 +5913 26 +5914 26 +5915 26 +5916 26 +5917 26 +5918 26 +5919 26 +5920 26 +5921 26 +5922 26 +5923 26 +5924 26 +5925 26 +5926 26 +5927 26 +5928 26 +5929 26 +5930 26 +5931 26 +5932 26 +5933 26 +5934 26 +5935 26 +5936 26 +5937 26 +5938 26 +5939 26 +5940 26 +5941 26 +5942 26 +5943 25 +5944 25 +5945 25 +5946 25 +5947 25 +5948 25 +5949 19 +5950 19 +5951 19 +5952 19 +5953 19 +5954 19 +5955 19 +5956 19 +5957 19 +5958 19 +5959 19 +5960 19 +5961 19 +5962 19 +5963 19 +5964 19 +5965 19 +5966 19 +5967 19 +5968 19 +5969 17 +5970 17 +5971 19 +5972 17 +5973 17 +5974 17 +5975 17 +5976 17 +5977 17 +5978 17 +5979 19 +5980 19 +5981 19 +5982 19 +5983 19 +5984 19 +5985 19 +5986 19 +5987 19 +5988 19 +5989 19 +5990 19 +5991 19 +5992 19 +5993 19 +5994 19 +5995 19 +5996 19 +5997 19 +5998 19 +5999 19 +6000 19 +6001 19 +6002 19 +6003 18 +6004 18 +6005 19 +6006 18 +6007 18 +6008 18 +6009 18 +6010 18 +6011 18 +6012 18 +6013 18 +6014 18 +6015 18 +6016 18 +6017 18 +6018 23 +6019 18 +6020 18 +6021 18 +6022 18 +6023 18 +6024 18 +6025 18 +6026 18 +6027 18 +6028 18 +6029 18 +6030 18 +6031 18 +6032 18 +6033 18 +6034 18 +6035 18 +6036 18 +6037 18 +6038 18 +6039 18 +6040 27 +6041 27 +6042 27 +6043 27 +6044 27 +6045 27 +6046 27 +6047 27 +6048 27 +6049 27 +6050 27 +6051 27 +6052 27 +6053 27 +6054 27 +6055 27 +6056 27 +6057 27 +6058 26 +6059 26 +6060 27 +6061 26 +6062 26 +6063 26 +6064 26 +6065 26 +6066 26 +6067 26 +6068 26 +6069 26 +6070 26 +6071 26 +6072 26 +6073 26 +6074 26 +6075 26 +6076 26 +6077 26 +6078 26 +6079 26 +6080 26 +6081 26 +6082 26 +6083 26 +6084 26 +6085 26 +6086 26 +6087 26 +6088 26 +6089 26 +6090 26 +6091 26 +6092 25 +6093 25 +6094 26 +6095 23 +6096 23 +6097 23 +6098 23 +6099 23 +6100 23 +6101 23 +6102 23 +6103 23 +6104 23 +6105 23 +6106 19 +6107 19 +6108 19 +6109 19 +6110 19 +6111 19 +6112 19 +6113 19 +6114 19 +6115 19 +6116 19 +6117 19 +6118 19 +6119 19 +6120 19 +6121 19 +6122 19 +6123 19 +6124 19 +6125 19 +6126 19 +6127 19 +6128 19 +6129 19 +6130 19 +6131 19 +6132 19 +6133 19 +6134 19 +6135 19 +6136 19 +6137 19 +6138 19 +6139 19 +6140 19 +6141 17 +6142 17 +6143 17 +6144 17 +6145 17 +6146 17 +6147 17 +6148 17 +6149 17 +6150 19 +6151 17 +6152 17 +6153 17 +6154 17 +6155 17 +6156 17 +6157 19 +6158 19 +6159 19 +6160 19 +6161 19 +6162 19 +6163 19 +6164 19 +6165 19 +6166 19 +6167 19 +6168 19 +6169 19 +6170 19 +6171 19 +6172 19 +6173 18 +6174 16 +6175 16 +6176 16 +6177 16 +6178 16 +6179 18 +6180 18 +6181 16 +6182 18 +6183 16 +6184 18 +6185 18 +6186 18 +6187 18 +6188 18 +6189 18 +6190 18 +6191 18 +6192 18 +6193 18 +6194 18 +6195 18 +6196 18 +6197 18 +6198 18 +6199 18 +6200 18 +6201 18 +6202 18 +6203 18 +6204 18 +6205 18 +6206 18 +6207 18 +6208 18 +6209 18 +6210 18 +6211 18 +6212 18 +6213 18 +6214 18 +6215 18 +6216 18 +6217 18 +6218 18 +6219 18 +6220 18 +6221 18 +6222 18 +6223 18 +6224 18 +6225 18 +6226 18 +6227 18 +6228 18 +6229 18 +6230 18 +6231 18 +6232 18 +6233 18 +6234 18 +6235 18 +6236 18 +6237 18 +6238 18 +6239 18 +6240 18 +6241 18 +6242 18 +6243 18 +6244 18 +6245 18 +6246 18 +6247 18 +6248 18 +6249 18 +6250 18 +6251 18 +6252 18 +6253 18 +6254 27 +6255 27 +6256 27 +6257 27 +6258 27 +6259 27 +6260 27 +6261 27 +6262 27 +6263 27 +6264 27 +6265 27 +6266 27 +6267 27 +6268 27 +6269 27 +6270 27 +6271 27 +6272 27 +6273 27 +6274 27 +6275 27 +6276 27 +6277 27 +6278 27 +6279 27 +6280 27 +6281 27 +6282 27 +6283 27 +6284 27 +6285 27 +6286 27 +6287 27 +6288 26 +6289 27 +6290 27 +6291 27 +6292 26 +6293 26 +6294 26 +6295 26 +6296 26 +6297 26 +6298 26 +6299 26 +6300 26 +6301 26 +6302 26 +6303 26 +6304 26 +6305 26 +6306 27 +6307 26 +6308 26 +6309 26 +6310 26 +6311 26 +6312 26 +6313 26 +6314 26 +6315 26 +6316 26 +6317 26 +6318 26 +6319 26 +6320 26 +6321 26 +6322 26 +6323 26 +6324 26 +6325 27 +6326 27 +6327 27 +6328 27 +6329 27 +6330 27 +6331 27 +6332 27 +6333 27 +6334 27 +6335 27 +6336 27 +6337 27 +6338 27 +6339 27 +6340 27 +6341 27 +6342 27 +6343 26 +6344 27 +6345 27 +6346 26 +6347 27 +6348 24 +6349 24 +6350 24 +6351 24 +6352 24 +6353 24 +6354 24 +6355 24 +6356 24 +6357 24 +6358 24 +6359 24 +6360 24 +6361 24 +6362 16 +6363 16 +6364 16 +6365 16 +6366 18 +6367 18 +6368 18 +6369 18 +6370 18 +6371 18 +6372 18 +6373 18 +6374 18 +6375 18 +6376 18 +6377 18 +6378 18 +6379 18 +6380 18 +6381 18 +6382 18 +6383 23 +6384 23 +6385 23 +6386 23 +6387 19 +6388 19 +6389 19 +6390 19 +6391 19 +6392 19 +6393 19 +6394 19 +6395 23 +6396 21 +6397 19 +6398 19 +6399 21 +6400 21 +6401 21 +6402 21 +6403 21 +6404 21 +6405 17 +6406 21 +6407 21 +6408 21 +6409 21 +6410 21 +6411 21 +6412 21 +6413 21 +6414 21 +6415 21 +6416 21 +6417 21 +6418 21 +6419 21 +6420 21 +6421 21 +6422 21 +6423 21 +6424 21 +6425 21 +6426 21 +6427 21 +6428 21 +6429 21 +6430 21 +6431 21 +6432 21 +6433 17 +6434 17 +6435 17 +6436 17 +6437 17 +6438 17 +6439 17 +6440 17 +6441 17 +6442 17 +6443 17 +6444 17 +6445 17 +6446 17 +6447 17 +6448 17 +6449 17 +6450 17 +6451 17 +6452 17 +6453 17 +6454 18 +6455 18 +6456 18 +6457 18 +6458 18 +6459 18 +6460 18 +6461 18 +6462 18 +6463 18 +6464 18 +6465 18 +6466 18 +6467 18 +6468 18 +6469 18 +6470 18 +6471 18 +6472 18 +6473 18 +6474 18 +6475 18 +6476 18 +6477 18 +6478 18 +6479 18 +6480 18 +6481 18 +6482 18 +6483 18 +6484 18 +6485 27 +6486 18 +6487 18 +6488 18 +6489 18 +6490 18 +6491 27 +6492 27 +6493 27 +6494 27 +6495 27 +6496 27 +6497 27 +6498 27 +6499 27 +6500 27 +6501 27 +6502 27 +6503 27 +6504 27 +6505 27 +6506 27 +6507 27 +6508 27 +6509 27 +6510 27 +6511 27 +6512 27 +6513 27 +6514 27 +6515 27 +6516 27 +6517 27 +6518 27 +6519 27 +6520 27 +6521 27 +6522 27 +6523 27 +6524 27 +6525 27 +6526 27 +6527 27 +6528 27 +6529 27 +6530 27 +6531 27 +6532 27 +6533 27 +6534 27 +6535 27 +6536 27 +6537 27 +6538 27 +6539 27 +6540 27 +6541 27 +6542 27 +6543 27 +6544 27 +6545 27 +6546 27 +6547 27 +6548 27 +6549 27 +6550 24 +6551 24 +6552 24 +6553 24 +6554 24 +6555 24 +6556 24 +6557 24 +6558 21 +6559 21 +6560 21 +6561 21 +6562 21 +6563 21 +6564 21 +6565 21 +6566 21 +6567 21 +6568 21 +6569 21 +6570 21 +6571 21 +6572 21 +6573 21 +6574 21 +6575 21 +6576 21 +6577 21 +6578 21 +6579 21 +6580 21 +6581 21 +6582 21 +6583 21 +6584 21 +6585 21 +6586 17 +6587 17 +6588 17 +6589 17 +6590 17 +6591 17 +6592 17 +6593 17 +6594 17 +6595 17 +6596 17 +6597 17 +6598 17 +6599 17 +6600 17 +6601 17 +6602 17 +6603 17 +6604 17 +6605 17 +6606 17 +6607 17 +6608 17 +6609 17 +6610 17 +6611 17 +6612 17 +6613 17 +6614 17 +6615 17 +6616 17 +6617 17 +6618 17 +6619 17 +6620 17 +6621 17 +6622 17 +6623 17 +6624 17 +6625 17 +6626 17 +6627 17 +6628 17 +6629 17 +6630 17 +6631 16 +6632 16 +6633 16 +6634 16 +6635 16 +6636 17 +6637 17 +6638 17 +6639 17 +6640 19 +6641 19 +6642 19 +6643 19 +6644 16 +6645 16 +6646 16 +6647 16 +6648 16 +6649 16 +6650 16 +6651 16 +6652 16 +6653 16 +6654 16 +6655 16 +6656 16 +6657 16 +6658 16 +6659 16 +6660 16 +6661 16 +6662 16 +6663 16 +6664 16 +6665 16 +6666 16 +6667 16 +6668 16 +6669 16 +6670 16 +6671 16 +6672 16 +6673 16 +6674 16 +6675 16 +6676 16 +6677 16 +6678 16 +6679 16 +6680 16 +6681 16 +6682 16 +6683 16 +6684 16 +6685 16 +6686 16 +6687 16 +6688 16 +6689 16 +6690 16 +6691 16 +6692 16 +6693 16 +6694 16 +6695 16 +6696 16 +6697 16 +6698 16 +6699 16 +6700 16 +6701 16 +6702 16 +6703 16 +6704 16 +6705 24 +6706 24 +6707 24 +6708 27 +6709 27 +6710 24 +6711 27 +6712 24 +6713 27 +6714 27 +6715 27 +6716 27 +6717 27 +6718 27 +6719 27 +6720 17 +6721 17 +6722 17 +6723 17 +6724 17 +6725 17 +6726 17 +6727 17 +6728 17 +6729 17 +6730 17 +6731 17 +6732 17 +6733 17 +6734 17 +6735 17 +6736 17 +6737 17 +6738 17 +6739 17 +6740 17 +6741 17 +6742 17 +6743 17 +6744 17 +6745 17 +6746 17 +6747 17 +6748 17 +6749 17 +6750 17 +6751 17 +6752 17 +6753 17 +6754 17 +6755 17 +6756 17 +6757 17 +6758 16 +6759 17 +6760 17 +6761 16 +6762 16 +6763 16 +6764 16 +6765 16 +6766 16 +6767 16 +6768 16 +6769 16 +6770 16 +6771 16 +6772 16 +6773 16 +6774 16 +6775 16 +6776 16 +6777 16 +6778 16 +6779 16 +6780 16 +6781 16 +6782 16 +6783 16 +6784 16 +6785 17 +6786 19 +6787 19 +6788 19 +6789 19 +6790 16 +6791 8 +6792 8 +6793 8 +6794 9 +6795 9 +6796 9 +6797 9 +6798 9 +6799 9 +6800 9 +6801 9 +6802 9 +6803 9 +6804 9 +6805 9 +6806 9 +6807 9 +6808 9 +6809 9 +6810 9 +6811 9 +6812 9 +6813 9 +6814 9 +6815 9 +6816 9 +6817 9 +6818 6 +6819 6 +6820 6 +6821 6 +6822 6 +6823 6 +6824 6 +6825 6 +6826 6 +6827 6 +6828 6 +6829 7 +6830 7 +6831 7 +6832 7 +6833 4 +6834 7 +6835 7 +6836 7 +6837 4 +6838 4 +6839 4 +6840 4 +6841 4 +6842 4 +6843 4 +6844 4 +6845 5 +6846 5 +6847 5 +6848 5 +6849 5 +6850 5 +6851 5 +6852 5 +6853 5 +6854 5 +6855 5 +6856 5 +6857 7 +6858 7 +6859 7 +6860 7 +6861 7 +6862 7 +6863 7 +6864 7 +6865 7 +6866 7 +6867 7 +6868 7 +6869 7 +6870 7 +6871 7 +6872 7 +6873 7 +6874 7 +6875 7 +6876 7 +6877 5 +6878 5 +6879 7 +6880 5 +6881 5 +6882 5 +6883 5 +6884 7 +6885 5 +6886 5 +6887 5 +6888 5 +6889 5 +6890 5 +6891 5 +6892 5 +6893 5 +6894 5 +6895 5 +6896 5 +6897 5 +6898 5 +6899 5 +6900 20 +6901 5 +6902 20 +6903 20 +6904 20 +6905 20 +6906 20 +6907 20 +6908 20 +6909 20 +6910 20 +6911 20 +6912 20 +6913 20 +6914 20 +6915 20 +6916 20 +6917 20 +6918 20 +6919 20 +6920 20 +6921 23 +6922 23 +6923 23 +6924 23 +6925 23 +6926 23 +6927 23 +6928 23 +6929 23 +6930 23 +6931 23 +6932 23 +6933 23 +6934 23 +6935 23 +6936 23 +6937 23 +6938 23 +6939 23 +6940 23 +6941 23 +6942 23 +6943 23 +6944 23 +6945 23 +6946 23 +6947 23 +6948 23 +6949 23 +6950 23 +6951 23 +6952 21 +6953 21 +6954 21 +6955 21 +6956 21 +6957 21 +6958 21 +6959 21 +6960 21 +6961 21 +6962 21 +6963 21 +6964 21 +6965 21 +6966 21 +6967 21 +6968 21 +6969 21 +6970 21 +6971 21 +6972 21 +6973 21 +6974 21 +6975 21 +6976 21 +6977 21 +6978 21 +6979 21 +6980 21 +6981 21 +6982 21 +6983 21 +6984 21 +6985 21 +6986 21 +6987 21 +6988 21 +6989 21 +6990 21 +6991 21 +6992 21 +6993 21 +6994 21 +6995 21 +6996 21 +6997 21 +6998 21 +6999 21 +7000 21 +7001 21 +7002 21 +7003 21 +7004 21 +7005 21 +7006 17 +7007 17 +7008 17 +7009 17 +7010 17 +7011 17 +7012 17 +7013 17 +7014 17 +7015 17 +7016 17 +7017 17 +7018 17 +7019 17 +7020 17 +7021 17 +7022 17 +7023 17 +7024 17 +7025 17 +7026 17 +7027 17 +7028 17 +7029 17 +7030 17 +7031 17 +7032 17 +7033 17 +7034 17 +7035 17 +7036 17 +7037 17 +7038 17 +7039 17 +7040 17 +7041 17 +7042 17 +7043 23 +7044 21 +7045 21 +7046 23 +7047 23 +7048 21 +7049 21 +7050 21 +7051 21 +7052 21 +7053 23 +7054 23 +7055 23 +7056 23 +7057 23 +7058 23 +7059 23 +7060 23 +7061 23 +7062 23 +7063 23 +7064 23 +7065 23 +7066 21 +7067 21 +7068 23 +7069 23 +7070 21 +7071 21 +7072 21 +7073 21 +7074 21 +7075 21 +7076 21 +7077 21 +7078 21 +7079 21 +7080 21 +7081 21 +7082 21 +7083 21 +7084 21 +7085 21 +7086 21 +7087 21 +7088 21 +7089 21 +7090 21 +7091 21 +7092 21 +7093 21 +7094 21 +7095 21 +7096 21 +7097 17 +7098 17 +7099 17 +7100 17 +7101 17 +7102 21 +7103 21 +7104 21 +7105 21 +7106 17 +7107 17 +7108 17 +7109 17 +7110 17 +7111 17 +7112 17 +7113 17 +7114 17 +7115 17 +7116 17 +7117 17 +7118 17 +7119 17 +7120 17 +7121 17 +7122 17 +7123 17 +7124 17 +7125 17 +7126 17 +7127 17 +7128 17 +7129 17 +7130 17 +7131 17 +7132 17 +7133 17 +7134 17 +7135 17 +7136 17 +7137 17 +7138 17 +7139 17 +7140 17 +7141 17 +7142 17 +7143 17 +7144 16 +7145 16 +7146 17 +7147 17 +7148 17 +7149 17 +7150 17 +7151 17 +7152 17 +7153 17 +7154 17 +7155 17 +7156 17 +7157 17 +7158 17 +7159 16 +7160 16 +7161 16 +7162 16 +7163 16 +7164 16 +7165 16 +7166 16 +7167 16 +7168 16 +7169 16 +7170 0 +7171 0 +7172 0 +7173 0 +7174 0 +7175 0 +7176 0 +7177 0 +7178 0 +7179 0 +7180 0 +7181 0 +7182 0 +7183 0 +7184 0 +7185 0 +7186 0 +7187 0 +7188 0 +7189 0 +7190 0 +7191 0 +7192 0 +7193 0 +7194 0 +7195 0 +7196 0 +7197 0 +7198 0 +7199 0 +7200 0 +7201 0 +7202 0 +7203 0 +7204 0 +7205 0 +7206 0 +7207 0 +7208 0 +7209 0 +7210 0 +7211 0 +7212 0 +7213 0 +7214 0 +7215 0 +7216 0 +7217 0 +7218 0 +7219 0 +7220 0 +7221 0 +7222 0 +7223 21 +7224 21 +7225 21 +7226 21 +7227 21 +7228 21 +7229 21 +7230 21 +7231 21 +7232 21 +7233 21 +7234 21 +7235 21 +7236 21 +7237 21 +7238 21 +7239 21 +7240 21 +7241 21 +7242 21 +7243 21 +7244 21 +7245 21 +7246 21 +7247 21 +7248 17 +7249 17 +7250 17 +7251 17 +7252 17 +7253 17 +7254 17 +7255 17 +7256 17 +7257 17 +7258 17 +7259 17 +7260 17 +7261 17 +7262 20 +7263 20 +7264 20 +7265 20 +7266 20 +7267 20 +7268 20 +7269 20 +7270 20 +7271 20 +7272 20 +7273 20 +7274 23 +7275 23 +7276 23 +7277 23 +7278 23 +7279 23 +7280 23 +7281 23 +7282 23 +7283 23 +7284 23 +7285 23 +7286 23 +7287 23 +7288 23 +7289 23 +7290 23 +7291 23 +7292 23 +7293 23 +7294 23 +7295 23 +7296 23 +7297 23 +7298 23 +7299 23 +7300 23 +7301 23 +7302 23 +7303 23 +7304 23 +7305 23 +7306 23 +7307 23 +7308 15 +7309 15 +7310 15 +7311 15 +7312 15 +7313 15 +7314 15 +7315 15 +7316 15 +7317 8 +7318 8 +7319 8 +7320 8 +7321 8 +7322 8 +7323 8 +7324 8 +7325 8 +7326 8 +7327 8 +7328 8 +7329 8 +7330 8 +7331 8 +7332 8 +7333 8 +7334 9 +7335 9 +7336 9 +7337 9 +7338 9 +7339 9 +7340 9 +7341 9 +7342 9 +7343 9 +7344 9 +7345 9 +7346 9 +7347 9 +7348 9 +7349 9 +7350 9 +7351 9 +7352 9 +7353 9 +7354 9 +7355 6 +7356 6 +7357 6 +7358 6 +7359 6 +7360 6 +7361 6 +7362 6 +7363 6 +7364 6 +7365 7 +7366 7 +7367 7 +7368 7 +7369 7 +7370 7 +7371 7 +7372 7 +7373 7 +7374 7 +7375 7 +7376 7 +7377 7 +7378 7 +7379 4 +7380 4 +7381 4 +7382 4 +7383 4 +7384 5 +7385 5 +7386 5 +7387 5 +7388 5 +7389 5 +7390 7 +7391 7 +7392 7 +7393 7 +7394 7 +7395 7 +7396 7 +7397 7 +7398 7 +7399 7 +7400 7 +7401 7 +7402 7 +7403 7 +7404 7 +7405 7 +7406 7 +7407 7 +7408 7 +7409 7 +7410 7 +7411 7 +7412 7 +7413 7 +7414 7 +7415 7 +7416 7 +7417 7 +7418 7 +7419 7 +7420 7 +7421 7 +7422 7 +7423 21 +7424 21 +7425 7 +7426 7 +7427 5 +7428 5 +7429 5 +7430 5 +7431 5 +7432 5 +7433 5 +7434 5 +7435 5 +7436 20 +7437 20 +7438 20 +7439 20 +7440 20 +7441 20 +7442 20 +7443 20 +7444 20 +7445 20 +7446 20 +7447 20 +7448 20 +7449 20 +7450 20 +7451 20 +7452 20 +7453 20 +7454 21 +7455 21 +7456 23 +7457 23 +7458 23 +7459 23 +7460 23 +7461 23 +7462 23 +7463 23 +7464 23 +7465 23 +7466 23 +7467 23 +7468 23 +7469 23 +7470 23 +7471 23 +7472 23 +7473 23 +7474 23 +7475 23 +7476 23 +7477 23 +7478 23 +7479 23 +7480 23 +7481 23 +7482 23 +7483 23 +7484 23 +7485 23 +7486 21 +7487 21 +7488 21 +7489 21 +7490 21 +7491 21 +7492 21 +7493 21 +7494 23 +7495 23 +7496 23 +7497 23 +7498 23 +7499 23 +7500 18 +7501 18 +7502 18 +7503 18 +7504 18 +7505 18 +7506 18 +7507 18 +7508 18 +7509 18 +7510 18 +7511 17 +7512 17 +7513 17 +7514 17 +7515 17 +7516 17 +7517 17 +7518 17 +7519 17 +7520 17 +7521 17 +7522 17 +7523 17 +7524 17 +7525 17 +7526 17 +7527 17 +7528 17 +7529 17 +7530 17 +7531 17 +7532 17 +7533 17 +7534 17 +7535 17 +7536 17 +7537 17 +7538 17 +7539 17 +7540 17 +7541 17 +7542 17 +7543 17 +7544 17 +7545 17 +7546 17 +7547 17 +7548 17 +7549 17 +7550 17 +7551 17 +7552 17 +7553 17 +7554 17 +7555 17 +7556 17 +7557 17 +7558 0 +7559 0 +7560 16 +7561 0 +7562 0 +7563 0 +7564 0 +7565 0 +7566 0 +7567 0 +7568 0 +7569 0 +7570 0 +7571 0 +7572 0 +7573 0 +7574 0 +7575 0 +7576 0 +7577 0 +7578 0 +7579 0 +7580 0 +7581 0 +7582 0 +7583 0 +7584 0 +7585 0 +7586 0 +7587 0 +7588 0 +7589 0 +7590 1 +7591 1 +7592 2 +7593 2 +7594 2 +7595 2 +7596 2 +7597 2 +7598 2 +7599 2 +7600 2 +7601 7 +7602 7 +7603 7 +7604 7 +7605 7 +7606 7 +7607 7 +7608 7 +7609 7 +7610 7 +7611 7 +7612 7 +7613 7 +7614 7 +7615 7 +7616 7 +7617 7 +7618 7 +7619 7 +7620 7 +7621 7 +7622 7 +7623 7 +7624 7 +7625 7 +7626 7 +7627 7 +7628 7 +7629 7 +7630 7 +7631 7 +7632 7 +7633 7 +7634 7 +7635 7 +7636 7 +7637 7 +7638 7 +7639 7 +7640 7 +7641 7 +7642 7 +7643 7 +7644 7 +7645 7 +7646 7 +7647 21 +7648 21 +7649 21 +7650 21 +7651 21 +7652 5 +7653 5 +7654 5 +7655 5 +7656 5 +7657 5 +7658 20 +7659 20 +7660 20 +7661 20 +7662 20 +7663 20 +7664 20 +7665 20 +7666 20 +7667 20 +7668 20 +7669 21 +7670 21 +7671 20 +7672 21 +7673 21 +7674 21 +7675 21 +7676 20 +7677 20 +7678 21 +7679 21 +7680 21 +7681 21 +7682 21 +7683 21 +7684 21 +7685 21 +7686 21 +7687 23 +7688 23 +7689 21 +7690 21 +7691 21 +7692 21 +7693 21 +7694 21 +7695 21 +7696 21 +7697 21 +7698 21 +7699 21 +7700 21 +7701 21 +7702 21 +7703 21 +7704 21 +7705 21 +7706 21 +7707 21 +7708 21 +7709 21 +7710 21 +7711 21 +7712 21 +7713 21 +7714 21 +7715 21 +7716 21 +7717 21 +7718 21 +7719 21 +7720 21 +7721 21 +7722 21 +7723 21 +7724 21 +7725 21 +7726 21 +7727 21 +7728 21 +7729 0 +7730 1 +7731 1 +7732 1 +7733 1 +7734 1 +7735 1 +7736 1 +7737 1 +7738 1 +7739 2 +7740 2 +7741 2 +7742 2 +7743 2 +7744 2 +7745 2 +7746 2 +7747 2 +7748 2 +7749 2 +7750 2 +7751 2 +7752 2 +7753 2 +7754 2 +7755 2 +7756 2 +7757 2 +7758 2 +7759 2 +7760 2 +7761 2 +7762 2 +7763 2 +7764 2 +7765 2 +7766 3 +7767 3 +7768 3 +7769 3 +7770 3 +7771 3 +7772 3 +7773 3 +7774 3 +7775 3 +7776 3 +7777 3 +7778 3 +7779 3 +7780 3 +7781 3 +7782 3 +7783 3 +7784 3 +7785 3 +7786 3 +7787 3 +7788 3 +7789 3 +7790 3 +7791 3 +7792 3 +7793 3 +7794 3 +7795 3 +7796 3 +7797 3 +7798 3 +7799 3 +7800 3 +7801 3 +7802 3 +7803 3 +7804 3 +7805 3 +7806 3 +7807 3 +7808 3 +7809 3 +7810 13 +7811 13 +7812 13 +7813 13 +7814 13 +7815 13 +7816 13 +7817 13 +7818 13 +7819 13 +7820 13 +7821 13 +7822 13 +7823 13 +7824 13 +7825 13 +7826 13 +7827 13 +7828 13 +7829 13 +7830 13 +7831 14 +7832 13 +7833 14 +7834 14 +7835 14 +7836 14 +7837 14 +7838 14 +7839 14 +7840 14 +7841 14 +7842 14 +7843 14 +7844 14 +7845 14 +7846 14 +7847 14 +7848 15 +7849 15 +7850 15 +7851 15 +7852 15 +7853 15 +7854 15 +7855 15 +7856 15 +7857 15 +7858 15 +7859 15 +7860 15 +7861 15 +7862 15 +7863 15 +7864 8 +7865 8 +7866 8 +7867 8 +7868 8 +7869 8 +7870 8 +7871 8 +7872 8 +7873 8 +7874 8 +7875 8 +7876 8 +7877 8 +7878 8 +7879 9 +7880 9 +7881 9 +7882 9 +7883 9 +7884 9 +7885 9 +7886 9 +7887 9 +7888 9 +7889 9 +7890 9 +7891 9 +7892 9 +7893 9 +7894 9 +7895 9 +7896 9 +7897 9 +7898 9 +7899 9 +7900 6 +7901 6 +7902 6 +7903 6 +7904 6 +7905 6 +7906 6 +7907 6 +7908 6 +7909 6 +7910 7 +7911 7 +7912 7 +7913 7 +7914 7 +7915 7 +7916 7 +7917 7 +7918 7 +7919 7 +7920 7 +7921 7 +7922 7 +7923 7 +7924 7 +7925 7 +7926 7 +7927 7 +7928 7 +7929 7 +7930 3 +7931 13 +7932 13 +7933 13 +7934 13 +7935 13 +7936 13 +7937 13 +7938 13 +7939 13 +7940 13 +7941 13 +7942 13 +7943 13 +7944 13 +7945 13 +7946 13 +7947 13 +7948 13 +7949 13 +7950 13 +7951 13 +7952 13 +7953 13 +7954 14 +7955 14 +7956 14 +7957 14 +7958 14 +7959 14 +7960 14 +7961 14 +7962 21 +7963 21 +7964 21 +7965 21 +7966 21 +7967 17 +7968 17 +7969 1 +7970 1 +7971 1 +7972 17 +7973 17 +7974 1 +7975 1 +7976 1 +7977 17 +7978 17 +7979 17 +7980 1 +7981 1 +7982 1 +7983 1 +7984 1 +7985 1 +7986 1 +7987 17 +7988 17 +7989 17 +7990 17 +7991 17 +7992 17 +7993 0 +7994 0 +7995 0 +7996 0 +7997 0 +7998 0 +7999 0 +8000 0 +8001 0 +8002 0 +8003 0 +8004 0 +8005 0 +8006 0 +8007 0 +8008 0 +8009 0 +8010 0 +8011 0 +8012 0 +8013 0 +8014 1 +8015 1 +8016 1 +8017 1 +8018 1 +8019 1 +8020 1 +8021 1 +8022 1 +8023 2 +8024 2 +8025 2 +8026 2 +8027 2 +8028 2 +8029 2 +8030 2 +8031 2 +8032 2 +8033 2 +8034 2 +8035 2 +8036 2 +8037 3 +8038 3 +8039 3 +8040 3 +8041 3 +8042 3 +8043 3 +8044 3 +8045 3 +8046 3 +8047 3 +8048 3 +8049 3 +8050 3 +8051 3 +8052 13 +8053 13 +8054 3 +8055 3 +8056 13 +8057 13 +8058 13 +8059 13 +8060 13 +8061 13 +8062 13 +8063 13 +8064 13 +8065 13 +8066 13 +8067 13 +8068 13 +8069 13 +8070 13 +8071 13 +8072 13 +8073 13 +8074 13 +8075 13 +8076 13 +8077 14 +8078 14 +8079 14 +8080 15 +8081 14 +8082 14 +8083 15 +8084 15 +8085 15 +8086 15 +8087 15 +8088 15 +8089 15 +8090 15 +8091 15 +8092 15 +8093 15 +8094 15 +8095 15 +8096 15 +8097 15 +8098 15 +8099 12 +8100 8 +8101 8 +8102 8 +8103 8 +8104 8 +8105 8 +8106 8 +8107 8 +8108 8 +8109 8 +8110 8 +8111 8 +8112 8 +8113 9 +8114 9 +8115 9 +8116 9 +8117 9 +8118 9 +8119 9 +8120 9 +8121 9 +8122 9 +8123 9 +8124 9 +8125 9 +8126 9 +8127 9 +8128 9 +8129 9 +8130 9 +8131 9 +8132 9 +8133 9 +8134 6 +8135 6 +8136 6 +8137 6 +8138 6 +8139 6 +8140 6 +8141 6 +8142 6 +8143 6 +8144 7 +8145 7 +8146 7 +8147 7 +8148 7 +8149 7 +8150 7 +8151 7 +8152 7 +8153 7 +8154 7 +8155 7 +8156 7 +8157 7 +8158 7 +8159 7 +8160 7 +8161 7 +8162 7 +8163 7 +8164 7 +8165 7 +8166 7 +8167 7 +8168 7 +8169 7 +8170 7 +8171 7 +8172 7 +8173 7 +8174 7 +8175 7 +8176 7 +8177 1 +8178 1 +8179 7 +8180 7 +8181 7 +8182 7 +8183 7 +8184 7 +8185 7 +8186 21 +8187 21 +8188 21 +8189 21 +8190 21 +8191 21 +8192 21 +8193 21 +8194 20 +8195 20 +8196 21 +8197 21 +8198 21 +8199 21 +8200 21 +8201 21 +8202 21 +8203 21 +8204 21 +8205 21 +8206 21 +8207 20 +8208 20 +8209 15 +8210 15 +8211 15 +8212 15 +8213 15 +8214 15 +8215 15 +8216 15 +8217 15 +8218 15 +8219 15 +8220 15 +8221 15 +8222 15 +8223 15 +8224 12 +8225 12 +8226 8 +8227 8 +8228 8 +8229 8 +8230 8 +8231 8 +8232 8 +8233 8 +8234 8 +8235 8 +8236 9 +8237 9 +8238 9 +8239 9 +8240 9 +8241 9 +8242 9 +8243 9 +8244 9 +8245 9 +8246 9 +8247 9 +8248 9 +8249 9 +8250 9 +8251 9 +8252 9 +8253 9 +8254 9 +8255 9 +8256 6 +8257 6 +8258 6 +8259 6 +8260 6 +8261 6 +8262 6 +8263 6 +8264 6 +8265 6 +8266 6 +8267 7 +8268 7 +8269 7 +8270 7 +8271 7 +8272 7 +8273 7 +8274 7 +8275 7 +8276 7 +8277 7 +8278 7 +8279 7 +8280 7 +8281 7 +8282 7 +8283 7 +8284 7 +8285 7 +8286 7 +8287 7 +8288 7 +8289 7 +8290 7 +8291 7 +8292 1 +8293 1 +8294 1 +8295 1 +8296 1 +8297 7 +8298 1 +8299 1 +8300 1 +8301 1 +8302 1 +8303 1 +8304 7 +8305 7 +8306 7 +8307 7 +8308 7 +8309 7 +8310 7 +8311 21 +8312 21 +8313 21 +8314 21 +8315 21 +8316 21 +8317 21 +8318 21 +8319 3 +8320 3 +8321 3 +8322 3 +8323 3 +8324 3 +8325 3 +8326 3 +8327 3 +8328 3 +8329 3 +8330 3 +8331 3 +8332 3 +8333 3 +8334 3 +8335 3 +8336 3 +8337 3 +8338 3 +8339 3 +8340 3 +8341 3 +8342 3 +8343 3 +8344 3 +8345 3 +8346 3 +8347 3 +8348 3 +8349 3 +8350 3 +8351 3 +8352 13 +8353 13 +8354 13 +8355 13 +8356 13 +8357 13 +8358 13 +8359 13 +8360 13 +8361 13 +8362 13 +8363 13 +8364 13 +8365 13 +8366 13 +8367 13 +8368 13 +8369 13 +8370 13 +8371 13 +8372 13 +8373 13 +8374 13 +8375 15 +8376 15 +8377 15 +8378 15 +8379 15 +8380 15 +8381 15 +8382 15 +8383 15 +8384 15 +8385 15 +8386 15 +8387 15 +8388 12 +8389 12 +8390 12 +8391 12 +8392 8 +8393 8 +8394 8 +8395 8 +8396 8 +8397 8 +8398 8 +8399 9 +8400 9 +8401 9 +8402 9 +8403 9 +8404 9 +8405 9 +8406 9 +8407 9 +8408 9 +8409 9 +8410 9 +8411 9 +8412 9 +8413 9 +8414 12 +8415 12 +8416 12 +8417 9 +8418 9 +8419 6 +8420 6 +8421 6 +8422 6 +8423 6 +8424 6 +8425 6 +8426 6 +8427 6 +8428 6 +8429 6 +8430 7 +8431 7 +8432 7 +8433 7 +8434 7 +8435 7 +8436 7 +8437 7 +8438 7 +8439 7 +8440 7 +8441 7 +8442 7 +8443 7 +8444 7 +8445 7 +8446 7 +8447 7 +8448 7 +8449 7 +8450 7 +8451 7 +8452 7 +8453 7 +8454 1 +8455 1 +8456 1 +8457 1 +8458 1 +8459 1 +8460 1 +8461 1 +8462 1 +8463 1 +8464 1 +8465 1 +8466 1 +8467 7 +8468 21 +8469 21 +8470 7 +8471 7 +8472 7 +8473 7 +8474 21 +8475 21 +8476 21 +8477 21 +8478 21 +8479 21 +8480 21 +8481 21 +8482 21 +8483 21 +8484 21 +8485 21 +8486 21 +8487 1 +8488 1 +8489 1 +8490 1 +8491 1 +8492 1 +8493 1 +8494 1 +8495 1 +8496 1 +8497 1 +8498 1 +8499 1 +8500 1 +8501 1 +8502 1 +8503 1 +8504 1 +8505 0 +8506 0 +8507 0 +8508 0 +8509 0 +8510 0 +8511 0 +8512 0 +8513 0 +8514 0 +8515 0 +8516 1 +8517 0 +8518 1 +8519 0 +8520 0 +8521 0 +8522 0 +8523 0 +8524 1 +8525 1 +8526 1 +8527 1 +8528 1 +8529 1 +8530 1 +8531 1 +8532 1 +8533 1 +8534 1 +8535 1 +8536 1 +8537 0 +8538 0 +8539 0 +8540 0 +8541 0 +8542 7 +8543 7 +8544 7 +8545 7 +8546 7 +8547 7 +8548 7 +8549 7 +8550 7 +8551 7 +8552 7 +8553 7 +8554 7 +8555 7 +8556 7 +8557 7 +8558 7 +8559 1 +8560 1 +8561 1 +8562 1 +8563 1 +8564 1 +8565 1 +8566 1 +8567 1 +8568 1 +8569 1 +8570 1 +8571 1 +8572 1 +8573 1 +8574 1 +8575 1 +8576 1 +8577 1 +8578 1 +8579 1 +8580 1 +8581 1 +8582 1 +8583 1 +8584 1 +8585 1 +8586 1 +8587 1 +8588 0 +8589 0 +8590 1 +8591 1 +8592 1 +8593 1 +8594 1 +8595 1 +8596 1 +8597 1 +8598 1 +8599 1 +8600 1 +8601 1 +8602 1 +8603 1 +8604 1 +8605 1 +8606 1 +8607 1 +8608 0 +8609 0 +8610 0 +8611 1 +8612 1 +8613 1 +8614 1 +8615 1 +8616 1 +8617 1 +8618 1 +8619 1 +8620 1 +8621 2 +8622 2 +8623 2 +8624 1 +8625 1 +8626 2 +8627 2 +8628 2 +8629 2 +8630 2 +8631 2 +8632 2 +8633 2 +8634 2 +8635 2 +8636 2 +8637 2 +8638 2 +8639 2 +8640 2 +8641 15 +8642 15 +8643 15 +8644 12 +8645 12 +8646 12 +8647 12 +8648 12 +8649 12 +8650 12 +8651 12 +8652 12 +8653 8 +8654 8 +8655 8 +8656 8 +8657 9 +8658 9 +8659 9 +8660 9 +8661 9 +8662 9 +8663 9 +8664 9 +8665 9 +8666 9 +8667 9 +8668 9 +8669 9 +8670 9 +8671 12 +8672 12 +8673 12 +8674 12 +8675 12 +8676 12 +8677 6 +8678 6 +8679 6 +8680 6 +8681 6 +8682 6 +8683 6 +8684 6 +8685 6 +8686 6 +8687 6 +8688 6 +8689 6 +8690 6 +8691 6 +8692 7 +8693 7 +8694 7 +8695 7 +8696 7 +8697 7 +8698 7 +8699 7 +8700 7 +8701 7 +8702 7 +8703 7 +8704 7 +8705 7 +8706 1 +8707 1 +8708 1 +8709 1 +8710 1 +8711 1 +8712 1 +8713 1 +8714 1 +8715 1 +8716 1 +8717 1 +8718 1 +8719 1 +8720 1 +8721 1 +8722 1 +8723 1 +8724 1 +8725 1 +8726 1 +8727 1 +8728 1 +8729 1 +8730 1 +8731 1 +8732 1 +8733 1 +8734 1 +8735 1 +8736 1 +8737 1 +8738 1 +8739 1 +8740 1 +8741 1 +8742 1 +8743 15 +8744 15 +8745 12 +8746 12 +8747 12 +8748 12 +8749 12 +8750 12 +8751 12 +8752 12 +8753 12 +8754 12 +8755 12 +8756 12 +8757 8 +8758 8 +8759 9 +8760 9 +8761 9 +8762 9 +8763 9 +8764 9 +8765 9 +8766 9 +8767 9 +8768 9 +8769 9 +8770 9 +8771 9 +8772 12 +8773 12 +8774 12 +8775 12 +8776 12 +8777 12 +8778 12 +8779 6 +8780 6 +8781 6 +8782 6 +8783 6 +8784 6 +8785 6 +8786 6 +8787 6 +8788 6 +8789 6 +8790 6 +8791 6 +8792 6 +8793 7 +8794 7 +8795 7 +8796 7 +8797 7 +8798 7 +8799 7 +8800 7 +8801 7 +8802 7 +8803 7 +8804 7 +8805 7 +8806 7 +8807 7 +8808 1 +8809 1 +8810 1 +8811 1 +8812 1 +8813 1 +8814 1 +8815 1 +8816 1 +8817 1 +8818 1 +8819 1 +8820 1 +8821 1 +8822 1 +8823 1 +8824 1 +8825 1 +8826 1 +8827 1 +8828 1 +8829 1 +8830 1 +8831 1 +8832 1 +8833 1 +8834 1 +8835 1 +8836 1 +8837 1 +8838 1 +8839 2 +8840 2 +8841 2 +8842 2 +8843 2 +8844 2 +8845 2 +8846 2 +8847 2 +8848 2 +8849 2 +8850 2 +8851 2 +8852 2 +8853 2 +8854 3 +8855 3 +8856 3 +8857 3 +8858 3 +8859 3 +8860 3 +8861 3 +8862 3 +8863 3 +8864 3 +8865 3 +8866 3 +8867 3 +8868 3 +8869 3 +8870 3 +8871 3 +8872 3 +8873 3 +8874 3 +8875 3 +8876 3 +8877 3 +8878 3 +8879 3 +8880 3 +8881 3 +8882 3 +8883 3 +8884 3 +8885 3 +8886 3 +8887 3 +8888 3 +8889 3 +8890 3 +8891 3 +8892 3 +8893 3 +8894 3 +8895 3 +8896 3 +8897 3 +8898 3 +8899 3 +8900 3 +8901 3 +8902 3 +8903 3 +8904 3 +8905 13 +8906 13 +8907 13 +8908 13 +8909 13 +8910 13 +8911 13 +8912 13 +8913 13 +8914 13 +8915 13 +8916 13 +8917 13 +8918 13 +8919 13 +8920 13 +8921 13 +8922 13 +8923 13 +8924 12 +8925 13 +8926 13 +8927 13 +8928 15 +8929 15 +8930 15 +8931 15 +8932 15 +8933 12 +8934 12 +8935 12 +8936 12 +8937 12 +8938 12 +8939 12 +8940 12 +8941 12 +8942 12 +8943 12 +8944 12 +8945 12 +8946 12 +8947 9 +8948 9 +8949 9 +8950 9 +8951 9 +8952 9 +8953 9 +8954 9 +8955 9 +8956 9 +8957 9 +8958 12 +8959 12 +8960 12 +8961 12 +8962 12 +8963 12 +8964 12 +8965 12 +8966 6 +8967 6 +8968 6 +8969 6 +8970 6 +8971 6 +8972 6 +8973 6 +8974 6 +8975 6 +8976 6 +8977 6 +8978 6 +8979 6 +8980 7 +8981 7 +8982 7 +8983 7 +8984 7 +8985 7 +8986 7 +8987 7 +8988 7 +8989 7 +8990 1 +8991 1 +8992 1 +8993 1 +8994 1 +8995 1 +8996 1 +8997 1 +8998 1 +8999 1 +9000 1 +9001 1 +9002 1 +9003 1 +9004 1 +9005 1 +9006 1 +9007 1 +9008 1 +9009 1 +9010 1 +9011 1 +9012 1 +9013 1 +9014 1 +9015 1 +9016 1 +9017 1 +9018 1 +9019 1 +9020 1 +9021 1 +9022 2 +9023 2 +9024 2 +9025 2 +9026 2 +9027 2 +9028 2 +9029 2 +9030 2 +9031 2 +9032 2 +9033 2 +9034 2 +9035 2 +9036 2 +9037 2 +9038 2 +9039 2 +9040 2 +9041 2 +9042 2 +9043 2 +9044 3 +9045 2 +9046 3 +9047 3 +9048 2 +9049 3 +9050 3 +9051 3 +9052 3 +9053 3 +9054 3 +9055 3 +9056 3 +9057 3 +9058 3 +9059 3 +9060 3 +9061 3 +9062 3 +9063 3 +9064 3 +9065 3 +9066 3 +9067 3 +9068 3 +9069 3 +9070 3 +9071 3 +9072 3 +9073 13 +9074 13 +9075 13 +9076 13 +9077 13 +9078 13 +9079 13 +9080 12 +9081 12 +9082 12 +9083 12 +9084 12 +9085 12 +9086 12 +9087 12 +9088 12 +9089 12 +9090 12 +9091 12 +9092 12 +9093 12 +9094 21 +9095 12 +9096 12 +9097 12 +9098 12 +9099 12 +9100 12 +9101 12 +9102 12 +9103 12 +9104 12 +9105 12 +9106 13 +9107 13 +9108 12 +9109 12 +9110 12 +9111 12 +9112 12 +9113 12 +9114 12 +9115 12 +9116 12 +9117 12 +9118 12 +9119 12 +9120 12 +9121 9 +9122 9 +9123 9 +9124 9 +9125 9 +9126 9 +9127 9 +9128 12 +9129 12 +9130 12 +9131 12 +9132 12 +9133 12 +9134 12 +9135 12 +9136 12 +9137 12 +9138 6 +9139 6 +9140 6 +9141 6 +9142 6 +9143 6 +9144 6 +9145 6 +9146 6 +9147 6 +9148 6 +9149 6 +9150 6 +9151 6 +9152 6 +9153 6 +9154 6 +9155 6 +9156 6 +9157 7 +9158 7 +9159 1 +9160 1 +9161 1 +9162 1 +9163 1 +9164 1 +9165 1 +9166 1 +9167 1 +9168 1 +9169 1 +9170 1 +9171 1 +9172 1 +9173 1 +9174 1 +9175 1 +9176 1 +9177 1 +9178 1 +9179 1 +9180 1 +9181 1 +9182 1 +9183 1 +9184 1 +9185 1 +9186 1 +9187 1 +9188 1 +9189 1 +9190 1 +9191 1 +9192 1 +9193 1 +9194 1 +9195 2 +9196 2 +9197 2 +9198 2 +9199 2 +9200 2 +9201 2 +9202 2 +9203 2 +9204 2 +9205 2 +9206 2 +9207 2 +9208 2 +9209 3 +9210 3 +9211 3 +9212 3 +9213 3 +9214 3 +9215 3 +9216 3 +9217 3 +9218 3 +9219 3 +9220 3 +9221 6 +9222 13 +9223 13 +9224 13 +9225 13 +9226 13 +9227 13 +9228 13 +9229 12 +9230 12 +9231 12 +9232 12 +9233 12 +9234 12 +9235 12 +9236 12 +9237 12 +9238 12 +9239 12 +9240 12 +9241 12 +9242 12 +9243 12 +9244 12 +9245 12 +9246 12 +9247 12 +9248 12 +9249 12 +9250 9 +9251 9 +9252 9 +9253 9 +9254 9 +9255 12 +9256 12 +9257 12 +9258 12 +9259 12 +9260 12 +9261 12 +9262 12 +9263 12 +9264 12 +9265 12 +9266 6 +9267 6 +9268 6 +9269 6 +9270 6 +9271 6 +9272 6 +9273 6 +9274 6 +9275 6 +9276 6 +9277 6 +9278 6 +9279 6 +9280 6 +9281 6 +9282 6 +9283 6 +9284 6 +9285 7 +9286 1 +9287 1 +9288 1 +9289 1 +9290 1 +9291 1 +9292 1 +9293 1 +9294 1 +9295 2 +9296 2 +9297 2 +9298 2 +9299 2 +9300 2 +9301 2 +9302 2 +9303 2 +9304 2 +9305 2 +9306 2 +9307 2 +9308 2 +9309 2 +9310 2 +9311 6 +9312 6 +9313 3 +9314 3 +9315 3 +9316 3 +9317 3 +9318 3 +9319 3 +9320 3 +9321 3 +9322 3 +9323 3 +9324 6 +9325 6 +9326 6 +9327 6 +9328 13 +9329 13 +9330 13 +9331 13 +9332 12 +9333 12 +9334 12 +9335 12 +9336 12 +9337 12 +9338 12 +9339 12 +9340 12 +9341 12 +9342 12 +9343 12 +9344 12 +9345 12 +9346 12 +9347 12 +9348 12 +9349 12 +9350 12 +9351 12 +9352 12 +9353 12 +9354 12 +9355 12 +9356 12 +9357 12 +9358 12 +9359 12 +9360 12 +9361 12 +9362 12 +9363 12 +9364 12 +9365 12 +9366 12 +9367 12 +9368 12 +9369 12 +9370 12 +9371 12 +9372 12 +9373 12 +9374 6 +9375 6 +9376 6 +9377 6 +9378 6 +9379 6 +9380 6 +9381 6 +9382 6 +9383 6 +9384 6 +9385 6 +9386 6 +9387 6 +9388 6 +9389 6 +9390 6 +9391 6 +9392 6 +9393 6 +9394 6 +9395 6 +9396 6 +9397 1 +9398 1 +9399 1 +9400 1 +9401 1 +9402 1 +9403 1 +9404 1 +9405 2 +9406 2 +9407 2 +9408 2 +9409 2 +9410 2 +9411 2 +9412 2 +9413 2 +9414 2 +9415 6 +9416 6 +9417 2 +9418 2 +9419 6 +9420 6 +9421 6 +9422 6 +9423 6 +9424 6 +9425 6 +9426 6 +9427 6 +9428 3 +9429 6 +9430 6 +9431 6 +9432 6 +9433 6 +9434 6 +9435 6 +9436 6 +9437 12 +9438 13 +9439 12 +9440 12 +9441 12 +9442 12 +9443 12 +9444 12 +9445 12 +9446 12 +9447 12 +9448 12 +9449 12 +9450 12 +9451 12 +9452 12 +9453 12 +9454 12 +9455 12 +9456 12 +9457 12 +9458 12 +9459 12 +9460 12 +9461 12 +9462 12 +9463 12 +9464 12 +9465 12 +9466 12 +9467 12 +9468 12 +9469 12 +9470 12 +9471 12 +9472 12 +9473 12 +9474 12 +9475 12 +9476 12 +9477 12 +9478 12 +9479 12 +9480 6 +9481 6 +9482 6 +9483 6 +9484 6 +9485 6 +9486 6 +9487 6 +9488 6 +9489 6 +9490 6 +9491 6 +9492 6 +9493 6 +9494 6 +9495 6 +9496 6 +9497 2 +9498 1 +9499 6 +9500 6 +9501 6 +9502 6 +9503 6 +9504 6 +9505 6 +9506 6 +9507 6 +9508 6 +9509 6 +9510 6 +9511 6 +9512 6 +9513 6 +9514 6 +9515 6 +9516 6 +9517 6 +9518 6 +9519 6 +9520 6 +9521 6 +9522 6 +9523 6 +9524 6 +9525 6 +9526 6 +9527 6 +9528 6 +9529 6 +9530 6 +9531 6 +9532 12 +9533 12 +9534 12 +9535 12 +9536 12 +9537 12 +9538 12 +9539 12 +9540 12 +9541 12 +9542 12 +9543 12 +9544 12 +9545 12 +9546 12 +9547 12 +9548 12 +9549 12 +9550 12 +9551 12 +9552 12 +9553 12 +9554 12 +9555 12 +9556 12 +9557 12 +9558 12 +9559 12 +9560 12 +9561 12 +9562 12 +9563 6 +9564 6 +9565 6 +9566 6 +9567 6 +9568 6 +9569 6 +9570 6 +9571 6 +9572 6 +9573 6 +9574 6 +9575 6 +9576 6 +9577 6 +9578 6 +9579 6 +9580 6 +9581 6 +9582 6 +9583 6 +9584 6 +9585 6 +9586 6 +9587 6 +9588 6 +9589 6 +9590 6 +9591 6 +9592 6 +9593 6 +9594 6 +9595 6 +9596 6 +9597 12 +9598 12 +9599 12 +9600 12 +9601 12 +9602 12 +9603 12 +9604 12 +9605 12 +9606 12 +9607 12 +9608 12 +9609 12 +9610 12 +9611 12 +9612 12 +9613 12 +9614 12 +9615 12 +9616 12 +9617 12 +9618 12 +9619 12 +9620 12 +9621 12 +9622 12 +9623 6 +9624 6 +9625 6 +9626 6 +9627 6 +9628 6 +9629 6 +9630 6 +9631 6 +9632 6 +9633 6 +9634 6 +9635 6 +9636 6 +9637 6 +9638 6 +9639 6 +9640 6 +9641 6 +9642 6 +9643 6 +9644 6 +9645 6 +9646 12 +9647 12 +9648 12 +9649 12 +9650 12 +9651 12 +9652 12 +9653 12 +9654 12 +9655 12 +9656 12 +9657 12 +9658 12 +9659 12 +9660 6 +9661 6 +9662 6 +9663 6 +9664 6 +9665 6 +9666 12 +9667 12 +9668 12 +9669 12 +9670 16 +9671 16 +9672 16 +9673 16 +9674 18 +9675 18 +9676 16 +9677 18 +9678 18 +9679 18 +9680 16 +9681 16 +9682 16 +9683 18 +9684 18 +9685 16 +9686 16 +9687 16 +9688 16 +9689 16 +9690 16 +9691 16 +9692 18 +9693 18 +9694 23 +9695 23 +9696 23 +9697 29 +9698 29 +9699 29 +9700 23 +9701 23 +9702 23 +9703 23 +9704 18 +9705 18 +9706 27 +9707 27 +9708 27 +9709 27 +9710 27 +9711 27 +9712 27 +9713 27 +9714 27 +9715 27 +9716 27 +9717 27 +9718 27 +9719 27 +9720 27 +9721 16 +9722 16 +9723 16 +9724 16 +9725 18 +9726 18 +9727 18 +9728 18 +9729 18 +9730 18 +9731 18 +9732 18 +9733 18 +9734 18 +9735 18 +9736 18 +9737 19 +9738 19 +9739 25 +9740 25 +9741 25 +9742 25 +9743 25 +9744 25 +9745 0 +9746 0 +9747 24 +9748 24 +9749 24 +9750 16 +9751 14 +9752 26 +9753 26 +9754 26 +9755 26 +9756 26 +9757 26 +9758 26 +9759 26 +9760 26 +9761 16 +9762 16 +9763 21 +9764 21 +9765 21 +9766 2 +9767 21 +9768 18 +9769 18 +9770 18 +9771 18 +9772 18 +9773 18 +9774 18 +9775 17 +9776 25 +9777 17 +9778 18 +9779 18 +9780 18 +9781 27 +9782 19 +9783 19 +9784 0 +9785 16 +9786 0 +9787 0 +9788 0 +9789 0 +9790 21 +9791 3 +9792 16 +9793 29 +9794 29 +9795 29 +9796 16 +9797 16 +9798 16 +9799 16 diff --git a/scotch_6.0.3/src/check/data/m16x16.grf b/scotch_6.0.3/src/check/data/m16x16.grf new file mode 100644 index 00000000..d0cdd9f5 --- /dev/null +++ b/scotch_6.0.3/src/check/data/m16x16.grf @@ -0,0 +1,259 @@ +0 +256 960 +0 000 +2 1 16 +3 0 2 17 +3 1 3 18 +3 2 4 19 +3 3 5 20 +3 4 6 21 +3 5 7 22 +3 6 8 23 +3 7 9 24 +3 8 10 25 +3 9 11 26 +3 10 12 27 +3 11 13 28 +3 12 14 29 +3 13 15 30 +2 14 31 +3 0 17 32 +4 1 16 18 33 +4 2 17 19 34 +4 3 18 20 35 +4 4 19 21 36 +4 5 20 22 37 +4 6 21 23 38 +4 7 22 24 39 +4 8 23 25 40 +4 9 24 26 41 +4 10 25 27 42 +4 11 26 28 43 +4 12 27 29 44 +4 13 28 30 45 +4 14 29 31 46 +3 15 30 47 +3 16 33 48 +4 17 32 34 49 +4 18 33 35 50 +4 19 34 36 51 +4 20 35 37 52 +4 21 36 38 53 +4 22 37 39 54 +4 23 38 40 55 +4 24 39 41 56 +4 25 40 42 57 +4 26 41 43 58 +4 27 42 44 59 +4 28 43 45 60 +4 29 44 46 61 +4 30 45 47 62 +3 31 46 63 +3 32 49 64 +4 33 48 50 65 +4 34 49 51 66 +4 35 50 52 67 +4 36 51 53 68 +4 37 52 54 69 +4 38 53 55 70 +4 39 54 56 71 +4 40 55 57 72 +4 41 56 58 73 +4 42 57 59 74 +4 43 58 60 75 +4 44 59 61 76 +4 45 60 62 77 +4 46 61 63 78 +3 47 62 79 +3 48 65 80 +4 49 64 66 81 +4 50 65 67 82 +4 51 66 68 83 +4 52 67 69 84 +4 53 68 70 85 +4 54 69 71 86 +4 55 70 72 87 +4 56 71 73 88 +4 57 72 74 89 +4 58 73 75 90 +4 59 74 76 91 +4 60 75 77 92 +4 61 76 78 93 +4 62 77 79 94 +3 63 78 95 +3 64 81 96 +4 65 80 82 97 +4 66 81 83 98 +4 67 82 84 99 +4 68 83 85 100 +4 69 84 86 101 +4 70 85 87 102 +4 71 86 88 103 +4 72 87 89 104 +4 73 88 90 105 +4 74 89 91 106 +4 75 90 92 107 +4 76 91 93 108 +4 77 92 94 109 +4 78 93 95 110 +3 79 94 111 +3 80 97 112 +4 81 96 98 113 +4 82 97 99 114 +4 83 98 100 115 +4 84 99 101 116 +4 85 100 102 117 +4 86 101 103 118 +4 87 102 104 119 +4 88 103 105 120 +4 89 104 106 121 +4 90 105 107 122 +4 91 106 108 123 +4 92 107 109 124 +4 93 108 110 125 +4 94 109 111 126 +3 95 110 127 +3 96 113 128 +4 97 112 114 129 +4 98 113 115 130 +4 99 114 116 131 +4 100 115 117 132 +4 101 116 118 133 +4 102 117 119 134 +4 103 118 120 135 +4 104 119 121 136 +4 105 120 122 137 +4 106 121 123 138 +4 107 122 124 139 +4 108 123 125 140 +4 109 124 126 141 +4 110 125 127 142 +3 111 126 143 +3 112 129 144 +4 113 128 130 145 +4 114 129 131 146 +4 115 130 132 147 +4 116 131 133 148 +4 117 132 134 149 +4 118 133 135 150 +4 119 134 136 151 +4 120 135 137 152 +4 121 136 138 153 +4 122 137 139 154 +4 123 138 140 155 +4 124 139 141 156 +4 125 140 142 157 +4 126 141 143 158 +3 127 142 159 +3 128 145 160 +4 129 144 146 161 +4 130 145 147 162 +4 131 146 148 163 +4 132 147 149 164 +4 133 148 150 165 +4 134 149 151 166 +4 135 150 152 167 +4 136 151 153 168 +4 137 152 154 169 +4 138 153 155 170 +4 139 154 156 171 +4 140 155 157 172 +4 141 156 158 173 +4 142 157 159 174 +3 143 158 175 +3 144 161 176 +4 145 160 162 177 +4 146 161 163 178 +4 147 162 164 179 +4 148 163 165 180 +4 149 164 166 181 +4 150 165 167 182 +4 151 166 168 183 +4 152 167 169 184 +4 153 168 170 185 +4 154 169 171 186 +4 155 170 172 187 +4 156 171 173 188 +4 157 172 174 189 +4 158 173 175 190 +3 159 174 191 +3 160 177 192 +4 161 176 178 193 +4 162 177 179 194 +4 163 178 180 195 +4 164 179 181 196 +4 165 180 182 197 +4 166 181 183 198 +4 167 182 184 199 +4 168 183 185 200 +4 169 184 186 201 +4 170 185 187 202 +4 171 186 188 203 +4 172 187 189 204 +4 173 188 190 205 +4 174 189 191 206 +3 175 190 207 +3 176 193 208 +4 177 192 194 209 +4 178 193 195 210 +4 179 194 196 211 +4 180 195 197 212 +4 181 196 198 213 +4 182 197 199 214 +4 183 198 200 215 +4 184 199 201 216 +4 185 200 202 217 +4 186 201 203 218 +4 187 202 204 219 +4 188 203 205 220 +4 189 204 206 221 +4 190 205 207 222 +3 191 206 223 +3 192 209 224 +4 193 208 210 225 +4 194 209 211 226 +4 195 210 212 227 +4 196 211 213 228 +4 197 212 214 229 +4 198 213 215 230 +4 199 214 216 231 +4 200 215 217 232 +4 201 216 218 233 +4 202 217 219 234 +4 203 218 220 235 +4 204 219 221 236 +4 205 220 222 237 +4 206 221 223 238 +3 207 222 239 +3 208 225 240 +4 209 224 226 241 +4 210 225 227 242 +4 211 226 228 243 +4 212 227 229 244 +4 213 228 230 245 +4 214 229 231 246 +4 215 230 232 247 +4 216 231 233 248 +4 217 232 234 249 +4 218 233 235 250 +4 219 234 236 251 +4 220 235 237 252 +4 221 236 238 253 +4 222 237 239 254 +3 223 238 255 +2 224 241 +3 225 240 242 +3 226 241 243 +3 227 242 244 +3 228 243 245 +3 229 244 246 +3 230 245 247 +3 231 246 248 +3 232 247 249 +3 233 248 250 +3 234 249 251 +3 235 250 252 +3 236 251 253 +3 237 252 254 +3 238 253 255 +2 239 254 diff --git a/scotch_6.0.3/src/check/data/m16x16_b1.grf b/scotch_6.0.3/src/check/data/m16x16_b1.grf new file mode 100644 index 00000000..896cf24b --- /dev/null +++ b/scotch_6.0.3/src/check/data/m16x16_b1.grf @@ -0,0 +1,259 @@ +0 +256 960 +1 000 +2 2 17 +3 1 3 18 +3 2 4 19 +3 3 5 20 +3 4 6 21 +3 5 7 22 +3 6 8 23 +3 7 9 24 +3 8 10 25 +3 9 11 26 +3 10 12 27 +3 11 13 28 +3 12 14 29 +3 13 15 30 +3 14 16 31 +2 15 32 +3 1 18 33 +4 2 17 19 34 +4 3 18 20 35 +4 4 19 21 36 +4 5 20 22 37 +4 6 21 23 38 +4 7 22 24 39 +4 8 23 25 40 +4 9 24 26 41 +4 10 25 27 42 +4 11 26 28 43 +4 12 27 29 44 +4 13 28 30 45 +4 14 29 31 46 +4 15 30 32 47 +3 16 31 48 +3 17 34 49 +4 18 33 35 50 +4 19 34 36 51 +4 20 35 37 52 +4 21 36 38 53 +4 22 37 39 54 +4 23 38 40 55 +4 24 39 41 56 +4 25 40 42 57 +4 26 41 43 58 +4 27 42 44 59 +4 28 43 45 60 +4 29 44 46 61 +4 30 45 47 62 +4 31 46 48 63 +3 32 47 64 +3 33 50 65 +4 34 49 51 66 +4 35 50 52 67 +4 36 51 53 68 +4 37 52 54 69 +4 38 53 55 70 +4 39 54 56 71 +4 40 55 57 72 +4 41 56 58 73 +4 42 57 59 74 +4 43 58 60 75 +4 44 59 61 76 +4 45 60 62 77 +4 46 61 63 78 +4 47 62 64 79 +3 48 63 80 +3 49 66 81 +4 50 65 67 82 +4 51 66 68 83 +4 52 67 69 84 +4 53 68 70 85 +4 54 69 71 86 +4 55 70 72 87 +4 56 71 73 88 +4 57 72 74 89 +4 58 73 75 90 +4 59 74 76 91 +4 60 75 77 92 +4 61 76 78 93 +4 62 77 79 94 +4 63 78 80 95 +3 64 79 96 +3 65 82 97 +4 66 81 83 98 +4 67 82 84 99 +4 68 83 85 100 +4 69 84 86 101 +4 70 85 87 102 +4 71 86 88 103 +4 72 87 89 104 +4 73 88 90 105 +4 74 89 91 106 +4 75 90 92 107 +4 76 91 93 108 +4 77 92 94 109 +4 78 93 95 110 +4 79 94 96 111 +3 80 95 112 +3 81 98 113 +4 82 97 99 114 +4 83 98 100 115 +4 84 99 101 116 +4 85 100 102 117 +4 86 101 103 118 +4 87 102 104 119 +4 88 103 105 120 +4 89 104 106 121 +4 90 105 107 122 +4 91 106 108 123 +4 92 107 109 124 +4 93 108 110 125 +4 94 109 111 126 +4 95 110 112 127 +3 96 111 128 +3 97 114 129 +4 98 113 115 130 +4 99 114 116 131 +4 100 115 117 132 +4 101 116 118 133 +4 102 117 119 134 +4 103 118 120 135 +4 104 119 121 136 +4 105 120 122 137 +4 106 121 123 138 +4 107 122 124 139 +4 108 123 125 140 +4 109 124 126 141 +4 110 125 127 142 +4 111 126 128 143 +3 112 127 144 +3 113 130 145 +4 114 129 131 146 +4 115 130 132 147 +4 116 131 133 148 +4 117 132 134 149 +4 118 133 135 150 +4 119 134 136 151 +4 120 135 137 152 +4 121 136 138 153 +4 122 137 139 154 +4 123 138 140 155 +4 124 139 141 156 +4 125 140 142 157 +4 126 141 143 158 +4 127 142 144 159 +3 128 143 160 +3 129 146 161 +4 130 145 147 162 +4 131 146 148 163 +4 132 147 149 164 +4 133 148 150 165 +4 134 149 151 166 +4 135 150 152 167 +4 136 151 153 168 +4 137 152 154 169 +4 138 153 155 170 +4 139 154 156 171 +4 140 155 157 172 +4 141 156 158 173 +4 142 157 159 174 +4 143 158 160 175 +3 144 159 176 +3 145 162 177 +4 146 161 163 178 +4 147 162 164 179 +4 148 163 165 180 +4 149 164 166 181 +4 150 165 167 182 +4 151 166 168 183 +4 152 167 169 184 +4 153 168 170 185 +4 154 169 171 186 +4 155 170 172 187 +4 156 171 173 188 +4 157 172 174 189 +4 158 173 175 190 +4 159 174 176 191 +3 160 175 192 +3 161 178 193 +4 162 177 179 194 +4 163 178 180 195 +4 164 179 181 196 +4 165 180 182 197 +4 166 181 183 198 +4 167 182 184 199 +4 168 183 185 200 +4 169 184 186 201 +4 170 185 187 202 +4 171 186 188 203 +4 172 187 189 204 +4 173 188 190 205 +4 174 189 191 206 +4 175 190 192 207 +3 176 191 208 +3 177 194 209 +4 178 193 195 210 +4 179 194 196 211 +4 180 195 197 212 +4 181 196 198 213 +4 182 197 199 214 +4 183 198 200 215 +4 184 199 201 216 +4 185 200 202 217 +4 186 201 203 218 +4 187 202 204 219 +4 188 203 205 220 +4 189 204 206 221 +4 190 205 207 222 +4 191 206 208 223 +3 192 207 224 +3 193 210 225 +4 194 209 211 226 +4 195 210 212 227 +4 196 211 213 228 +4 197 212 214 229 +4 198 213 215 230 +4 199 214 216 231 +4 200 215 217 232 +4 201 216 218 233 +4 202 217 219 234 +4 203 218 220 235 +4 204 219 221 236 +4 205 220 222 237 +4 206 221 223 238 +4 207 222 224 239 +3 208 223 240 +3 209 226 241 +4 210 225 227 242 +4 211 226 228 243 +4 212 227 229 244 +4 213 228 230 245 +4 214 229 231 246 +4 215 230 232 247 +4 216 231 233 248 +4 217 232 234 249 +4 218 233 235 250 +4 219 234 236 251 +4 220 235 237 252 +4 221 236 238 253 +4 222 237 239 254 +4 223 238 240 255 +3 224 239 256 +2 225 242 +3 226 241 243 +3 227 242 244 +3 228 243 245 +3 229 244 246 +3 230 245 247 +3 231 246 248 +3 232 247 249 +3 233 248 250 +3 234 249 251 +3 235 250 252 +3 236 251 253 +3 237 252 254 +3 238 253 255 +3 239 254 256 +2 240 255 diff --git a/scotch_6.0.3/src/check/data/m4x4.grf b/scotch_6.0.3/src/check/data/m4x4.grf new file mode 100644 index 00000000..e77a4c2e --- /dev/null +++ b/scotch_6.0.3/src/check/data/m4x4.grf @@ -0,0 +1,19 @@ +0 +16 48 +0 000 +2 1 4 +3 0 2 5 +3 1 3 6 +2 2 7 +3 0 5 8 +4 1 4 6 9 +4 2 5 7 10 +3 3 6 11 +3 4 9 12 +4 5 8 10 13 +4 6 9 11 14 +3 7 10 15 +2 8 13 +3 9 12 14 +3 10 13 15 +2 11 14 diff --git a/scotch_6.0.3/src/check/data/m4x4_b1.grf b/scotch_6.0.3/src/check/data/m4x4_b1.grf new file mode 100644 index 00000000..999a5e5f --- /dev/null +++ b/scotch_6.0.3/src/check/data/m4x4_b1.grf @@ -0,0 +1,19 @@ +0 +16 48 +1 000 +2 2 5 +3 1 3 6 +3 2 4 7 +2 3 8 +3 1 6 9 +4 2 5 7 10 +4 3 6 8 11 +3 4 7 12 +3 5 10 13 +4 6 9 11 14 +4 7 10 12 15 +3 8 11 16 +2 9 14 +3 10 13 15 +3 11 14 16 +2 12 15 diff --git a/scotch_6.0.3/src/check/test_common_thread.c b/scotch_6.0.3/src/check/test_common_thread.c new file mode 100644 index 00000000..8327bc77 --- /dev/null +++ b/scotch_6.0.3/src/check/test_common_thread.c @@ -0,0 +1,207 @@ +/* Copyright 2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_common_thread.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the sequential **/ +/** strategy building routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 04 nov 2012 **/ +/** to 23 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 +#endif /* _XOPEN_SOURCE */ +#ifndef __USE_XOPEN2K +#define __USE_XOPEN2K /* For POSIX pthread_barrier_t */ +#endif /* __USE_XOPEN2K */ + +#include +#if ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) +#include +#endif /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ + +#include "../libscotch/module.h" +#include "../libscotch/common.h" + +#define COMPVAL(n) (((n) * ((n) + 1)) / 2) + +/* +** The type and structure definitions. +*/ + +/*+ The block data structure +*/ + +typedef struct TestThreadGroup_ { + ThreadGroupHeader thrddat; /*+ Thread handling data +*/ + int redusum; /*+ Value to compare reduction to +*/ +} TestThreadGroup; + +/*+ The thread-specific data block. +*/ + +typedef struct TestThread_ { + ThreadHeader thrddat; /*+ Thread management data +*/ + int reduval; /*+ Value to reduce +*/ + int scanval; /*+ Value for scan +*/ + int dummval; /*+ Dummy value for scan +*/ +} TestThread; + +/*************************/ +/* */ +/* The threaded routine. */ +/* */ +/*************************/ + +#if ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) + +static +void +testReduce ( +TestThread * restrict const tlocptr, /* Pointer to local thread */ +void * restrict const vlocptr, /* Pointer to local value */ +void * restrict const vremptr) /* Pointer to remote value */ +{ + TestThread * restrict const tremptr = (TestThread *) vremptr; + + tlocptr->reduval += tremptr->reduval; +} + +static +void +testScan ( +TestThread * restrict const tlocptr, /* Pointer to local thread */ +int * restrict const vlocptr, /* Pointer to local value */ +int * restrict const vremptr, /* Pointer to remote value */ +const int phasval) /* Phase index */ +{ + vlocptr[1 - phasval] = vlocptr[phasval] + ((vremptr == NULL) ? 0 : vremptr[phasval]); +} + +static +int +testThreads ( +TestThread * restrict thrdptr) +{ + TestThreadGroup * restrict const grouptr = (TestThreadGroup *) (thrdptr->thrddat.grouptr); + const int thrdnbr = grouptr->thrddat.thrdnbr; + const int thrdnum = thrdptr->thrddat.thrdnum; + int o; + + printf ("%d: running\n", thrdnum); + + o = 0; + + if (thrdnum == 0) + printf ("Performing reduction\n"); + + threadBarrier (thrdptr); + + thrdptr->reduval = 1 + thrdptr->thrddat.thrdnum; + threadReduce (thrdptr, thrdptr, (ThreadReduceFunc) testReduce, 0); + + if ((thrdnum == 0) && /* Test reduction result on thread 0 */ + (thrdptr->reduval != grouptr->redusum)) { + printf ("0: invalid reduction operator\n"); + o = 1; + } + + if (thrdnum == 0) + printf ("Performing scan\n"); + + threadBarrier (thrdptr); + + thrdptr->scanval = 1 + thrdptr->thrddat.thrdnum; + threadScan (thrdptr, &thrdptr->scanval, (ThreadScanFunc) testScan); + + if (thrdptr->scanval != COMPVAL (thrdnum + 1)) { + printf ("%d: invalid scan operator\n", thrdnum); + o = 1; + } + + threadBarrier (thrdptr); + + return (o); +} + +#endif /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + TestThreadGroup groudat; +#if ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) + TestThread * restrict thrdtab; + int thrdnbr; +#endif /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ + + SCOTCH_errorProg (argv[0]); + +#if ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) + thrdnbr = SCOTCH_PTHREAD_NUMBER; + + groudat.redusum = COMPVAL (thrdnbr); + + if ((thrdtab = malloc (thrdnbr * sizeof (TestThread))) == NULL) { + errorPrint ("main: out of memory"); + return (1); + } + + if (threadLaunch (&groudat, thrdtab, sizeof (TestThread), (ThreadLaunchStartFunc) testThreads, (ThreadLaunchJoinFunc) NULL, + thrdnbr, THREADCANBARRIER | THREADCANREDUCE | THREADCANSCAN) != 0) { + errorPrint ("main: cannot launch or run threads"); + return (1); + } +#else /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ + printf ("Scotch not compiled with either COMMON_PTHREAD or SCOTCH_PTHREAD\n"); +#endif /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ + + free (thrdtab); + + return (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_arch.c b/scotch_6.0.3/src/check/test_scotch_arch.c new file mode 100644 index 00000000..d955b35a --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_arch.c @@ -0,0 +1,135 @@ +/* Copyright 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_arch.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_arch*() routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 25 jun 2014 **/ +/** to 25 jun 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include + +#include "scotch.h" + + + int + SCOTCH_Arch archdat; + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + + SCOTCH_Num baseval; + SCOTCH_Num vertnbr; + SCOTCH_Num vertnum; + SCOTCH_Num colonbr; + SCOTCH_Num colonum; + SCOTCH_Num * colotab; + SCOTCH_Num * cnbrtab; + + SCOTCH_errorProg (argv[0]); + + if (SCOTCH_graphInit (&grafdat) != 0) { /* Initialize source graph */ + SCOTCH_errorPrint ("main: cannot initialize graph"); + return (1); + } + + if ((fileptr = fopen (argv[1], "r")) == NULL) { + SCOTCH_errorPrint ("main: cannot open file"); + return (1); + } + + if (SCOTCH_graphLoad (&grafdat, fileptr, -1, 0) != 0) { /* Read source graph */ + SCOTCH_errorPrint ("main: cannot load graph"); + return (1); + } + + fclose (fileptr); + + SCOTCH_graphSize (&grafdat, &vertnbr, NULL); + + if ((colotab = malloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) { + SCOTCH_errorPrint ("main: out of memory (1)"); + return (1); + } + + if ((cnbrtab = malloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) { + SCOTCH_errorPrint ("main: out of memory (1)"); + return (1); + } + memset (cnbrtab, 0, vertnbr * sizeof (SCOTCH_Num)); + + if (SCOTCH_graphColor (&grafdat, colotab, &colonbr, 0) != 0) { + SCOTCH_errorPrint ("main: cannot color graph"); + return (1); + } + + printf ("Number of colors: %ld\n", (long) colonbr); + + for (vertnum = 0; vertnum < vertnbr; vertnum ++) /* Sum-up color histogram */ + cnbrtab[colotab[vertnum]] ++; + + for (colonum = 0; colonum < colonbr; colonum ++) + printf ("Color %5ld: %ld\n", + (long) colonum, + (long) cnbrtab[colonum]); + + free (cnbrtab); + free (colotab); + SCOTCH_graphExit (&grafdat); + + return (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_dgraph_band.c b/scotch_6.0.3/src/check/test_scotch_dgraph_band.c new file mode 100644 index 00000000..eeac6030 --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_dgraph_band.c @@ -0,0 +1,207 @@ +/* Copyright 2011,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_dgraph_band.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_dgraphBand() routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 10 nov 2011 **/ +/** to 23 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include +#include +#include +#include + +#include "ptscotch.h" + +#define errorProg SCOTCH_errorProg +#define errorPrint SCOTCH_errorPrint + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( + +int argc, +char * argv[]) +{ + MPI_Comm proccomm; + int procglbnbr; /* Number of processes sharing graph data */ + int proclocnum; /* Number of this process */ + SCOTCH_Num vertglbnbr; + SCOTCH_Num vertlocnbr; + SCOTCH_Num * fronloctab; + SCOTCH_Num baseval; + SCOTCH_Dgraph grafdat; + SCOTCH_Dgraph bandgrafdat; + SCOTCH_Num bandvertglbnbr; + SCOTCH_Num bandvertlocnbr; + SCOTCH_Num * bandvlblloctab; + FILE * file; + int procnum; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + errorProg (argv[0]); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + if (argc != 2) { + errorPrint ("main: invalid number of parameters"); + exit (1); + } + + proccomm = MPI_COMM_WORLD; + MPI_Comm_size (proccomm, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (proccomm, &proclocnum); + + fprintf (stderr, "Proc %2d of %2d, pid %d\n", proclocnum, procglbnbr, getpid ()); + +#ifndef SCOTCH_CHECK_AUTO + if (proclocnum == 0) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } +#endif /* SCOTCH_CHECK_AUTO */ + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) { /* Initialize source graph */ + errorPrint ("main: cannot initialize graph (1)"); + return (1); + } + + file = NULL; + if ((proclocnum == 0) && + ((file = fopen (argv[1], "r")) == NULL)) { + errorPrint ("main: cannot open graph file"); + return (1); + } + + if (SCOTCH_dgraphLoad (&grafdat, file, 0, 0) != 0) { + errorPrint ("main: cannot load graph"); + return (1); + } + + if (file != NULL) + fclose (file); + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + SCOTCH_dgraphData (&grafdat, NULL, &vertglbnbr, &vertlocnbr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + if ((fronloctab = malloc (vertlocnbr * sizeof (SCOTCH_Num))) == NULL) { + errorPrint ("main: cannot allocate frontier array"); + return (1); + } + + if (SCOTCH_dgraphInit (&bandgrafdat, proccomm) != 0) { /* Initialize band graph */ + errorPrint ("main: cannot initialize graph (2)"); + return (1); + } + + fronloctab[0] = 0; + + if (SCOTCH_dgraphBand (&grafdat, (proclocnum == 1) ? 1 : 0, fronloctab, 4, &bandgrafdat) != 0) { + errorPrint ("main: cannot compute band graph"); + return (1); + } + + SCOTCH_dgraphData (&bandgrafdat, &baseval, &bandvertglbnbr, &bandvertlocnbr, NULL, NULL, NULL, NULL, NULL, &bandvlblloctab, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + for (procnum = 0; procnum < procglbnbr; procnum ++) { + SCOTCH_Num bandvertlocnum; + + MPI_Barrier (proccomm); + + if (procnum == proclocnum) { + if ((file = fopen ("/tmp/test_scotch_dgraph_band.map", (procnum == 0) ? "w" : "a+")) == NULL) { + errorPrint ("main: cannot open mapping file"); + return (1); + } + + if (procnum == 0) + fprintf (file, "%ld\n", (long) bandvertglbnbr); + + for (bandvertlocnum = 0; bandvertlocnum < bandvertlocnbr; bandvertlocnum ++) + fprintf (file, "%ld\t1\n", (long) bandvlblloctab[bandvertlocnum]); + + fclose (file); + } + } + + SCOTCH_dgraphExit (&bandgrafdat); + SCOTCH_dgraphExit (&grafdat); + + MPI_Finalize (); + exit (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_dgraph_check.c b/scotch_6.0.3/src/check/test_scotch_dgraph_check.c new file mode 100644 index 00000000..55fd1f96 --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_dgraph_check.c @@ -0,0 +1,160 @@ +/* Copyright 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_dgraph_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_dgraphCheck() routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 28 sep 2014 **/ +/** to 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include +#include +#include +#include + +#include "ptscotch.h" + +#define errorProg SCOTCH_errorProg +#define errorPrint SCOTCH_errorPrint + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( + +int argc, +char * argv[]) +{ + MPI_Comm proccomm; + int procglbnbr; /* Number of processes sharing graph data */ + int proclocnum; /* Number of this process */ + SCOTCH_Dgraph grafdat; + FILE * file; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + errorProg (argv[0]); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + if (argc != 2) { + errorPrint ("main: invalid number of parameters"); + exit (1); + } + + proccomm = MPI_COMM_WORLD; + MPI_Comm_size (proccomm, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (proccomm, &proclocnum); + + fprintf (stderr, "Proc %2d of %2d, pid %d\n", proclocnum, procglbnbr, getpid ()); + +#ifndef SCOTCH_CHECK_AUTO + if (proclocnum == 0) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } +#endif /* SCOTCH_CHECK_AUTO */ + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) { /* Initialize source graph */ + errorPrint ("main: cannot initialize graph"); + return (1); + } + + file = NULL; + if ((proclocnum == 0) && + ((file = fopen (argv[1], "r")) == NULL)) { + errorPrint ("main: cannot open graph file"); + return (1); + } + + if (SCOTCH_dgraphLoad (&grafdat, file, 0, 0) != 0) { + errorPrint ("main: cannot load graph"); + return (1); + } + + if (file != NULL) + fclose (file); + + if (SCOTCH_dgraphCheck (&grafdat) != 0) { + errorPrint ("main: invalid graph"); + return (1); + } + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + SCOTCH_dgraphExit (&grafdat); + + MPI_Finalize (); + exit (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_dgraph_coarsen.c b/scotch_6.0.3/src/check/test_scotch_dgraph_coarsen.c new file mode 100644 index 00000000..b1e4d166 --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_dgraph_coarsen.c @@ -0,0 +1,242 @@ +/* Copyright 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_dgraph_coarsen.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_dgraphCoarsen() routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 28 sep 2014 **/ +/** to 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include +#include +#include +#include + +#include "ptscotch.h" + +#define errorProg SCOTCH_errorProg +#define errorPrint SCOTCH_errorPrint + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( + +int argc, +char * argv[]) +{ + MPI_Comm proccomm; + int procglbnbr; /* Number of processes sharing graph data */ + int proclocnum; /* Number of this process */ + SCOTCH_Num vertglbnbr; + SCOTCH_Num vertlocnbr; + SCOTCH_Num baseval; + SCOTCH_Dgraph grafdat; + SCOTCH_Dgraph coargrafdat; + SCOTCH_Num coarvertglbnbr; + SCOTCH_Num coarvertlocnbr; + double coarrat; + FILE * file; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + int i; + + errorProg (argv[0]); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + if (argc != 2) { + errorPrint ("main: invalid number of parameters"); + exit (1); + } + + proccomm = MPI_COMM_WORLD; + MPI_Comm_size (proccomm, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (proccomm, &proclocnum); + + fprintf (stderr, "Proc %2d of %2d, pid %d\n", proclocnum, procglbnbr, getpid ()); + +#ifndef SCOTCH_CHECK_AUTO + if (proclocnum == 0) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } +#endif /* SCOTCH_CHECK_AUTO */ + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) { /* Initialize source graph */ + errorPrint ("main: cannot initialize graph (1)"); + return (1); + } + + file = NULL; + if ((proclocnum == 0) && + ((file = fopen (argv[1], "r")) == NULL)) { + errorPrint ("main: cannot open graph file"); + return (1); + } + + if (SCOTCH_dgraphLoad (&grafdat, file, 0, 0) != 0) { + errorPrint ("main: cannot load graph"); + return (1); + } + + if (file != NULL) + fclose (file); + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + SCOTCH_dgraphData (&grafdat, NULL, &vertglbnbr, &vertlocnbr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + coarrat = 0.8; /* Lazy coarsening ratio */ + + for (i = 0; i < 3; i ++) { /* For all test cases */ + SCOTCH_Num * multloctab; + SCOTCH_Num multlocsiz; + SCOTCH_Num foldval; + char * foldstr; + char * coarstr; + int procnum; + int o; + + switch (i) { + case 0 : + multlocsiz = vertlocnbr; + foldval = SCOTCH_COARSENNONE; + foldstr = "Plain coarsening"; + break; + case 1 : + multlocsiz = (SCOTCH_Num) (((double) vertglbnbr * coarrat) / (double) (procglbnbr / 2)) + 1; + foldval = SCOTCH_COARSENFOLD; + foldstr = "Folding"; + break; + case 2 : + multlocsiz = (SCOTCH_Num) (((double) vertglbnbr * coarrat) / (double) (procglbnbr / 2)) + 1; + foldval = SCOTCH_COARSENFOLDDUP; + foldstr = "Folding with duplication"; + break; + } + + if (proclocnum == 0) + printf ("%s\n", foldstr); + + if ((multloctab = malloc (multlocsiz * 2 * sizeof (SCOTCH_Num))) == NULL) { + errorPrint ("main: cannot allocate multinode array"); + return (1); + } + + if (SCOTCH_dgraphInit (&coargrafdat, proccomm) != 0) { /* Initialize band graph */ + errorPrint ("main: cannot initialize graph (2)"); + return (1); + } + + o = SCOTCH_dgraphCoarsen (&grafdat, 0, coarrat, foldval, &coargrafdat, multloctab); + + SCOTCH_dgraphData (&coargrafdat, NULL, &coarvertglbnbr, &coarvertlocnbr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + for (procnum = 0; procnum < procglbnbr; procnum ++) { + switch (o) { + case 0 : + coarstr = "coarse graph created"; + break; + case 1 : + coarstr = "graph could not be coarsened"; + break; + case 2 : + coarstr = "folded graph not created here"; + break; + case 3 : + coarstr = "cannot create coarse graph"; + break; + } + + if (procnum == proclocnum) + printf ("%d: %s (%ld / %ld / %ld)\n", procnum, coarstr, (long) multlocsiz, (long) coarvertlocnbr, (long) vertlocnbr); + + MPI_Barrier (proccomm); + } + + if (coarvertlocnbr > multlocsiz) { + errorPrint ("main: invalid local multinode array size"); + return (1); + } + + SCOTCH_dgraphExit (&coargrafdat); + free (multloctab); + } + + SCOTCH_dgraphExit (&grafdat); + + MPI_Finalize (); + exit (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_dgraph_grow.c b/scotch_6.0.3/src/check/test_scotch_dgraph_grow.c new file mode 100644 index 00000000..c607058a --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_dgraph_grow.c @@ -0,0 +1,231 @@ +/* Copyright 2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_dgraph_grow.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_dgraphGrow() routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 26 sep 2012 **/ +/** to 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include +#include +#include +#include +#include + +#include "ptscotch.h" + +#define errorProg SCOTCH_errorProg +#define errorPrint SCOTCH_errorPrint + +void _SCOTCHintRandInit (void); +SCOTCH_Num _SCOTCHintRandVal (SCOTCH_Num); + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( + +int argc, +char * argv[]) +{ + MPI_Status statdat; + MPI_Comm proccomm; + int procglbnbr; /* Number of processes sharing graph data */ + int proclocnum; /* Number of this process */ + long vertlocadj; + SCOTCH_Num vertglbnbr; + SCOTCH_Num vertlocnbr; + SCOTCH_Num vertgstnbr; + SCOTCH_Num * seedloctab; + SCOTCH_Num * partgsttab; + SCOTCH_Num baseval; + SCOTCH_Dgraph grafdat; + FILE * file; + int procnum; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + errorProg (argv[0]); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + if (argc != 2) { + errorPrint ("main: invalid number of parameters"); + exit (1); + } + + proccomm = MPI_COMM_WORLD; + MPI_Comm_size (proccomm, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (proccomm, &proclocnum); + + fprintf (stderr, "Proc %2d of %2d, pid %d\n", proclocnum, procglbnbr, getpid ()); + +#ifndef SCOTCH_CHECK_AUTO + if (proclocnum == 0) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } +#endif /* SCOTCH_CHECK_AUTO */ + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) { /* Initialize source graph */ + errorPrint ("main: cannot initialize graph"); + return (1); + } + + file = NULL; + if ((proclocnum == 0) && + ((file = fopen (argv[1], "r")) == NULL)) { + errorPrint ("main: cannot open graph file"); + return (1); + } + + if (SCOTCH_dgraphLoad (&grafdat, file, 0, 0) != 0) { + errorPrint ("main: cannot load graph"); + return (1); + } + + if (file != NULL) + fclose (file); + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + if (SCOTCH_dgraphGhst (&grafdat) != 0) { + errorPrint ("main: cannot compute ghost edge array"); + return (1); + } + + SCOTCH_dgraphData (&grafdat, &baseval, &vertglbnbr, &vertlocnbr, NULL, &vertgstnbr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + if ((seedloctab = malloc (vertlocnbr * sizeof (SCOTCH_Num))) == NULL) { + errorPrint ("main: cannot allocate seed array"); + return (1); + } + + if ((partgsttab = malloc (vertgstnbr * sizeof (SCOTCH_Num))) == NULL) { + errorPrint ("main: cannot allocate part array"); + return (1); + } + + memset (partgsttab, ~0, vertgstnbr * sizeof (SCOTCH_Num)); + + _SCOTCHintRandInit (); + seedloctab[0] = _SCOTCHintRandVal (vertlocnbr); + seedloctab[1] = _SCOTCHintRandVal (vertlocnbr); + seedloctab[2] = _SCOTCHintRandVal (vertlocnbr); + + partgsttab[seedloctab[0] - baseval] = 0; + partgsttab[seedloctab[1] - baseval] = 1; + partgsttab[seedloctab[2] - baseval] = 2; + + if (SCOTCH_dgraphGrow (&grafdat, 3, seedloctab, 4, partgsttab) != 0) { + errorPrint ("main: cannot compute grown regions"); + return (1); + } + + for (procnum = 0; procnum < procglbnbr; procnum ++) { + SCOTCH_Num vertlocnum; + + MPI_Barrier (proccomm); + + if (procnum == proclocnum) { + if ((file = fopen ("/tmp/test_scotch_dgraph_grow.map", (procnum == 0) ? "w" : "a+")) == NULL) { + errorPrint ("main: cannot open mapping file"); + return (1); + } + + if (procnum == 0) { + fprintf (file, "%ld\n", (long) vertglbnbr); + vertlocadj = (long) baseval; + } + else + MPI_Recv (&vertlocadj, 1, MPI_LONG, procnum - 1, 0, MPI_COMM_WORLD, &statdat); + + for (vertlocnum = 0; vertlocnum < vertlocnbr; vertlocnum ++) + fprintf (file, "%ld\t%ld\n", vertlocadj + (long) vertlocnum, (long) partgsttab[vertlocnum]); + + fclose (file); + + if (procnum < (procglbnbr - 1)) { + vertlocadj += (long) vertlocnbr; + MPI_Send (&vertlocadj, 1, MPI_LONG, procnum + 1, 0, MPI_COMM_WORLD); + } + } + } + + SCOTCH_dgraphExit (&grafdat); + + MPI_Finalize (); + exit (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_dgraph_redist.c b/scotch_6.0.3/src/check/test_scotch_dgraph_redist.c new file mode 100644 index 00000000..8648e333 --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_dgraph_redist.c @@ -0,0 +1,188 @@ +/* Copyright 2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_dgraph_redist.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_dgraphBand() routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 21 feb 2012 **/ +/** to 23 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include +#include +#include +#include + +#include "ptscotch.h" + +#define errorProg SCOTCH_errorProg +#define errorPrint SCOTCH_errorPrint + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( + +int argc, +char * argv[]) +{ + MPI_Comm proccomm; + int procglbnbr; /* Number of processes sharing graph data */ + int proclocnum; /* Number of this process */ + SCOTCH_Num vertglbnbr; + SCOTCH_Num vertlocnbr; + SCOTCH_Num vertlocnum; + SCOTCH_Num * partloctab; + SCOTCH_Num baseval; + SCOTCH_Dgraph srcgrafdat; + SCOTCH_Dgraph dstgrafdat; + FILE * file; + int procnum; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + errorProg (argv[0]); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + if (argc != 2) { + errorPrint ("main: invalid number of parameters"); + exit (1); + } + + proccomm = MPI_COMM_WORLD; + MPI_Comm_size (proccomm, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (proccomm, &proclocnum); + + fprintf (stderr, "Proc %2d of %2d, pid %d\n", proclocnum, procglbnbr, getpid ()); + +#ifndef SCOTCH_CHECK_AUTO + if (proclocnum == 0) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } +#endif /* SCOTCH_CHECK_AUTO */ + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + if (SCOTCH_dgraphInit (&srcgrafdat, proccomm) != 0) { /* Initialize source graph */ + errorPrint ("main: cannot initialize source graph"); + return (1); + } + if (SCOTCH_dgraphInit (&dstgrafdat, proccomm) != 0) { /* Initialize destination graph */ + errorPrint ("main: cannot initialize destination graph"); + return (1); + } + + file = NULL; + if ((proclocnum == 0) && + ((file = fopen (argv[1], "r")) == NULL)) { + errorPrint ("main: cannot open graph file"); + return (1); + } + + if (SCOTCH_dgraphLoad (&srcgrafdat, file, -1, 0) != 0) { + errorPrint ("main: cannot load source graph"); + return (1); + } + + if (file != NULL) + fclose (file); + + if (SCOTCH_dgraphCheck (&srcgrafdat) != 0) { + errorPrint ("main: invalid source graph"); + return (1); + } + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize for debug */ + errorPrint ("main: cannot communicate"); + return (1); + } + + SCOTCH_dgraphData (&srcgrafdat, NULL, &vertglbnbr, &vertlocnbr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + if ((partloctab = malloc (vertlocnbr * sizeof (SCOTCH_Num))) == NULL) { + errorPrint ("main: cannot allocate frontier array"); + return (1); + } + + for (vertlocnum = 0; vertlocnum < vertlocnbr; vertlocnum ++) /* Create packs of 3 vertices each */ + partloctab[vertlocnum] = (vertlocnum / 3) % procglbnbr; + + if (SCOTCH_dgraphRedist (&srcgrafdat, partloctab, NULL, -1, -1, &dstgrafdat) != 0) { + errorPrint ("main: cannot compute redistributed graph"); + return (1); + } + + SCOTCH_dgraphExit (&dstgrafdat); + SCOTCH_dgraphExit (&srcgrafdat); + free (partloctab); + + MPI_Finalize (); + exit (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_graph_color.c b/scotch_6.0.3/src/check/test_scotch_graph_color.c new file mode 100644 index 00000000..a3d1349d --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_graph_color.c @@ -0,0 +1,132 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_graph_color.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_graphColor() routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 06 jan 2012 **/ +/** to 26 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include + +#include "scotch.h" + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + FILE * fileptr; + SCOTCH_Graph grafdat; + SCOTCH_Num baseval; + SCOTCH_Num vertnbr; + SCOTCH_Num vertnum; + SCOTCH_Num colonbr; + SCOTCH_Num colonum; + SCOTCH_Num * colotab; + SCOTCH_Num * cnbrtab; + + SCOTCH_errorProg (argv[0]); + + if (SCOTCH_graphInit (&grafdat) != 0) { /* Initialize source graph */ + SCOTCH_errorPrint ("main: cannot initialize graph"); + return (1); + } + + if ((fileptr = fopen (argv[1], "r")) == NULL) { + SCOTCH_errorPrint ("main: cannot open file"); + return (1); + } + + if (SCOTCH_graphLoad (&grafdat, fileptr, -1, 0) != 0) { /* Read source graph */ + SCOTCH_errorPrint ("main: cannot load graph"); + return (1); + } + + fclose (fileptr); + + SCOTCH_graphSize (&grafdat, &vertnbr, NULL); + + if ((colotab = malloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) { + SCOTCH_errorPrint ("main: out of memory (1)"); + return (1); + } + + if ((cnbrtab = malloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) { + SCOTCH_errorPrint ("main: out of memory (1)"); + return (1); + } + memset (cnbrtab, 0, vertnbr * sizeof (SCOTCH_Num)); + + if (SCOTCH_graphColor (&grafdat, colotab, &colonbr, 0) != 0) { + SCOTCH_errorPrint ("main: cannot color graph"); + return (1); + } + + printf ("Number of colors: %ld\n", (long) colonbr); + + for (vertnum = 0; vertnum < vertnbr; vertnum ++) /* Sum-up color histogram */ + cnbrtab[colotab[vertnum]] ++; + + for (colonum = 0; colonum < colonbr; colonum ++) + printf ("Color %5ld: %ld\n", + (long) colonum, + (long) cnbrtab[colonum]); + + free (cnbrtab); + free (colotab); + SCOTCH_graphExit (&grafdat); + + return (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_graph_map.c b/scotch_6.0.3/src/check/test_scotch_graph_map.c new file mode 100644 index 00000000..42edc2b9 --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_graph_map.c @@ -0,0 +1,243 @@ +/* Copyright 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_graph_map.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_graphMap*() routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 12 aug 2014 **/ +/** to 20 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include + +#include "scotch.h" + +#define ARCHNBR 4 +#define STRANBR 2 + +#define COORD(x,y) ((y) * xdimsiz + (x)) + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Mapping mappdat; /* Mapping to compute */ + SCOTCH_Mapping mapodat; /* Old mapping */ + FILE * fileptr; + SCOTCH_Graph grafdat; + SCOTCH_Num xdimsiz; + int archnum; + SCOTCH_Arch archtab[ARCHNBR]; + SCOTCH_Strat stratab[STRANBR]; + int stranum; + int typenum; + SCOTCH_Num baseval; + SCOTCH_Num vertnbr; + SCOTCH_Num vertnum; + SCOTCH_Num * parttab; + SCOTCH_Num * parotab; + SCOTCH_Num * vmlotab; + SCOTCH_Num * vmloptr; /* vmlotab or NULL */ + + SCOTCH_errorProg (argv[0]); + + if (SCOTCH_graphInit (&grafdat) != 0) { /* Initialize source graph */ + SCOTCH_errorPrint ("main: cannot initialize graph"); + return (1); + } + + if ((fileptr = fopen (argv[1], "r")) == NULL) { /* Read a square 2D grid graph */ + SCOTCH_errorPrint ("main: cannot open file (1)"); + return (1); + } + + if (SCOTCH_graphLoad (&grafdat, fileptr, -1, 0) != 0) { /* Read source graph */ + SCOTCH_errorPrint ("main: cannot load graph"); + return (1); + } + + fclose (fileptr); + + SCOTCH_graphSize (&grafdat, &vertnbr, NULL); + xdimsiz = (SCOTCH_Num) sqrt ((double) vertnbr); + if (vertnbr != (xdimsiz * xdimsiz)) { + SCOTCH_errorPrint ("main: graph is not a square grid"); + return (1); + } + + if (((parttab = malloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) || + ((parotab = malloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) || + ((vmlotab = malloc (vertnbr * sizeof (SCOTCH_Num))) == NULL)) { + SCOTCH_errorPrint ("main: out of memory"); + return (1); + } + + for (vertnum = 0; vertnum < vertnbr; vertnum ++) /* Fill vertex migration load array */ + vmlotab[vertnum] = vertnum % 3; + + for (stranum = 0; stranum < STRANBR; stranum ++) { /* Initialize mapping strategies */ + if (SCOTCH_stratInit (&stratab[stranum]) != 0) { + SCOTCH_errorPrint ("main: cannot initialize strategy"); + return (1); + } + } + SCOTCH_stratGraphMapBuild (&stratab[0], SCOTCH_STRATRECURSIVE, 4, 0.05); + SCOTCH_stratGraphMapBuild (&stratab[1], SCOTCH_STRATDEFAULT, 4, 0.05); + + for (archnum = 0; archnum < ARCHNBR; archnum ++) { /* Initialize architectures */ + if (SCOTCH_archInit (&archtab[archnum]) != 0) { + SCOTCH_errorPrint ("main: cannot initialize architecture"); + return (1); + } + } + SCOTCH_archCmplt (&archtab[0], 5); + SCOTCH_archMesh2 (&archtab[1], 2, 2); + SCOTCH_archMesh2 (&archtab[2], xdimsiz * 2, xdimsiz * 2); /* Oversized architecture */ + SCOTCH_archVhcub (&archtab[3]); + + if ((fileptr = tmpfile ()) == NULL) { /* Open temporary file for resulting output */ + SCOTCH_errorPrint ("main: cannot open file (2)"); + return (1); + } + + for (stranum = 0; stranum < STRANBR; stranum ++) { + for (archnum = 0; archnum < ARCHNBR; archnum ++) { + SCOTCH_Num archsiz; + + if (SCOTCH_graphMapInit (&grafdat, &mappdat, &archtab[archnum], parttab) != 0) { /* Initialize new mapping */ + SCOTCH_errorPrint ("main: cannot initialize mapping (1)"); + return (1); + } + if (SCOTCH_graphMapInit (&grafdat, &mapodat, &archtab[archnum], parotab) != 0) { /* Initialize old mapping */ + SCOTCH_errorPrint ("main: cannot initialize mapping (2)"); + return (1); + } + + archsiz = SCOTCH_archSize (&archtab[archnum]); + + for (typenum = 0; typenum < 6; typenum ++) { + int i; + int o; + + memset (parttab, ~0, xdimsiz * xdimsiz * sizeof (SCOTCH_Num)); /* Assume all vertices are not fixed */ + if (archnum < 2) { /* For fixed-size architectures */ + for (i = 0; i < (xdimsiz - 1); i ++) { /* Place fixed vertices at all four sides */ + parttab[COORD (0, i)] = 0; + parttab[COORD (i + 1, 0)] = 1; + parttab[COORD (xdimsiz - 1, i + 1)] = archsiz - 2; + parttab[COORD (i, xdimsiz - 1)] = archsiz - 1; + } + } + else { /* For variable-sized architectures */ + for (i = 0; i < (xdimsiz - 1); i ++) { /* Place fixed vertices at all four sides */ + parttab[COORD (0, i)] = vertnbr - 2; + parttab[COORD (i + 1, 0)] = vertnbr - 1; + parttab[COORD (xdimsiz - 1, i + 1)] = vertnbr; + parttab[COORD (i, xdimsiz - 1)] = vertnbr + 1; + } + } + + printf ("Strat %d, arch %d, type %d\n", stranum, archnum, typenum); + + vmloptr = vmlotab; + switch (typenum) { + case 0 : /* Plain mapping */ + o = SCOTCH_graphMapCompute (&grafdat, &mappdat, &stratab[stranum]); + memcpy (parotab, parttab, vertnbr * sizeof (SCOTCH_Num)); /* Use plain mapping as old mapping in the following */ + break; + case 1 : /* Plain mapping with fixed vertices */ + o = SCOTCH_graphMapFixedCompute (&grafdat, &mappdat, &stratab[stranum]); + break; + case 2 : /* Remapping without vertex migration load array */ + vmloptr = NULL; + case 3 : /* Remapping with vertex migration load array */ + o = SCOTCH_graphRemapCompute (&grafdat, &mappdat, &mapodat, 0.2, vmloptr, &stratab[stranum]); + break; + case 4 : /* Remapping with fixed vertices and without vertex migration load array */ + vmloptr = NULL; + case 5 : /* Remapping with fixed vertices and with vertex migration load array */ + o = SCOTCH_graphRemapFixedCompute (&grafdat, &mappdat, &mapodat, 0.2, vmloptr, &stratab[stranum]); + break; + } + + if (o != 0) { + SCOTCH_errorPrint ("main: cannot compute mapping"); + return (1); + } + } + + SCOTCH_graphMapSave (&grafdat, &mappdat, fileptr); + + SCOTCH_graphMapExit (&grafdat, &mapodat); + SCOTCH_graphMapExit (&grafdat, &mappdat); + } + } + + + for (archnum = 0; archnum < ARCHNBR; archnum ++) + SCOTCH_archExit (&archtab[archnum]); + + for (stranum = 0; stranum < STRANBR; stranum ++) + SCOTCH_stratExit (&stratab[stranum]); + + free (vmlotab); + free (parotab); + free (parttab); + SCOTCH_graphExit (&grafdat); + + fclose (fileptr); + + return (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_graph_order.c b/scotch_6.0.3/src/check/test_scotch_graph_order.c new file mode 100644 index 00000000..281b2ef7 --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_graph_order.c @@ -0,0 +1,168 @@ +/* Copyright 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_graph_order.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the operation of **/ +/** the SCOTCH_graphOrderCompute*() **/ +/** routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 05 aug 2014 **/ +/** to 29 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include + +#include "scotch.h" + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + FILE * fileptr; + SCOTCH_Graph grafdat; + SCOTCH_Ordering ordedat; + SCOTCH_Strat stradat; + SCOTCH_Num baseval; + SCOTCH_Num vertnbr; + SCOTCH_Num vertnum; + SCOTCH_Num listnbr; + SCOTCH_Num listnum; + SCOTCH_Num * listtab; + + SCOTCH_errorProg (argv[0]); + + if (SCOTCH_graphInit (&grafdat) != 0) { /* Initialize source graph */ + SCOTCH_errorPrint ("main: cannot initialize graph"); + return (1); + } + + if ((fileptr = fopen (argv[1], "r")) == NULL) { + SCOTCH_errorPrint ("main: cannot open file (1)"); + return (1); + } + + if (SCOTCH_graphLoad (&grafdat, fileptr, -1, 0) != 0) { /* Read source graph */ + SCOTCH_errorPrint ("main: cannot load graph"); + return (1); + } + + fclose (fileptr); + + SCOTCH_graphData (&grafdat, &baseval, &vertnbr, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + listnbr = (vertnbr + 1) / 2; /* Only keep half of the vertices in induced graph */ + if ((listtab = malloc (listnbr * sizeof (SCOTCH_Num))) == NULL) { + SCOTCH_errorPrint ("main: out of memory (1)"); + return (1); + } + for (listnum = 0, vertnum = baseval + (listnbr / 4); /* Keep only middle half of the vertices */ + listnum < listnbr; listnum ++, vertnum ++) + listtab[listnum] = vertnum; + + if ((fileptr = tmpfile ()) == NULL) { /* Open temporary file for resulting output */ + SCOTCH_errorPrint ("main: cannot open file (2)"); + return (1); + } + + if (SCOTCH_stratInit (&stradat) != 0) { /* Initialize ordering strategy */ + SCOTCH_errorPrint ("main: cannot initialize strategy"); + return (1); + } + + if (SCOTCH_graphOrderInit (&grafdat, &ordedat, NULL, NULL, NULL, NULL, NULL) != 0) { /* Initialize ordering */ + SCOTCH_errorPrint ("main: cannot initialize ordering (1)"); + return (1); + } + + if (SCOTCH_graphOrderCompute (&grafdat, &ordedat, &stradat) != 0) { + SCOTCH_errorPrint ("main: cannot order graph"); + return (1); + } + + if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) { + SCOTCH_errorPrint ("main: invalid ordering (1)"); + return (1); + } + + SCOTCH_graphOrderSave (&grafdat, &ordedat, fileptr); /* Test ordering data output routines */ + SCOTCH_graphOrderSaveMap (&grafdat, &ordedat, fileptr); + SCOTCH_graphOrderSaveTree (&grafdat, &ordedat, fileptr); + + SCOTCH_graphOrderExit (&grafdat, &ordedat); /* Free computed ordering */ + + if (SCOTCH_graphOrderInit (&grafdat, &ordedat, NULL, NULL, NULL, NULL, NULL) != 0) { /* Initialize ordering again */ + SCOTCH_errorPrint ("main: cannot initialize ordering (2)"); + return (1); + } + + if (SCOTCH_graphOrderComputeList (&grafdat, &ordedat, listnbr, listtab, &stradat) != 0) { + SCOTCH_errorPrint ("main: cannot order induced graph"); + return (1); + } + + if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) { + SCOTCH_errorPrint ("main: invalid ordering (2)"); + return (1); + } + + SCOTCH_graphOrderSave (&grafdat, &ordedat, fileptr); /* Test ordering data output routines */ + SCOTCH_graphOrderSaveMap (&grafdat, &ordedat, fileptr); + SCOTCH_graphOrderSaveTree (&grafdat, &ordedat, fileptr); + + free (listtab); + SCOTCH_stratExit (&stradat); + SCOTCH_graphOrderExit (&grafdat, &ordedat); + SCOTCH_graphExit (&grafdat); + + return (0); +} diff --git a/scotch_6.0.3/src/check/test_scotch_graph_part_ovl.c b/scotch_6.0.3/src/check/test_scotch_graph_part_ovl.c new file mode 100644 index 00000000..17a9357d --- /dev/null +++ b/scotch_6.0.3/src/check/test_scotch_graph_part_ovl.c @@ -0,0 +1,230 @@ +/* Copyright 2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_scotch_graph_part_ovl.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the sequential **/ +/** graph partitioning with overlap **/ +/** routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 20 sep 2014 **/ +/** to 20 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include +#include + +#include "scotch.h" + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Graph grafdat; + SCOTCH_Strat stradat; + SCOTCH_Num baseval; + SCOTCH_Num partnbr; + SCOTCH_Num partnum; + SCOTCH_Num * restrict parttax; + SCOTCH_Num vertnbr; + SCOTCH_Num vertnum; + SCOTCH_Num * verttab; + SCOTCH_Num * vendtab; + SCOTCH_Num * velotab; + SCOTCH_Num * vlbltab; + SCOTCH_Num * edgetax; + SCOTCH_Num * restrict flagtab; + SCOTCH_Num * restrict loadtab; + SCOTCH_Num loadmin; + SCOTCH_Num loadmax; + SCOTCH_Num loadsum; + double loadavg; + FILE * fileptr; + + SCOTCH_errorProg (argv[0]); + + if ((argc < 4) || (argc > 5)) { + SCOTCH_errorPrint ("main: usage is \"%s []\"\n", argv[0]); + exit (1); + } + + if ((partnbr = (SCOTCH_Num) atoi (argv[1])) < 1) { + SCOTCH_errorPrint ("main: invalid number of parts (\"%s\")", argv[1]); + return (1); + } + + if (SCOTCH_stratInit (&stradat) != 0) { + SCOTCH_errorPrint ("main: cannot initialize strategy"); + return (1); + } + if (argc == 5) { + if (SCOTCH_stratGraphPartOvl (&stradat, argv[4]) != 0) { + SCOTCH_errorPrint ("main: invalid user-provided strategy"); + return (1); + } + } + + if (SCOTCH_graphInit (&grafdat) != 0) { + SCOTCH_errorPrint ("main: cannot initialize graph"); + return (1); + } + + if ((fileptr = fopen (argv[2], "r")) == NULL) { + SCOTCH_errorPrint ("main: cannot open file (1)"); + return (1); + } + + if (SCOTCH_graphLoad (&grafdat, fileptr, -1, 0) != 0) { + SCOTCH_errorPrint ("main: cannot load graph"); + return (1); + } + + fclose (fileptr); + + SCOTCH_graphData (&grafdat, &baseval, &vertnbr, &verttab, &vendtab, &velotab, &vlbltab, NULL, &edgetax, NULL); + + if (((parttax = malloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) || + ((flagtab = malloc (partnbr * sizeof (SCOTCH_Num))) == NULL) || + ((loadtab = malloc (partnbr * sizeof (SCOTCH_Num))) == NULL)) { + SCOTCH_errorPrint ("main: out of memory"); + return (1); + } + + if (SCOTCH_graphPartOvl (&grafdat, partnbr, &stradat, parttax) != 0) { /* Parttax is not based yet */ + SCOTCH_errorPrint ("main: cannot compute mapping"); + return (1); + } + + edgetax -= baseval; + parttax -= baseval; + + memset (loadtab, 0, partnbr * sizeof (SCOTCH_Num)); /* Part loads set to 0 */ + memset (flagtab, ~0, partnbr * sizeof (SCOTCH_Num)); /* Flags set to invalid vertex number */ + + for (vertnum = 0; vertnum < vertnbr; vertnum ++) { + SCOTCH_Num veloval; + SCOTCH_Num partval; + + veloval = (velotab == NULL) ? 1 : velotab[vertnum]; + partval = parttax[vertnum + baseval]; /* vertnum is not based */ + if (partval >= 0) /* If vertex belongs to one part only */ + loadtab[partval] += veloval; /* Add vertex load to this part */ + else { /* Vertex belongs to several parts */ + SCOTCH_Num edgenum; + + for (edgenum = verttab[vertnum]; edgenum < vendtab[vertnum]; edgenum ++) { + SCOTCH_Num vertend; + SCOTCH_Num partend; + + vertend = edgetax[edgenum]; + partend = parttax[vertend]; /* vertend is based */ + if (partend < 0) /* If neighbor has no identifiable part */ + continue; + if (flagtab[partend] == vertnum) /* If neighbor part already accounted for, skip it */ + continue; + + loadtab[partend] += veloval; /* Vertex load contributes to this part */ + flagtab[partend] = vertnum; /* Record a contribution has been made */ + } + } + } + + loadsum = + loadmax = 0; + loadmin = SCOTCH_NUMMAX; + for (partnum = 0; partnum < partnbr; partnum ++) { + loadsum += loadtab[partnum]; + if (loadtab[partnum] > loadmax) + loadmax = loadtab[partnum]; + if (loadtab[partnum] < loadmin) + loadmin = loadtab[partnum]; + + printf ("M\tCompload[%02ld]\t%ld\n", + (long) partnum, + (long) loadtab[partnum]); + } + + loadavg = (double) loadsum / (double) partnbr; + printf ("M\tCompLoadAvg\t%g\n", + (double) loadavg); + printf ("M\tCompLoadMax/Avg\t%g\n", + (double) loadmax / loadavg); + + if ((fileptr = fopen (argv[3], "w")) == NULL) { + SCOTCH_errorPrint ("main: cannot open file (2)"); + return (1); + } + + if (fprintf (fileptr, "%ld\n", (long) vertnbr) == EOF) { + SCOTCH_errorPrint ("main: bad output (1)"); + return (1); + } + + for (vertnum = 0; vertnum < vertnbr; vertnum ++) { + if (fprintf (fileptr, "%ld\t%ld\n", + (long) ((vlbltab == NULL) ? vertnum : vlbltab[vertnum]), + (long) parttax[vertnum + baseval]) == EOF) { + SCOTCH_errorPrint ("main: bad output (2)"); + return (1); + } + } + + fclose (fileptr); + + free (loadtab); + free (flagtab); + free (parttax + baseval); + + SCOTCH_stratExit (&stradat); + SCOTCH_graphExit (&grafdat); + + exit (0); +} diff --git a/scotch_6.0.3/src/check/test_strat_par.c b/scotch_6.0.3/src/check/test_strat_par.c new file mode 100644 index 00000000..96f5ce89 --- /dev/null +++ b/scotch_6.0.3/src/check/test_strat_par.c @@ -0,0 +1,123 @@ +/* Copyright 2012,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_strat_seq.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the sequential **/ +/** strategy building routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 08 jan 2012 **/ +/** to 11 oct 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include + +#include "ptscotch.h" + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Strat stradat; + + SCOTCH_errorProg (argv[0]); + + printf ("Parallel mapping strategy, SCOTCH_STRATDEFAULT\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphMapBuild (&stradat, SCOTCH_STRATDEFAULT, 16, 16, 0.03); + SCOTCH_stratExit (&stradat); + + printf ("Parallel mapping strategy, SCOTCH_STRATRECURSIVE\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphMapBuild (&stradat, SCOTCH_STRATRECURSIVE, 16, 16, 0.03); + SCOTCH_stratExit (&stradat); + + printf ("Parallel ordering strategy, SCOTCH_STRATDEFAULT\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphOrderBuild (&stradat, SCOTCH_STRATDEFAULT, 1, 0, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Parallel ordering strategy, SCOTCH_STRATLEVELMAX\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphOrderBuild (&stradat, SCOTCH_STRATLEVELMAX, 1, 3, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Parallel ordering strategy, SCOTCH_STRATLEVELMIN\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphOrderBuild (&stradat, SCOTCH_STRATLEVELMIN, 1, 3, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Parallel ordering strategy, SCOTCH_STRATLEVELMAX | SCOTCH_STRATLEVELMIN\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphOrderBuild (&stradat, SCOTCH_STRATLEVELMAX | SCOTCH_STRATLEVELMIN, 1, 3, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Parallel ordering strategy, SCOTCH_STRATLEAFSIMPLE\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphOrderBuild (&stradat, SCOTCH_STRATLEAFSIMPLE, 1, 0, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Parallel ordering strategy, SCOTCH_STRATSEPASIMPLE\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphOrderBuild (&stradat, SCOTCH_STRATSEPASIMPLE, 1, 0, 0.2); + SCOTCH_stratExit (&stradat); + + return (0); +} diff --git a/scotch_6.0.3/src/check/test_strat_seq.c b/scotch_6.0.3/src/check/test_strat_seq.c new file mode 100644 index 00000000..182d8033 --- /dev/null +++ b/scotch_6.0.3/src/check/test_strat_seq.c @@ -0,0 +1,134 @@ +/* Copyright 2012,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : test_strat_seq.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tests the sequential **/ +/** strategy building routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 08 jan 2012 **/ +/** to 11 oct 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#include + +#include "scotch.h" + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Strat stradat; + + SCOTCH_errorProg (argv[0]); + + printf ("Sequential mapping strategy, SCOTCH_STRATDEFAULT\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphMapBuild (&stradat, SCOTCH_STRATDEFAULT, 16, 0.03); + SCOTCH_stratExit (&stradat); + + printf ("Sequential mapping strategy, SCOTCH_STRATRECURSIVE\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphMapBuild (&stradat, SCOTCH_STRATRECURSIVE, 16, 0.03); + SCOTCH_stratExit (&stradat); + + printf ("Sequential mapping strategy, SCOTCH_STRATREMAP\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphMapBuild (&stradat, SCOTCH_STRATREMAP, 16, 0.03); + SCOTCH_stratExit (&stradat); + + printf ("Sequential mapping strategy, SCOTCH_STRATRECURSIVE | SCOTCH_STRATREMAP\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphMapBuild (&stradat, SCOTCH_STRATRECURSIVE | SCOTCH_STRATREMAP, 16, 0.03); + SCOTCH_stratExit (&stradat); + + printf ("Sequential ordering strategy, SCOTCH_STRATDEFAULT\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphOrderBuild (&stradat, SCOTCH_STRATDEFAULT, 0, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Sequential ordering strategy, SCOTCH_STRATLEVELMAX\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphOrderBuild (&stradat, SCOTCH_STRATLEVELMAX, 3, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Sequential ordering strategy, SCOTCH_STRATLEVELMIN\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphOrderBuild (&stradat, SCOTCH_STRATLEVELMIN, 3, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Sequential ordering strategy, SCOTCH_STRATLEVELMAX | SCOTCH_STRATLEVELMIN\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphOrderBuild (&stradat, SCOTCH_STRATLEVELMAX | SCOTCH_STRATLEVELMIN, 3, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Sequential ordering strategy, SCOTCH_STRATLEAFSIMPLE\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphOrderBuild (&stradat, SCOTCH_STRATLEAFSIMPLE, 3, 0.2); + SCOTCH_stratExit (&stradat); + + printf ("Sequential ordering strategy, SCOTCH_STRATSEPASIMPLE\n"); + + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphOrderBuild (&stradat, SCOTCH_STRATSEPASIMPLE, 3, 0.2); + SCOTCH_stratExit (&stradat); + + return (0); +} diff --git a/scotch_6.0.3/src/esmumps/Makefile b/scotch_6.0.3/src/esmumps/Makefile new file mode 100644 index 00000000..9eb64aaf --- /dev/null +++ b/scotch_6.0.3/src/esmumps/Makefile @@ -0,0 +1,165 @@ +## Copyright 2004,2007-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +## +## This file is part of the Scotch software package for static mapping, +## graph partitioning and sparse matrix ordering. +## +## This software is governed by the CeCILL-C license under French law +## and abiding by the rules of distribution of free software. You can +## use, modify and/or redistribute the software under the terms of the +## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +## URL: "http://www.cecill.info". +## +## As a counterpart to the access to the source code and rights to copy, +## modify and redistribute granted by the license, users are provided +## only with a limited warranty and the software's author, the holder of +## the economic rights, and the successive licensors have only limited +## liability. +## +## In this respect, the user's attention is drawn to the risks associated +## with loading, using, modifying and/or developing or reproducing the +## software by the user in light of its specific status of free software, +## that may mean that it is complicated to manipulate, and that also +## therefore means that it is reserved for developers and experienced +## professionals having in-depth computer knowledge. Users are therefore +## encouraged to load and test the software's suitability as regards +## their requirements in conditions enabling the security of their +## systems and/or data to be ensured and, more generally, to use and +## operate it in the same conditions as regards security. +## +## The fact that you are presently reading this means that you have had +## knowledge of the CeCILL-C license and that you accept its terms. +## + +bindir = ../../bin +includedir = ../../include +libdir = ../../lib + +## +## General inference rules. +## + +include ../Makefile.inc + +%$(OBJ) : %.c + $(CC) $(CFLAGS) $(CLIBFLAGS) -I$(includedir) -c $(<) -o $(@) + +%$(EXE) : %.c + $(CC) $(CFLAGS) -I$(includedir) $(<) -o $(@) -L$(libdir) $(LDFLAGS) -L. -l$(ESMUMPSLIB) -l$(SCOTCHLIB) -lscotch -l$(SCOTCHLIB)errexit -lm + +## +## Project rules. +## + +.PHONY : ptscotch scotch ptinstall install clean realclean + +scotch : clean + $(MAKE) CC="$(CCS)" CCD="$(CCS)" SCOTCHLIB=scotch ESMUMPSLIB=esmumps \ + libesmumps$(LIB) \ + main_esmumps$(EXE) + +ptscotch : clean + $(MAKE) CFLAGS="$(CFLAGS) -DSCOTCH_PTSCOTCH" CC=$(CCP) SCOTCHLIB=ptscotch ESMUMPSLIB=ptesmumps \ + libesmumps$(LIB) \ + main_esmumps$(EXE) + +install : + -$(CP) esmumps.h $(includedir) + -$(CP) libesmumps$(LIB) $(libdir) + +ptinstall : + -$(CP) esmumps.h $(includedir) + -$(CP) libptesmumps$(LIB) $(libdir) + +clean : + -$(RM) *~ common.h *$(OBJ) lib*$(LIB) main_esmumps$(EXE) + +realclean : clean + +## +## Todo list. +## + +common.h : ../libscotch/common.h \ + module.h + $(CAT) module.h ../libscotch/common.h > $(@) + +graph_graph$(OBJ) : graph_graph.c \ + common.h \ + $(includedir)/$(SCOTCHLIB).h \ + graph.h + +order$(OBJ) : order.c \ + order.h \ + common.h \ + graph.h + +order_scotch_graph$(OBJ) : order_scotch_graph.c \ + order.h \ + common.h \ + graph.h \ + $(includedir)/$(SCOTCHLIB).h + +dof$(OBJ) : dof.c \ + dof.h \ + common.h \ + graph.h \ + $(includedir)/$(SCOTCHLIB).h + +symbol$(OBJ) : symbol.c \ + symbol.h \ + common.h + +symbol_fax$(OBJ) : symbol_fax.c \ + common.h \ + graph.h \ + symbol.h \ + order.h \ + fax.h + +symbol_fax_graph$(OBJ) : symbol_fax_graph.c \ + symbol_fax.c \ + common.h \ + graph.h \ + symbol.h \ + order.h \ + fax.h \ + $(includedir)/$(SCOTCHLIB).h + +esmumps$(OBJ) : esmumps.c \ + common.h \ + graph.h \ + symbol.h \ + order.h \ + fax.h \ + esmumps.h \ + $(includedir)/$(SCOTCHLIB).h + +esmumps_f$(OBJ) : esmumps_f.c \ + common.h \ + esmumps.h + +esmumps_strats$(OBJ) : esmumps_strats.c \ + common.h \ + esmumps.h + +libesmumps$(LIB) : graph_graph$(OBJ) \ + order$(OBJ) \ + order_scotch_graph$(OBJ) \ + dof$(OBJ) \ + symbol$(OBJ) \ + symbol_fax_graph$(OBJ) \ + esmumps$(OBJ) \ + esmumps_f$(OBJ) \ + esmumps_strats$(OBJ) + $(AR) $(ARFLAGS) lib$(ESMUMPSLIB)$(LIB) $(?) + -$(RANLIB) lib$(ESMUMPSLIB)$(LIB) + +main_esmumps$(EXE) : main_esmumps.c \ + common.h \ + graph.h \ + order.h \ + symbol.h \ + esmumps.h \ + lib$(ESMUMPSLIB)$(LIB) \ + $(libdir)/lib$(SCOTCHLIB)$(LIB) \ + $(libdir)/lib$(SCOTCHLIB)errexit$(LIB) diff --git a/scotch_6.0.3/src/esmumps/dof.c b/scotch_6.0.3/src/esmumps/dof.c new file mode 100644 index 00000000..03272ed1 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/dof.c @@ -0,0 +1,188 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dof.c **/ +/** **/ +/** AUTHORS : David GOUDIN **/ +/** Pascal HENON **/ +/** Francois PELLEGRINI **/ +/** Pierre RAMET **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the general purpose **/ +/** routines for the DOF structure. **/ +/** **/ +/** DATES : # Version 0.0 : from : 07 oct 1998 **/ +/** to 14 oct 1998 **/ +/** # Version 3.0 : from : 28 feb 2004 **/ +/** to 03 feb 2006 **/ +/** # Version 5.1 : from : 22 jan 2009 **/ +/** to 22 jan 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DOF + +#include "common.h" +#ifdef SCOTCH_PTSCOTCH +#include "ptscotch.h" +#else /* SCOTCH_PTSCOTCH */ +#include "scotch.h" +#endif /* SCOTCH_PTSCOTCH */ +#include "graph.h" +#include "dof.h" + +/******************************/ +/* */ +/* The DOF handling routines. */ +/* */ +/******************************/ + +/*+ This routine initializes +*** the given DOF structure. +*** It returns: +*** - 0 : in all cases. ++*/ + +int +dofInit ( +Dof * const deofptr) +{ + deofptr->baseval = 0; + deofptr->nodenbr = 0; + deofptr->noddval = 1; /* Set constant, non zero, number of DOFs */ + deofptr->noddtab = NULL; + + return (0); +} + +/*+ This routine frees the contents +*** of the given DOF structure. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +dofExit ( +Dof * const deofptr) +{ + if (deofptr->noddtab != NULL) + memFree (deofptr->noddtab); + +#ifdef DOF_DEBUG + dofInit (deofptr); +#endif /* DOF_DEBUG */ +} + +/*+ This routine sets the number of DOFs +*** per node to a constant value. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +dofConstant ( +Dof * const deofptr, +const INT baseval, +const INT nodenbr, +const INT noddval) +{ + deofptr->baseval = baseval; + deofptr->nodenbr = nodenbr; + if (deofptr->noddtab != NULL) { /* If DOF array already allocated */ + memFree (deofptr->noddtab); /* It is no longer of use */ + deofptr->noddtab = NULL; + } + deofptr->noddval = noddval; +} + +/*+ This routine builds the DOF index +*** array from the graph vertex array. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +dofGraph ( +Dof * const deofptr, /*+ DOF index array to build [based] +*/ +const Graph * const grafptr, /*+ Matrix adjacency structure [based] +*/ +const INT deofval, /*+ DOFs per node if no graph vertex load array +*/ +const INT * const peritab) /*+ Inverse vertex->node permutation array +*/ +{ + INT baseval; + INT vertnbr; + INT * velotab; + INT edgenbr; + + SCOTCH_graphData (grafptr, &baseval, &vertnbr, NULL, NULL, &velotab, NULL, &edgenbr, NULL, NULL); + + deofptr->baseval = baseval; + deofptr->nodenbr = vertnbr; + if (velotab == NULL) { /* If no vertex weight (i.e. DOF) array */ + deofptr->noddtab = NULL; /* No DOF array */ + deofptr->noddval = deofval; /* Get node DOF value */ + } + else { /* Vertex load array present */ +#ifdef DOF_CONSTANT + deofptr->noddtab = NULL; /* No DOF array */ + deofptr->noddval = deofval; +#else /* DOF_CONSTANT */ + const INT * restrict velotax; /* Based access to grafptr->velotab */ + INT nodenum; /* Number of current node */ + INT * noddtnd; /* Pointer to end of DOF index array */ + INT * noddptr; /* Pointer to current DOF index */ + const INT * periptr; + + deofptr->noddval = 0; /* DOF values are not constant */ + if ((deofptr->noddtab = (INT *) memAlloc ((vertnbr + 1) * sizeof (INT))) == NULL) { + errorPrint ("dofGraph: out of memory"); + return (1); + } + for (noddptr = deofptr->noddtab, noddtnd = noddptr + vertnbr, + periptr = peritab, nodenum = baseval, + velotax = velotab - baseval; + noddptr < noddtnd; noddptr ++, periptr ++) { + *noddptr = nodenum; /* Set index to DOF array */ + nodenum += velotax[*periptr]; /* Add number of DOFs for vertex */ + } + *noddptr = nodenum; /* Set end of DOF array */ +#endif /* DOF_CONSTANT */ + } + + return (0); +} diff --git a/scotch_6.0.3/src/esmumps/dof.h b/scotch_6.0.3/src/esmumps/dof.h new file mode 100644 index 00000000..dad92e83 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/dof.h @@ -0,0 +1,102 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dof.h **/ +/** **/ +/** AUTHORS : David GOUDIN **/ +/** Pascal HENON **/ +/** Francois PELLEGRINI **/ +/** Pierre RAMET **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the data declarations **/ +/** for the DOF handling structure. **/ +/** **/ +/** DATES : # Version 0.0 : from : 07 oct 1998 **/ +/** to 16 oct 1998 **/ +/** # Version 1.0 : from : 06 jun 2002 **/ +/** to 06 jun 2002 **/ +/** # Version 3.0 : from : 28 feb 2004 **/ +/** to 29 feb 2004 **/ +/** **/ +/************************************************************/ + +#define DOF_H + +#define DOF_CONSTANT /* Constant DOFs for ESMUMPS */ + +/* +** The type and structure definitions. +*/ + +/*+ The DOF structure. This structure is + always associated to a Graph structure, + which holds the base value. +*/ + +typedef struct Dof_ { + INT baseval; /*+ Base value for indexing +*/ + INT nodenbr; /*+ Number of nodes in DOF array +*/ + INT noddval; /*+ DOF value for every node (if noddtab == NULL, 0 else) +*/ + INT * restrict noddtab; /*+ Array of node->first DOF indexes (if noddval == 0) [+1,based] +*/ +} Dof; + +/* +** The function prototypes. +*/ + +#ifndef DOF +#define static +#endif + +int dofInit (Dof * const deofptr); +void dofExit (Dof * const deofptr); +int dofLoad (Dof * const deofptr, FILE * const stream); +int dofSave (const Dof * const deofptr, FILE * const stream); +void dofConstant (Dof * const deofptr, const INT baseval, const INT nodenbr, const INT noddval); +#ifdef GRAPH_H +int dofGraph (Dof * const deofptr, const Graph * grafptr, const INT, const INT * const peritab); +#endif /* GRAPH_H */ + +#undef static + +/* +** The macro definitions. +*/ + +#ifdef DOF_CONSTANT +#define noddVal(deofptr,nodenum) ((deofptr)->baseval + (deofptr)->noddval * ((nodenum) - (deofptr)->baseval)) +#define noddDlt(deofptr,nodenum) ((deofptr)->noddval) +#else /* DOF_CONSTANT */ +#define noddVal(deofptr,nodenum) (((deofptr)->noddtab != NULL) ? (deofptr)->noddtab[(deofptr)->baseval + (nodenum)] : ((deofptr)->baseval + (deofptr)->noddval * ((nodenum) - (deofptr)->baseval))) +#define noddDlt(deofptr,nodenum) (((deofptr)->noddtab != NULL) ? ((deofptr)->noddtab[(deofptr)->baseval + (nodenum) + 1] - (deofptr)->noddtab[(deofptr)->baseval + (nodenum)]) : (deofptr)->noddval) +#endif /* DOF_CONSTANT */ diff --git a/scotch_6.0.3/src/esmumps/esmumps.c b/scotch_6.0.3/src/esmumps/esmumps.c new file mode 100644 index 00000000..bdddd99c --- /dev/null +++ b/scotch_6.0.3/src/esmumps/esmumps.c @@ -0,0 +1,185 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : esmumps.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains a MUMPS interface **/ +/** for the ordering routines of the **/ +/** libSCOTCH + Emilio libfax libraries. **/ +/** **/ +/** DATES : # Version 0.0 : from : 16 may 2001 **/ +/** to 04 jun 2001 **/ +/** # Version 0.1 : from : 13 feb 2002 **/ +/** to 13 feb 2002 **/ +/** # Version 1.0 : from : 06 dec 2004 **/ +/** to 06 dec 2004 **/ +/** # Version 5.1 : from : 22 jan 2009 **/ +/** to 22 jan 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ESMUMPS + +#include "common.h" +#ifdef SCOTCH_PTSCOTCH +#include "ptscotch.h" +#else /* SCOTCH_PTSCOTCH */ +#include "scotch.h" +#endif /* SCOTCH_PTSCOTCH */ +#include "graph.h" +#include "dof.h" +#include "symbol.h" +#include "order.h" +#include "fax.h" +#include "esmumps.h" + +/**************************************/ +/* */ +/* This routine acts as an interface */ +/* between ordering software such as */ +/* MUMPS and Scotch+Emilio. */ +/* */ +/**************************************/ + +/* Meaning of the parameters : +** - n : order of the system (that is, number of columns). +** - iwlen : not used. Here for compatibility. +** - pe : on input, position in array iw of the extra-diagonal +** terms for the considered column. +** on output, -pe(i) is the father of node i in the elimination +** tree if i is a principal variable, or it is the index of +** the principal variable if i is a secondary variable. +** - pfree : number of extra-diagonal terms for the considered +** node (that is, the number of arcs dans le graph for this +** vertex). +** - len : array holding the number of extra-diagonal terms for +** each column. +** - iw : array of extra-diagonal terms (preserved). +** - nv : on output, nv(i) = 0 if variable i is a secondary +** variable, else nv(i) is the number of columns that are +** merged into principal variable i. +** - elen : on output, direct permutation (for MUMPS; the +** meaning of the "direct" and "inverse" permutations is +** just the opposite for Scotch) : +** k=elen(i) <==> column i is the k-th pivot. +** - last : on output, inverse permutation (for MUMPS) : +** i=last(k) <==> column i est le k-th pivot +*/ + +int +esmumps ( +const INT n, +const INT iwlen, /* Not used, just here for consistency */ +INT * restrict const petab, +const INT pfree, +INT * restrict const lentab, +INT * restrict const iwtab, +INT * restrict const nvtab, +INT * restrict const elentab, /* Permutations computed for debugging only */ +INT * restrict const lasttab) /* Permutations computed for debugging only */ +{ + INT baseval; /* Base value */ + INT * restrict vendtab; /* Vertex end array */ + Graph grafdat; /* Graph */ + Order ordedat; /* Graph ordering */ + SymbolMatrix symbdat; /* Block factored matrix */ + Dof deofdat; /* Matrix DOF structure */ + INT vertnum; + INT cblknum; + INT colnum; + + if ((vendtab = memAlloc (n * sizeof (INT))) == NULL) { + errorPrint ("esmumps: out of memory"); + return (1); + } + for (vertnum = 0; vertnum < n; vertnum ++) + vendtab[vertnum] = petab[vertnum] + lentab[vertnum]; + + baseval = 1; /* Assume Fortran-based indexing */ + graphInit (&grafdat); + graphBuildGraph2 (&grafdat, baseval, n, pfree - 1, petab, vendtab, NULL, NULL, iwtab, NULL); + + dofInit (&deofdat); + dofConstant (&deofdat, 1, n, 1); /* One DOF per node, Fortran-based indexing */ + + orderInit (&ordedat); + orderGraph (&ordedat, &grafdat); /* Compute ordering with Scotch */ + +#ifdef ESMUMPS_DEBUG /* Permutations are output for debugging only */ + memCpy (elentab, ordedat.permtab, n * sizeof (INT)); /* Copy permutations */ + memCpy (lasttab, ordedat.peritab, n * sizeof (INT)); +#endif /* ESMUMPS_DEBUG */ + + symbolInit (&symbdat); + symbolFaxGraph (&symbdat, &grafdat, &ordedat); /* Compute block symbolic factorizaion */ + + for (cblknum = 0; cblknum < symbdat.cblknbr; cblknum ++) { /* For all column blocks */ + INT degnbr; /* True degree of column block */ + INT bloknum; + + for (bloknum = symbdat.cblktab[cblknum].bloknum, degnbr = 0; + bloknum < symbdat.cblktab[cblknum + 1].bloknum; bloknum ++) + degnbr += symbdat.bloktab[bloknum - baseval].lrownum - + symbdat.bloktab[bloknum - baseval].frownum + 1; + nvtab[ordedat.peritab[symbdat.cblktab[cblknum].fcolnum - baseval] - baseval] = degnbr; /* Set true block degree */ + + for (colnum = symbdat.cblktab[cblknum].fcolnum + 1; /* For all secondary variables */ + colnum <= symbdat.cblktab[cblknum].lcolnum; colnum ++) { + nvtab[ordedat.peritab[colnum - baseval] - baseval] = 0; /* Set nv = 0 and pe = - principal variable */ + petab[ordedat.peritab[colnum - baseval] - baseval] = + - ordedat.peritab[symbdat.cblktab[cblknum].fcolnum - baseval]; + } + + if (symbdat.cblktab[cblknum].bloknum == /* If column block has no extra-diagonals */ + symbdat.cblktab[cblknum + 1].bloknum - 1) /* Then mark block as root of subtree */ + petab[ordedat.peritab[symbdat.cblktab[cblknum].fcolnum - baseval] - baseval] = 0; + else + petab[ordedat.peritab[symbdat.cblktab[cblknum].fcolnum - baseval] - baseval] = + - ordedat.peritab[symbdat.cblktab[symbdat.bloktab[symbdat.cblktab[cblknum].bloknum + 1 - baseval].cblknum - baseval].fcolnum - baseval]; + } + + symbolExit (&symbdat); + orderExit (&ordedat); + dofExit (&deofdat); + graphExit (&grafdat); + + memFree (vendtab); + + return (0); +} diff --git a/scotch_6.0.3/src/esmumps/esmumps.h b/scotch_6.0.3/src/esmumps/esmumps.h new file mode 100644 index 00000000..f2c7b6de --- /dev/null +++ b/scotch_6.0.3/src/esmumps/esmumps.h @@ -0,0 +1,62 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : esmumps.h **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the symbolic factorization routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 22 jul 1998 **/ +/** to 24 sep 1998 **/ +/** # Version 0.1 : from : 04 apr 1999 **/ +/** to 01 may 1999 **/ +/** **/ +/************************************************************/ + +#define ESMUMPS_H + +/* +** The function prototypes. +*/ + +#ifndef ESMUMPS +#define static +#endif + +int esmumps (const INT n, const INT iwlen, INT * const pe, const INT pfree, INT * const len, INT * const iw, INT * const nv, INT * const elen, INT * const last); + +int esmumps_strat1 (const INT procnbr, const INT leafsiz, const int leorval, const INT cminval, const INT cmaxval, const double fratval, const int verbval, FILE * const stream, char * const straptr); + +#undef static diff --git a/scotch_6.0.3/src/esmumps/esmumps_f.c b/scotch_6.0.3/src/esmumps/esmumps_f.c new file mode 100644 index 00000000..6421ef08 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/esmumps_f.c @@ -0,0 +1,76 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : esmumps_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains Fortran MUMPS **/ +/** stubs for the ordering routines of the **/ +/** libSCOTCH + Emilio libfax libraries. **/ +/** **/ +/** DATES : # Version 0.0 : from : 16 may 2001 **/ +/** to 17 may 2001 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include "common.h" +#include "esmumps.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the MUMPS ordering routine. */ +/* */ +/**************************************/ + +FORTRAN ( \ +ESMUMPSF, esmumpsf, ( \ +const INT * const n, \ +const INT * const iwlen, \ +INT * const petab, \ +const INT * const pfree, \ +INT * const lentab, \ +INT * const iwtab, \ +INT * const nvtab, \ +INT * const elentab, \ +INT * const lasttab, \ +INT * const ncmpa), \ +(n, iwlen, petab, pfree, lentab, iwtab, nvtab, elentab, lasttab, ncmpa)) +{ + *ncmpa = esmumps (*n, *iwlen, petab, *pfree, lentab, iwtab, nvtab, elentab, lasttab); +} diff --git a/scotch_6.0.3/src/esmumps/esmumps_strats.c b/scotch_6.0.3/src/esmumps/esmumps_strats.c new file mode 100644 index 00000000..6a44ef01 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/esmumps_strats.c @@ -0,0 +1,134 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : esmumps_strats.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains defalut strategy **/ +/** building routines for calling Scotch **/ +/** from MUMPS. **/ +/** **/ +/** DATES : # Version 1.0 : from : 08 dec 2003 **/ +/** to 08 dec 2003 **/ +/** # Version 1.1 : from : 21 jun 2007 **/ +/** to 21 jun 2007 **/ +/** # Version 5.0 : from : 08 feb 2008 **/ +/** to 08 feb 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ESMUMPS + +#include "common.h" +#include "esmumps.h" + +/**************************************/ +/* */ +/* This routine creates a strategy */ +/* string from the given parameters. */ +/* */ +/**************************************/ + +/* Meaning of the parameters : +** - procnbr : number of processors. +** - leafsiz : limit size in vertices of the leaf subgraphs. +** - leorval : type of halo ordering : 0 : HAMD; 1 : HAMF. +** - cminval : minimum number of column blocks. +** - cmaxval : maximum number of column blocks. +** - fratval : maximum fill ratio. +** - verbval : verbose flag if > 0. +** - stream : verbose stream. +** - straptr : pointer to character string of sufficient size +** to hold the resulting Scotch strategy. +*/ + +int +esmumps_strat1 ( +const INT procnbr, +const INT leafsiz, +const int leorval, +const INT cminval, +const INT cmaxval, +const double fratval, +const int verbval, +FILE * const stream, +char * const straptr) +{ + INT levlval; /* Nested dissection level */ + INT procmax; + char hamxval; /* Type of halo ordering routine */ + + for (levlval = 1, procmax = 1; procmax < procnbr; procmax <<= 1, levlval ++) ; /* Compute log2 of procnbr, + 1 */ + + hamxval = (leorval == 0) ? 'h' : 'f'; /* HAMD if 0, HAMF if 1 */ + + if (verbval != 0) { + fprintf (stream, "Scotch strategy:\n- %ld levels of ND are necessary for %ld processors\n", + (long) levlval, + (long) procnbr); + fprintf (stream, "- If compressed (0.7) graph, then perform %ld levels of ND, then switch to HAM(%c)\n", + (long) levlval, + (char) hamxval); + fprintf (stream, "- If uncompressed graph, then perform at least %ld levels of ND, and proceed\n until graph size less than %ld vertices, then switch to HAM(%c)\n", + (long) levlval, + (long) leafsiz, + (char) hamxval); + fprintf (stream, "- At the end of HAM(%c), amalgamate if number of columns not greater than %ld,\n and if either column size is smaller than %ld or fill ratio less than %lf\n", + (char) hamxval, + (long) cmaxval, + (long) cminval, + (double) fratval); + fprintf (stream, "- During uncoarsening, band graphs of width 3 are used for refinement\n"); + fprintf (stream, "- Separators are not split and are ordered in natural order\n"); + } + + sprintf (straptr, "c{rat=0.7,cpr=n{sep=/((levl<%ld)|(vert>%ld))?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}};,ole=%c{cmin=%ld,cmax=%ld,frat=%lf},ose=s},unc=n{sep=/(levl<%ld)?(m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}})|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}};,ole=%c{cmin=%ld,cmax=%ld,frat=%lf},ose=s}}", + (long) levlval, + (long) leafsiz, + (char) hamxval, + (long) cminval, + (long) cmaxval, + (double) fratval, + (long) levlval, + (char) hamxval, + (long) cminval, + (long) cmaxval, + (double) fratval); + + return (0); +} diff --git a/scotch_6.0.3/src/esmumps/fax.h b/scotch_6.0.3/src/esmumps/fax.h new file mode 100644 index 00000000..919cadc6 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/fax.h @@ -0,0 +1,96 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : fax.h **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Jean ROMAN (v0.0) **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the data declarations **/ +/** for the symbolic factorization routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 22 jul 1998 **/ +/** to 24 sep 1998 **/ +/** # Version 0.1 : from : 04 apr 1999 **/ +/** to 01 may 1999 **/ +/** # Version 1.0 : from : 01 jun 2002 **/ +/** to 25 jun 2002 **/ +/** # Version 1.1 : from : 26 jun 2002 **/ +/** to 25 sep 2002 **/ +/** # Version 1.3 : from : 17 jun 2003 **/ +/** to 17 jul 2003 **/ +/** # Version 2.0 : from : 21 mar 2003 **/ +/** to 29 oct 2003 **/ +/** # Version 2.0 : from : 03 mar 2004 **/ +/** to 03 mar 2004 **/ +/** # Version 3.0 : from : 23 nov 2004 **/ +/** to 03 mar 2005 **/ +/** **/ +/************************************************************/ + +#define FAX_H + +/* +** The function prototypes. +*/ + +#ifndef FAX +#define static +#endif + +int symbolCompact (SymbolMatrix * const symbptr); +int symbolFax (SymbolMatrix * const symbptr, const INT vertnbr, const INT edgenbr, const INT baseval, void * const ngbdptr, INT ngbfrst (void * const, const INT), INT ngbnext (void * const), INT ngbdegr (void * const, const INT), const Order * const ordeptr); +#ifdef GRAPH_H +int symbolFaxGraph (SymbolMatrix * const symbptr, const Graph * const grafptr, const Order * const ordeptr); +#endif /* GRAPH_H */ +int symbolFaxGrid2C (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr); +int symbolFaxGrid2D (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr); +int symbolFaxGrid2E (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr); +int symbolFaxGrid3C (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr); +int symbolFaxGrid3D (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr); +int symbolFaxGrid3E (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr); +#ifdef MESH_H +int symbolFaxMesh (SymbolMatrix * const symbptr, const Mesh * const meshptr, const Order * const ordeptr); +#endif /* MESH_H */ + +int symbolFaxi (SymbolMatrix * const symbptr, const INT vertnbr, const INT edgenbr, const INT baseval, void * const ngbdptr, INT ngbfrst (void * const, const INT), INT ngbnext (void * const), INT ngbdegr (void * const, const INT), const Order * const ordeptr, const INT levfmax); +#ifdef GRAPH_H +int symbolFaxiGraph (SymbolMatrix * const symbptr, const Graph * const grafptr, const Order * const ordeptr, const INT levfmax); +#endif /* GRAPH_H */ +int symbolFaxiGrid2D (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr, const INT levfmax); +int symbolFaxiGrid2E (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr, const INT levfmax); +int symbolFaxiGrid3D (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr, const INT levfmax); +int symbolFaxiGrid3E (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr, const INT levfmax); + +#undef static diff --git a/scotch_6.0.3/src/esmumps/graph.h b/scotch_6.0.3/src/esmumps/graph.h new file mode 100644 index 00000000..ceea0afe --- /dev/null +++ b/scotch_6.0.3/src/esmumps/graph.h @@ -0,0 +1,80 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph.h **/ +/** **/ +/** AUTHORS : David GOUDIN **/ +/** Pascal HENON **/ +/** Francois PELLEGRINI **/ +/** Pierre RAMET **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the data declarations **/ +/** for the graph structure. **/ +/** **/ +/** DATES : # Version 0.0 : from : 27 jul 1998 **/ +/** to 24 jan 2004 **/ +/** # Version 2.0 : from : 28 feb 2004 **/ +/** to 23 apr 2004 **/ +/** **/ +/************************************************************/ + +#define GRAPH_H + +/* +** The defines. +*/ + +#define Graph SCOTCH_Graph + +#define graphInit SCOTCH_graphInit +#define graphExit SCOTCH_graphExit +#define graphLoad SCOTCH_graphLoad +#define graphSave SCOTCH_graphSave +#define graphBase SCOTCH_graphBase +#define graphData SCOTCH_graphData +#define graphCheck SCOTCH_graphCheck + +/* +** The function prototypes. +*/ + +#ifndef GRAPH +#define static +#endif + +int graphBuild (Graph * const grafptr, const INT baseval, const INT vertnbr, const INT edgenbr, void * const ngbdptr, INT nghbfrstfunc (void * const, const INT), INT nghbnextfunc (void * const)); +int graphBuildGraph (Graph * const grafptr, const INT baseval, const INT vertnbr, const INT edgenbr, INT * restrict verttab, INT * restrict velotab, INT * restrict edgetab); +int graphBuildGraph2 (Graph * const grafptr, const INT baseval, const INT vertnbr, const INT edgenbr, INT * restrict verttab, INT * restrict vendtab, INT * restrict velotab, INT * restrict vlbltab, INT * restrict edgetab, INT * restrict edlotab); + +#undef static diff --git a/scotch_6.0.3/src/esmumps/graph_graph.c b/scotch_6.0.3/src/esmumps/graph_graph.c new file mode 100644 index 00000000..234e92ff --- /dev/null +++ b/scotch_6.0.3/src/esmumps/graph_graph.c @@ -0,0 +1,145 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_graph.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These module holds the array graph **/ +/** building routine. **/ +/** **/ +/** DATES : # Version 1.3 : from : 14 oct 2003 **/ +/** to 22 jan 2004 **/ +/** # Version 2.0 : from : 28 feb 2004 **/ +/** to 06 dec 2004 **/ +/** # Version 5.1 : from : 22 jan 2009 **/ +/** to 22 jan 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH + +#include "common.h" +#ifdef SCOTCH_PTSCOTCH +#include "ptscotch.h" +#else /* SCOTCH_PTSCOTCH */ +#include "scotch.h" +#endif /* SCOTCH_PTSCOTCH */ +#include "graph.h" + +/********************************/ +/* */ +/* The graph handling routines. */ +/* */ +/********************************/ + +/* This routine builds a graph +** structure from the given +** arrays. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphBuildGraph ( +Graph * const grafptr, /*+ Graph to build +*/ +const INT baseval, /*+ Base value +*/ +const INT vertnbr, /*+ Number of vertices +*/ +const INT edgenbr, /*+ Number of arcs +*/ +INT * restrict verttab, /*+ Vertex array +*/ +INT * restrict velotab, /*+ Array of vertex weights (DOFs) if not NULL +*/ +INT * restrict edgetab) /*+ Edge array +*/ +{ + if (sizeof (INT) != sizeof (SCOTCH_Num)) { /* Check integer consistency */ + errorPrint ("graphBuildGraph: inconsistent integer types"); + return (1); + } + + SCOTCH_graphBuild (grafptr, baseval, vertnbr, verttab, NULL, velotab, + NULL, edgenbr, edgetab, NULL); + +#ifdef GRAPH_DEBUG + if (graphCheck (grafptr) != 0) { /* Check graph consistency */ + errorPrint ("graphBuildGraph: inconsistent graph data"); + return (1); + } +#endif /* GRAPH_DEBUG */ + + return (0); +} + +/* This routine builds a graph +** structure from the given +** arrays, with full libScotch +** features. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphBuildGraph2 ( +Graph * const grafptr, /*+ Graph to build +*/ +const INT baseval, /*+ Base value +*/ +const INT vertnbr, /*+ Number of vertices +*/ +const INT edgenbr, /*+ Number of arcs +*/ +INT * restrict verttab, /*+ Vertex array +*/ +INT * restrict vendtab, /*+ Vertex end array +*/ +INT * restrict velotab, /*+ Array of vertex weights (DOFs) if not NULL +*/ +INT * restrict vlbltab, /*+ Array of vertex labels if not NULL +*/ +INT * restrict edgetab, /*+ Edge array +*/ +INT * restrict edlotab) /*+ Edge load array +*/ +{ + if (sizeof (INT) != sizeof (SCOTCH_Num)) { /* Check integer consistency */ + errorPrint ("graphBuildGraph2: inconsistent integer types"); + return (1); + } + + SCOTCH_graphBuild (grafptr, baseval, vertnbr, verttab, vendtab, velotab, + vlbltab, edgenbr, edgetab, edlotab); + +#ifdef GRAPH_DEBUG + if (graphCheck (grafptr) != 0) { /* Check graph consistency */ + errorPrint ("graphBuildGraph2: inconsistent graph data"); + return (1); + } +#endif /* GRAPH_DEBUG */ + + return (0); +} diff --git a/scotch_6.0.3/src/esmumps/main_esmumps.c b/scotch_6.0.3/src/esmumps/main_esmumps.c new file mode 100644 index 00000000..5c388ce1 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/main_esmumps.c @@ -0,0 +1,155 @@ +/* Copyright 2004,2007,2009,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : main_mumps.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This is the test module for the MUMPS **/ +/** interface routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 17 may 2001 **/ +/** to 17 may 2001 **/ +/** # Version 1.0 : from : 17 jun 2005 **/ +/** to 17 jun 2005 **/ +/** # Version 5.1 : from : 22 jan 2009 **/ +/** to 22 jan 2009 **/ +/** # Version 6.0 : from : 01 dec 2012 **/ +/** to 01 dec 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include "common.h" +#ifdef SCOTCH_PTSCOTCH +#include "ptscotch.h" +#else /* SCOTCH_PTSCOTCH */ +#include "scotch.h" +#endif /* SCOTCH_PTSCOTCH */ +#include "graph.h" +#include "esmumps.h" + +void ESMUMPSF (const INT * const, const INT * const, INT * const, const INT * const, INT * const, INT * const, INT * const, INT * const, INT * const, INT * const); + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main (argc, argv) +int argc; +char * argv[]; +{ + Graph grafdat; /* Graph to load */ + INT vertnbr; + INT * verttab; + INT edgenbr; + INT * edgetab; + INT * lentab; + INT * nvtab; + INT * elentab; + INT * lasttab; + INT pfree; + INT ncmpa; + INT vertnum; + FILE * stream; + + if (argc != 2) { + errorPrint ("main_esmumps: usage: main_esmumps graph_file"); + return (1); + } + + graphInit (&grafdat); + if ((stream = fopen (argv[1], "r")) == NULL) { + errorPrint ("main_esmumps: cannot open graph file"); + graphExit (&grafdat); + return (1); + } + if (graphLoad (&grafdat, stream, 1, 3) != 0) { /* Base graph with base value 1, no loads */ + errorPrint ("main_esmumps: cannot open graph file"); + graphExit (&grafdat); + return (1); + } + fclose (stream); + + graphData (&grafdat, NULL, &vertnbr, &verttab, NULL, NULL, NULL, &edgenbr, &edgetab, NULL); + + if ((lentab = (INT *) memAlloc (vertnbr * sizeof (INT))) == NULL) { + errorPrint ("main_esmumps: out of memory (1)"); + graphExit (&grafdat); + return (1); + } + for (vertnum = 0; vertnum < vertnbr; vertnum ++) { + if (verttab[vertnum] == verttab[vertnum + 1]) { + lentab[vertnum] = 0; + verttab[vertnum] = 0; /* Graph structure no longer valid in Emilio */ + } + else + lentab[vertnum] = verttab[vertnum + 1] - verttab[vertnum]; + } + + if (((nvtab = (INT *) memAlloc (vertnbr * sizeof (INT))) == NULL) || + ((elentab = (INT *) memAlloc (vertnbr * sizeof (INT))) == NULL) || + ((lasttab = (INT *) memAlloc (vertnbr * sizeof (INT))) == NULL)) { + errorPrint ("main_esmumps: out of memory (2)"); + if (nvtab != NULL) { + if (elentab != NULL) + memFree (elentab); + memFree (nvtab); + } + graphExit (&grafdat); + return (1); + } + + pfree = edgenbr + 1; + ESMUMPSF (&vertnbr, &edgenbr, verttab, &pfree, + lentab, edgetab, nvtab, elentab, lasttab, &ncmpa); + + memFree (lasttab); + memFree (elentab); + memFree (nvtab); + memFree (lentab); + graphExit (&grafdat); + + if (ncmpa < 0) { + errorPrint ("main_esmumps: error in ESMUMPSF (%d)", ncmpa); + return (1); + } + + exit (0); +} diff --git a/scotch_6.0.3/src/esmumps/module.h b/scotch_6.0.3/src/esmumps/module.h new file mode 100644 index 00000000..8533f246 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/module.h @@ -0,0 +1,79 @@ +/* Copyright 2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : module.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This is the global configuration file **/ +/** for the ESMUMPS library module. **/ +/** **/ +/** DATES : # Version 5.1 : from : 22 jan 2009 **/ +/** to 22 jan 2009 **/ +/** **/ +/************************************************************/ + +#define MODULE_H + +/* +** Function renaming. +*/ + +#if ((! defined SCOTCH_COMMON_EXTERNAL) || (defined SCOTCH_COMMON_RENAME)) +#define clockGet _SCOTCHclockGet + +#define fileNameDistExpand _SCOTCHfileNameDistExpand + +#define usagePrint _SCOTCHusagePrint + +#define errorPrint SCOTCH_errorPrint +#define errorPrintW SCOTCH_errorPrintW +#define errorProg SCOTCH_errorProg + +#define intLoad _SCOTCHintLoad +#define intSave _SCOTCHintSave +#define intAscn _SCOTCHintAscn +#define intPerm _SCOTCHintPerm +#define intRandReset _SCOTCHintRandReset +#define intRandInit _SCOTCHintRandInit +/* #define intRandVal _SCOTCHintRandVal Already a macro */ +#define intSearchDicho _SCOTCHintSearchDicho +#define intSort1asc1 _SCOTCHintSort1asc1 +#define intSort2asc1 _SCOTCHintSort2asc1 +#define intSort2asc2 _SCOTCHintSort2asc2 +#define intSort3asc1 _SCOTCHintSort3asc1 + +#define memAllocGroup _SCOTCHmemAllocGroup +#define memReallocGroup _SCOTCHmemReallocGroup +#define memOffset _SCOTCHmemOffset +#endif /* ((! defined SCOTCH_COMMON_EXTERNAL) || (defined SCOTCH_COMMON_RENAME)) */ diff --git a/scotch_6.0.3/src/esmumps/order.c b/scotch_6.0.3/src/esmumps/order.c new file mode 100644 index 00000000..d8ef7a0c --- /dev/null +++ b/scotch_6.0.3/src/esmumps/order.c @@ -0,0 +1,96 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : order.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** This module computes orderings. **/ +/** **/ +/** DATES : # Version 0.0 : from : 20 aug 1998 **/ +/** to 24 sep 1998 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ORDER + +#include "common.h" +#include "order.h" + +/***********************************/ +/* */ +/* The ordering handling routines. */ +/* */ +/***********************************/ + +/* This routine initializes the given +** ordering structure. +** It returns: +** - 0 : in all cases. +*/ + +int +orderInit ( +Order * const ordeptr) +{ + memSet (ordeptr, 0, sizeof (Order)); + + return (0); +} + +/* This routine frees the contents +** of the given ordering. +** It returns: +** - VOID : in all cases. +*/ + +void +orderExit ( +Order * const ordeptr) +{ + if (ordeptr->rangtab != NULL) + memFree (ordeptr->rangtab); + if (ordeptr->permtab != NULL) + memFree (ordeptr->permtab); + if (ordeptr->peritab != NULL) + memFree (ordeptr->peritab); + +#ifdef ORDER_DEBUG + memSet (ordeptr, ~0, sizeof (Order)); +#endif /* ORDER_DEBUG */ +} diff --git a/scotch_6.0.3/src/esmumps/order.h b/scotch_6.0.3/src/esmumps/order.h new file mode 100644 index 00000000..27314e13 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/order.h @@ -0,0 +1,103 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : order.h **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the data declarations **/ +/** for the graph ordering routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 22 aug 1998 **/ +/** to 01 may 1999 **/ +/** # Version 2.0 : from : 25 oct 2003 **/ +/** to 02 jul 2010 **/ +/** **/ +/************************************************************/ + +#define ORDER_H + +/* +** The type and structure definitions. +*/ + +/*+ Ordering structure. vnodbas holds the base + value for node indexings. vnodbas is equal + to baseval for graphs, and to vnodbas for + meshes. The same holds for rangtab, with + rangtab[0] = vnodbas. +*/ + +typedef struct Order_ { + INT cblknbr; /*+ Number of column blocks +*/ + INT * rangtab; /*+ Column block range array [based,+1] +*/ + INT * permtab; /*+ Permutation array [based] +*/ + INT * peritab; /*+ Inverse permutation array [based] +*/ +} Order; + +/* +** The function prototypes. +*/ + +#ifndef ORDER +#define static +#endif + +int orderInit (Order * const ordeptr); +void orderExit (Order * const ordeptr); +int orderLoad (Order * const ordeptr, FILE * const stream); +int orderSave (const Order * const ordeptr, FILE * const stream); +void orderBase (Order * restrict const ordeptr, const INT baseval); + +int orderCheck (const Order * const ordeptr); + +int orderGrid2 (Order * const ordeptr, const INT xnbr, const INT ynbr, const INT baseval, const INT xlim, const INT ylim); +int orderGrid2C (Order * const ordeptr, const INT xnbr, const INT ynbr, const INT baseval, const INT xlim, const INT ylim); +int orderGrid3 (Order * const ordeptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const INT xlim, const INT ylim, const INT zlim); +int orderGrid3C (Order * const ordeptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const INT xlim, const INT ylim, const INT zlim); + +#ifdef GRAPH_H +int orderGraph (Order * restrict const ordeptr, Graph * restrict const grafptr); +int orderGraphList (Order * restrict const ordeptr, Graph * restrict const grafptr, const INT listnbr, const INT * restrict const listtab); +int orderGraphStrat (Order * restrict const ordeptr, Graph * restrict const grafptr, const char * restrict const); +int orderGraphListStrat (Order * restrict const ordeptr, Graph * restrict const grafptr, const INT listnbr, const INT * restrict const listtab, const char * const); +#endif /* GRAPH_H */ + +#ifdef MESH_H +int orderMesh (Order * restrict const ordeptr, Mesh * restrict const meshptr); +int orderMeshList (Order * restrict const ordeptr, Mesh * restrict const meshptr, const INT listnbr, const INT * restrict const listtab); +int orderMeshStrat (Order * restrict const ordeptr, Mesh * restrict const meshptr, const char * const); +int orderMeshListStrat (Order * restrict const ordeptr, Mesh * restrict const meshptr, const INT listnbr, const INT * restrict const listtab, const char * const); +#endif /* MESH_H */ + +#undef static diff --git a/scotch_6.0.3/src/esmumps/order_scotch_graph.c b/scotch_6.0.3/src/esmumps/order_scotch_graph.c new file mode 100644 index 00000000..f781283c --- /dev/null +++ b/scotch_6.0.3/src/esmumps/order_scotch_graph.c @@ -0,0 +1,203 @@ +/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : order_scotch_graph.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** This is the interface module with the **/ +/** libSCOTCH matrix ordering library. **/ +/** **/ +/** DATES : # Version 0.0 : from : 20 aug 1998 **/ +/** to 18 may 1999 **/ +/** # Version 1.0 : from : 18 mar 2003 **/ +/** to 21 jan 2004 **/ +/** # Version 2.0 : from : 28 feb 2004 **/ +/** to 04 jan 2005 **/ +/** # Version 2.1 : from : 21 jun 2007 **/ +/** to 21 jun 2007 **/ +/** # Version 5.0 : from : 08 feb 2008 **/ +/** to 01 jun 2008 **/ +/** # Version 5.1 : from : 22 jan 2009 **/ +/** to 02 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ORDER_GRAPH + +#include "common.h" +#ifdef SCOTCH_PTSCOTCH +#include "ptscotch.h" +#else /* SCOTCH_PTSCOTCH */ +#include "scotch.h" +#endif /* SCOTCH_PTSCOTCH */ +#include "graph.h" +#include "order.h" + +/****************************/ +/* */ +/* Graph ordering routines. */ +/* */ +/****************************/ + +/*+ This routine orders the given +*** graph using the Emilio default +*** ordering strategy. +*** It returns: +*** - 0 : if ordering succeeded. +*** - !0 : on error. ++*/ + +int +orderGraph ( +Order * restrict const ordeptr, /*+ Ordering to compute +*/ +Graph * restrict const grafptr) /*+ Graph matrix to order +*/ +{ + INT vertnbr; + + SCOTCH_graphSize (grafptr, &vertnbr, NULL); + return (orderGraphList (ordeptr, grafptr, vertnbr, NULL)); +} + +/*+ This routine orders the subgraph of +*** the given graph induced by the given +*** vertex list, using the Emilio default +*** ordering strategy. +*** It returns: +*** - 0 : if ordering succeeded. +*** - !0 : on error. ++*/ + +int +orderGraphList ( +Order * restrict const ordeptr, /*+ Ordering to compute +*/ +Graph * restrict const grafptr, /*+ Graph matrix to order +*/ +const INT listnbr, /*+ Number of vertices in list +*/ +const INT * restrict const listtab) /*+ Vertex list array +*/ +{ + return (orderGraphListStrat (ordeptr, grafptr, listnbr, listtab, + "c{rat=0.7,cpr=n{sep=/(vert>120)?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=(|h{pass=10})f{bal=0.2}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=(|h{pass=10})f{bal=0.2}}};,ole=f{cmin=0,cmax=100000,frat=0.0},ose=g},unc=n{sep=/(vert>120)?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=(|h{pass=10})f{bal=0.2}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=(|h{pass=10})f{bal=0.2}}};,ole=f{cmin=15,cmax=100000,frat=0.0},ose=g}}")); +} + +/*+ This routine orders the given +*** graph using the given ordering +*** strategy. +*** It returns: +*** - 0 : if ordering succeeded. +*** - !0 : on error. ++*/ + +int +orderGraphStrat ( +Order * restrict const ordeptr, /*+ Ordering to compute +*/ +Graph * restrict const grafptr, /*+ Graph matrix to order +*/ +const char * restrict const stratptr) /*+ Ordering strategy +*/ +{ + INT vertnbr; + + SCOTCH_graphSize (grafptr, &vertnbr, NULL); + return (orderGraphListStrat (ordeptr, grafptr, vertnbr, NULL, stratptr)); +} + +/*+ This routine orders the subgraph of +*** the given graph induced by the given +*** vertex list, using the given ordering +*** strategy. +*** It returns: +*** - 0 : if ordering succeeded. +*** - !0 : on error. ++*/ + +int +orderGraphListStrat ( +Order * restrict const ordeptr, /*+ Ordering to compute +*/ +Graph * restrict const grafptr, /*+ Graph matrix to order +*/ +const INT listnbr, /*+ Number of vertices in list +*/ +const INT * restrict const listtab, /*+ Vertex list array +*/ +const char * restrict const stratptr) /*+ Ordering strategy +*/ +{ + SCOTCH_Strat scotstrat; /* Scotch ordering strategy */ + INT baseval; + INT vertnbr; + INT edgenbr; + int o; + + if (sizeof (INT) != sizeof (SCOTCH_Num)) { /* Check integer consistency */ + errorPrint ("orderGraphListStrat: inconsistent integer types"); + return (1); + } + + SCOTCH_graphData (grafptr, &baseval, &vertnbr, NULL, NULL, NULL, NULL, &edgenbr, NULL, NULL); + + if (((ordeptr->permtab = (INT *) memAlloc ( vertnbr * sizeof (INT))) == NULL) || + ((ordeptr->peritab = (INT *) memAlloc ( vertnbr * sizeof (INT))) == NULL) || + ((ordeptr->rangtab = (INT *) memAlloc ((vertnbr + 1) * sizeof (INT))) == NULL)) { + errorPrint ("orderGraphListStrat: out of memory"); + orderExit (ordeptr); + orderInit (ordeptr); + return (1); + } + + SCOTCH_stratInit (&scotstrat); /* Initialize default ordering strategy */ + + o = SCOTCH_stratGraphOrder (&scotstrat, stratptr); + if (o == 0) + o = SCOTCH_graphOrderList (grafptr, /* Compute graph ordering */ + (SCOTCH_Num) listnbr, (SCOTCH_Num *) listtab, &scotstrat, + (SCOTCH_Num *) ordeptr->permtab, (SCOTCH_Num *) ordeptr->peritab, + (SCOTCH_Num *) &ordeptr->cblknbr, (SCOTCH_Num *) ordeptr->rangtab, NULL); + + SCOTCH_stratExit (&scotstrat); + + if (o != 0) { /* If something failed in Scotch */ + orderExit (ordeptr); /* Free ordering arrays */ + orderInit (ordeptr); + return (1); + } +#ifdef ORDER_DEBUG + if ((ordeptr->rangtab[0] != baseval) || + (ordeptr->rangtab[ordeptr->cblknbr] != baseval + vertnbr) || + (orderCheck (ordeptr) != 0)) { + errorPrint ("orderGraphListStrat: invalid ordering"); + } +#endif /* ORDER_DEBUG */ + + ordeptr->rangtab = (INT *) memRealloc (ordeptr->rangtab, (ordeptr->cblknbr + 1) * sizeof (INT)); + + return (0); +} diff --git a/scotch_6.0.3/src/esmumps/symbol.c b/scotch_6.0.3/src/esmumps/symbol.c new file mode 100644 index 00000000..8158abbb --- /dev/null +++ b/scotch_6.0.3/src/esmumps/symbol.c @@ -0,0 +1,128 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : symbol.c **/ +/** **/ +/** AUTHORS : David GOUDIN **/ +/** Pascal HENON **/ +/** Francois PELLEGRINI **/ +/** Pierre RAMET **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the general purpose **/ +/** routines for the symbolic matrix. **/ +/** **/ +/** DATES : # Version 0.0 : from : 22 jul 1998 **/ +/** to 07 oct 1998 **/ +/** # Version 0.1 : from : 03 dec 1998 **/ +/** to 03 dec 1998 **/ +/** # Version 3.0 : from : 29 feb 2004 **/ +/** to 29 feb 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define SYMBOL + +#include "common.h" +#include "symbol.h" + +/******************************************/ +/* */ +/* The symbolic matrix handling routines. */ +/* */ +/******************************************/ + +/*+ This routine initializes the given +*** symbolic block matrix structure. +*** It returns: +*** - 0 : in all cases. ++*/ + +int +symbolInit ( +SymbolMatrix * const symbptr) +{ + memSet (symbptr, 0, sizeof (SymbolMatrix)); + + return (0); +} + +/*+ This routine frees the contents +*** of the given symbolic block matrix. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +symbolExit ( +SymbolMatrix * const symbptr) +{ + if (symbptr->cblktab != NULL) + memFree (symbptr->cblktab); + if (symbptr->bloktab != NULL) + memFree (symbptr->bloktab); + +#ifdef SYMBOL_DEBUG + symbolInit (symbptr); +#endif /* SYMBOL_DEBUG */ +} + +/*+ This routine reallocates the arrays +*** of the given symbolic block matrix. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +symbolRealloc ( +SymbolMatrix * const symbptr) +{ + SymbolCblk * cblktab; + SymbolBlok * bloktab; + + if ((cblktab = (SymbolCblk *) memAlloc ((symbptr->cblknbr + 1) * sizeof (SymbolCblk))) == NULL) + return; /* Cannot move smallest array */ + memCpy (cblktab, symbptr->cblktab, (symbptr->cblknbr + 1) * sizeof (SymbolCblk)); + memFree (symbptr->cblktab); /* Move column block array */ + symbptr->cblktab = cblktab; + + if ((bloktab = (SymbolBlok *) memAlloc (symbptr->bloknbr * sizeof (SymbolBlok))) == NULL) + return; /* Cannot move array */ + memCpy (bloktab, symbptr->bloktab, symbptr->bloknbr * sizeof (SymbolBlok)); + memFree (symbptr->bloktab); /* Move column block array */ + symbptr->bloktab = bloktab; +} diff --git a/scotch_6.0.3/src/esmumps/symbol.h b/scotch_6.0.3/src/esmumps/symbol.h new file mode 100644 index 00000000..03a0481f --- /dev/null +++ b/scotch_6.0.3/src/esmumps/symbol.h @@ -0,0 +1,163 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : symbol.h **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** David GOUDIN (v0.0) **/ +/** Pascal HENON (v0.0) **/ +/** Pierre RAMET (v0.0) **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the data declarations **/ +/** for the symbolic matrix. **/ +/** **/ +/** DATES : # Version 0.0 : from : 22 jul 1998 **/ +/** to 07 oct 1998 **/ +/** # Version 0.1 : from : 21 mar 2002 **/ +/** to 21 mar 2002 **/ +/** # Version 1.0 : from : 03 jun 2002 **/ +/** to 26 jun 2002 **/ +/** # Version 1.3 : from : 10 apr 2003 **/ +/** to 10 jun 2003 **/ +/** # Version 3.0 : from : 28 feb 2004 **/ +/** to 03 mar 2005 **/ +/** # Version 5.1 : from : 05 nov 2010 **/ +/** to 05 nov 2010 **/ +/** **/ +/************************************************************/ + +#define SYMBOL_H +#define SYMBOL_VERSION 1 + +/* +** The type and structure definitions. +*/ + +/*+ The column block structure. +*/ + +typedef struct SymbolCblk_ { + INT fcolnum; /*+ First column index +*/ + INT lcolnum; /*+ Last column index (inclusive) +*/ + INT bloknum; /*+ First block in column (diagonal) +*/ +} SymbolCblk; + +/*+ The column block structure. +*/ + +typedef struct SymbolBlok_ { + INT frownum; /*+ First row index +*/ + INT lrownum; /*+ Last row index (inclusive) +*/ + INT cblknum; /*+ Facing column block +*/ + INT levfval; /*+ Level-of-fill value +*/ +} SymbolBlok; + +/*+ The symbolic block matrix. +*/ + +typedef struct SymbolMatrix_ { + INT baseval; /*+ Base value for numberings +*/ + INT cblknbr; /*+ Number of column blocks +*/ + INT bloknbr; /*+ Number of blocks +*/ + SymbolCblk * cblktab; /*+ Array of column blocks [+1,based] +*/ + SymbolBlok * bloktab; /*+ Array of blocks [based] +*/ + INT nodenbr; /*+ Number of nodes in matrix +*/ +} SymbolMatrix; + +/*+ The type of cost computations. +*/ + +typedef enum SymbolCostType_ { + SYMBOLCOSTLDLT /*+ Crout (i.e. LDLt) cost function +*/ +} SymbolCostType; + +/* Structure for keeping track of selected + blocks in the matrix pattern. The values + of the tables are the remaining values + for the yet unselected blocks. */ + +typedef struct SymbolKeepBlok_ { + INT levfval; /*+ Values for incomplete factorisation +*/ + INT nupdval; + INT ctrival; + INT ctroval; + INT hghtval; +} SymbolKeepBlok; + +typedef struct SymbolKeep_ { + INT levfmax; /*+ Maximum values for incomplete fax +*/ + INT nupdmax; + INT ctrimax; + INT ctromax; + INT hghtmax; + byte * keeptab; /*+ Flag array for kept blocks +*/ + SymbolKeepBlok * kblktab; /*+ Block parameter array +*/ + double * levftab; /*+ Area arrays for selected blocks +*/ + double * nupdtab; + double * ctritab; + double * ctrotab; + double * hghttab; +} SymbolKeep; + +/* +** The function prototypes. +*/ + +#ifndef SYMBOL +#define static +#endif + +int symbolInit (SymbolMatrix * const symbptr); +void symbolExit (SymbolMatrix * const symbptr); +void symbolRealloc (SymbolMatrix * const symbptr); +int symbolLoad (SymbolMatrix * const symbptr, FILE * const stream); +int symbolSave (const SymbolMatrix * const symbptr, FILE * const stream); +int symbolCheck (const SymbolMatrix * const symbptr); +int symbolDraw (const SymbolMatrix * const symbptr, FILE * const stream); +int symbolDrawFunc (const SymbolMatrix * const symbptr, int (*) (const SymbolMatrix * const, const SymbolBlok * const, void * const, float * const), int (*) (const SymbolMatrix * const, const SymbolBlok * const, void * const, float * const), void * const, FILE * const stream); +void symbolDrawColor (const INT labl, float * const coloptr); +#ifdef DOF_H +int symbolCost (const SymbolMatrix * const symbptr, const Dof * const deofptr, const SymbolCostType typeval, double * const nnzptr, double * const opcptr); +int symbolCosti (const SymbolMatrix * const symbptr, const Dof * const deofptr, const SymbolCostType typeval, const INT levfval, double * const nnzptr, double * const opcptr); +int symbolLevf (const SymbolMatrix * const symbptr, INT * const levfmax, INT ** const levftab); +int symbolTree (const SymbolMatrix * const symbptr, const Dof * const deofptr, INT * const leafnbr, INT * const heigmin, INT * const heigmax, double * const heigavg, double * const heigdlt); +int symbolNonzeros (const SymbolMatrix * const symbptr, FILE * const stream); +#endif /* DOF_H */ + +int symbolKeepInit (SymbolKeep * restrict const keepptr, const SymbolMatrix * const symbptr); +void symbolKeepExit (SymbolKeep * restrict const keepptr); +void symbolKeepAdd (SymbolKeep * restrict const keepptr, const SymbolMatrix * const symbptr, int (* funcptr) (const SymbolKeepBlok * const, void * const), void * dataptr); +void symbolKeepDel (SymbolKeep * restrict const keepptr, const SymbolMatrix * const symbptr, int (* funcptr) (const SymbolKeepBlok * const, void * const), void * dataptr); +int symbolKeepCompute (SymbolKeep * restrict const keepptr, const SymbolMatrix * const symbptr); +int symbolKeepHisto (SymbolKeep * const keepptr, const SymbolMatrix * const, int (* funcptr) (const SymbolKeepBlok * const, void * const), void * dataptr); +int symbolKeepPurge (SymbolKeep * restrict const keepptr, SymbolMatrix * restrict const symbptr); +int symbolKeepView (const SymbolKeep * const keepptr, const double nnzlmax, const char * const nameptr); + +#undef static diff --git a/scotch_6.0.3/src/esmumps/symbol_fax.c b/scotch_6.0.3/src/esmumps/symbol_fax.c new file mode 100644 index 00000000..b86dd509 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/symbol_fax.c @@ -0,0 +1,483 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : symbol_fax.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Jean ROMAN (v0.0) **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** This is the generic block symbolic **/ +/** factorization routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 22 jul 1998 **/ +/** to 29 sep 1998 **/ +/** # Version 0.1 : from : 04 apr 1999 **/ +/** to 21 apr 1999 **/ +/** # Version 0.2 : from : 08 may 2000 **/ +/** to 09 may 2000 **/ +/** # Version 1.0 : from : 13 mar 2002 **/ +/** to 08 jun 2002 **/ +/** # Version 1.2 : from : 23 aug 2002 **/ +/** to 23 aug 2002 **/ +/** # Version 2.0 : from : 21 mar 2003 **/ +/** to 21 mar 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#ifndef SYMBOL_FAX_INCLUDED /* If included from other file */ +#define SYMBOL_FAX + +#include "common.h" +#include "symbol.h" +#include "order.h" +#include "fax.h" +#include "symbol_fax.h" +#endif /* SYMBOL_FAX_INCLUDED */ + +/***********************************/ +/* */ +/* Symbolic factorization routine. */ +/* */ +/***********************************/ + +/*+ This routine computes the block symbolic +*** factorization of the given matrix +*** according to the given vertex ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. +*** Algorithm: +*** The algorithm is implemented in a +*** cache-friendly manner, by using a single +*** dynamic array which grows along with the +*** number of computed blocks. The array is +*** decomposed in the following manner: +*** - In a first phase, a hash table and a +*** sort area are reserved at the end of +*** the space of already computed blocks. +*** The sort area is created far enough from +*** the end of the array of already computed +*** blocks such that if there are no contributing +*** blocks all new blocks can be created without +*** colliding with the sort area. +*** - Then, in a second phase, if the current +*** column block does have contributing column +*** blocks, an area for simply-linked temporary +*** blocks is reserved at least after the sort area, +*** leaving enough space to create all of the +*** corresponding potential new blocks +*** just after all the blocks of the previous +*** column block (right picture). +*** ___________ +*** |ccccccccccc| <- bloktab (bloktax) +*** |ccccccccccc| +*** |ccccccccccc| :ccccccccccc: +*** |ccccccccccc| >- Computed blocks ----------< |ccccccccccc| +*** |ccccccccccc| |ccccccccccc| +*** |-----------| |:::::::::::| +*** |hhhhhhhhhhh| <- hashtab = bloknum --------> |bcbcbcbcbcb| +*** |hhhhhhhhhhh| | |cbcbcbcbcbc| +*** |hhhhhhhhhhh| | |bcbcbcbcbcb| +*** |hhhhhhhhhhh| | |cbcbcbcbcbc| +*** |-----------| | |bcbcbcbcbcb| +*** | | | |-----------| +*** |-----------| <- sorttab...... ------------> | | +*** |sssssssssss| | | +*** |sssssssssss| | | +*** |-----------| <- ............................| | +*** | | tloktab -> |-----------| +*** | | |ttttttttttt| +*** | | |ttttttttttt| +*** : : |-----------| +*** :___________: :___________: +*** <- bloktab + blokmax ++*/ + +#ifndef SYMBOL_FAX_INCLUDED +#define SYMBOL_FAX_ITERATOR(ngbdptr, vertnum, vertend) \ + for (vertend = ngbfrst ((ngbdptr), (vertnum)); \ + vertend >= baseval; \ + vertend = ngbnext (ngbdptr)) { + +#define SYMBOL_FAX_VERTEX_DEGREE(ngbdptr, vertnum) \ + (ngbdegr ((ngbdptr), (vertnum))) + +int +symbolFax ( +SymbolMatrix * const symbptr, /*+ Symbolic block matrix [based] +*/ +const INT vertnbr, /*+ Number of vertices +*/ +const INT edgenbr, /*+ Number of edges +*/ +const INT baseval, /*+ Base value +*/ +void * const ngbdptr, /*+ Neighbor bookkeeping area +*/ +INT ngbfrst (void * const, const INT), /*+ First neighbor function +*/ +INT ngbnext (void * const), /*+ Next neighbor function +*/ +INT ngbdegr (void * const, const INT), /*+ Vertex degree function (upper bound) +*/ +const Order * const ordeptr) /*+ Matrix ordering +*/ +#endif /* SYMBOL_FAX_INCLUDED */ +{ + INT vertnum; /* Vertex number of current column */ + INT vertend; /* Current end vertex number */ + const INT * restrict permtax; /* Based access to direct permutation array */ + const INT * restrict peritax; /* Based access to inverse permutation array */ + const INT * restrict rangtax; /* Based access to column block range array */ + INT * restrict ctrbtax; /* Based access to array of contribution chains */ + SymbolCblk * restrict cblktax; /* Based access to column block array */ + INT cblknum; /* Based number of current column block */ + INT cblkctr; /* Based number of current contributing column block */ + SymbolBlok * restrict bloktax; /* Based access to block array */ + INT bloknum; /* Based number of current first free block slot */ + INT blokmax; /* Maximum number of blocks in array */ + SymbolFaxTlok * restrict tloktab; /* Beginning of array of temporary blocks */ + INT ctrbsum; /* Number of contributing blocks for column block */ + INT * restrict sorttab; /* Beginning of sort area */ + INT sortnbr; /* Number of vertices in sort area and hash table */ + INT * restrict hashtab; /* Hash vertex table */ + INT hashmsk; /* Mask for access to hash table */ + INT colend; /* Column number of vertex neighbor */ + + permtax = ordeptr->permtab - baseval; /* Compute array bases */ + peritax = ordeptr->peritab - baseval; + rangtax = ordeptr->rangtab - baseval; + + blokmax = ordeptr->cblknbr * (2 + edgenbr / vertnbr) + 2; /* Estimate size of initial block array */ + + { /* Allocate arrays for factoring */ + INT * ctrbtab; /* Array for contribution chaining */ + SymbolCblk * cblktab; /* Column block array */ + SymbolBlok * bloktab; /* Block array */ + + if (((ctrbtab = (INT *) memAlloc (ordeptr->cblknbr * sizeof (INT))) == NULL) || + ((cblktab = (SymbolCblk *) memAlloc ((ordeptr->cblknbr + 1) * sizeof (SymbolCblk))) == NULL) || + ((bloktab = (SymbolBlok *) memAlloc (blokmax * sizeof (SymbolBlok))) == NULL)) { + errorPrint ("symbolFax: out of memory (1)"); + if (ctrbtab != NULL) { + if (cblktab != NULL) + memFree (cblktab); + memFree (ctrbtab); + } + return (1); + } + cblktax = cblktab - baseval; /* Set based accesses */ + bloktax = bloktab - baseval; + ctrbtax = ctrbtab - baseval; + + memset (ctrbtab, ~0, ordeptr->cblknbr * sizeof (INT)); /* Initialize column block contributions link array */ + } + + bloknum = baseval; + for (cblknum = baseval; cblknum < baseval + ordeptr->cblknbr; cblknum ++) { /* For all column blocks */ + INT colnum; /* Number of current column [based] */ + INT colmax; /* Maximum column index for current column block */ + + { /* Compute offsets and check for array size */ + INT degrsum; + INT hashsiz; + INT hashmax; + INT ctrbtmp; + INT sortoft; /* Offset of sort array */ + INT tlokoft; /* Offset of temporary block array */ + INT tlndoft; /* Offset of end of temporary block array */ + INT tlokmax; + + colnum = rangtax[cblknum]; + colmax = rangtax[cblknum + 1]; /* Get maximum column value */ + + cblktax[cblknum].fcolnum = colnum; /* Set column block data */ + cblktax[cblknum].lcolnum = colmax - 1; + cblktax[cblknum].bloknum = bloknum; + + degrsum = 0; + for ( ; colnum < colmax; colnum ++) /* For all columns */ + degrsum += SYMBOL_FAX_VERTEX_DEGREE (ngbdptr, peritax[colnum]); /* Add column degrees */ + + for (hashmax = 256; hashmax < degrsum; hashmax *= 2) ; /* Get upper bound on hash table size */ + hashsiz = hashmax << 2; /* Fill hash table at 1/4 of capacity */ + hashmsk = hashsiz - 1; + + for (ctrbsum = 0, ctrbtmp = ctrbtax[cblknum]; /* Follow chain of contributing column blocks */ + ctrbtmp != ~0; ctrbtmp = ctrbtax[ctrbtmp]) + ctrbsum += cblktax[ctrbtmp + 1].bloknum - cblktax[ctrbtmp].bloknum - 2; /* Sum contributing column blocks */ + + tlokmax = degrsum + ctrbsum; + sortoft = tlokmax * sizeof (SymbolBlok); + if ((hashsiz * sizeof (INT)) > sortoft) /* Compute offset of sort area */ + sortoft = (hashsiz * sizeof (INT)); + tlokoft = sortoft + degrsum * sizeof (INT); /* Compute offset of temporary block area */ + tlndoft = tlokoft + tlokmax * sizeof (SymbolFaxTlok); /* Compute end of area */ + + if (((byte *) (bloktax + bloknum) + tlndoft) > /* If not enough room */ + ((byte *) (bloktax + blokmax))) { + SymbolBlok * bloktmp; /* Temporary pointer for array resizing */ + + do + blokmax = blokmax + (blokmax >> 2) + 4; /* Increase block array size by 25% as long as it does not fit */ + while (((byte *) (bloktax + bloknum) + tlndoft) > ((byte *) (bloktax + blokmax))); + + if ((bloktmp = (SymbolBlok *) memRealloc (bloktax + baseval, (blokmax * sizeof (SymbolBlok)))) == NULL) { + errorPrint ("symbolFax: out of memory (2)"); + memFree (bloktax + baseval); + memFree (cblktax + baseval); + memFree (ctrbtax + baseval); + return (1); + } + bloktax = bloktmp - baseval; + } + + hashtab = (INT *) (bloktax + bloknum); + sorttab = (INT *) ((byte *) hashtab + sortoft); + tloktab = (SymbolFaxTlok *) ((byte *) hashtab + tlokoft); + + memset (hashtab, ~0, hashsiz * sizeof (INT)); /* Initialize hash table */ + } + + sortnbr = 0; /* No vertices yet */ + for (colnum = rangtax[cblknum]; colnum < colmax; colnum ++) { /* For all columns */ + INT hashnum; + + vertnum = peritax[colnum]; /* Get associated vertex */ + SYMBOL_FAX_ITERATOR (ngbdptr, vertnum, vertend) /* For all adjacent edges */ + colend = permtax[vertend]; /* Get end column number */ + + if (colend < colmax) /* If end vertex number in left columns */ + continue; /* Skip to next neighbor */ + + for (hashnum = (colend * SYMBOL_FAX_HASHPRIME) & hashmsk; ; /* Search end column in hash table */ + hashnum = (hashnum + 1) & hashmsk) { + INT * hashptr; + + hashptr = hashtab + hashnum; /* Point to hash slot */ + if (*hashptr == colend) /* If end column in hash table */ + break; /* Skip to next end column */ + if (*hashptr == ~0) { /* If slot is empty */ + *hashptr = colend; /* Set column in hash table */ + sorttab[sortnbr ++] = colend; /* Add end column to sort array */ + break; + } + } + } /* End of loop on neighbors */ + } /* End of loop on columns */ + + intSort1asc1 (sorttab, sortnbr); /* Sort neighbor array */ + + cblkctr = cblknum; + if (ctrbtax[cblknum] == ~0) { /* If column is not to be updated */ + INT sortnum; + + bloktax[bloknum].frownum = cblktax[cblknum].fcolnum; /* Build diagonal block */ + bloktax[bloknum].lrownum = cblktax[cblknum].lcolnum; + bloktax[bloknum].cblknum = cblknum; + bloktax[bloknum].levfval = 0; + bloknum ++; + + for (sortnum = 0; sortnum < sortnbr; ) { /* For all entries in sorted array */ + INT colend; /* Column number of current entry */ + + colend = sorttab[sortnum]; + if (colend >= rangtax[cblkctr + 1]) { /* If column block number to be found */ + INT cblktmm; /* Median value */ + INT cblktmx; /* Maximum value */ + + for (cblkctr ++, /* Find new column block by dichotomy */ + cblktmx = ordeptr->cblknbr + baseval; + cblktmx - cblkctr > 1; ) { + cblktmm = (cblktmx + cblkctr) >> 1; + if (rangtax[cblktmm] <= colend) + cblkctr = cblktmm; + else + cblktmx = cblktmm; + } + } + + bloktax[bloknum].frownum = colend; /* Set beginning of new block */ + while ((++ sortnum < sortnbr) && /* Scan extent of block */ + (sorttab[sortnum] - 1 == sorttab[sortnum - 1]) && + (sorttab[sortnum] < rangtax[cblkctr + 1])) ; + bloktax[bloknum].lrownum = sorttab[sortnum - 1]; /* Set end of block */ + bloktax[bloknum].cblknum = cblkctr; + bloktax[bloknum].levfval = 0; + bloknum ++; /* One more block */ + } + } + else { /* Column will be updated */ + INT sortnum; /* Current index in sort array */ + INT tloknum; /* Current index on temporary block */ + INT tlokfre; /* Index of first free block */ + + tloktab->frownum = cblktax[cblknum].fcolnum; /* Build diagonal chained block */ + tloktab->lrownum = cblktax[cblknum].lcolnum; + tloktab->cblknum = cblknum; + tloktab->nextnum = 1; + tloknum = 1; + + for (sortnum = 0; sortnum < sortnbr; ) { /* For all entries in sorted array */ + INT colend; /* Column number of current entry */ + + colend = sorttab[sortnum]; + if (colend >= rangtax[cblkctr + 1]) { /* If column block number to be found */ + INT cblktmm; /* Median value */ + INT cblktmx; /* Maximum value */ + + for (cblkctr ++, /* Find new column block by dichotomy */ + cblktmx = ordeptr->cblknbr + baseval; + cblktmx - cblkctr > 1; ) { + cblktmm = (cblktmx + cblkctr) >> 1; + if (rangtax[cblktmm] <= colend) + cblkctr = cblktmm; + else + cblktmx = cblktmm; + } + } + tloktab[tloknum].frownum = colend; /* Set beginning of new block */ + while ((++ sortnum < sortnbr) && /* Scan extent of block */ + (sorttab[sortnum] - 1 == sorttab[sortnum - 1]) && + (sorttab[sortnum] < rangtax[cblkctr + 1])) ; + tloktab[tloknum].lrownum = sorttab[sortnum - 1]; /* Set end of block */ + tloktab[tloknum].cblknum = cblkctr; + tloktab[tloknum].nextnum = tloknum + 1; /* Chain block */ + tloknum = tloknum + 1; + } + tloktab[tloknum].frownum = /* Build trailing block */ + tloktab[tloknum].lrownum = vertnbr + baseval; + tloktab[tloknum].cblknum = ordeptr->cblknbr + baseval; + tloktab[tloknum].nextnum = 0; /* Set end of chain (never chain to diagonal block) */ + + tlokfre = ++ tloknum; /* Build free chain for possible contributing blocks */ + for ( ; tloknum < tlokfre + ctrbsum; tloknum = tloknum + 1) + tloktab[tloknum].nextnum = tloknum + 1; + tloktab[tloknum].nextnum = ~0; /* Set end of free chain */ + + for (cblkctr = ctrbtax[cblknum]; cblkctr != ~0; cblkctr = ctrbtax[cblkctr]) { /* Follow chain */ + INT blokctr; /* Current index of contributing column block */ + INT tloklst; /* Index of previous temporary block */ + + tloklst = 0; /* Previous is diagonal block */ + tloknum = 0; /* Current is diagonal block */ + + for (blokctr = cblktax[cblkctr].bloknum + 2; /* For all blocks in contributing column block */ + blokctr < cblktax[cblkctr + 1].bloknum; blokctr ++) { + while ((tloktab[tloknum].cblknum < bloktax[blokctr].cblknum) || /* Skip unmatched chained blocks */ + (tloktab[tloknum].lrownum < bloktax[blokctr].frownum - 1)) { + tloklst = tloknum; + tloknum = tloktab[tloknum].nextnum; + } + + if ((bloktax[blokctr].cblknum < tloktab[tloknum].cblknum) || /* If contributing block has no mate */ + (bloktax[blokctr].lrownum < tloktab[tloknum].frownum - 1)) { + INT tloktmp; + +#ifdef FAX_DEBUG + if (tlokfre == ~0) { + errorPrint ("symbolFax: internal error (1)"); + memFree (bloktax + baseval); + memFree (cblktax + baseval); + memFree (ctrbtax + baseval); + return (1); + } +#endif /* FAX_DEBUG */ + tloktmp = + tloktab[tloklst].nextnum = tlokfre; /* Chain new block */ + tloktab[tlokfre].frownum = bloktax[blokctr].frownum; /* Copy block data */ + tloktab[tlokfre].lrownum = bloktax[blokctr].lrownum; + tloktab[tlokfre].cblknum = bloktax[blokctr].cblknum; + tlokfre = tloktab[tlokfre].nextnum; + tloktab[tloktmp].nextnum = tloknum; /* Complete chainimg */ + tloknum = tloktab[tloklst].nextnum; /* Resume from new block */ + continue; /* Process next block */ + } + + if ((bloktax[blokctr].lrownum >= tloktab[tloknum].frownum - 1) && /* Update chained block lower bound */ + (bloktax[blokctr].frownum < tloktab[tloknum].frownum)) + tloktab[tloknum].frownum = bloktax[blokctr].frownum; + + if ((bloktax[blokctr].frownum <= tloktab[tloknum].lrownum + 1) && /* Update chained block upper bound */ + (bloktax[blokctr].lrownum > tloktab[tloknum].lrownum)) { + INT tloktmp; + + tloktab[tloknum].lrownum = bloktax[blokctr].lrownum; + + for (tloktmp = tloktab[tloknum].nextnum; /* Aggregate following chained blocks */ + (tloktab[tloktmp].cblknum == tloktab[tloknum].cblknum) && + (tloktab[tloktmp].frownum <= tloktab[tloknum].lrownum + 1); + tloktmp = tloktab[tloknum].nextnum) { + if (tloktab[tloktmp].lrownum > tloktab[tloknum].lrownum) /* Merge aggregated block */ + tloktab[tloknum].lrownum = tloktab[tloktmp].lrownum; + tloktab[tloknum].nextnum = tloktab[tloktmp].nextnum; /* Unlink aggregated block */ + tloktab[tloktmp].nextnum = tlokfre; + tlokfre = tloktmp; + } + } + } + } + + for (tloknum = 0; /* For all chained blocks */ + tloktab[tloknum].nextnum != 0; /* Until trailer block is reached */ + tloknum = tloktab[tloknum].nextnum, bloknum ++) { /* Copy block data to block array */ + bloktax[bloknum].frownum = tloktab[tloknum].frownum; + bloktax[bloknum].lrownum = tloktab[tloknum].lrownum; + bloktax[bloknum].cblknum = tloktab[tloknum].cblknum; + bloktax[bloknum].levfval = 0; + } + } + if ((bloknum - cblktax[cblknum].bloknum) > 2) { /* If more than one extra-diagonal blocks exist */ + ctrbtax[cblknum] = ctrbtax[bloktax[cblktax[cblknum].bloknum + 1].cblknum]; /* Link contributing column blocks */ + ctrbtax[bloktax[cblktax[cblknum].bloknum + 1].cblknum] = cblknum; + } + } + cblktax[cblknum].fcolnum = /* Set last column block data */ + cblktax[cblknum].lcolnum = vertnbr + baseval; + cblktax[cblknum].bloknum = bloknum; + + memFree (ctrbtax + baseval); /* Free contribution link array */ + + symbptr->baseval = baseval; /* Fill in matrix fields */ + symbptr->cblknbr = ordeptr->cblknbr; + symbptr->bloknbr = bloknum - baseval; + symbptr->cblktab = cblktax + baseval; + symbptr->bloktab = memRealloc (bloktax + baseval, (bloknum - baseval) * sizeof (SymbolBlok)); /* Set array to its exact size */ + symbptr->nodenbr = vertnbr; + +#ifdef FAX_DEBUG + if (symbolCheck (symbptr) != 0) { + errorPrint ("symbolFax: internal error (2)"); + symbolExit (symbptr); + return (1); + } +#endif /* FAX_DEBUG */ + + return (0); +} diff --git a/scotch_6.0.3/src/esmumps/symbol_fax.h b/scotch_6.0.3/src/esmumps/symbol_fax.h new file mode 100644 index 00000000..8751d29c --- /dev/null +++ b/scotch_6.0.3/src/esmumps/symbol_fax.h @@ -0,0 +1,79 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : symbol_fax.h **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Jean ROMAN (v0.0) **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the data declarations **/ +/** for the symbolic factorization routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 22 jul 1998 **/ +/** to 24 sep 1998 **/ +/** # Version 0.1 : from : 04 apr 1999 **/ +/** to 01 may 1999 **/ +/** # Version 1.0 : from : 01 jun 2002 **/ +/** to 05 jun 2002 **/ +/** # Version 1.1 : from : 26 jun 2002 **/ +/** to 26 jun 2002 **/ +/** # Version 3.0 : from : 03 mar 2004 **/ +/** to 03 mar 2004 **/ +/** **/ +/************************************************************/ + +#define SYMBOL_FAX_H + +/* +** The defines. +*/ + +/* Prime number for hashing vertex numbers. */ + +#define SYMBOL_FAX_HASHPRIME 17 /*+ Prime number for hashing +*/ + +/* +** The type and structure definitions. +*/ + +/*+ The chained column block structure. These + blocks are chained in a single linked list + for block merge with blocks of left columns. +*/ + +typedef struct SymbolFaxTlok_ { + INT frownum; /*+ First row index +*/ + INT lrownum; /*+ Last row index (inclusive) +*/ + INT cblknum; /*+ Facing column block +*/ + INT nextnum; /*+ Index of next block +*/ +} SymbolFaxTlok; diff --git a/scotch_6.0.3/src/esmumps/symbol_fax_graph.c b/scotch_6.0.3/src/esmumps/symbol_fax_graph.c new file mode 100644 index 00000000..0c928db1 --- /dev/null +++ b/scotch_6.0.3/src/esmumps/symbol_fax_graph.c @@ -0,0 +1,132 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : symbol_fax_graph.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** This is the block symbolic factoriza- **/ +/** tion routine for graphs. **/ +/** **/ +/** DATES : # Version 0.0 : from : 22 jul 1998 **/ +/** to 29 sep 1998 **/ +/** # Version 0.2 : from : 08 may 2000 **/ +/** to 09 may 2000 **/ +/** # Version 1.0 : from : 01 jun 2002 **/ +/** to 03 jun 2002 **/ +/** # Version 1.1 : from : 26 jun 2002 **/ +/** to 26 jun 2002 **/ +/** # Version 2.0 : from : 21 mar 2003 **/ +/** to 21 mar 2003 **/ +/** # Version 3.0 : from : 02 mar 2004 **/ +/** to 02 mar 2004 **/ +/** # Version 5.1 : from : 22 jan 2009 **/ +/** to 22 jan 2009 **/ +/** **/ +/** NOTES : # symbolFaxGraph() could have called **/ +/** symbolFax() in the regular way, as **/ +/** do all of the grid-like factorization **/ +/** routines. However, for efficiency **/ +/** reasons, we have decided to inline **/ +/** symbolFax(), to avoid a function call **/ +/** for every arc. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define SYMBOL_FAX +#define SYMBOL_FAX_GRAPH + +#include "common.h" +#ifdef SCOTCH_PTSCOTCH +#include "ptscotch.h" +#else /* SCOTCH_PTSCOTCH */ +#include "scotch.h" +#endif /* SCOTCH_PTSCOTCH */ +#include "graph.h" +#include "symbol.h" +#include "order.h" +#include "fax.h" +#include "symbol_fax.h" + +/***********************************/ +/* */ +/* Symbolic factorization routine. */ +/* */ +/***********************************/ + +/*+ This routine computes the block symbolic +*** factorization of the given matrix graph +*** according to the given vertex ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +symbolFaxGraph ( +SymbolMatrix * const symbptr, /*+ Symbolic block matrix [based] +*/ +const Graph * const grafptr, /*+ Matrix adjacency structure [based] +*/ +const Order * const ordeptr) /*+ Matrix ordering +*/ +{ + INT baseval; + INT vertnbr; + INT * verttab; + const INT * restrict verttax; + INT edgenbr; + INT edgenum; + INT * edgetab; + const INT * restrict edgetax; + + SCOTCH_graphData (grafptr, &baseval, &vertnbr, &verttab, NULL, NULL, NULL, &edgenbr, &edgetab, NULL); + verttax = verttab - baseval; + edgetax = edgetab - baseval; + +#define SYMBOL_FAX_ITERATOR(ngbdptr, vertnum, vertend) \ + for (edgenum = verttax[vertnum]; \ + edgenum < verttax[vertnum + 1]; \ + edgenum ++) { \ + vertend = edgetax[edgenum]; + +#define SYMBOL_FAX_VERTEX_DEGREE(ngbdptr, vertnum) \ + (verttax[(vertnum) + 1] - verttax[(vertnum)]) + + { +#define SYMBOL_FAX_INCLUDED +#include "symbol_fax.c" + } +} diff --git a/scotch_6.0.3/src/libscotch/Makefile b/scotch_6.0.3/src/libscotch/Makefile new file mode 100644 index 00000000..073ac010 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/Makefile @@ -0,0 +1,2987 @@ +## Copyright 2004,2007-2013 IPB, Universite de Bordeaux, INRIA & CNRS +## +## This file is part of the Scotch software package for static mapping, +## graph partitioning and sparse matrix ordering. +## +## This software is governed by the CeCILL-C license under French law +## and abiding by the rules of distribution of free software. You can +## use, modify and/or redistribute the software under the terms of the +## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +## URL: "http://www.cecill.info". +## +## As a counterpart to the access to the source code and rights to copy, +## modify and redistribute granted by the license, users are provided +## only with a limited warranty and the software's author, the holder of +## the economic rights, and the successive licensors have only limited +## liability. +## +## In this respect, the user's attention is drawn to the risks associated +## with loading, using, modifying and/or developing or reproducing the +## software by the user in light of its specific status of free software, +## that may mean that it is complicated to manipulate, and that also +## therefore means that it is reserved for developers and experienced +## professionals having in-depth computer knowledge. Users are therefore +## encouraged to load and test the software's suitability as regards +## their requirements in conditions enabling the security of their +## systems and/or data to be ensured and, more generally, to use and +## operate it in the same conditions as regards security. +## +## The fact that you are presently reading this means that you have had +## knowledge of the CeCILL-C license and that you accept its terms. +## + +includedir = ../../include +libdir = ../../lib + +## +## General inference rules. +## + +include ../Makefile.inc + +%$(OBJ) : %.c + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -o $(@) + +%$(EXE) : %.c + $(CC) $(CFLAGS) -DSCOTCH_VERSION=$(VERSION) -DSCOTCH_RELEASE=$(RELEASE) -DSCOTCH_PATCHLEVEL=$(PATCHLEVEL) $(<) -o $(@) $(LDFLAGS) + +## +## Project rules. +## + +.PHONY : ptscotch scotch ptinstall install clean realclean + +scotch : + $(MAKE) CC="$(CCS)" CCD="$(CCS)" \ + scotch.h \ + scotchf.h \ + libscotch$(LIB) \ + libscotcherr$(LIB) \ + libscotcherrexit$(LIB) + +ptscotch : scotch + $(MAKE) CFLAGS="$(CFLAGS) -DSCOTCH_PTSCOTCH" CC="$(CCP)" \ + ptscotch.h \ + ptscotchf.h \ + libptscotch$(LIB) \ + libptscotcherr$(LIB) \ + libptscotcherrexit$(LIB) + +install : $(includedir)/scotch.h \ + $(includedir)/scotchf.h \ + $(libdir)/libscotch$(LIB) + +ptinstall : install \ + $(includedir)/ptscotch.h \ + $(includedir)/ptscotchf.h \ + $(libdir)/libptscotch$(LIB) + +clean : + -$(RM) *~ *$(OBJ) lib*$(LIB) parser_yy.c parser_ly.h parser_ll.c *scotch.h *scotchf.h y.output *dummysizes$(EXE) + +realclean : clean + + +## +## Installation dependencies +## + +$(includedir)/scotch.h : scotch.h + -$(CP) scotch.h $(includedir) + +$(includedir)/scotchf.h : scotchf.h + -$(CP) scotchf.h $(includedir) + +$(includedir)/ptscotch.h : ptscotch.h + -$(CP) ptscotch.h $(includedir) + +$(includedir)/ptscotchf.h : ptscotchf.h + -$(CP) ptscotchf.h $(includedir) + +$(libdir)/libscotch$(LIB) : libscotch$(LIB) + -$(CP) libscotch$(LIB) libscotcherr*$(LIB) $(libdir) + +$(libdir)/libptscotch$(LIB) : libptscotch$(LIB) + -$(CP) libptscotch$(LIB) libptscotcherr*$(LIB) $(libdir) + +## +## Library dependencies. +## + +LIBPTSCOTCHDEPS = bdgraph$(OBJ) \ + bdgraph_bipart_bd$(OBJ) \ + bdgraph_bipart_df$(OBJ) \ + bdgraph_bipart_ex$(OBJ) \ + bdgraph_bipart_ml$(OBJ) \ + bdgraph_bipart_sq$(OBJ) \ + bdgraph_bipart_st$(OBJ) \ + bdgraph_bipart_zr$(OBJ) \ + bdgraph_check$(OBJ) \ + bdgraph_gather_all$(OBJ) \ + bdgraph_store$(OBJ) \ + comm$(OBJ) \ + dgraph$(OBJ) \ + dgraph_allreduce$(OBJ) \ + dgraph_band$(OBJ) \ + dgraph_build$(OBJ) \ + dgraph_build_grid3d$(OBJ) \ + dgraph_build_hcub$(OBJ) \ + dgraph_check$(OBJ) \ + dgraph_coarsen$(OBJ) \ + dgraph_fold$(OBJ) \ + dgraph_fold_comm$(OBJ) \ + dgraph_fold_dup$(OBJ) \ + dgraph_gather$(OBJ) \ + dgraph_gather_all$(OBJ) \ + dgraph_ghst$(OBJ) \ + dgraph_halo$(OBJ) \ + dgraph_induce$(OBJ) \ + dgraph_io_load$(OBJ) \ + dgraph_io_save$(OBJ) \ + dgraph_match$(OBJ) \ + dgraph_match_sync_coll$(OBJ) \ + dgraph_match_sync_ptop$(OBJ) \ + dgraph_match_check$(OBJ) \ + dgraph_redist$(OBJ) \ + dgraph_scatter$(OBJ) \ + dgraph_view$(OBJ) \ + dmapping$(OBJ) \ + dmapping_io$(OBJ) \ + dorder$(OBJ) \ + dorder_gather$(OBJ) \ + dorder_io$(OBJ) \ + dorder_io_block$(OBJ) \ + dorder_io_tree$(OBJ) \ + dorder_perm$(OBJ) \ + dorder_tree_dist$(OBJ) \ + hdgraph$(OBJ) \ + hdgraph_check$(OBJ) \ + hdgraph_fold$(OBJ) \ + hdgraph_gather$(OBJ) \ + hdgraph_induce$(OBJ) \ + hdgraph_order_nd$(OBJ) \ + hdgraph_order_si$(OBJ) \ + hdgraph_order_sq$(OBJ) \ + hdgraph_order_st$(OBJ) \ + kdgraph$(OBJ) \ + kdgraph_gather$(OBJ) \ + kdgraph_map_rb$(OBJ) \ + kdgraph_map_rb_map$(OBJ) \ + kdgraph_map_rb_part$(OBJ) \ + kdgraph_map_st$(OBJ) \ + library_dgraph$(OBJ) \ + library_dgraph_f$(OBJ) \ + library_dgraph_band$(OBJ) \ + library_dgraph_band_f$(OBJ) \ + library_dgraph_build$(OBJ) \ + library_dgraph_build_f$(OBJ) \ + library_dgraph_build_grid3d$(OBJ) \ + library_dgraph_build_grid3d_f$(OBJ) \ + library_dgraph_check$(OBJ) \ + library_dgraph_check_f$(OBJ) \ + library_dgraph_coarsen$(OBJ) \ + library_dgraph_coarsen_f$(OBJ) \ + library_dgraph_gather$(OBJ) \ + library_dgraph_gather_f$(OBJ) \ + library_dgraph_grow$(OBJ) \ + library_dgraph_halo$(OBJ) \ + library_dgraph_halo_f$(OBJ) \ + library_dgraph_induce$(OBJ) \ + library_dgraph_induce_f$(OBJ) \ + library_dgraph_io_load$(OBJ) \ + library_dgraph_io_load_f$(OBJ) \ + library_dgraph_io_save$(OBJ) \ + library_dgraph_io_save_f$(OBJ) \ + library_dgraph_map$(OBJ) \ + library_dgraph_map_f$(OBJ) \ + library_dgraph_map_view$(OBJ) \ + library_dgraph_map_view_f$(OBJ) \ + library_dgraph_order$(OBJ) \ + library_dgraph_order_f$(OBJ) \ + library_dgraph_order_gather$(OBJ) \ + library_dgraph_order_gather_f$(OBJ) \ + library_dgraph_order_io$(OBJ) \ + library_dgraph_order_io_f$(OBJ) \ + library_dgraph_order_io_block$(OBJ) \ + library_dgraph_order_io_block_f$(OBJ) \ + library_dgraph_order_perm$(OBJ) \ + library_dgraph_order_perm_f$(OBJ) \ + library_dgraph_order_tree_dist$(OBJ) \ + library_dgraph_order_tree_dist_f$(OBJ) \ + library_dgraph_redist$(OBJ) \ + library_dgraph_redist_f$(OBJ) \ + library_dgraph_scatter$(OBJ) \ + library_dgraph_scatter_f$(OBJ) \ + library_dgraph_stat$(OBJ) \ + library_dgraph_stat_f$(OBJ) \ + library_dmapping$(OBJ) \ + library_dorder$(OBJ) \ + vdgraph$(OBJ) \ + vdgraph_check$(OBJ) \ + vdgraph_gather_all$(OBJ) \ + vdgraph_separate_bd$(OBJ) \ + vdgraph_separate_df$(OBJ) \ + vdgraph_separate_ml$(OBJ) \ + vdgraph_separate_sq$(OBJ) \ + vdgraph_separate_st$(OBJ) \ + vdgraph_separate_zr$(OBJ) \ + vdgraph_store$(OBJ) + +LIBSCOTCHDEPS = arch$(OBJ) \ + arch_build$(OBJ) \ + arch_cmplt$(OBJ) \ + arch_cmpltw$(OBJ) \ + arch_deco$(OBJ) \ + arch_dist$(OBJ) \ + arch_hcub$(OBJ) \ + arch_mesh$(OBJ) \ + arch_tleaf$(OBJ) \ + arch_torus$(OBJ) \ + arch_vcmplt$(OBJ) \ + arch_vhcub$(OBJ) \ + bgraph$(OBJ) \ + bgraph_bipart_bd$(OBJ) \ + bgraph_bipart_df$(OBJ) \ + bgraph_bipart_ex$(OBJ) \ + bgraph_bipart_fm$(OBJ) \ + bgraph_bipart_gg$(OBJ) \ + bgraph_bipart_gp$(OBJ) \ + bgraph_bipart_ml$(OBJ) \ + bgraph_bipart_st$(OBJ) \ + bgraph_bipart_zr$(OBJ) \ + bgraph_check$(OBJ) \ + bgraph_store$(OBJ) \ + common$(OBJ) \ + common_file$(OBJ) \ + common_file_compress$(OBJ) \ + common_file_uncompress$(OBJ) \ + common_integer$(OBJ) \ + common_memory$(OBJ) \ + common_string$(OBJ) \ + common_stub$(OBJ) \ + common_thread$(OBJ) \ + fibo$(OBJ) \ + gain$(OBJ) \ + geom$(OBJ) \ + graph$(OBJ) \ + graph_base$(OBJ) \ + graph_band$(OBJ) \ + graph_check$(OBJ) \ + graph_coarsen$(OBJ) \ + graph_induce$(OBJ) \ + graph_io$(OBJ) \ + graph_io_chac$(OBJ) \ + graph_io_habo$(OBJ) \ + graph_io_mmkt$(OBJ) \ + graph_io_scot$(OBJ) \ + graph_list$(OBJ) \ + graph_match$(OBJ) \ + hall_order_hd$(OBJ) \ + hall_order_hf$(OBJ) \ + hall_order_hx$(OBJ) \ + hgraph$(OBJ) \ + hgraph_check$(OBJ) \ + hgraph_induce$(OBJ) \ + hgraph_order_bl$(OBJ) \ + hgraph_order_cp$(OBJ) \ + hgraph_order_gp$(OBJ) \ + hgraph_order_hd$(OBJ) \ + hgraph_order_hf$(OBJ) \ + hgraph_order_hx$(OBJ) \ + hgraph_order_kp$(OBJ) \ + hgraph_order_nd$(OBJ) \ + hgraph_order_si$(OBJ) \ + hgraph_order_st$(OBJ) \ + hmesh$(OBJ) \ + hmesh_check$(OBJ) \ + hmesh_hgraph$(OBJ) \ + hmesh_induce$(OBJ) \ + hmesh_mesh$(OBJ) \ + hmesh_order_bl$(OBJ) \ + hmesh_order_cp$(OBJ) \ + hmesh_order_gr$(OBJ) \ + hmesh_order_gp$(OBJ) \ + hmesh_order_hd$(OBJ) \ + hmesh_order_hf$(OBJ) \ + hmesh_order_hx$(OBJ) \ + hmesh_order_nd$(OBJ) \ + hmesh_order_si$(OBJ) \ + hmesh_order_st$(OBJ) \ + kgraph$(OBJ) \ + kgraph_band$(OBJ) \ + kgraph_check$(OBJ) \ + kgraph_map_bd$(OBJ) \ + kgraph_map_cp$(OBJ) \ + kgraph_map_df$(OBJ) \ + kgraph_map_ex$(OBJ) \ + kgraph_map_fm$(OBJ) \ + kgraph_map_ml$(OBJ) \ + kgraph_map_rb$(OBJ) \ + kgraph_map_rb_map$(OBJ) \ + kgraph_map_rb_part$(OBJ) \ + kgraph_map_st$(OBJ) \ + kgraph_store$(OBJ) \ + library_arch$(OBJ) \ + library_arch_f$(OBJ) \ + library_arch_build$(OBJ) \ + library_arch_build_f$(OBJ) \ + library_common_f$(OBJ) \ + library_geom$(OBJ) \ + library_geom_f$(OBJ) \ + library_graph$(OBJ) \ + library_graph_f$(OBJ) \ + library_graph_base$(OBJ) \ + library_graph_base_f$(OBJ) \ + library_graph_check$(OBJ) \ + library_graph_check_f$(OBJ) \ + library_graph_coarsen$(OBJ) \ + library_graph_coarsen_f$(OBJ) \ + library_graph_color$(OBJ) \ + library_graph_color_f$(OBJ) \ + library_graph_io_chac$(OBJ) \ + library_graph_io_chac_f$(OBJ) \ + library_graph_io_habo$(OBJ) \ + library_graph_io_habo_f$(OBJ) \ + library_graph_io_mmkt$(OBJ) \ + library_graph_io_mmkt_f$(OBJ) \ + library_graph_io_scot$(OBJ) \ + library_graph_io_scot_f$(OBJ) \ + library_graph_map$(OBJ) \ + library_graph_map_f$(OBJ) \ + library_graph_map_io$(OBJ) \ + library_graph_map_io_f$(OBJ) \ + library_graph_map_view$(OBJ) \ + library_graph_map_view_f$(OBJ) \ + library_graph_order$(OBJ) \ + library_graph_order_f$(OBJ) \ + library_graph_part_ovl$(OBJ) \ + library_graph_part_ovl_f$(OBJ) \ + library_mapping$(OBJ) \ + library_memory$(OBJ) \ + library_memory_f$(OBJ) \ + library_mesh$(OBJ) \ + library_mesh_f$(OBJ) \ + library_mesh_graph$(OBJ) \ + library_mesh_graph_f$(OBJ) \ + library_mesh_io_habo$(OBJ) \ + library_mesh_io_habo_f$(OBJ) \ + library_mesh_io_scot$(OBJ) \ + library_mesh_io_scot_f$(OBJ) \ + library_mesh_order$(OBJ) \ + library_mesh_order_f$(OBJ) \ + library_order$(OBJ) \ + library_parser$(OBJ) \ + library_parser_f$(OBJ) \ + library_random$(OBJ) \ + library_random_f$(OBJ) \ + library_strat$(OBJ) \ + library_version$(OBJ) \ + library_version_f$(OBJ) \ + mapping$(OBJ) \ + mapping_io$(OBJ) \ + mesh$(OBJ) \ + mesh_check$(OBJ) \ + mesh_coarsen$(OBJ) \ + mesh_graph$(OBJ) \ + mesh_induce_sepa$(OBJ) \ + mesh_io$(OBJ) \ + mesh_io_habo$(OBJ) \ + mesh_io_scot$(OBJ) \ + order$(OBJ) \ + order_check$(OBJ) \ + order_io$(OBJ) \ + parser$(OBJ) \ + parser_ll$(OBJ) \ + parser_yy$(OBJ) \ + vgraph$(OBJ) \ + vgraph_check$(OBJ) \ + vgraph_separate_bd$(OBJ) \ + vgraph_separate_df$(OBJ) \ + vgraph_separate_es$(OBJ) \ + vgraph_separate_fm$(OBJ) \ + vgraph_separate_gg$(OBJ) \ + vgraph_separate_gp$(OBJ) \ + vgraph_separate_ml$(OBJ) \ + vgraph_separate_st$(OBJ) \ + vgraph_separate_th$(OBJ) \ + vgraph_separate_vw$(OBJ) \ + vgraph_separate_zr$(OBJ) \ + vgraph_store$(OBJ) \ + vmesh$(OBJ) \ + vmesh_check$(OBJ) \ + vmesh_separate_fm$(OBJ) \ + vmesh_separate_gg$(OBJ) \ + vmesh_separate_gr$(OBJ) \ + vmesh_separate_ml$(OBJ) \ + vmesh_separate_zr$(OBJ) \ + vmesh_separate_st$(OBJ) \ + vmesh_store$(OBJ) \ + wgraph$(OBJ) \ + wgraph_check$(OBJ) \ + wgraph_part_fm$(OBJ) \ + wgraph_part_gg$(OBJ) \ + wgraph_part_gp$(OBJ) \ + wgraph_part_ml$(OBJ) \ + wgraph_part_rb$(OBJ) \ + wgraph_part_st$(OBJ) \ + wgraph_part_zr$(OBJ) \ + wgraph_store$(OBJ) + +## +## Todo list. +## + +common$(OBJ) : common.c \ + module.h \ + common.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +common_file$(OBJ) : common_file.c \ + module.h \ + common.h \ + common_file.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +common_file_compress$(OBJ) : common_file_compress.c \ + module.h \ + common.h \ + common_file.h \ + common_file_compress.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +common_file_uncompress$(OBJ) : common_file_uncompress.c \ + module.h \ + common.h \ + common_file.h \ + common_file_compress.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +common_integer$(OBJ) : common_integer.c \ + module.h \ + common.h \ + common_sort.c + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +common_memory$(OBJ) : common_memory.c \ + module.h \ + common.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +common_string$(OBJ) : common_string.c \ + module.h \ + common.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +common_stub$(OBJ) : common_stub.c \ + module.h \ + common.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +common_thread$(OBJ) : common_thread.c \ + module.h \ + common.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) + +arch$(OBJ) : arch.c \ + module.h \ + common.h \ + arch.h \ + arch_cmplt.h \ + arch_cmpltw.h \ + arch_deco.h \ + arch_dist.h \ + arch_hcub.h \ + arch_mesh.h \ + arch_tleaf.h \ + arch_torus.h \ + arch_vcmplt.h \ + arch_vhcub.h + +arch_build$(OBJ) : arch_build.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + arch_deco.h \ + arch_vcmplt.h \ + mapping.h \ + bgraph.h \ + bgraph_bipart_st.h \ + arch_build.h + +arch_cmplt$(OBJ) : arch_cmplt.c \ + module.h \ + common.h \ + arch.h \ + arch_cmplt.h + +arch_cmpltw$(OBJ) : arch_cmpltw.c \ + module.h \ + common.h \ + arch.h \ + arch_cmpltw.h + +arch_deco$(OBJ) : arch_deco.c \ + module.h \ + common.h \ + arch.h \ + arch_deco.h + +arch_dist$(OBJ) : arch_dist.c \ + module.h \ + common.h \ + arch.h \ + arch_dist.h + +arch_hcub$(OBJ) : arch_hcub.c \ + module.h \ + common.h \ + arch.h \ + arch_hcub.h + +arch_mesh$(OBJ) : arch_mesh.c \ + module.h \ + common.h \ + arch.h \ + arch_mesh.h + +arch_tleaf$(OBJ) : arch_tleaf.c \ + module.h \ + common.h \ + arch.h \ + arch_tleaf.h + +arch_torus$(OBJ) : arch_torus.c \ + module.h \ + common.h \ + arch.h \ + arch_torus.h + +arch_vcpmlt$(OBJ) : arch_vcmplt.c \ + module.h \ + common.h \ + arch.h \ + arch_vcmplt.h + +arch_vhcub$(OBJ) : arch_vhcub.c \ + module.h \ + common.h \ + arch.h \ + arch_vhcub.h + +bdgraph$(OBJ) : bdgraph.c \ + module.h \ + common.h \ + arch$(OBJ) \ + dgraph.h \ + dmapping.h \ + bdgraph.h + +bdgraph_bipart_bd$(OBJ) : bdgraph_bipart_bd.c \ + module.h \ + common.h \ + parser.h \ + arch$(OBJ) \ + dgraph.h \ + dgraph_halo.h \ + bdgraph.h \ + bdgraph_bipart_bd.h \ + bdgraph_bipart_st.h + +bdgraph_bipart_df$(OBJ) : bdgraph_bipart_df.c \ + module.h \ + common.h \ + arch$(OBJ) \ + dgraph.h \ + bdgraph.h \ + bdgraph_bipart_df.h + +bdgraph_bipart_ex$(OBJ) : bdgraph_bipart_ex.c \ + module.h \ + common.h \ + arch$(OBJ) \ + dgraph.h \ + bdgraph.h \ + bdgraph_bipart_ex.h + +bdgraph_bipart_ml$(OBJ) : bdgraph_bipart_ml.c \ + module.h \ + common.h \ + parser.h \ + arch$(OBJ) \ + dgraph.h \ + dgraph_coarsen.h \ + bdgraph.h \ + bdgraph_bipart_ml.h \ + bdgraph_bipart_st.h + +bdgraph_bipart_sq$(OBJ) : bdgraph_bipart_sq.c \ + module.h \ + common.h \ + comm.h \ + parser.h \ + arch$(OBJ) \ + graph.h \ + bgraph.h \ + bgraph_bipart_st.h \ + dgraph.h \ + bdgraph.h \ + bdgraph_bipart_sq.h + +bdgraph_bipart_st$(OBJ) : bdgraph_bipart_st.c \ + module.h \ + common.h \ + gain.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_st.h \ + dgraph.h \ + dgraph_coarsen.h \ + bdgraph.h \ + bdgraph_bipart_bd.h \ + bdgraph_bipart_df.h \ + bdgraph_bipart_ex.h \ + bdgraph_bipart_ml.h \ + bdgraph_bipart_sq.h \ + bdgraph_bipart_st.h \ + bdgraph_bipart_zr.h + +bdgraph_bipart_zr$(OBJ) : bdgraph_bipart_zr.c \ + module.h \ + common.h \ + arch$(OBJ) \ + dgraph.h \ + bdgraph.h \ + bdgraph_bipart_zr.h + +bdgraph_check$(OBJ) : bdgraph_check.c \ + module.h \ + common.h \ + arch$(OBJ) \ + dgraph.h \ + bdgraph.h + +bdgraph_gather_all$(OBJ) : bdgraph_gather_all.c \ + module.h \ + common.h \ + comm.h \ + arch$(OBJ) \ + graph.h \ + bgraph.h \ + dgraph.h \ + bdgraph.h + +bdgraph_store$(OBJ) : bdgraph_store.c \ + module.h \ + common.h \ + arch$(OBJ) \ + dgraph.h \ + bdgraph.h + +bgraph$(OBJ) : bgraph.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + bgraph.h + +bgraph_bipart_bd$(OBJ) : bgraph_bipart_bd.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_bd.h \ + bgraph_bipart_st.h + +bgraph_bipart_df$(OBJ) : bgraph_bipart_df.c \ + bgraph_bipart_df_loop.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_df.h + +bgraph_bipart_ex$(OBJ) : bgraph_bipart_ex.c \ + module.h \ + common.h \ + gain.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_ex.h \ + bgraph_bipart_fm.h \ + bgraph_bipart_gg.h + +bgraph_bipart_fm$(OBJ) : bgraph_bipart_fm.c \ + gain.h \ + fibo.h \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_fm.h + +bgraph_bipart_gg$(OBJ) : bgraph_bipart_gg.c \ + gain.h \ + fibo.h \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_gg.h + +bgraph_bipart_gp$(OBJ) : bgraph_bipart_gp.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_gp.h + +bgraph_bipart_ml$(OBJ) : bgraph_bipart_ml.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + graph_coarsen.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_ml.h \ + bgraph_bipart_st.h + +bgraph_bipart_st$(OBJ) : bgraph_bipart_st.c \ + gain.h \ + fibo.h \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_bd.h \ + bgraph_bipart_df.h \ + bgraph_bipart_ex.h \ + bgraph_bipart_fm.h \ + bgraph_bipart_gg.h \ + bgraph_bipart_gp.h \ + bgraph_bipart_ml.h \ + bgraph_bipart_st.h \ + bgraph_bipart_zr.h + +bgraph_bipart_zr$(OBJ) : bgraph_bipart_zr.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h \ + bgraph_bipart_zr.h + +bgraph_check$(OBJ) : bgraph_check.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h + +bgraph_store$(OBJ) : bgraph_store.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + bgraph.h + +comm$(OBJ) : comm.c \ + module.h \ + common.h \ + comm.h + +dgraph$(OBJ) : dgraph.c \ + module.h \ + common.h \ + dgraph.h + +dgraph_allreduce$(OBJ) : dgraph_allreduce.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_allreduce.h + +dgraph_band$(OBJ) : dgraph_band.c \ + module.h \ + common.h \ + dgraph.h + +dgraph_build$(OBJ) : dgraph_build.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_allreduce.h \ + dgraph_build.h + +dgraph_build_grid3d$(OBJ) : dgraph_build_grid3d.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_build_grid3d.h + +dgraph_build_hcub$(OBJ) : dgraph_build_hcub.c \ + module.h \ + common.h \ + dgraph.h + +dgraph_check$(OBJ) : dgraph_check.c \ + module.h \ + common.h \ + dgraph.h + +dgraph_coarsen$(OBJ) : dgraph_coarsen.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_allreduce.h \ + dgraph_coarsen.h \ + dgraph_match.h + +dgraph_fold$(OBJ) : dgraph_fold.c \ + module.h \ + common.h \ + comm.h \ + dgraph.h \ + dgraph_fold.h \ + dgraph_fold_comm.h + +dgraph_fold_comm$(OBJ) : dgraph_fold_comm.c \ + module.h \ + common.h \ + comm.h \ + dgraph.h \ + dgraph_fold_comm.h + +dgraph_fold_dup$(OBJ) : dgraph_fold_dup.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_fold_dup.h + +dgraph_gather$(OBJ) : dgraph_gather.c \ + module.h \ + common.h \ + graph.h \ + dgraph.h + +dgraph_gather_all$(OBJ) : dgraph_gather_all.c \ + module.h \ + common.h \ + comm.h \ + graph.h \ + dgraph.h + +dgraph_ghst$(OBJ) : dgraph_ghst.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_ghst.h + +dgraph_halo$(OBJ) : dgraph_halo.c \ + dgraph_halo_fill.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_halo.h + +dgraph_induce$(OBJ) : dgraph_induce.c \ + module.h \ + common.h \ + dgraph.h + +dgraph_io_load$(OBJ) : dgraph_io_load.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_io_load.h + +dgraph_io_save$(OBJ) : dgraph_io_save.c \ + module.h \ + common.h \ + dgraph.h + +dgraph_match$(OBJ) : dgraph_match.c \ + dgraph_match_scan.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_coarsen.h \ + dgraph_match.h + +dgraph_match_check$(OBJ) : dgraph_match_check.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_coarsen.h \ + dgraph_match.h + +dgraph_match_sync_coll$(OBJ) : dgraph_match_sync_coll.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_coarsen.h \ + dgraph_match.h \ + graph.h + +dgraph_match_sync_ptop$(OBJ) : dgraph_match_sync_ptop.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_coarsen.h \ + dgraph_match.h \ + graph.h + +dgraph_redist$(OBJ) : dgraph_redist.c \ + module.h \ + common.h \ + graph.h \ + dgraph.h + +dgraph_scatter$(OBJ) : dgraph_scatter.c \ + module.h \ + common.h \ + graph.h \ + dgraph.h + +dgraph_view$(OBJ) : dgraph_view.c \ + module.h \ + common.h \ + dgraph.h + +dmapping$(OBJ) : dmapping.c \ + module.h \ + common.h \ + arch$(OBJ) \ + dgraph.h \ + dmapping.h + +dmapping_io$(OBJ) : dmapping_io.c \ + module.h \ + common.h \ + comm.h \ + arch$(OBJ) \ + dgraph.h \ + dgraph_allreduce.h \ + dmapping.h + +dorder$(OBJ) : dorder.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h + +dorder_gather$(OBJ) : dorder_gather.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_allreduce.h \ + dorder.h \ + dorder_gather.h \ + order.h + +dorder_io$(OBJ) : dorder_io.c \ + module.h \ + common.h \ + comm.h \ + dgraph.h \ + dorder.h \ + order.h + +dorder_io_block$(OBJ) : dorder_io_block.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h \ + order.h + +dorder_io_tree$(OBJ) : dorder_io_tree.c \ + module.h \ + common.h \ + comm.h \ + dgraph.h \ + dorder.h \ + order.h + +dorder_perm$(OBJ) : dorder_perm.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h \ + dorder_perm.h + +dorder_tree_dist$(OBJ) : dorder_tree_dist.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h + +fibo$(OBJ) : fibo.c \ + module.h \ + common.h \ + fibo.h + +gain$(OBJ) : gain.c \ + module.h \ + common.h \ + gain.h + +geom$(OBJ) : geom.c \ + module.h \ + common.h \ + geom.h + +graph$(OBJ) : graph.c \ + module.h \ + common.h \ + graph.h + +graph_band$(OBJ) : graph_band.c \ + module.h \ + common.h \ + graph.h + +graph_base$(OBJ) : graph_base.c \ + module.h \ + common.h \ + graph.h + +graph_check$(OBJ) : graph_check.c \ + module.h \ + common.h \ + graph.h + +graph_coarsen$(OBJ) : graph_coarsen.c \ + graph_coarsen_edge.c \ + module.h \ + common.h \ + graph.h \ + graph_coarsen.h + +graph_induce$(OBJ) : graph_induce.c \ + module.h \ + common.h \ + graph.h \ + graph_induce.h + +graph_io$(OBJ) : graph_io.c \ + module.h \ + common.h \ + graph.h \ + graph_io.h + +graph_io_chac$(OBJ) : graph_io_chac.c \ + module.h \ + common.h \ + geom.h \ + graph.h + +graph_io_habo$(OBJ) : graph_io_habo.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + graph_io_habo.h + +graph_io_mmkt$(OBJ) : graph_io_mmkt.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + graph_io_mmkt.h + +graph_io_scot$(OBJ) : graph_io_scot.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + graph_io_scot.h + +graph_list$(OBJ) : graph_list.c \ + module.h \ + common.h \ + graph.h + +graph_match$(OBJ) : graph_match.c \ + graph_match_scan.c \ + module.h \ + common.h \ + graph.h \ + graph_coarsen.h \ + graph_match.h + +hall_order_hd$(OBJ) : hall_order_hd.c \ + module.h \ + common.h \ + graph.h \ + hall_order_hd.h + +hall_order_hf$(OBJ) : hall_order_hf.c \ + module.h \ + common.h \ + graph.h \ + hall_order_hf.h + +hall_order_hx$(OBJ) : hall_order_hx.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + hall_order_hx.h + +hdgraph$(OBJ) : hdgraph.c \ + module.h \ + common.h \ + dgraph.h \ + hdgraph.h + +hdgraph_check$(OBJ) : hdgraph_check.c \ + module.h \ + common.h \ + dgraph.h \ + hdgraph.h + +hdgraph_fold$(OBJ) : hdgraph_fold.c \ + module.h \ + common.h \ + comm.h \ + dgraph.h \ + dgraph_fold_comm.h \ + hdgraph.h \ + hdgraph_fold.h + +hdgraph_gather$(OBJ) : hdgraph_gather.c \ + module.h \ + common.h \ + comm.h \ + graph.h \ + hgraph.h \ + dgraph.h \ + hdgraph.h + +hdgraph_induce$(OBJ) : hdgraph_induce.c \ + module.h \ + common.h \ + dgraph.h \ + hdgraph.h + +hdgraph_order_nd$(OBJ) : hdgraph_order_nd.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + hgraph.h \ + hgraph_order_st.h \ + dgraph.h \ + dorder.h \ + hdgraph.h \ + hdgraph_order_nd.h \ + hdgraph_order_sq.h \ + hdgraph_order_st.h \ + vdgraph.h \ + vdgraph_separate_st.h + +hdgraph_order_si$(OBJ) : hdgraph_order_si.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h \ + hdgraph.h \ + hdgraph_order_si.h + +hdgraph_order_sq$(OBJ) : hdgraph_order_sq.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + hgraph.h \ + hgraph_order_st.h \ + dgraph.h \ + dorder.h \ + hdgraph.h \ + hdgraph_order_sq.h + +hdgraph_order_st$(OBJ) : hdgraph_order_st.c \ + module.h \ + common.h \ + parser.h \ + dgraph.h \ + dgraph_coarsen.h \ + dorder.h \ + hdgraph.h \ + vdgraph.h \ + vdgraph_separate_st.h \ + hdgraph_order_nd.h \ + hdgraph_order_si.h \ + hdgraph_order_sq.h \ + hdgraph_order_st.h + +hgraph$(OBJ) : hgraph.c \ + module.h \ + common.h \ + graph.h \ + hgraph.h + +hgraph_check$(OBJ) : hgraph_check.c \ + module.h \ + common.h \ + graph.h \ + hgraph.h + +hgraph_induce$(OBJ) : hgraph_induce.c \ + hgraph_induce_edge.c \ + module.h \ + common.h \ + graph.h \ + hgraph.h \ + hgraph_induce.h + +hgraph_order_bl$(OBJ) : hgraph_order_bl.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + hgraph.h \ + hgraph_order_bl.h + +hgraph_order_cp$(OBJ) : hgraph_order_cp.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + hgraph.h \ + hgraph_order_cp.h \ + hgraph_order_st.h + +hgraph_order_gp$(OBJ) : hgraph_order_gp.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + hgraph.h \ + hgraph_order_gp.h + +hgraph_order_hd$(OBJ) : hgraph_order_hd.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + hgraph.h \ + hall_order_hd.h \ + hall_order_hx.h \ + hgraph_order_hd.h \ + hgraph_order_hx.h \ + hgraph_order_si.h + +hgraph_order_hf$(OBJ) : hgraph_order_hf.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + hgraph.h \ + hall_order_hf.h \ + hall_order_hx.h \ + hgraph_order_hf.h \ + hgraph_order_hx.h \ + hgraph_order_si.h + +hgraph_order_hx$(OBJ) : hgraph_order_hx.c \ + module.h \ + common.h \ + graph.h \ + hgraph.h \ + hgraph_order_hx.h + +hgraph_order_kp$(OBJ) : hgraph_order_kp.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch.h \ + mapping.h \ + order.h \ + hgraph.h \ + hgraph_order_kp.h \ + hgraph_order_si.h \ + hgraph_order_st.h \ + kgraph.h \ + kgraph_map_st.h \ + scotch.h + +hgraph_order_nd$(OBJ) : hgraph_order_nd.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + hgraph.h \ + hgraph_order_nd.h \ + hgraph_order_st.h \ + vgraph.h \ + vgraph_separate_st.h + +hgraph_order_si$(OBJ) : hgraph_order_si.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + hgraph.h \ + hgraph_order_si.h + +hgraph_order_st$(OBJ) : hgraph_order_st.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + order.h \ + hgraph.h \ + hgraph_order_bl.h \ + hgraph_order_cp.h \ + hgraph_order_gp.h \ + hgraph_order_hd.h \ + hgraph_order_hf.h \ + hgraph_order_kp.h \ + hgraph_order_nd.h \ + hgraph_order_si.h \ + hgraph_order_st.h \ + kgraph.h \ + kgraph_map_st.h \ + vgraph.h \ + vgraph_separate_st.h + +hmesh$(OBJ) : hmesh.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + hmesh.h + +hmesh_check$(OBJ) : hmesh_check.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + hmesh.h + +hmesh_hgraph$(OBJ) : hmesh_hgraph.c \ + module.h \ + common.h \ + graph.h \ + hgraph.h \ + mesh.h \ + hmesh.h \ + hmesh_hgraph.h + +hmesh_induce$(OBJ) : hmesh_induce.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + hmesh.h + +hmesh_mesh$(OBJ) : hmesh_mesh.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + hmesh.h + +hmesh_order_bl$(OBJ) : hmesh_order_bl.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + mesh.h \ + hmesh.h \ + hmesh_order_bl.h \ + hmesh_order_st.h + +hmesh_order_cp$(OBJ) : hmesh_order_cp.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + mesh.h \ + hmesh.h \ + hmesh_order_cp.h \ + hmesh_order_st.h + +hmesh_order_gp$(OBJ) : hmesh_order_gp.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + mesh.h \ + hmesh.h \ + hmesh_order_gp.h + +hmesh_order_gp$(OBJ) : hmesh_order_gp.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + mesh.h \ + hmesh.h \ + hmesh_order_gp.h + +hmesh_order_hd$(OBJ) : hmesh_order_hd.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + mesh.h \ + hmesh.h \ + hall_order_hd.h \ + hall_order_hx.h \ + hmesh_order_hd.h \ + hmesh_order_si.h + +hmesh_order_hf$(OBJ) : hmesh_order_hf.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + mesh.h \ + hmesh.h \ + hall_order_hf.h \ + hall_order_hx.h \ + hmesh_order_hf.h \ + hmesh_order_si.h + +hmesh_order_hx$(OBJ) : hmesh_order_hx.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + hmesh.h \ + hmesh_order_hx.h + +hmesh_order_nd$(OBJ) : hmesh_order_nd.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + mesh.h \ + hmesh.h \ + hmesh_order_nd.h \ + hmesh_order_st.h \ + vmesh.h \ + vmesh_separate_st.h + +hmesh_order_si$(OBJ) : hmesh_order_si.c \ + module.h \ + common.h \ + graph.h \ + order.h \ + mesh.h \ + hmesh.h \ + hmesh_order_si.h + +hmesh_order_st$(OBJ) : hmesh_order_st.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + hgraph.h \ + hgraph_order_st.h \ + mesh.h \ + hmesh.h \ + order.h \ + vmesh_separate_st.h \ + hmesh_order_bl.h \ + hmesh_order_gp.h \ + hmesh_order_gr.h \ + hmesh_order_hd.h \ + hmesh_order_hf.h \ + hmesh_order_nd.h \ + hmesh_order_si.h \ + hmesh_order_st.h + +kdgraph$(OBJ) : kdgraph.c \ + module.h \ + common.h \ + arch$(OBJ) \ + dgraph.h \ + dmapping.h \ + kdgraph.h + +kdgraph_gather$(OBJ) : kdgraph_gather.c \ + module.h \ + common.h \ + arch$(OBJ) \ + graph.h \ + mapping.h \ + kgraph.h \ + dgraph.h \ + kdgraph.h + +kdgraph_map_rb$(OBJ) : kdgraph_map_rb.c \ + module.h \ + common.h \ + parser.h \ + arch$(OBJ) \ + graph.h \ + dgraph.h \ + dmapping.h \ + kdgraph.h \ + kdgraph_map_rb.h \ + kdgraph_map_rb_map.h \ + kdgraph_map_rb_part.h + +kdgraph_map_rb_map$(OBJ) : kdgraph_map_rb_map.c \ + module.h \ + common.h \ + parser.h \ + arch$(OBJ) \ + graph.h \ + bgraph.h \ + bgraph_bipart_st.h \ + mapping.h \ + kgraph.h \ + kgraph_map_st.h \ + dgraph.h \ + dmapping.h \ + bdgraph.h \ + bdgraph_bipart_st.h \ + kdgraph.h \ + kdgraph_map_rb.h \ + kdgraph_map_rb_map.h \ + kdgraph_map_st.h + +kdgraph_map_rb_part$(OBJ) : kdgraph_map_rb_part.c \ + module.h \ + common.h \ + parser.h \ + arch$(OBJ) \ + graph.h \ + bgraph.h \ + bgraph_bipart_st.h \ + mapping.h \ + kgraph.h \ + kgraph_map_st.h \ + dgraph.h \ + dmapping.h \ + bdgraph.h \ + bdgraph_bipart_st.h \ + kdgraph.h \ + kdgraph_map_rb.h \ + kdgraph_map_rb_part.h \ + kdgraph_map_st.h + +kdgraph_map_st$(OBJ) : kdgraph_map_st.c \ + module.h \ + common.h \ + parser.h \ + arch$(OBJ) \ + graph.h \ + dgraph.h \ + dgraph_coarsen.h \ + mapping.h \ + dmapping.h \ + bdgraph.h \ + bdgraph_bipart_st.h \ + kgraph.h \ + kgraph_map_st.h \ + kdgraph.h \ + kdgraph_map_rb.h \ + kdgraph_map_st.h + +kgraph$(OBJ) : kgraph.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h + +kgraph_band$(OBJ) : kgraph_band.c \ + module.h \ + common.h \ + arch$(OBJ) \ + graph.h \ + mapping.h \ + kgraph.h + +kgraph_check$(OBJ) : kgraph_check.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h + +kgraph_map_bd$(OBJ) : kgraph_map_bd.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h \ + kgraph_map_bd.h + +kgraph_map_cp$(OBJ) : kgraph_map_cp.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h \ + kgraph_map_cp.h + +kgraph_map_df$(OBJ) : kgraph_map_df.c \ + kgraph_map_df_loop.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h \ + kgraph_map_df.h + +kgraph_map_ex$(OBJ) : kgraph_map_ex.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h \ + kgraph_map_ex.h + +kgraph_map_fm$(OBJ) : kgraph_map_fm.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h \ + kgraph_map_fm.h \ + kgraph_map_rb.h + +kgraph_map_ml$(OBJ) : kgraph_map_ml.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + graph_coarsen.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h \ + kgraph_map_ml.h + +kgraph_map_rb$(OBJ) : kgraph_map_rb.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + bgraph.h \ + bgraph_bipart_st.h \ + kgraph.h \ + kgraph_map_rb.h \ + kgraph_map_rb_map.h \ + kgraph_map_rb_part.h + +kgraph_map_rb_map$(OBJ) : kgraph_map_rb_map.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + bgraph.h \ + bgraph_bipart_st.h \ + kgraph.h \ + kgraph_map_rb.h \ + kgraph_map_rb_map.h + +kgraph_map_rb_part$(OBJ) : kgraph_map_rb_part.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + bgraph.h \ + bgraph_bipart_st.h \ + kgraph.h \ + kgraph_map_rb.h \ + kgraph_map_rb_part.h + +kgraph_map_st$(OBJ) : kgraph_map_st.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + bgraph.h \ + bgraph_bipart_st.h \ + kgraph.h \ + kgraph_map_bd.h \ + kgraph_map_cp.h \ + kgraph_map_df.h \ + kgraph_map_fm.h \ + kgraph_map_ml.h \ + kgraph_map_rb.h + +kgraph_store$(OBJ) : kgraph_store.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h + +library_arch$(OBJ) : library_arch.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + arch_cmplt.h \ + scotch.h + +library_arch_f$(OBJ) : library_arch_f.c \ + module.h \ + common.h \ + scotch.h + +library_arch_build$(OBJ) : library_arch_build.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + arch_build.h \ + mapping.h \ + bgraph.h \ + bgraph_bipart_st.h \ + scotch.h + +library_arch_build_f$(OBJ) : library_arch_build_f.c \ + module.h \ + common.h \ + scotch.h + +library_common_f$(OBJ) : library_common_f.c \ + module.h \ + common.h \ + scotch.h + +library_dgraph$(OBJ) : library_dgraph.c \ + module.h \ + common.h \ + graph.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_f$(OBJ) : library_dgraph_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_band$(OBJ) : library_dgraph_band.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_band_f$(OBJ) : library_dgraph_band_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_build$(OBJ) : library_dgraph_build.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_build_f$(OBJ) : library_dgraph_build_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_build_grid3d$(OBJ): library_dgraph_build_grid3d.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_build_grid3d_f$(OBJ): library_dgraph_build_grid3d_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_check$(OBJ) : library_dgraph_check.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_check_f$(OBJ) : library_dgraph_check_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_coarsen$(OBJ) : library_dgraph_coarsen.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_coarsen.h \ + ptscotch.h + +library_dgraph_coarsen_f$(OBJ) : library_dgraph_coarsen_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_gather$(OBJ) : library_dgraph_gather.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_gather_f$(OBJ) : library_dgraph_gather_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_grow$(OBJ) : library_dgraph_grow.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_halo$(OBJ) : library_dgraph_halo.c \ + module.h \ + common.h \ + dgraph.h \ + dgraph_halo.h \ + ptscotch.h + +library_dgraph_halo_f$(OBJ) : library_dgraph_halo_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_induce$(OBJ) : library_dgraph_induce.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_induce_f$(OBJ) : library_dgraph_induce_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_io_load$(OBJ) : library_dgraph_io_load.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_io_load_f$(OBJ) : library_dgraph_io_load_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_io_save$(OBJ) : library_dgraph_io_save.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_io_save_f$(OBJ) : library_dgraph_io_save_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_map$(OBJ) : library_dgraph_map.c \ + module.h \ + common.h \ + parser.h \ + arch$(OBJ) \ + dgraph.h \ + dmapping.h \ + kdgraph.h \ + kdgraph_map_st.h \ + library_dmapping.h \ + ptscotch.h + +library_dgraph_map_f$(OBJ) : library_dgraph_map_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_map_view$(OBJ) : library_dgraph_map_view.c \ + module.h \ + common.h \ + parser.h \ + dgraph.h \ + dgraph_halo.h \ + arch$(OBJ) \ + dmapping.h \ + kdgraph.h \ + library_dmapping.h \ + ptscotch.h + +library_dgraph_map_view_f$(OBJ) : library_dgraph_map_view_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_order$(OBJ) : library_dgraph_order.c \ + module.h \ + common.h \ + parser.h \ + dgraph.h \ + dorder.h \ + hdgraph.h \ + hdgraph_order_st.h \ + ptscotch.h + +library_dgraph_order_f$(OBJ) : library_dgraph_order_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_order_gather$(OBJ): library_dgraph_order_gather.c \ + module.h \ + common.h \ + dgraph.h \ + order.h \ + dorder.h \ + library_order.h \ + ptscotch.h + +library_dgraph_order_gather_f$(OBJ): library_dgraph_order_gather_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_order_io$(OBJ) : library_dgraph_order_io.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h \ + ptscotch.h + +library_dgraph_order_io_f$(OBJ) : library_dgraph_order_io_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_order_io_block$(OBJ): library_dgraph_order_io_block.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h \ + ptscotch.h + +library_dgraph_order_io_block_f$(OBJ): library_dgraph_order_io_block_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_order_perm$(OBJ) : library_dgraph_order_perm.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h \ + ptscotch.h + +library_dgraph_order_perm_f$(OBJ): library_dgraph_order_perm_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_order_tree_dist$(OBJ): library_dgraph_order_tree_dist.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h \ + ptscotch.h + +library_dgraph_order_tree_dist_f$(OBJ): library_dgraph_order_tree_dist_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_redist$(OBJ) : library_dgraph_redist.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_redist_f$(OBJ) : library_dgraph_redist_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_scatter$(OBJ) : library_dgraph_scatter.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h + +library_dgraph_scatter_f$(OBJ) : library_dgraph_scatter_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dgraph_stat$(OBJ) : library_dgraph_stat.c \ + module.h \ + common.h \ + dgraph.h \ + ptscotch.h \ + library_dgraph_stat.h + +library_dgraph_stat_f$(OBJ) : library_dgraph_stat_f.c \ + module.h \ + common.h \ + ptscotch.h + +library_dmapping$(OBJ) : library_dmapping.c \ + module.h \ + common.h \ + ptscotch.h + +library_dorder$(OBJ) : library_dorder.c \ + module.h \ + common.h \ + ptscotch.h + +library_error$(OBJ) : library_error.c \ + module.h \ + common.h \ + scotch.h + +library_error_exit$(OBJ) : library_error_exit.c \ + module.h \ + common.h \ + scotch.h + +library_error_pt$(OBJ) : library_error.c \ + module.h \ + common.h \ + scotch.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -o $(@) + +library_error_exit_pt$(OBJ) : library_error_exit.c \ + module.h \ + common.h \ + scotch.h + $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -o $(@) + +library_geom$(OBJ) : library_geom.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + scotch.h + +library_geom_f$(OBJ) : library_geom_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph$(OBJ) : library_graph.c \ + module.h \ + common.h \ + graph.h \ + graph_io.h \ + scotch.h + +library_graph_f$(OBJ) : library_graph_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_base$(OBJ) : library_graph_base.c \ + module.h \ + common.h \ + graph.h \ + scotch.h + +library_graph_base_f$(OBJ) : library_graph_base_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_check$(OBJ) : library_graph_check.c \ + module.h \ + common.h \ + graph.h \ + scotch.h + +library_graph_check_f$(OBJ) : library_graph_check_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_coarsen$(OBJ) : library_graph_coarsen.c \ + module.h \ + common.h \ + graph.h \ + graph_coarsen.h \ + scotch.h + +library_graph_coarsen_f$(OBJ) : library_graph_coarsen_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_color$(OBJ) : library_graph_color.c \ + module.h \ + common.h \ + graph.h \ + scotch.h + +library_graph_color_f$(OBJ) : library_graph_color_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_io_chac$(OBJ) : library_graph_io_chac.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + scotch.h + +library_graph_io_chac_f$(OBJ) : library_graph_io_chac_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_io_habo$(OBJ) : library_graph_io_habo.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + scotch.h + +library_graph_io_habo_f$(OBJ) : library_graph_io_habo_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_io_mmkt$(OBJ) : library_graph_io_mmkt.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + scotch.h + +library_graph_io_mmkt_f$(OBJ) : library_graph_io_mmkt_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_io_scot$(OBJ) : library_graph_io_scot.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + scotch.h + +library_graph_io_scot_f$(OBJ) : library_graph_io_scot_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_map$(OBJ) : library_graph_map.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h \ + kgraph_map_st.h \ + library_mapping.h \ + scotch.h + +library_graph_map_f$(OBJ) : library_graph_map_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_map_io$(OBJ) : library_graph_map_io.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + library_mapping.h \ + library_graph_map_io.h \ + scotch.h + +library_graph_map_io_f$(OBJ) : library_graph_map_io_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_map_view$(OBJ) : library_graph_map_view.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + kgraph.h \ + library_mapping.h \ + library_graph_map_view.h \ + scotch.h + +library_graph_map_view_f$(OBJ) : library_graph_map_view_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_order$(OBJ) : library_graph_order.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + order.h \ + hgraph.h \ + hgraph_order_st.h \ + library_order.h \ + scotch.h + +library_graph_order_f$(OBJ) : library_graph_order_f.c \ + module.h \ + common.h \ + scotch.h + +library_graph_part_ovl$(OBJ) : library_graph_part_ovl.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + wgraph.h \ + wgraph_part_st.h \ + scotch.h + +library_graph_part_ovl_f$(OBJ) : library_graph_part_ovl_f.c \ + module.h \ + common.h \ + scotch.h + +library_mapping$(OBJ) : library_mapping.c \ + module.h \ + common.h \ + scotch.h + +library_memory$(OBJ) : library_memory.c \ + module.h \ + common.h \ + scotch.h + +library_memory_f$(OBJ) : library_memory_f.c \ + module.h \ + common.h \ + scotch.h + +library_mesh$(OBJ) : library_mesh.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + scotch.h + +library_mesh_f$(OBJ) : library_mesh_f.c \ + module.h \ + common.h \ + scotch.h + +library_mesh_graph$(OBJ) : library_mesh_graph.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + scotch.h + +library_mesh_graph_f$(OBJ) : library_mesh_graph_f.c \ + module.h \ + common.h \ + scotch.h + +library_mesh_io_habo$(OBJ) : library_mesh_io_habo.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + mesh.h \ + scotch.h + +library_mesh_io_habo_f$(OBJ) : library_mesh_io_habo_f.c \ + module.h \ + common.h \ + scotch.h + +library_mesh_io_scot$(OBJ) : library_mesh_io_scot.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + mesh.h \ + scotch.h + +library_mesh_io_scot_f$(OBJ) : library_mesh_io_scot_f.c \ + module.h \ + common.h \ + scotch.h + +library_mesh_order$(OBJ) : library_mesh_order.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + mesh.h \ + hmesh.h \ + order.h \ + hmesh_order_st.h \ + scotch.h \ + library_order.h + +library_mesh_order_f$(OBJ) : library_mesh_order_f.c \ + module.h \ + common.h \ + scotch.h + +library_order$(OBJ) : library_order.c \ + module.h \ + common.h \ + scotch.h + +library_parser$(OBJ) : library_parser.c \ + module.h \ + common.h \ + parser.h \ + scotch.h + +library_parser_f$(OBJ) : library_parser_f.c \ + module.h \ + common.h \ + scotch.h + +library_random$(OBJ) : library_random.c \ + module.h \ + common.h \ + scotch.h + +library_random_f$(OBJ) : library_random_f.c \ + module.h \ + common.h \ + scotch.h + +library_strat$(OBJ) : library_strat.c \ + module.h \ + common.h \ + scotch.h + +library_version$(OBJ) : library_version.c \ + module.h \ + common.h \ + scotch.h + +library_version_f$(OBJ) : library_version_f.c \ + module.h \ + common.h \ + scotch.h + +mapping$(OBJ) : mapping.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + mapping.h + +mapping_io$(OBJ) : mapping_io.c \ + module.h \ + common.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + mapping_io.h + +mesh$(OBJ) : mesh.c \ + module.h \ + common.h \ + graph.h \ + mesh.h + +mesh_check$(OBJ) : mesh_check.c \ + module.h \ + common.h \ + graph.h \ + mesh.h + +mesh_coarsen$(OBJ) : mesh_coarsen.c \ + module.h \ + common.h \ + graph.h \ + mesh.h + +mesh_graph$(OBJ) : mesh_graph.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + mesh_graph.h + +mesh_induce_sepa$(OBJ) : mesh_induce_sepa.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + mesh_induce_sepa.h + +mesh_io$(OBJ) : mesh_io.c \ + module.h \ + common.h \ + graph.h \ + graph_io.h \ + mesh.h \ + mesh_io.h + +mesh_io_habo$(OBJ) : mesh_io_habo.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + mesh.h + +mesh_io_scot$(OBJ) : mesh_io_scot.c \ + module.h \ + common.h \ + geom.h \ + graph.h \ + mesh.h + +order$(OBJ) : order.c \ + module.h \ + common.h \ + graph.h \ + order.h + +order_check$(OBJ) : order_check.c \ + module.h \ + common.h \ + graph.h \ + order.h + +order_io$(OBJ) : order_io.c \ + module.h \ + common.h \ + graph.h \ + order.h + +order_tree$(OBJ) : order_tree.c \ + module.h \ + common.h \ + graph.h \ + order.h + +parser$(OBJ) : parser.c \ + module.h \ + common.h \ + parser.h \ + parser_yy.h + +parser_ll.c : parser_ll.l \ + module.h \ + common.h \ + parser.h \ + parser_ll.h \ + parser_ly.h + ($(LEX) parser_ll.l && \ + $(MV) lex.yy.c parser_ll.c) || \ + $(CP) last_resort/parser_ll.c . + +parser_ll$(OBJ) : parser_ll.c \ + parser_ly.h + +parser_ly.h : parser_yy$(OBJ) + +parser_yy.c : parser_yy.y \ + module.h \ + common.h \ + parser.h \ + parser_yy.h + ($(YACC) -d -v parser_yy.y && \ + $(MV) y.tab.c parser_yy.c && \ + $(MV) y.tab.h parser_ly.h) || \ + $(CP) last_resort/parser_ly.h last_resort/parser_yy.c . + +parser_yy$(OBJ) : parser_yy.c + +vdgraph$(OBJ) : vdgraph.c \ + module.h \ + common.h \ + dgraph.h \ + vdgraph.h + +vdgraph_check$(OBJ) : vdgraph_check.c \ + module.h \ + common.h \ + dgraph.h \ + vdgraph.h + +vdgraph_gather_all$(OBJ) : vdgraph_gather_all.c \ + module.h \ + common.h \ + comm.h \ + graph.h \ + vgraph.h \ + dgraph.h \ + vdgraph.h + +vdgraph_separate_bd$(OBJ) : vdgraph_separate_bd.c \ + module.h \ + common.h \ + parser.h \ + dgraph.h \ + vdgraph.h \ + vdgraph_separate_bd.h \ + vdgraph_separate_st.h + +vdgraph_separate_df$(OBJ) : vdgraph_separate_df.c \ + module.h \ + common.h \ + dgraph.h \ + vdgraph.h \ + vdgraph_separate_df.h + +vdgraph_separate_ml$(OBJ) : vdgraph_separate_ml.c \ + module.h \ + common.h \ + parser.h \ + dgraph.h \ + dgraph_coarsen.h \ + vdgraph.h \ + vdgraph_separate_ml.h \ + vdgraph_separate_st.h + +vdgraph_separate_sq$(OBJ) : vdgraph_separate_sq.c \ + module.h \ + common.h \ + comm.h \ + parser.h \ + graph.h \ + vgraph.h \ + vgraph_separate_st.h \ + dgraph.h \ + vdgraph.h \ + vdgraph_separate_sq.h + +vdgraph_separate_st$(OBJ) : vdgraph_separate_st.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + vgraph.h \ + vgraph_separate_st.h \ + dgraph.h \ + dgraph_coarsen.h \ + vdgraph.h \ + vdgraph_separate_bd.h \ + vdgraph_separate_df.h \ + vdgraph_separate_ml.h \ + vdgraph_separate_sq.h \ + vdgraph_separate_st.h \ + vdgraph_separate_zr.h + +vdgraph_separate_zr$(OBJ) : vdgraph_separate_zr.c \ + module.h \ + common.h \ + dgraph.h \ + vdgraph.h \ + vdgraph_separate_zr.h + +vdgraph_store$(OBJ) : vdgraph_store.c \ + module.h \ + common.h \ + dgraph.h \ + vdgraph.h + +vgraph$(OBJ) : vgraph.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h + +vgraph_check$(OBJ) : vgraph_check.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h + +vgraph_separate_bd$(OBJ) : vgraph_separate_bd.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + vgraph.h \ + vgraph_separate_bd.h \ + vgraph_separate_st.h + +vgraph_separate_df$(OBJ) : vgraph_separate_df.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h \ + vgraph_separate_df.h + +vgraph_separate_es$(OBJ) : vgraph_separate_es.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + bgraph.h \ + bgraph_bipart_st.h \ + vgraph.h \ + vgraph_separate_es.h + +vgraph_separate_fm$(OBJ) : vgraph_separate_fm.c \ + module.h \ + common.h \ + gain.h \ + graph.h \ + vgraph.h \ + vgraph_separate_gg.h \ + vgraph_separate_fm.h + +vgraph_separate_gg$(OBJ) : vgraph_separate_gg.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h \ + vgraph_separate_gg.h + +vgraph_separate_gp$(OBJ) : vgraph_separate_gp.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h \ + vgraph_separate_gp.h + +vgraph_separate_ml$(OBJ) : vgraph_separate_ml.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + graph_coarsen.h \ + vgraph.h \ + vgraph_separate_ml.h \ + vgraph_separate_st.h + +vgraph_separate_th$(OBJ) : vgraph_separate_th.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h \ + vgraph_separate_th.h + +vgraph_separate_vw$(OBJ) : vgraph_separate_vw.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h \ + vgraph_separate_vw.h + +vgraph_separate_zr$(OBJ) : vgraph_separate_zr.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h \ + vgraph_separate_zr.h + +vgraph_separate_st$(OBJ) : vgraph_separate_st.c \ + gain.h \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch$(OBJ) \ + mapping.h \ + bgraph.h \ + bgraph_bipart_st.h \ + vgraph.h \ + vgraph_separate_bd.h \ + vgraph_separate_df.h \ + vgraph_separate_fm.h \ + vgraph_separate_gg.h \ + vgraph_separate_gp.h \ + vgraph_separate_ml.h \ + vgraph_separate_th.h \ + vgraph_separate_vw.h \ + vgraph_separate_zr.h \ + vgraph_separate_st.h + +vgraph_store$(OBJ) : vgraph_store.c \ + module.h \ + common.h \ + graph.h \ + vgraph.h + +vmesh$(OBJ) : vmesh.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + vmesh.h + +vmesh_check$(OBJ) : vmesh_check.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + vmesh.h + +vmesh_separate_fm$(OBJ) : vmesh_separate_fm.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + vmesh.h \ + vmesh_separate_fm.h + +vmesh_separate_gg$(OBJ) : vmesh_separate_gg.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + vmesh.h \ + vmesh_separate_gg.h + +vmesh_separate_gr$(OBJ) : vmesh_separate_gr.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + vgraph.h \ + vgraph_separate_st.h \ + mesh.h \ + vmesh.h \ + vmesh_separate_gr.h + +vmesh_separate_ml$(OBJ) : vmesh_separate_ml.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + mesh.h \ + mesh_coarsen.h \ + vmesh.h \ + vmesh_separate_ml.h \ + vmesh_separate_st.h + +vmesh_separate_zr$(OBJ) : vmesh_separate_zr.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + vmesh.h \ + vmesh_separate_zr.h + +vmesh_separate_st$(OBJ) : vmesh_separate_st.c \ + gain.h \ + module.h \ + common.h \ + parser.h \ + graph.h \ + mesh.h \ + mesh_coarsen.h \ + vmesh.h \ + vmesh_separate_fm.h \ + vmesh_separate_gg.h \ + vmesh_separate_gr.h \ + vmesh_separate_ml.h \ + vmesh_separate_zr.h \ + vmesh_separate_st.h + +vmesh_store$(OBJ) : vmesh_store.c \ + module.h \ + common.h \ + graph.h \ + mesh.h \ + vmesh.h + +wgraph$(OBJ) : wgraph.c \ + module.h \ + common.h \ + graph.h \ + wgraph.h + +wgraph_check$(OBJ) : wgraph_check.c \ + module.h \ + common.h \ + graph.h \ + wgraph.h + +wgraph_part_fm$(OBJ) : wgraph_part_fm.c \ + module.h \ + common.h \ + graph.h \ + wgraph.h \ + wgraph_part_fm.h + +wgraph_part_gg$(OBJ) : wgraph_part_gg.c \ + module.h \ + common.h \ + graph.h \ + wgraph.h \ + wgraph_part_gg.h + +wgraph_part_gp$(OBJ) : wgraph_part_gp.c \ + module.h \ + common.h \ + graph.h \ + wgraph.h \ + wgraph_part_gp.h + +wgraph_part_ml$(OBJ) : wgraph_part_ml.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + graph_coarsen.h \ + wgraph.h \ + wgraph_part_ml.h \ + wgraph_part_st.h + +wgraph_part_rb$(OBJ) : wgraph_part_rb.c \ + module.h \ + common.h \ + parser.h \ + graph.h \ + arch.h \ + mapping.h \ + vgraph.h \ + vgraph_separate_st.h \ + vgraph_separate_zr.h \ + wgraph.h \ + wgraph_part_rb.h \ + scotch.h + +wgraph_part_st$(OBJ) : wgraph_part_st.c \ + gain.h \ + module.h \ + common.h \ + parser.h \ + graph.h \ + graph_coarsen.h \ + vgraph.h \ + vgraph_separate_st.h \ + wgraph.h \ + wgraph_part_fm.h \ + wgraph_part_gg.h \ + wgraph_part_gp.h \ + wgraph_part_ml.h \ + wgraph_part_rb.h \ + wgraph_part_zr.h \ + wgraph_part_st.h + +wgraph_part_zr$(OBJ) : wgraph_part_zr.c \ + module.h \ + common.h \ + graph.h \ + wgraph.h \ + wgraph_part_zr.h + +wgraph_store$(OBJ) : wgraph_store.c \ + module.h \ + common.h \ + graph.h \ + wgraph.h + +dummysizes$(EXE) : dummysizes.c \ + module.h \ + common.h \ + arch$(OBJ) \ + graph.h \ + geom.h \ + mesh.h \ + mapping.h \ + order.h \ + parser.h + $(CCD) $(CFLAGS) -DSCOTCH_VERSION=$(VERSION) -DSCOTCH_RELEASE=$(RELEASE) -DSCOTCH_PATCHLEVEL=$(PATCHLEVEL) $(<) -o $(@) $(LDFLAGS) + +ptdummysizes$(EXE) : dummysizes.c \ + module.h \ + common.h \ + dgraph.h \ + dorder.h + $(CCD) $(CFLAGS) -DSCOTCH_VERSION=$(VERSION) -DSCOTCH_RELEASE=$(RELEASE) -DSCOTCH_PATCHLEVEL=$(PATCHLEVEL) $(<) -o $(@) $(LDFLAGS) + +scotch.h : dummysizes$(EXE) \ + library.h + ./dummysizes$(EXE) library.h scotch.h + +scotchf.h : dummysizes$(EXE) \ + library_f.h + ./dummysizes$(EXE) library_f.h scotchf.h + +ptscotch.h : ptdummysizes$(EXE) \ + library_pt.h + ./ptdummysizes$(EXE) library_pt.h ptscotch.h + +ptscotchf.h : ptdummysizes$(EXE) \ + library_pt_f.h + ./ptdummysizes$(EXE) library_pt_f.h ptscotchf.h + +libscotch$(LIB) : $(LIBSCOTCHDEPS) + $(AR) $(ARFLAGS) $(@) $(?) + -$(RANLIB) $(@) + +libscotcherr$(LIB) : library_error$(OBJ) + $(AR) $(ARFLAGS) $(@) $(?) + -$(RANLIB) $(@) + +libscotcherrexit$(LIB) : library_error_exit$(OBJ) + $(AR) $(ARFLAGS) $(@) $(?) + -$(RANLIB) $(@) + +libptscotch$(LIB) : $(LIBPTSCOTCHDEPS) + $(AR) $(ARFLAGS) $(@) $(?) + -$(RANLIB) $(@) + +libptscotcherr$(LIB) : library_error_pt$(OBJ) + $(AR) $(ARFLAGS) $(@) $(?) + -$(RANLIB) $(@) + +libptscotcherrexit$(LIB) : library_error_exit_pt$(OBJ) + $(AR) $(ARFLAGS) $(@) $(?) + -$(RANLIB) $(@) diff --git a/scotch_6.0.3/src/libscotch/arch.c b/scotch_6.0.3/src/libscotch/arch.c new file mode 100644 index 00000000..a904b209 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch.c @@ -0,0 +1,514 @@ +/* Copyright 2004,2007-2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the generic target **/ +/** architecture functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 23 dec 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 29 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 16 aug 1995 **/ +/** # Version 3.1 : from : 02 may 1996 **/ +/** to 17 jul 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 28 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 08 nov 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 04 nov 2003 **/ +/** to 09 jan 2004 **/ +/** # Version 5.1 : from : 11 dec 2007 **/ +/** to 25 jun 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 26 nov 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_cmplt.h" +#include "arch_cmpltw.h" +#include "arch_deco.h" +#include "arch_dist.h" +#include "arch_hcub.h" +#include "arch_mesh.h" +#include "arch_tleaf.h" +#include "arch_torus.h" +#include "arch_vcmplt.h" +#include "arch_vhcub.h" + +/* +** The static definitions. +*/ + +static const ArchClass archClassTab[] = { ARCHCLASSBLOCK ("cmplt", Cmplt, ARCHPART), + ARCHCLASSBLOCK ("cmpltw", Cmpltw, ARCHPART), + ARCHCLASSBLOCK ("deco", Deco, ARCHNONE), + ARCHCLASSBLOCK ("dist", Dist, ARCHNONE), + ARCHCLASSBLOCK ("hcub", Hcub, ARCHNONE), + ARCHCLASSBLOCK ("tleaf", Tleaf, ARCHNONE), + ARCHCLASSBLOCK ("ltleaf", Ltleaf, ARCHNONE), + ARCHCLASSBLOCK ("mesh2D", Mesh2, ARCHNONE), +#ifdef SCOTCH_DEBUG_ARCH3 + ARCHCLASSBLOCK ("mesh2O", Mesh2o, ARCHNONE), + ARCHCLASSBLOCK ("mesh2U", Mesh2u, ARCHNONE), +#endif /* SCOTCH_DEBUG_ARCH3 */ + ARCHCLASSBLOCK ("mesh3D", Mesh3, ARCHNONE), + ARCHCLASSBLOCK ("torus2D", Torus2, ARCHNONE), + ARCHCLASSBLOCK ("torus3D", Torus3, ARCHNONE), + ARCHCLASSBLOCK ("torusXD", TorusX, ARCHNONE), + ARCHCLASSBLOCK ("varcmplt", Vcmplt, ARCHPART | ARCHVAR), + ARCHCLASSBLOCK ("varhcub", Vhcub, ARCHVAR), + ARCHCLASSBLOCKNULL }; + +/**************************************/ +/* */ +/* These are the entry points for the */ +/* generic architecture routines. */ +/* */ +/**************************************/ + +/* This routine initializes an architecture structure. +** It zeroes the architecture body so that architecture +** specific routines can check if their pointers have +** been initialized or not. +** It returns: +** - !NULL : pointer to the target architecture. +** - NULL : on error. +*/ + +int +archInit ( +Arch * restrict const archptr) +{ + memSet (archptr, 0, sizeof (Arch)); /* Initialize architecture body (arch->class = NULL) */ + + return (0); +} + +/* This routine deletes an architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archExit ( +Arch * restrict const archptr) +{ + return (archFree (archptr)); /* Free architecture data */ +} + +/* This routine frees the architecture data. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archFree ( +Arch * restrict const archptr) +{ + int o; + + o = 0; /* Assume everything will be all right */ + if ((archptr->class != NULL) && + (archptr->class->archFree != NULL)) /* If there is a specific freeing routing */ + o = archptr->class->archFree (&archptr->data); /* Call it */ + memSet (archptr, 0, sizeof (Arch)); /* Initialize the architecture body (arch->class = NULL) */ + + return (o); +} + +/* This routine loads an architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archLoad ( +Arch * restrict const archptr, +FILE * const stream) +{ + const ArchClass * restrict class; /* Pointer to architecture class */ + char name[256]; /* Architecture name string */ + + if (fscanf (stream, "%255s", name) != 1) { /* Read architecture name */ + errorPrint ("archLoad: cannot load architecture type"); + return (1); + } + name[255] = '\0'; /* Set end of string */ + + if ((class = archClass (name)) == NULL) { /* Get class from its name */ + errorPrint ("archLoad: invalid architecture type"); + return (1); + } + + if (class->archLoad != NULL) { /* If class has loading function */ + if (class->archLoad (&archptr->data, stream) != 0) { /* Load class data */ + errorPrint ("archLoad: cannot load architecture data"); + class->archFree (&archptr->data); /* Perform clean-up */ + memSet (archptr, 0, sizeof (Arch)); /* Initialize architecture body */ + return (1); + } + } + archptr->class = class; /* Set architecture class */ + archptr->flagval = archptr->class->flagval; /* Copy architecture flag */ + + return (0); +} + +/* This routine saves an architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archSave ( +const Arch * restrict const archptr, +FILE * restrict const stream) +{ + int o; + + if (archptr->class == NULL) /* If no architecture type defined */ + return (0); /* Nothing to do */ + + o = (fprintf (stream, "%s\n", /* Write architecture class */ + archptr->class->archname) == EOF); + if (archptr->class->archSave != NULL) /* If class has saving function */ + o |= archptr->class->archSave (&archptr->data, stream); /* Write architecture data */ + o |= (fprintf (stream, "\n") == EOF); + if (o != 0) + errorPrint ("archSave: bad output"); + + return (o); +} + +/* This routine returns the pointer to +** the class of a given architecture +** name. +** It returns: +** - !NULL : class pointer. +** - NULL : on error. +*/ + +const ArchClass * +archClass ( +const char * const name) +{ + const ArchClass * restrict class; /* Pointer to architecture class */ + + for (class = archClassTab; /* For all classes */ + (class->archname != NULL) && /* Search if class names match */ + (strcasecmp (name, class->archname) != 0); + class ++) ; + + return ((class->archname != NULL) ? class : NULL); +} + +/**************************************/ +/* */ +/* These are the entry points for the */ +/* generic domain routines. They are */ +/* used only in debugging mode, to */ +/* provide breakpoints for routines */ +/* which are else implemented as */ +/* macros for the sake of efficiency. */ +/* */ +/**************************************/ + +/* This function returns the smallest number +** of terminal domain included within the +** given domain. +*/ + +#ifdef SCOTCH_DEBUG_ARCH2 + +ArchDomNum +archDomNum ( +const Arch * const archptr, +const ArchDom * const domptr) +{ + return (archDomNum2 (archptr, domptr)); /* Call proper routine */ +} + +#endif /* SCOTCH_DEBUG_ARCH2 */ + +/* This function computes the terminal domain +** associated with the given terminal number. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +#ifdef SCOTCH_DEBUG_ARCH2 + +int +archDomTerm ( +const Arch * const archptr, +ArchDom * restrict const domptr, +const ArchDomNum domnum) +{ + return (archDomTerm2 (archptr, domptr, domnum)); /* Call proper routine */ +} + +#endif /* SCOTCH_DEBUG_ARCH2 */ + +/* This function returns the number +** of elements in the given domain. +** It returns: +** - >0 : size of the domain. +** - 0 : on error. +*/ + +#ifdef SCOTCH_DEBUG_ARCH2 + +Anum +archDomSize ( +const Arch * const archptr, +const ArchDom * const domptr) +{ + return (archDomSize2 (archptr, domptr)); /* Call proper routine */ +} + +#endif /* SCOTCH_DEBUG_ARCH2 */ + +/* This function returns the weight +** of the given domain. +** It returns: +** - >0 : weight of the domain. +** - 0 : on error. +*/ + +#ifdef SCOTCH_DEBUG_ARCH2 + +Anum +archDomWght ( +const Arch * const archptr, +const ArchDom * const domptr) +{ + return (archDomWght2 (archptr, domptr)); /* Call proper routine */ +} + +#endif /* SCOTCH_DEBUG_ARCH2 */ + +/* This function gives the average +** distance between two domains. +** It returns: +** - !-1 : distance between subdomains. +** - -1 : on error. +*/ + +#ifdef SCOTCH_DEBUG_ARCH2 + +Anum +archDomDist ( +const Arch * const archptr, +const ArchDom * const dom0ptr, +const ArchDom * const dom1ptr) +{ + return (archDomDist2 (archptr, dom0ptr, dom1ptr)); /* Call proper routine */ +} + +#endif /* SCOTCH_DEBUG_ARCH2 */ + +/* This function sets the biggest +** available domain for the given +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +#ifdef SCOTCH_DEBUG_ARCH2 + +int +archDomFrst ( +const Arch * const archptr, +ArchDom * const domptr) +{ + return (archDomFrst2 (archptr, domptr)); /* Call proper routine */ +} + +#endif /* SCOTCH_DEBUG_ARCH2 */ + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archDomLoad ( +const Arch * const archptr, +ArchDom * const domptr, +FILE * const stream) +{ + return (archptr->class->domLoad (&archptr->data, /* Call proper routine */ + &domptr->data, + stream)); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archDomSave ( +const Arch * const archptr, +const ArchDom * const domptr, +FILE * const stream) +{ + return (archptr->class->domSave (&archptr->data, /* Call proper routine */ + &domptr->data, + stream)); +} + +/* This function tries to split a domain into +** two subdomains. The two subdomains are created +** so that subdomain 0 has same T_domNum as +** original domain. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +#ifdef SCOTCH_DEBUG_ARCH2 + +int +archDomBipart ( +const Arch * const archptr, +const ArchDom * const domptr, +ArchDom * const dom0ptr, +ArchDom * const dom1ptr) +{ + int o; + + o = archDomBipart2 (archptr, domptr, dom0ptr, dom1ptr); /* Call proper routine */ + + if ((o == 0) && /* Check domain number consistency for fixed-sized architectures */ + (strncmp (archName (archptr), "var", 3) != 0) && + (archDomNum (archptr, dom0ptr) != archDomNum (archptr, domptr))) { + errorPrint ("archDomBipart: domain number mismatch"); + return (2); + } + + return (o); +} + +#endif /* SCOTCH_DEBUG_ARCH2 */ + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +#ifdef SCOTCH_DEBUG_ARCH2 + +int +archDomIncl ( +const Arch * const archptr, +const ArchDom * const dom0ptr, +const ArchDom * const dom1ptr) +{ + return archDomIncl2 (archptr, dom0ptr, dom1ptr); +} + +#endif /* SCOTCH_DEBUG_ARCH2 */ + +/* This function creates the MPI_Datatype for +** complete graph domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH + +int +archDomMpiType ( +const Arch * const archptr, +MPI_Datatype * const typeptr) +{ + int bloktab[2]; + MPI_Aint disptab[2]; + MPI_Datatype typetab[2]; + int o; + + bloktab[0] = /* Build structured type to set up upper bound of domain datatype */ + bloktab[1] = 1; + disptab[0] = 0; /* Displacement of real datatype is base of array */ + disptab[1] = sizeof (ArchDom); /* Displacement of upper bound is size of ArchDom */ + typetab[1] = MPI_UB; + o = ((int (*) (const void * const, const void * const)) archptr->class->domMpiType) ((const void * const) &archptr->data, &typetab[0]); + if (o == 0) + o = (MPI_Type_struct (2, bloktab, disptab, typetab, typeptr) != MPI_SUCCESS); + if (o == 0) + o = (MPI_Type_commit (typeptr) != MPI_SUCCESS); /* Created MPI types have to be committed */ + + return (o); +} + +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch.h b/scotch_6.0.3/src/libscotch/arch.h new file mode 100644 index 00000000..cf54c599 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch.h @@ -0,0 +1,284 @@ +/* Copyright 2004,2007-2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the generic target architecture **/ +/** functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 08 sep 1995 **/ +/** # Version 3.1 : from : 02 may 1996 **/ +/** to 20 jul 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 13 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 07 oct 1998 **/ +/** # Version 3.4 : from : 08 nov 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 01 jan 2002 **/ +/** to 07 dec 2004 **/ +/** # Version 5.1 : from : 11 dec 2007 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 01 aug 2014 **/ +/** **/ +/************************************************************/ + +#define ARCH_H + +/* +** The defines. +*/ + +/*+ Architecture flags. +*/ + +#define ARCHNONE 0x0000 /*+ No options set +*/ +#define ARCHPART 0x0001 /*+ Architecture without external gains +*/ +#define ARCHVAR 0x0002 /*+ Variable-sized architecture +*/ + +/* +** The type and structure definitions. +*/ + +typedef INT Anum; /*+ Generic integer +*/ + +#define ANUMMAX INTVALMAX +#define ANUMSTRING INTSTRING +#define ANUM_MPI COMM_INT /*+ MPI type for Gnum is MPI type for INT +*/ + +/*+ The domain number type. +*/ + +typedef Anum ArchDomNum; /*+ Domain number +*/ + +#define ARCHDOMNOTTERM ((ArchDomNum) ~0) /*+ Not-terminal number +*/ + +/*+ The sub-includes for structure size computations. +*/ + +#define ARCH_NOPROTO +#include "arch_cmplt.h" +#include "arch_cmpltw.h" +#include "arch_deco.h" +#include "arch_dist.h" +#include "arch_hcub.h" +#include "arch_tleaf.h" +#include "arch_mesh.h" +#include "arch_torus.h" +#include "arch_vcmplt.h" +#include "arch_vhcub.h" +#undef ARCH_NOPROTO + +/*+ The architecture class type. +*/ + +typedef struct ArchClass_ { + char * archname; /*+ Architecture name +*/ + int flagval; /*+ Architecture flags of the class +*/ + int (* archLoad) (); /*+ Architecture loading function +*/ + int (* archSave) (); /*+ Architecture saving function +*/ + int (* archFree) (); /*+ Architecture freeing function +*/ + ArchDomNum (* domNum) (); /*+ Domain labeling function +*/ + int (* domTerm) (); /*+ Terminal domain building function +*/ + Anum (* domSize) (); /*+ Domain size function +*/ + Anum (* domWght) (); /*+ Domain weight function +*/ + Anum (* domDist) (); /*+ Distance computation function +*/ + int (* domFrst) (); /*+ Compute biggest domain +*/ + int (* domLoad) (); /*+ Domain loading routine +*/ + int (* domSave) (); /*+ Domain saving routine +*/ + int (* domBipart) (); /*+ Domain bipartitioning routine +*/ + int (* domIncl) (); /*+ Domain inclusion routine +*/ +#ifdef SCOTCH_PTSCOTCH + int (* domMpiType) (); /*+ Domain MPI type building routine +*/ +#endif /* SCOTCH_PTSCOTCH */ + int domsizeof; /*+ Size in bytes of domain data +*/ +} ArchClass; + +/*+ The architecture union type. +*/ + +typedef union { /*+ Architecture data +*/ + ArchCmplt cmplt; /*+ Complete graph architecture +*/ + ArchCmpltw cmpltw; /*+ Weighted complete graph architecture +*/ + ArchDeco deco; /*+ Decomposition-described architecture +*/ + ArchDist dist; /*+ Distance multiplicator pseudo-architecture +*/ + ArchHcub hcub; /*+ Hypercube architecture +*/ + ArchMesh2 mesh2; /*+ 2D-mesh architecture +*/ + ArchMesh3 mesh3; /*+ 3D-mesh architecture +*/ + ArchTleaf tleaf; /*+ Tree-leaf architecture +*/ + ArchTorusX torusx; /*+ xD-torus architecture (includes 2D and 3D) +*/ + ArchVcmplt vcmplt; /*+ Variable-sized complete graph architecture +*/ + ArchVhcub vhcub; /*+ Variable-sized hypercube architecture +*/ +} ArchDummy; + +/*+ The architecture type. +*/ + +typedef struct Arch_ { + const ArchClass * class; /*+ Pointer to architecture class +*/ + int flagval; /*+ (Possibly updated) architecture flags +*/ + ArchDummy data; /*+ Architecture data +*/ +} Arch; + +/*+ The architecture domain union type. +*/ + +typedef union { /*+ The domain data +*/ + ArchCmpltDom cmplt; /*+ Complete graph domain type +*/ + ArchCmpltwDom cmpltw; /*+ Weighted complete graph domain type +*/ + ArchDecoDom deco; /*+ Decomposition-descripted domain type +*/ +/*+ ArchDistDom dist; *+ Distance multiplicator domain is ArchDom +*/ + ArchHcubDom hcub; /*+ Hypercube domain type +*/ + ArchMesh2Dom mesh2; /*+ 2D-mesh domain type +*/ + ArchMesh3Dom mesh3; /*+ 3D-mesh domain type +*/ + ArchTleafDom tleaf; /*+ Tree-leaf domain type +*/ + ArchTorusXDom torusx; /*+ xD-torus domain type (includes 2D and 3D) +*/ + ArchVcmpltDom vcmplt; /*+ Variable-sized complete graph domain type +*/ + ArchVhcubDom vhcub; /*+ Variable-sized hypercube domain type +*/ +} ArchDomDummy; + +/*+ The domain structure type. +*/ + +typedef struct ArchDom_ { + ArchDomDummy data; /*+ The domain data +*/ +} ArchDom; + +/* +** The function prototypes. +*/ + +#ifndef ARCH +#define static +#endif + +int archInit (Arch * restrict const); +int archExit (Arch * restrict const); +int archFree (Arch * restrict const); +int archLoad (Arch * restrict const, FILE * const); +int archSave (const Arch * const, FILE * const); +char * archName (const Arch * const); +const ArchClass * archClass (const char * const); + +ArchDomNum archDomNum (const Arch * const, const ArchDom * const); +int archDomTerm (const Arch * const, ArchDom * const, const ArchDomNum); +Anum archDomSize (const Arch * const, const ArchDom * const); +Anum archDomWght (const Arch * const, const ArchDom * const); +Anum archDomDist (const Arch * const, const ArchDom * const, const ArchDom * const); +int archDomFrst (const Arch * const, ArchDom * const); +int archDomLoad (const Arch * const, ArchDom * const, FILE * const); +int archDomSave (const Arch * const, const ArchDom * const, FILE * const); +int archDomBipart (const Arch * const, const ArchDom * const, ArchDom * const, ArchDom * const); +int archDomIncl (const Arch * const, const ArchDom * const, const ArchDom * const); +#ifdef SCOTCH_PTSCOTCH +int archDomMpiType (const Arch * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +/* +** The macro definitions. +*/ + +#define archDomSizeof(a) ((a)->class->domsizeof) +#define archName(a) (((a)->class == NULL) ? "" : (a)->class->archname) +#define archPart(a) ((((a)->flagval) & ARCHPART) != 0) +#define archVar(a) ((((a)->flagval) & ARCHVAR) != 0) + +#if ((! defined SCOTCH_DEBUG_ARCH2) || (defined ARCH)) +#define archDomNum2(arch,dom) (((ArchDomNum (*) (const void * const, const void * const)) (arch)->class->domNum) ((const void * const) &(arch)->data, (const void * const) &(dom)->data)) +#define archDomTerm2(arch,dom,num) (((int (*) (const void * const, void * const, const ArchDomNum)) (arch)->class->domTerm) ((void *) &(arch)->data, (void *) &(dom)->data, (num))) +#define archDomSize2(arch,dom) (((Anum (*) (const void * const, const void * const)) (arch)->class->domSize) ((void *) &(arch)->data, (void *) &(dom)->data)) +#define archDomWght2(arch,dom) (((Anum (*) (const void * const, const void * const)) (arch)->class->domWght) ((void *) &(arch)->data, (void *) &(dom)->data)) +#define archDomDist2(arch,dom0,dom1) (((Anum (*) (const void * const, const void * const, const void * const)) (arch)->class->domDist) ((const void *) &(arch)->data, (const void *) &(dom0)->data, (const void *) &(dom1)->data)) +#define archDomFrst2(arch,dom) (((int (*) (const void * const, void * const)) (arch)->class->domFrst) ((const void * const) &(arch)->data, (void * const) &(dom)->data)) +#define archDomBipart2(arch,dom,dom0,dom1) (((int (*) (const void * const, const void * const, void * const, void * const)) (arch)->class->domBipart) ((const void * const) &(arch)->data, (const void * const) &(dom)->data, (void * const) &(dom0)->data, (void * const) &(dom1)->data)) +#define archDomIncl2(arch,dom0,dom1) (((int (*) (const void * const, const void * const, void * const)) (arch)->class->domIncl) ((const void * const) &(arch)->data, (void * const) &(dom0)->data, (void * const) &(dom1)->data)) +#endif +#ifndef SCOTCH_DEBUG_ARCH2 +#define archDomNum archDomNum2 +#define archDomTerm archDomTerm2 +#define archDomSize archDomSize2 +#define archDomWght archDomWght2 +#define archDomDist archDomDist2 +#define archDomFrst archDomFrst2 +#define archDomBipart archDomBipart2 +#define archDomIncl archDomIncl2 +#endif /* SCOTCH_DEBUG_ARCH2 */ + +#ifdef SCOTCH_PTSCOTCH +#define ARCHCLASSBLOCK(s,n,f) { s, f, \ + arch##n##ArchLoad, \ + arch##n##ArchSave, \ + arch##n##ArchFree, \ + arch##n##DomNum, \ + arch##n##DomTerm, \ + arch##n##DomSize, \ + arch##n##DomWght, \ + arch##n##DomDist, \ + arch##n##DomFrst, \ + arch##n##DomLoad, \ + arch##n##DomSave, \ + arch##n##DomBipart, \ + arch##n##DomIncl, \ + arch##n##DomMpiType, \ + sizeof (Arch##n##Dom) } +#else /* SCOTCH_PTSCOTCH */ +#define ARCHCLASSBLOCK(s,n,f) { s, f, \ + arch##n##ArchLoad, \ + arch##n##ArchSave, \ + arch##n##ArchFree, \ + arch##n##DomNum, \ + arch##n##DomTerm, \ + arch##n##DomSize, \ + arch##n##DomWght, \ + arch##n##DomDist, \ + arch##n##DomFrst, \ + arch##n##DomLoad, \ + arch##n##DomSave, \ + arch##n##DomBipart, \ + arch##n##DomIncl, \ + sizeof (Arch##n##Dom) } +#endif /* SCOTCH_PTSCOTCH */ + +#define ARCHCLASSBLOCKNULL { NULL, ARCHNONE } + +#define ARCH_H_END diff --git a/scotch_6.0.3/src/libscotch/arch_build.c b/scotch_6.0.3/src/libscotch/arch_build.c new file mode 100644 index 00000000..341db2a3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_build.c @@ -0,0 +1,424 @@ +/* Copyright 2004,2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_build.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module builds a decomposition- **/ +/** based architecture from a source graph. **/ +/** **/ +/** DATES : # Version 3.2 : from : 29 may 1997 **/ +/** to 30 aug 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 30 oct 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 29 nov 2003 **/ +/** to 10 mar 2005 **/ +/** # Version 5.0 : from : 10 sep 2007 **/ +/** to 03 apr 2008 **/ +/** # Version 5.1 : from : 28 sep 2008 **/ +/** to 28 jun 2011 **/ +/** # Version 6.0 : from : 28 jun 2011 **/ +/** to 05 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_BUILD + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "arch_deco.h" +#include "arch_vcmplt.h" +#include "mapping.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "arch_build.h" + +/************************************/ +/* */ +/* These routines handle job pools. */ +/* */ +/************************************/ + +/* This routine frees the contents of +** the given job pool. +** It returns: +** - VOID : in all cases. +*/ + +static +void +archBuildJobExit ( +ArchBuildJob * const jobtab) +{ + ArchBuildJob * jobptr; + + jobptr = jobtab; + do { + graphExit (&jobptr->grafdat); + jobptr = jobptr->joblink; + } while (jobptr != NULL); +} + +/********************************************/ +/* */ +/* The main routine, which computes the */ +/* decomposition-based target architecture. */ +/* */ +/********************************************/ + +/* +** This routine builds a target architecture from +** the given source graph and the optional vertex +** list. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archBuild ( +Arch * restrict const tgtarchptr, /*+ Decomposition architecture to build +*/ +const Graph * const tgtgrafptr, /*+ Source graph modeling the architecture +*/ +const VertList * const tgtlistptr, /*+ Subset of source graph vertices +*/ +const Strat * const mapstrat) /*+ Bipartitioning strategy +*/ +{ + Gnum * restrict mapparttax; /* Based access to mapping part array */ + Arch archdat; /* Variable-sized architecture for bipartitioning */ + ArchDom domsub0; /* Temporary space for subdomain 0 */ + Gnum termdomnbr; /* Number of terminal domains */ + Gnum termdommax; /* Maximum terminal number */ + ArchDecoTermVert * restrict termverttab; /* Terminal vertex table */ + Anum * restrict termdisttab; /* Vertex distance table */ + ArchBuildDistElem * restrict disttax; /* Distance table */ + ArchBuildQueuElem * restrict queutab; /* Distance queue table */ + Gnum queuhead; /* Head-of-queue index */ + Gnum queutail; /* Tail-of-queue index */ + Mapping mappdat; /* Partial and final mapping data */ + ArchBuildJob * restrict jobtab; /* Job array */ + ArchBuildJob * joblink; /* Linked list of jobs to process */ + ArchBuildJob * joborgptr; /* Pointer to original job and first subjob */ + ArchBuildJob * jobsubptr; /* Pointer to second subjob */ + Bgraph actgrafdat; /* Active graph for bipartitioning */ + Gnum invedlosiz; /* Size of inversed edge load array */ + Gnum * restrict invedlotax; /* Inversed edge load array for cutting */ + Gnum * restrict actfrontab; /* Frontier array for all bipartitionings */ + GraphPart * restrict actparttax; /* Part array for all bipartitionings */ + GraphPart actpartval; /* Part value to put to subjob */ + Gnum actpartnbr; /* Size of part value to put to subjob */ + Gnum termdomnum; + + const Gnum * restrict const tgtverttax = tgtgrafptr->verttax; + const Gnum * restrict const tgtvendtax = tgtgrafptr->vendtax; + const Gnum * restrict const tgtedgetax = tgtgrafptr->edgetax; + const Gnum * restrict const tgtedlotax = tgtgrafptr->edlotax; + + archInit (tgtarchptr); /* Initialize architecture body */ + tgtarchptr->class = archClass ("deco"); /* Set architecture class */ + + termdomnbr = (tgtlistptr != NULL) ? tgtlistptr->vnumnbr : tgtgrafptr->vertnbr; + if (termdomnbr == 0) /* If nothing to do */ + return (0); + + intRandInit (); /* Initialize random generator */ + + invedlosiz = (tgtedlotax != NULL) ? tgtgrafptr->edgenbr : 0; + if ((memAllocGroup ((void **) (void *) + &jobtab, (size_t) (termdomnbr * sizeof (ArchBuildJob)), + &actfrontab, (size_t) (termdomnbr * sizeof (Gnum)), + &actparttax, (size_t) (termdomnbr * sizeof (GraphPart)), + &invedlotax, (size_t) (invedlosiz * sizeof (Gnum)), NULL) == NULL) || + ((mappdat.parttax = memAlloc (tgtgrafptr->vertnbr * sizeof (ArchDomNum))) == NULL) || /* Final mapping array is for all graph vertices */ + ((mappdat.domntab = memAlloc (termdomnbr * sizeof (ArchDom))) == NULL)) { + errorPrint ("archBuild: out of memory (1)"); + if (jobtab != NULL) { + memFree (jobtab); + if (mappdat.parttax != NULL) + memFree (mappdat.parttax); + } + return (1); + } + memSet (mappdat.parttax, 0, termdomnbr * sizeof (ArchDomNum)); + actparttax -= tgtgrafptr->baseval; + mappdat.flagval = MAPPINGFREEPART | MAPPINGFREEDOMN; + mappdat.grafptr = tgtgrafptr; + mappdat.archptr = &archdat; + mappdat.parttax -= tgtgrafptr->baseval; + mappdat.domnmax = termdomnbr; + + archInit (&archdat); /* Initialize terminal architecture */ + archdat.class = archClass ("varcmplt"); /* Set architecture class */ + archDomFrst (&archdat, &mappdat.domntab[0]); /* Get initial domain */ + mappdat.domnnbr = 1; + + jobtab[0].domnum = 0; /* All vertices mapped to first domain */ + if ((tgtlistptr != NULL) && (tgtlistptr->vnumtab != NULL)) /* If vertex list given */ + graphInduceList (tgtgrafptr, tgtlistptr, &jobtab[0].grafdat); /* Restrict initial job */ + else { /* If no vertex list given */ + memCpy (&jobtab[0].grafdat, tgtgrafptr, sizeof (Graph)); /* Job takes whole graph */ + jobtab[0].grafdat.flagval &= ~GRAPHFREETABS; /* Graph is a clone */ + jobtab[0].grafdat.vnumtax = NULL; /* Assume we have no vertex index array */ + } + + if (tgtedlotax != NULL) { /* If architecture graph has edge loads */ + Gnum vertnum; + Gnum vertnnd; + Gnum edlomin; + Gnum edlomax; + float prodval; + + const Gnum * restrict const indverttax = jobtab[0].grafdat.verttax; + const Gnum * restrict const indvendtax = jobtab[0].grafdat.vendtax; + const Gnum * restrict const indedlotax = jobtab[0].grafdat.edlotax; /* Point to possibly induced original edge array */ + + invedlotax -= tgtgrafptr->baseval; /* Base inversed edge load array */ + + edlomin = GNUMMAX; + edlomax = 1; + for (vertnum = jobtab[0].grafdat.baseval, vertnnd = jobtab[0].grafdat.vertnnd; /* Handle non-compact graphs as well as compact graphs */ + vertnum < vertnnd; vertnum ++) { + Gnum edgenum; + Gnum edgennd; + + for (edgenum = indverttax[vertnum], edgennd = indvendtax[vertnum]; + edgenum < edgennd; edgenum ++) { + Gnum edloval; + + edloval = indedlotax[edgenum]; + if (edloval < edlomin) + edlomin = edloval; + if (edloval > edlomax) + edlomax = edloval; + } + } + + prodval = (float) edlomin * (float) edlomax; + + for (vertnum = jobtab[0].grafdat.baseval; + vertnum < vertnnd; vertnum ++) { + Gnum edgenum; + Gnum edgennd; + + for (edgenum = indverttax[vertnum], edgennd = indvendtax[vertnum]; + edgenum < edgennd; edgenum ++) { + Gnum edloval; + + edloval = indedlotax[edgenum]; + if (edloval == edlomin) + edloval = edlomax; + else if (edloval == edlomax) + edloval = edlomin; + else + edloval = (Gnum) (prodval / (float) edloval + 0.49F); +#ifdef SCOTCH_DEBUG_ARCH2 + if ((edloval < edlomin) || (edloval > edlomax)) { + errorPrint ("archBuild: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH2 */ + invedlotax[edgenum] = edloval; /* Write inversed cost in working array */ + } + } + + jobtab[0].grafdat.edlotax = invedlotax; /* Replace potentially induced edge array with inversed one */ + } /* Edge array will be freed along with jobtab group leader */ + + mapparttax = mappdat.parttax; + + actgrafdat.veextax = NULL; /* No external gain array */ + actgrafdat.parttax = actparttax; /* Set global auxiliary arrays */ + actgrafdat.frontab = actfrontab; + joblink = NULL; /* Initialize job list */ + if (jobtab[0].grafdat.vertnbr > 1) { /* If job is worth bipartitioning */ + jobtab[0].joblink = joblink; /* Add initial job to list */ + joblink = &jobtab[0]; + } + while (joblink != NULL) { /* For all jobs in list */ + joborgptr = joblink; /* Get job */ + joblink = joblink->joblink; /* Remove job from list */ + joborgptr->joblink = NULL; /* In case of freeing */ + + memCpy (&actgrafdat.s, &joborgptr->grafdat, sizeof (Graph)); + actgrafdat.s.flagval = joborgptr->grafdat.flagval & ~GRAPHFREETABS; + bgraphInit2 (&actgrafdat, 1, 1, 1, 0, 0); /* Create active graph */ + if (bgraphBipartSt (&actgrafdat, mapstrat) != 0) { /* Perform bipartitioning */ + errorPrint ("archBuild: internal error (2)"); + archBuildJobExit (joborgptr); + archBuildJobExit (joblink); + archExit (&archdat); + mapExit (&mappdat); + memFree (jobtab); + return (1); + } + if ((actgrafdat.compsize0 == 0) || /* If one of the jobs is empty */ + (actgrafdat.compsize0 == actgrafdat.s.vertnbr)) { + errorPrint ("archBuild: strategy leads to empty domains"); + graphExit (&actgrafdat.s); /* Only free graph part, global arrays kept */ + archBuildJobExit (joborgptr); + archBuildJobExit (joblink); + archExit (&archdat); + mapExit (&mappdat); + memFree (jobtab); + return (1); + } + + archVcmpltDomBipart ((const ArchVcmplt * const) (void *) &archdat, /* Update mapping domains */ + (const ArchVcmpltDom * const) (void *) &mappdat.domntab[joborgptr->domnum], + (ArchVcmpltDom * const) (void *) &domsub0, + (ArchVcmpltDom * const) (void *) &mappdat.domntab[mappdat.domnnbr]); + mappdat.domntab[joborgptr->domnum] = domsub0; + actpartval = actgrafdat.parttax[actgrafdat.s.baseval]; /* Always keep first vertex in sub0 */ + actpartnbr = (actpartval == 0) ? actgrafdat.compsize0 : (actgrafdat.s.vertnbr - actgrafdat.compsize0); + if (actgrafdat.s.vnumtax != NULL) { /* Update mapping fraction */ + Gnum actvertnum; + + for (actvertnum = actgrafdat.s.baseval; actvertnum < actgrafdat.s.vertnnd; actvertnum ++) { + if (actgrafdat.parttax[actvertnum] != actpartval) + mappdat.parttax[actgrafdat.s.vnumtax[actvertnum]] = mappdat.domnnbr; + } + } + else { + Gnum actvertnum; + + for (actvertnum = actgrafdat.s.baseval; actvertnum < actgrafdat.s.vertnnd; actvertnum ++) { + if (actgrafdat.parttax[actvertnum] != actpartval) + mappdat.parttax[actvertnum] = mappdat.domnnbr; + } + } + + jobsubptr = jobtab + mappdat.domnnbr; /* Point to new subjob */ + jobsubptr->domnum = mappdat.domnnbr ++; /* Build subjobs */ + actgrafdat.s.flagval = joborgptr->grafdat.flagval; /* Active is now main copy */ + + if (actpartnbr < (actgrafdat.s.vertnbr - 1)) { /* If part 1 splittable */ + graphInducePart (&actgrafdat.s, actgrafdat.parttax, actgrafdat.s.vertnbr - actpartnbr, + 1 - actpartval, &jobsubptr->grafdat); + jobsubptr->joblink = joblink; /* Link subjobs in list */ + joblink = jobsubptr; + } + if (actpartnbr > 1) { /* If part 0 splittable */ + graphInducePart (&actgrafdat.s, actgrafdat.parttax, actpartnbr, + actpartval, &joborgptr->grafdat); + joborgptr->joblink = joblink; /* Link subjobs in list */ + joblink = joborgptr; + } + graphExit (&actgrafdat.s); /* Only free graph part, global arrays kept */ + } + + memFree (jobtab); /* Free group leader */ + + if (memAllocGroup ((void **) (void *) + &termverttab, (size_t) (termdomnbr * sizeof (ArchDecoTermVert)), + &termdisttab, (size_t) (((termdomnbr * (termdomnbr - 1)) / 2) * sizeof (Anum)), + &disttax, (size_t) (tgtgrafptr->vertnbr * sizeof (ArchBuildDistElem)), + &queutab, (size_t) (tgtgrafptr->vertnbr * sizeof (ArchBuildQueuElem)), NULL) == NULL) { + errorPrint ("archBuild: out of memory (2)"); + mapExit (&mappdat); + archExit (&archdat); + return (1); + } + + for (termdomnum = 0, termdommax = 0; termdomnum < termdomnbr; termdomnum ++) { /* Set terminal vertex array */ + Gnum tgtvertnum; + + tgtvertnum = (tgtlistptr != NULL) ? tgtlistptr->vnumtab[termdomnum] : (termdomnum + tgtgrafptr->baseval); + termverttab[termdomnum].labl = tgtvertnum; + termverttab[termdomnum].wght = (tgtgrafptr->velotax != NULL) ? tgtgrafptr->velotax[tgtvertnum] : 1; + termverttab[termdomnum].num = archDomNum (&archdat, mapDomain (&mappdat, tgtvertnum - tgtgrafptr->baseval)); + if (termverttab[termdomnum].num > termdommax) /* Find maximum terminal number */ + termdommax = termverttab[termdomnum].num; + } + + disttax -= tgtgrafptr->baseval; + for (termdomnum = 1; termdomnum < termdomnbr; termdomnum ++) { /* For all active terminal vertices except the first */ + Gnum termdomend; + Gnum tgtvertnum; + + for (tgtvertnum = tgtgrafptr->baseval; tgtvertnum < (tgtgrafptr->vertnbr + tgtgrafptr->baseval); tgtvertnum ++) { + disttax[tgtvertnum].queued = 0; /* Vertex not queued */ + disttax[tgtvertnum].distval = INTVALMAX; /* Assume maximum distance */ + } + + queuhead = /* Reset the queue */ + queutail = 0; + tgtvertnum = termverttab[termdomnum].labl; + queutab[queutail].vertnum = tgtvertnum; /* Insert root vertex */ + queutab[queutail ++].distval = 0; + disttax[tgtvertnum].queued = 1; /* Mark vertex as queued */ + disttax[tgtvertnum].distval = 0; + + while (queuhead < queutail) { /* As long as there are vertices in queue */ + Gnum vertnum; /* Number of current vertex */ + Gnum vertdist; /* Current distance value */ + Gnum edgenum; + + vertnum = queutab[queuhead].vertnum; /* Retrieve vertex from queue */ + vertdist = queutab[queuhead ++].distval; + + for (edgenum = tgtverttax[vertnum]; /* For all vertex edges */ + edgenum < tgtvendtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = tgtedgetax[edgenum]; + if (disttax[vertend].queued == 0) { /* If end vertex not queued */ + queutab[queutail].vertnum = vertend; /* Queue the vertex */ + queutab[queutail ++].distval = + disttax[vertend].distval = vertdist + ((tgtedlotax != NULL) ? tgtedlotax[edgenum] : 1); + disttax[vertend].queued = 1; /* Mark vertex as queued */ + } + } + } + + for (termdomend = 0; termdomend < termdomnum; termdomend ++) /* For all previous terminal domains */ + termdisttab[((termdomnum * (termdomnum - 1)) / 2) + termdomend] = /* Retrieve distance */ + disttax[termverttab[termdomend].labl].distval; + } + + archDecoArchBuild ((ArchDeco *) (void *) &tgtarchptr->data, termdomnbr, termdommax, termverttab, termdisttab); + + memFree (termverttab); /* Free group leader */ + mapExit (&mappdat); + archExit (&archdat); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/arch_build.h b/scotch_6.0.3/src/libscotch/arch_build.h new file mode 100644 index 00000000..9767537c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_build.h @@ -0,0 +1,92 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_build.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the architecture building routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 29 may 1997 **/ +/** to 01 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 29 nov 2003 **/ +/** to 29 nov 2003 **/ +/** **/ +/** NOTES : # This file contains pieces of code **/ +/** extracted from release 3.1 of **/ +/** "amk_src.c". **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Job to process. +*/ + +typedef struct ArchBuildJob_ { + struct ArchBuildJob_ * joblink; /*+ Link to job pool +*/ + ArchDomNum domnum; /*+ Mapping domain to which vertices belong +*/ + Graph grafdat; /*+ Job graph data +*/ +} ArchBuildJob; + +/*+ Vertex distance information. +*/ + +typedef struct ArchBuildDistElem_ { + int queued; /*+ Flag set if vertex queued +*/ + Anum distval; /*+ Distance to initial vertex +*/ +} ArchBuildDistElem; + +/*+ Queue element. +*/ + +typedef struct ArchBuildQueuElem_ { + Gnum vertnum; /*+ Vertex number in source graph +*/ + Anum distval; /*+ Distance reached +*/ +} ArchBuildQueuElem; + +/* +** The function prototypes. +*/ + +#ifndef ARCH_BUILD +#define static +#endif + +static void archBuildJobExit (ArchBuildJob *); + +int archBuild (Arch * const, const Graph * const, const VertList * const, const Strat * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/arch_cmplt.c b/scotch_6.0.3/src/libscotch/arch_cmplt.c new file mode 100644 index 00000000..3ec086dc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_cmplt.c @@ -0,0 +1,346 @@ +/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_cmplt.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the complete graph **/ +/** target architecture. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 23 dec 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 29 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 08 sep 1995 **/ +/** # Version 3.1 : from : 11 jun 1996 **/ +/** to 11 jun 1996 **/ +/** # Version 3.2 : from : 21 sep 1996 **/ +/** to 13 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 09 jan 2004 **/ +/** to 10 mar 2005 **/ +/** # Version 5.1 : from : 19 jan 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 14 fev 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_CMPLT + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_cmplt.h" + +/******************************************/ +/* */ +/* These are the complete graph routines. */ +/* */ +/******************************************/ + +/* This routine loads the complete +** graph architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archCmpltArchLoad ( +ArchCmplt * restrict const archptr, +FILE * restrict const stream) +{ + long numnbr; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchCmplt) > sizeof (ArchDummy)) || + (sizeof (ArchCmpltDom) > sizeof (ArchDomDummy))) { + errorPrint ("archCmpltArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((fscanf (stream, "%ld", &numnbr) != 1) || + (numnbr < 1)) { + errorPrint ("archCmpltArchLoad: bad input"); + return (1); + } + archptr->numnbr = (Anum) numnbr; + + return (0); +} + +/* This routine saves the +** complete graph architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archCmpltArchSave ( +const ArchCmplt * const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchCmplt) > sizeof (ArchDummy)) || + (sizeof (ArchCmpltDom) > sizeof (ArchDomDummy))) { + errorPrint ("archCmpltArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING " ", (Anum) archptr->numnbr) == EOF) { + errorPrint ("archCmpltArchSave: bad output"); + return (1); + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archCmpltDomNum ( +const ArchCmplt * const archptr, +const ArchCmpltDom * const domptr) +{ + return (domptr->nummin); /* Return vertex number */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archCmpltDomTerm ( +const ArchCmplt * const archptr, +ArchCmpltDom * const domptr, +const ArchDomNum domnum) +{ + if (domnum < archptr->numnbr) { /* If valid label */ + domptr->nummin = domnum; /* Set the domain */ + domptr->numnbr = 1; + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the complete domain. +*/ + +Anum +archCmpltDomSize ( +const ArchCmplt * const archptr, +const ArchCmpltDom * const domptr) +{ + return (domptr->numnbr); +} + +/* This function returns the average +** distance between two complete +** subdomains. +*/ + +Anum +archCmpltDomDist ( +const ArchCmplt * const archptr, +const ArchCmpltDom * const dom0ptr, +const ArchCmpltDom * const dom1ptr) +{ + return (((dom0ptr->nummin == dom1ptr->nummin) && /* All domains are at distance 1 */ + (dom0ptr->numnbr == dom1ptr->numnbr)) ? 0 : 1); /* If they are different */ +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archCmpltDomFrst ( +const ArchCmplt * const archptr, +ArchCmpltDom * restrict const domptr) +{ + domptr->nummin = 0; + domptr->numnbr = archptr->numnbr; + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archCmpltDomLoad ( +const ArchCmplt * const archptr, +ArchCmpltDom * restrict const domptr, +FILE * const stream) +{ + long nummin; + long numnbr; + + if ((fscanf (stream, "%ld%ld", + &nummin, + &numnbr) != 2) || + (numnbr < 1) || + (numnbr + nummin > (long) archptr->numnbr)) { + errorPrint ("archCmpltDomLoad: bad input"); + return (1); + } + domptr->nummin = (Anum) nummin; + domptr->numnbr = (Anum) numnbr; + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archCmpltDomSave ( +const ArchCmplt * const archptr, +const ArchCmpltDom * const domptr, +FILE * const stream) +{ + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", + (Anum) domptr->nummin, + (Anum) domptr->numnbr) == EOF) { + errorPrint ("archCmpltDomSave: bad output"); + return (1); + } + + return (0); +} + +/* This function tries to split a complete +** graph domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archCmpltDomBipart ( +const ArchCmplt * const archptr, +const ArchCmpltDom * const domptr, +ArchCmpltDom * restrict const dom0ptr, +ArchCmpltDom * restrict const dom1ptr) +{ + if (domptr->numnbr <= 1) /* Return if cannot bipartition more */ + return (1); + + dom0ptr->nummin = domptr->nummin; /* Bipartition vertices */ + dom0ptr->numnbr = domptr->numnbr / 2; + dom1ptr->nummin = domptr->nummin + dom0ptr->numnbr; + dom1ptr->numnbr = domptr->numnbr - dom0ptr->numnbr; + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archCmpltDomIncl ( +const ArchCmplt * const archptr, +const ArchCmpltDom * const dom0ptr, +const ArchCmpltDom * const dom1ptr) +{ + if ((dom1ptr->nummin >= dom0ptr->nummin) && + ((dom1ptr->nummin + dom1ptr->numnbr) <= (dom0ptr->nummin + dom0ptr->numnbr))) + return (1); + + return (0); +} + +/* This function creates the MPI_Datatype for +** complete graph domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archCmpltDomMpiType ( +const ArchCmplt * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (2, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch_cmplt.h b/scotch_6.0.3/src/libscotch/arch_cmplt.h new file mode 100644 index 00000000..ea10eca0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_cmplt.h @@ -0,0 +1,122 @@ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_cmplt.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the complete graph target **/ +/** architecture functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 24 jul 1995 **/ +/** # Version 3.1 : from : 11 jun 1996 **/ +/** to 11 jun 1996 **/ +/** # Version 3.2 : from : 20 sep 1996 **/ +/** to 13 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 09 jan 2004 **/ +/** to 09 jan 2004 **/ +/** # Version 5.1 : from : 19 jan 2008 **/ +/** to 19 jan 2008 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 01 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +#ifndef ARCH_CMPLT_H_STRUCT +#define ARCH_CMPLT_H_STRUCT + +/*+ The complete graph definitions. +*/ + +typedef struct ArchCmplt_ { + Anum numnbr; /*+ Number of vertices +*/ +} ArchCmplt; + +typedef struct ArchCmpltDom_ { + Anum nummin; /*+ Minimum vertex number +*/ + Anum numnbr; /*+ Number of vertices +*/ +} ArchCmpltDom; + +#endif /* ARCH_CMPLT_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_CMPLT_H_PROTO +#define ARCH_CMPLT_H_PROTO + +#ifndef ARCH_CMPLT +#define static +#endif + +int archCmpltArchLoad (ArchCmplt * restrict const, FILE * restrict const); +int archCmpltArchSave (const ArchCmplt * const, FILE * restrict const); +#define archCmpltArchFree NULL +ArchDomNum archCmpltDomNum (const ArchCmplt * const, const ArchCmpltDom * const); +int archCmpltDomTerm (const ArchCmplt * const, ArchCmpltDom * restrict const, const ArchDomNum); +Anum archCmpltDomSize (const ArchCmplt * const, const ArchCmpltDom * const); +#define archCmpltDomWght archCmpltDomSize +Anum archCmpltDomDist (const ArchCmplt * const, const ArchCmpltDom * const, const ArchCmpltDom * const); +int archCmpltDomFrst (const ArchCmplt * const, ArchCmpltDom * const); +int archCmpltDomLoad (const ArchCmplt * const, ArchCmpltDom * const, FILE * const); +int archCmpltDomSave (const ArchCmplt * const, const ArchCmpltDom * const, FILE * const); +int archCmpltDomBipart (const ArchCmplt * const, const ArchCmpltDom * const, ArchCmpltDom * restrict const, ArchCmpltDom * restrict const); +int archCmpltDomIncl (const ArchCmplt * const, const ArchCmpltDom * const, const ArchCmpltDom * const); +#ifdef SCOTCH_PTSCOTCH +int archCmpltDomMpiType (const ArchCmplt * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +#endif /* ARCH_CMPLT_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/arch_cmpltw.c b/scotch_6.0.3/src/libscotch/arch_cmpltw.c new file mode 100644 index 00000000..e8d336d3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_cmpltw.c @@ -0,0 +1,582 @@ +/* Copyright 2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_cmpltw.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the weighted **/ +/** complete graph target architecture. **/ +/** **/ +/** DATES : # Version 5.1 : from : 11 dec 2007 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 23 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_CMPLTW + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "arch_cmpltw.h" + +/******************************************/ +/* */ +/* These are the complete graph routines. */ +/* */ +/******************************************/ + +/* This routine builds a complete weighted +** graph architecture from the given load array. +** It returns: +** - 0 : if the architecture has been successfully built. +** - !0 : on error. +*/ + +static +void +archCmpltwArchBuild3 ( +ArchCmpltwLoad * restrict const velotab, +ArchCmpltwLoad * restrict const vesotab, +Anum vertnbr, +Anum velosum) +{ + Anum velosum0; + Anum velosum1; + Anum vertnbr0; + Anum vertnbr1; + Anum vertnum0; + Anum vertnum1; + Anum vertnum; + + vertnum0 = + vertnum1 = vertnbr - 1; + velosum0 = velotab[vertnum0 --].veloval; + velosum1 = 0; + for (vertnum = vertnum0; vertnum >= 0; vertnum --) { + if (velosum1 < velosum0) { + velosum1 += velotab[vertnum].veloval; + vesotab[vertnum1 --] = velotab[vertnum]; + } + else { + velosum0 += velotab[vertnum].veloval; + velotab[vertnum0 --] = velotab[vertnum]; + } + } + + if (velosum0 >= velosum1) { + vertnbr0 = vertnbr - vertnum0 - 1; + vertnbr1 = vertnbr - vertnbr0; + memMov (velotab, velotab + vertnbr1, vertnbr0 * sizeof (ArchCmpltwLoad)); + memCpy (velotab + vertnbr0, vesotab + vertnbr0, vertnbr1 * sizeof (ArchCmpltwLoad)); + } + else { + Anum velotmp; + + vertnbr0 = vertnbr - vertnum1 - 1; + vertnbr1 = vertnbr - vertnbr0; + memCpy (velotab, vesotab + vertnbr1, vertnbr0 * sizeof (ArchCmpltwLoad)); + velotmp = velosum0; + velosum0 = velosum1; + velosum1 = velotmp; + } + + if (vertnbr0 > 2) + archCmpltwArchBuild3 (velotab, vesotab, vertnbr0, velosum0); + if (vertnbr1 > 2) + archCmpltwArchBuild3 (velotab + vertnbr0, vesotab + vertnbr0, vertnbr1, velosum1); +} + +static +int +archCmpltwArchBuild2 ( +ArchCmpltw * restrict const archptr) +{ + ArchCmpltwLoad * restrict vesotab; /* Auxiliary sort array for weighted vertices */ + + if (archptr->vertnbr < 3) /* No need to sort if less than 3 vertices */ + return (0); + + if ((vesotab = (ArchCmpltwLoad *) memAlloc (archptr->vertnbr * sizeof (ArchCmpltwLoad))) == NULL) { + errorPrint ("archCmpltwArchBuild2: out of memory"); + memFree (archptr->velotab); + archptr->velotab = NULL; + return (1); + } + + intSort2asc2 (archptr->velotab, archptr->vertnbr); /* Sort load array by both keys to be portable across sorting implementations */ + + archCmpltwArchBuild3 (archptr->velotab, vesotab, archptr->vertnbr, archptr->velosum); + + memFree (vesotab); + + return (0); +} + +int +archCmpltwArchBuild ( +ArchCmpltw * restrict const archptr, +const Anum vertnbr, +const Anum * restrict const velotab) +{ + Anum vertnum; + Anum velosum; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchCmpltw) > sizeof (ArchDummy)) || + (sizeof (ArchCmpltwDom) > sizeof (ArchDomDummy))) { + errorPrint ("archCmpltwArchBuild: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (vertnbr <= 0) { + errorPrint ("archCmpltwArchBuild: invalid parameters"); + return (1); + } + + archptr->vertnbr = (Anum) vertnbr; + + if ((archptr->velotab = (ArchCmpltwLoad *) memAlloc (archptr->vertnbr * sizeof (ArchCmpltwLoad))) == NULL) { + errorPrint ("archCmpltwArchBuild: out of memory"); + return (1); + } + + for (vertnum = 0, velosum = 0; vertnum < archptr->vertnbr; vertnum ++) { /* Fill vertex load array */ + Anum veloval; + + veloval = velotab[vertnum]; + velosum += veloval; + archptr->velotab[vertnum].veloval = veloval; + archptr->velotab[vertnum].vertnum = vertnum; + } + archptr->velosum = (Anum) velosum; + + return (archCmpltwArchBuild2 (archptr)); +} + +/* This routine loads the weighted complete +** graph architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archCmpltwArchLoad ( +ArchCmpltw * restrict const archptr, +FILE * restrict const stream) +{ + long vertnbr; + Anum velosum; + Anum vertnum; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchCmpltw) > sizeof (ArchDummy)) || + (sizeof (ArchCmpltwDom) > sizeof (ArchDomDummy))) { + errorPrint ("archCmpltwArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((fscanf (stream, "%ld", &vertnbr) != 1) || + (vertnbr < 1)) { + errorPrint ("archCmpltwArchLoad: bad input (1)"); + return (1); + } + archptr->vertnbr = (Anum) vertnbr; + + if ((archptr->velotab = (ArchCmpltwLoad *) memAlloc (archptr->vertnbr * sizeof (ArchCmpltwLoad))) == NULL) { + errorPrint ("archCmpltwArchLoad: out of memory"); + return (1); + } + + for (vertnum = 0, velosum = 0; vertnum < archptr->vertnbr; vertnum ++) { + long veloval; + Anum velotmp; + + if ((fscanf (stream, "%ld", &veloval) != 1) || + (veloval < 1)) { + errorPrint ("archCmpltwArchLoad: bad input (2)"); + return (1); + } + + velotmp = (Anum) veloval; + velosum += velotmp; + archptr->velotab[vertnum].veloval = velotmp; + archptr->velotab[vertnum].vertnum = vertnum; + } + archptr->velosum = (Anum) velosum; + + return (archCmpltwArchBuild2 (archptr)); +} + +/* This routine saves the weighted +** complete graph architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archCmpltwArchSave ( +const ArchCmpltw * const archptr, +FILE * restrict const stream) +{ + Anum vertnum; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchCmpltw) > sizeof (ArchDummy)) || + (sizeof (ArchCmpltwDom) > sizeof (ArchDomDummy))) { + errorPrint ("archCmpltwArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING, (Anum) archptr->vertnbr) == EOF) { + errorPrint ("archCmpltwArchSave: bad output (1)"); + return (1); + } + + for (vertnum = 0; vertnum < archptr->vertnbr; vertnum ++) { /* For all weights to output */ + Anum verttmp; + + for (verttmp = 0; verttmp < archptr->vertnbr; verttmp ++) { /* For all vertex indices: O(n^2) loop but we don't really care */ + if (archptr->velotab[verttmp].vertnum == vertnum) { + if (fprintf (stream, " " ANUMSTRING, (Anum) archptr->velotab[verttmp].veloval) == EOF) { + errorPrint ("archCmpltwArchSave: bad output (2)"); + return (1); + } + break; + } + if (verttmp == archptr->vertnbr) { + errorPrint ("archCmpltwArchSave: internal error"); + return (1); + } + } + } + + return (0); +} + +/* This routine frees the weighted complete +** graph architecture data structures. +** It returns: +** - 0 : if the architecture has been successfully freed. +** - !0 : on error. +*/ + +int +archCmpltwArchFree ( +ArchCmpltw * const archptr) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchCmpltw) > sizeof (ArchDummy)) || + (sizeof (ArchCmpltwDom) > sizeof (ArchDomDummy))) { + errorPrint ("archCmpltwArchFree: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (archptr->velotab != NULL) { + memFree (archptr->velotab); + archptr->velotab = NULL; + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archCmpltwDomNum ( +const ArchCmpltw * const archptr, +const ArchCmpltwDom * const domptr) +{ + return (archptr->velotab[domptr->vertmin].vertnum); /* Return vertex number */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archCmpltwDomTerm ( +const ArchCmpltw * const archptr, +ArchCmpltwDom * const domptr, +const ArchDomNum domnum) +{ + if (domnum < archptr->vertnbr) { /* If valid label */ + Anum vertnum; + + for (vertnum = 0; vertnum < archptr->vertnbr; vertnum ++) { /* Search for terminal domain index matching vertex label */ + if (archptr->velotab[vertnum].vertnum == domnum) + break; + } +#ifdef SCOTCH_DEBUG_ARCH2 + if (vertnum == archptr->vertnbr) { /* If index not found */ + errorPrint ("archCmpltwDomTerm: internal error"); + return (2); + } +#endif /* SCOTCH_DEBUG_ARCH2 */ + + domptr->vertmin = vertnum; /* Set the domain */ + domptr->vertnbr = 1; + domptr->veloval = archptr->velotab[vertnum].veloval; + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the complete domain. +*/ + +Anum +archCmpltwDomSize ( +const ArchCmpltw * const archptr, +const ArchCmpltwDom * const domptr) +{ + return (domptr->vertnbr); +} + +/* This function returns the weight of +** the complete domain. +*/ + +Anum +archCmpltwDomWght ( +const ArchCmpltw * const archptr, +const ArchCmpltwDom * const domptr) +{ + return (domptr->veloval); +} + +/* This function returns the average +** distance between two complete +** subdomains. +*/ + +Anum +archCmpltwDomDist ( +const ArchCmpltw * const archptr, +const ArchCmpltwDom * const dom0ptr, +const ArchCmpltwDom * const dom1ptr) +{ + return (((dom0ptr->vertmin == dom1ptr->vertmin) && /* All domains are at distance 1 */ + (dom0ptr->vertnbr == dom1ptr->vertnbr)) ? 0 : 1); /* If they are different */ +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archCmpltwDomFrst ( +const ArchCmpltw * const archptr, +ArchCmpltwDom * restrict const domptr) +{ + domptr->vertmin = 0; + domptr->vertnbr = archptr->vertnbr; + domptr->veloval = archptr->velosum; + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archCmpltwDomLoad ( +const ArchCmpltw * const archptr, +ArchCmpltwDom * restrict const domptr, +FILE * const stream) +{ + long vertmin; + long vertnbr; + Anum vertnum; + Anum vertnnd; + Anum velosum; + + if ((fscanf (stream, "%ld%ld", + &vertmin, + &vertnbr) != 2) || + (vertnbr < 1) || + (vertnbr + vertmin > (long) archptr->vertnbr)) { + errorPrint ("archCmpltwDomLoad: bad input"); + return (1); + } + domptr->vertmin = (Anum) vertmin; + domptr->vertnbr = (Anum) vertnbr; + + for (vertnum = domptr->vertmin, vertnnd = vertnum + domptr->vertnbr, velosum = 0; + vertnum < vertnnd; vertnum ++) + velosum += archptr->velotab[vertnum].veloval; + + domptr->veloval += velosum; + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archCmpltwDomSave ( +const ArchCmpltw * const archptr, +const ArchCmpltwDom * const domptr, +FILE * const stream) +{ + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", + (Anum) domptr->vertmin, + (Anum) domptr->vertnbr) == EOF) { + errorPrint ("archCmpltwDomSave: bad output"); + return (1); + } + + return (0); +} + +/* This function tries to split a complete +** graph domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archCmpltwDomBipart ( +const ArchCmpltw * const archptr, +const ArchCmpltwDom * const domptr, +ArchCmpltwDom * restrict const dom0ptr, +ArchCmpltwDom * restrict const dom1ptr) +{ + Anum vertnum; + Anum velosum1; + Anum velosum2; /* Half of overall load sum */ + + if (domptr->vertnbr <= 1) /* Return if cannot bipartition more */ + return (1); + + vertnum = domptr->vertmin + domptr->vertnbr - 1; + velosum1 = (Anum) archptr->velotab[vertnum].veloval; + velosum2 = domptr->veloval / 2; + for (vertnum --; vertnum > domptr->vertmin; vertnum --) { + Anum velotmp; + + velotmp = velosum1 + (Anum) archptr->velotab[vertnum].veloval; + if (velotmp > velosum2) /* Domain 1 is always the least loaded */ + break; + velosum1 = velotmp; + } + + dom0ptr->vertmin = domptr->vertmin; /* Bipartition vertices */ + dom1ptr->vertmin = vertnum + 1; + dom0ptr->vertnbr = dom1ptr->vertmin - domptr->vertmin; + dom1ptr->vertnbr = domptr->vertnbr - dom0ptr->vertnbr; + dom0ptr->veloval = domptr->veloval - velosum1; + dom1ptr->veloval = velosum1; + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archCmpltwDomIncl ( +const ArchCmpltw * const archptr, +const ArchCmpltwDom * const dom0ptr, +const ArchCmpltwDom * const dom1ptr) +{ + if ((dom1ptr->vertmin >= dom0ptr->vertmin) && + ((dom1ptr->vertmin + dom1ptr->vertnbr) <= (dom0ptr->vertmin + dom0ptr->vertnbr))) + return (1); + + return (0); +} + +/* This function creates the MPI_Datatype for +** weighted complete graph domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archCmpltwDomMpiType ( +const ArchCmpltw * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (3, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch_cmpltw.h b/scotch_6.0.3/src/libscotch/arch_cmpltw.h new file mode 100644 index 00000000..5ada5fa4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_cmpltw.h @@ -0,0 +1,117 @@ +/* Copyright 2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_cmpltw.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the weighted complete graph target **/ +/** architecture functions. **/ +/** **/ +/** DATES : # Version 5.1 : from : 11 dec 2007 **/ +/** to 04 nov 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 23 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +#ifndef ARCH_CMPLTW_H_STRUCT +#define ARCH_CMPLTW_H_STRUCT + +/*+ The weighted target vertex. Since Anum's + are INT's, they can be sorted, by means + of the intSort2asc1 routine. +*/ + +typedef struct ArchCmpltwLoad_ { + Anum veloval; /*+ Vertex load +*/ + Anum vertnum; /*+ Vertex index +*/ +} ArchCmpltwLoad; + +/*+ The weighted complete graph definitions. +*/ + +typedef struct ArchCmpltw_ { + Anum vertnbr; /*+ Number of vertices +*/ + ArchCmpltwLoad * velotab; /*+ Vertex index array +*/ + Anum velosum; /*+ Sum of all weights +*/ +} ArchCmpltw; + +/*+ The weighted domain structure. +*/ + +typedef struct ArchCmpltwDom_ { + Anum vertmin; /*+ Minimum vertex number +*/ + Anum vertnbr; /*+ Number of vertices +*/ + Anum veloval; /*+ Weight of subdomain +*/ +} ArchCmpltwDom; + +#endif /* ARCH_CMPLTW_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_CMPLTW_H_PROTO +#define ARCH_CMPLTW_H_PROTO + +#ifndef ARCH_CMPLTW +#define static +#endif + +int archCmpltwArchBuild (ArchCmpltw * restrict const archptr, const Anum, const Anum * restrict const); +int archCmpltwArchLoad (ArchCmpltw * restrict const, FILE * restrict const); +int archCmpltwArchSave (const ArchCmpltw * const, FILE * restrict const); +int archCmpltwArchFree (ArchCmpltw * restrict const); +ArchDomNum archCmpltwDomNum (const ArchCmpltw * const, const ArchCmpltwDom * const); +int archCmpltwDomTerm (const ArchCmpltw * const, ArchCmpltwDom * restrict const, const ArchDomNum); +Anum archCmpltwDomSize (const ArchCmpltw * const, const ArchCmpltwDom * const); +Anum archCmpltwDomWght (const ArchCmpltw * const, const ArchCmpltwDom * const); +Anum archCmpltwDomDist (const ArchCmpltw * const, const ArchCmpltwDom * const, const ArchCmpltwDom * const); +int archCmpltwDomFrst (const ArchCmpltw * const, ArchCmpltwDom * const); +int archCmpltwDomLoad (const ArchCmpltw * const, ArchCmpltwDom * const, FILE * const); +int archCmpltwDomSave (const ArchCmpltw * const, const ArchCmpltwDom * const, FILE * const); +int archCmpltwDomBipart (const ArchCmpltw * const, const ArchCmpltwDom * const, ArchCmpltwDom * restrict const, ArchCmpltwDom * restrict const); +int archCmpltwDomIncl (const ArchCmpltw * const, const ArchCmpltwDom * const, const ArchCmpltwDom * const); +#ifdef SCOTCH_PTSCOTCH +int archCmpltwDomMpiType (const ArchCmpltw * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +#endif /* ARCH_CMPLTW_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/arch_deco.c b/scotch_6.0.3/src/libscotch/arch_deco.c new file mode 100644 index 00000000..5ee7e84c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_deco.c @@ -0,0 +1,624 @@ +/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_deco.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the decomposition- **/ +/** defined target architecture. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 23 dec 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 29 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 14 sep 1995 **/ +/** # Version 3.1 : from : 20 jul 1996 **/ +/** to 23 jul 1996 **/ +/** # Version 3.2 : from : 11 sep 1996 **/ +/** to 28 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 17 may 1999 **/ +/** # Version 4.0 : from : 29 nov 2003 **/ +/** to 10 mar 2005 **/ +/** # Version 5.0 : from : 10 sep 2007 **/ +/** to 28 feb 2008 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 14 fev 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_DECO + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_deco.h" + +/***************************************/ +/* */ +/* These are the decomposition-defined */ +/* architecture routines. */ +/* */ +/***************************************/ + +/* This routine builds a compiled +** decomposition-defined architecture +** from the raw terminal tables that are +** passed to it. +** It returns: +** - 0 : if the decomposition has been successfully computed. +** - !0 : on error. +*/ + +int +archDecoArchBuild ( +ArchDeco * restrict const archptr, /*+ Architecture to build +*/ +const Anum termdomnbr, /*+ Number of terminal domains (ie processors) +*/ +const Anum termdommax, /*+ Maximum domain number given to a terminal domain +*/ +const ArchDecoTermVert * const termverttab, /*+ Terminal vertex array +*/ +const Anum * const termdisttab) /*+ Terminal distance map +*/ +{ + Anum i, j, k; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchDeco) > sizeof (ArchDummy)) || + (sizeof (ArchDecoDom) > sizeof (ArchDomDummy))) { + errorPrint ("archDecoArchBuild: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (memAllocGroup ((void **) (void *) + &archptr->domverttab, (size_t) (termdommax * sizeof (ArchDecoVert)), + &archptr->domdisttab, (size_t) ((((termdommax * (termdommax - 1)) / 2) + 1) * sizeof (Anum)), NULL) == NULL) { + errorPrint ("archDecoArchBuild: out of memory"); + return (1); + } + archptr->flagval = ARCHDECOFREE; + archptr->domtermnbr = termdomnbr; + archptr->domvertnbr = termdommax; + + for (i = 0; i < termdommax; i ++) { + archptr->domverttab[i].labl = ARCHDOMNOTTERM; /* Assume domain is not a terminal */ + archptr->domverttab[i].size = 0; /* Assume domain is not used (yet) */ + archptr->domverttab[i].wght = 0; /* Assume domain is not used (yet) */ + } + + for (i = 0; i < termdomnbr; i ++) { /* Set terminal data of all declared terminals */ +#ifdef SCOTCH_DEBUG_ARCH1 + if (termverttab[i].num > termdommax) { /* If incorrect maximum terminal number */ + errorPrint ("archDecoArchBuild: bad maximum terminal"); + archDecoArchFree (archptr); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + archptr->domverttab[termverttab[i].num - 1].labl = termverttab[i].labl; + archptr->domverttab[termverttab[i].num - 1].size = 1; + archptr->domverttab[termverttab[i].num - 1].wght = termverttab[i].wght; + } + + for (i = termdommax - 1; i > 0; i --) { /* Accumulate data from terminals to root */ + j = ((i - 1) >> 1); + if (archptr->domverttab[i].labl != ARCHDOMNOTTERM) { + if ((archptr->domverttab[j].labl == ARCHDOMNOTTERM) || /* Get smallest label */ + (archptr->domverttab[j].labl > archptr->domverttab[i].labl)) + archptr->domverttab[j].labl = archptr->domverttab[i].labl; + archptr->domverttab[j].size += archptr->domverttab[i].size; + archptr->domverttab[j].wght += archptr->domverttab[i].wght; + } + } +#ifdef SCOTCH_DEBUG_ARCH1 + if (archptr->domverttab[0].size != termdomnbr) { /* If incorrect accumulation */ + errorPrint ("archDecoArchBuild: bad terminal count"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + memSet (archptr->domdisttab, 0, termdommax * (termdommax - 1) * sizeof (Anum) / 2); + /* Assume distance is not known */ + for (i = 1, k = 0; i < termdomnbr; i ++) { /* Read the terminal distance map */ + for (j = 0; j < i; j ++, k ++) + archDecoArchDist (archptr, termverttab[i].num, termverttab[j].num) = termdisttab[k]; + } + + for (j = termdommax; j > 0; j --) { /* Loop on domains */ + if (archDecoArchSize (archptr, j) == 0) /* If domain is unused, skip it */ + continue; + for (i = termdommax; i > j; i --) { /* Double loop on distance array values */ + if (archDecoArchSize (archptr, i) == 0) /* If domain is unused, skip it */ + continue; + if (archDecoArchSize (archptr, i) > 1) { /* If domain i has subdomains */ + if (archDecoArchSize (archptr, j) > 1) /* If domain j has subdomains */ + archDecoArchDist (archptr, i, j) = (archDecoArchDistE (archptr, 2 * i, 2 * j) + + archDecoArchDistE (archptr, 2 * i, 2 * j + 1) + + archDecoArchDistE (archptr, 2 * i + 1, 2 * j) + + archDecoArchDistE (archptr, 2 * i + 1, 2 * j + 1) + 2) / 4; + else /* If domain j is a terminal */ + archDecoArchDist (archptr, i, j) = (archDecoArchDistE (archptr, 2 * i, j) + + archDecoArchDistE (archptr, 2 * i + 1, j) + 1) / 2; + } + else { /* If domain i is a terminal */ + if (archDecoArchSize (archptr, j) > 1) /* If domain j has subdomains */ + archDecoArchDist (archptr, i, j) = (archDecoArchDistE (archptr, i, 2 * j) + + archDecoArchDistE (archptr, i, 2 * j + 1) + 1) / 2; +#ifdef SCOTCH_DEBUG_ARCH1 + else { /* If both domain are terminals */ + if (archDecoArchDist (archptr, i, j) == 0) { /* Distance value must be greater than zero */ + errorPrint ("archDecoArchBuild: invalid null distance"); + archDecoArchFree (archptr); + return (1); + } + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + } + } + } + + return (0); +} + +/* This routine loads and computes the +** decomposition-defined architecture +** tables. +** It returns: +** - 0 : if the decomposition has been successfully read. +** - !0 : on error. +*/ + +int +archDecoArchLoad ( +ArchDeco * restrict const archptr, +FILE * restrict const stream) +{ + INT decotype; /* Type of decomposition */ + INT termdomnbr; /* Number of terminal domains (ie processors) */ + INT termdommax; /* Maximum domain number given to a terminal domain */ + ArchDecoTermVert * restrict termverttab; /* Table of terminal vertex data */ + Anum * restrict termdisttab; /* Table of terminal-to-terminal distances */ + INT i, j; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchDeco) > sizeof (ArchDummy)) || + (sizeof (ArchDecoDom) > sizeof (ArchDomDummy))) { + errorPrint ("archDecoArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((intLoad (stream, &decotype) != 1) || /* Read header */ + (intLoad (stream, &termdomnbr) != 1) || + (intLoad (stream, &termdommax) != 1) || + (decotype < 0) || + (decotype > 1) || + (termdommax < termdomnbr) || + (termdomnbr < 1)) { + errorPrint ("archDecoArchLoad: bad input (1)"); + return (1); + } + + if (decotype == 0) { /* If raw decomposition */ + if (memAllocGroup ((void **) (void *) + &termverttab, (size_t) (termdomnbr * sizeof (ArchDecoTermVert)), + &termdisttab, (size_t) ((((termdommax * (termdommax - 1)) / 2) + 1) * sizeof (Anum)), NULL) == NULL) { + errorPrint ("archDecoArchLoad: out of memory (1)"); + return (1); + } + + for (i = 0; i < termdomnbr; i ++) { /* For all declared terminals */ + INT termvertlabl; + INT termvertwght; + INT termvertnum; + + if ((intLoad (stream, &termvertlabl) != 1) || /* Read terminal data */ + (intLoad (stream, &termvertwght) != 1) || + (intLoad (stream, &termvertnum) != 1) || + (termvertnum < 1) || + (termvertnum > termdommax)) { + errorPrint ("archDecoArchLoad: bad input (2)"); + memFree (termverttab); /* Free group leader */ + return (1); + } + termverttab[i].labl = (ArchDomNum) termvertlabl; + termverttab[i].wght = (Anum) termvertwght; + termverttab[i].num = (Anum) termvertnum; + } + + for (i = 0, j = (termdomnbr * (termdomnbr - 1)) / 2; i < j; i ++) { /* Read terminal distance map */ + INT termdistval; + + if ((intLoad (stream, &termdistval) != 1) || + (termdistval < 1)) { + errorPrint ("archDecoArchLoad: bad input (3)"); + memFree (termverttab); /* Free group leader */ + return (1); + } + termdisttab[i] = (Anum) termdistval; + } + + archDecoArchBuild (archptr, termdomnbr, termdommax, termverttab, termdisttab); + + memFree (termverttab); /* Free group leader */ + } + else { /* If it is a compiled decomposition */ + if (memAllocGroup ((void **) (void *) + &archptr->domverttab, (size_t) (termdommax * sizeof (ArchDecoVert)), + &archptr->domdisttab, (size_t) ((((termdommax * (termdommax - 1)) / 2) + 1) * sizeof (Anum)), NULL) == NULL) { + errorPrint ("archDecoArchLoad: out of memory (2)"); + return (1); + } + archptr->flagval = ARCHDECOFREE; + archptr->domtermnbr = (Anum) termdomnbr; + archptr->domvertnbr = (Anum) termdommax; + + for (i = 0; i < termdommax; i ++) { /* Read domain array */ + INT domvertlabl; + INT domvertsize; + INT domvertwght; + + if ((intLoad (stream, &domvertlabl) != 1) || + (intLoad (stream, &domvertsize) != 1) || + (intLoad (stream, &domvertwght) != 1)) { + errorPrint ("archDecoArchLoad: bad input (4)"); + archDecoArchFree (archptr); + return (1); + } + archptr->domverttab[i].labl = (ArchDomNum) domvertlabl; + archptr->domverttab[i].size = (Anum) domvertsize; + archptr->domverttab[i].wght = (Anum) domvertwght; + } + + for (i = 0; i < (termdommax * (termdommax - 1)) / 2; i ++) { /* Read distance array */ + INT domdistval; + + if (intLoad (stream, &domdistval) != 1) { + errorPrint ("archDecoArchLoad: bad input (5)"); + archDecoArchFree (archptr); + return (1); + } + archptr->domdisttab[i] = domdistval; + } + } + + return (0); +} + +/* This routine frees the decomposition +** architecture structures. +** It returns: +** - 0 : if the decomposition has been successfully freed. +** - !0 : on error. +*/ + +int +archDecoArchFree ( +ArchDeco * const archptr) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchDeco) > sizeof (ArchDummy)) || + (sizeof (ArchDecoDom) > sizeof (ArchDomDummy))) { + errorPrint ("archDecoArchFree: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (((archptr->flagval & ARCHDECOFREE) != 0) && + (archptr->domverttab != NULL)) + memFree (archptr->domverttab); /* Free group leader */ + + archptr->domtermnbr = + archptr->domvertnbr = 0; + archptr->domverttab = NULL; + archptr->domdisttab = NULL; + + return (0); +} + +/* This routine saves the given target architecture +** as compiled decomposition tables. +** It returns: +** - 0 : if the decomposition has been successfully written. +** - !0 : on error. +*/ + +int +archDecoArchSave ( +const ArchDeco * const archptr, +FILE * restrict const stream) +{ + Anum i, j; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchDeco) > sizeof (ArchDummy)) || + (sizeof (ArchDecoDom) > sizeof (ArchDomDummy))) { + errorPrint ("archDecoArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, "1\n" ANUMSTRING "\t" ANUMSTRING "\n", /* Write number of domains */ + (Anum) archptr->domtermnbr, + (Anum) archptr->domvertnbr) == EOF) { + errorPrint ("archDecoArchSave: bad output (1)"); + return (1); + } + + for (i = 0; i < archptr->domvertnbr; i ++) { /* Write domain array */ + if (fprintf (stream, ANUMSTRING "\t" ANUMSTRING "\t" ANUMSTRING "\n", + (Anum) archptr->domverttab[i].labl, + (Anum) archptr->domverttab[i].size, + (Anum) archptr->domverttab[i].wght) == EOF) { + errorPrint ("archDecoArchSave: bad output (2)"); + return (1); + } + } + + j = (archptr->domvertnbr * (archptr->domvertnbr - 1)) / 2; + for (i = 0; i < j; i ++) { /* Write distance array */ + if (fprintf (stream, ANUMSTRING "%c", + (Anum) archptr->domdisttab[i], + (((i % 8) == 7) && (i != (j - 1))) ? '\n' : '\t') == EOF) { + errorPrint ("archDecoArchSave: bad output (3)"); + return (1); + } + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archDecoDomNum ( +const ArchDeco * const archptr, +const ArchDecoDom * const domptr) +{ + return (archptr->domverttab[domptr->num - 1].labl); +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archDecoDomTerm ( +const ArchDeco * const archptr, +ArchDecoDom * const domptr, +const ArchDomNum domnum) +{ + Anum domtermnum; + Anum domvertnum; + + for (domtermnum = archptr->domtermnbr, domvertnum = archptr->domvertnbr - 1; + (domtermnum > 0) && (domvertnum != (Anum) (-1)); domvertnum --) { + if (archptr->domverttab[domvertnum].size == 1) { /* If terminal vertex */ + domtermnum --; /* One more terminal scanned */ + if (archptr->domverttab[domvertnum].labl == domnum) { /* If terminal domain number found */ + domptr->num = domvertnum; /* Set domain number */ + return (0); + } + } + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the given domain. +*/ + +Anum +archDecoDomSize ( +const ArchDeco * const archptr, +const ArchDecoDom * const domptr) +{ + return (archptr->domverttab[domptr->num - 1].size); +} + +/* This function returns the weight of +** the given domain. +*/ + +Anum +archDecoDomWght ( +const ArchDeco * const archptr, +const ArchDecoDom * const domptr) +{ + return (archptr->domverttab[domptr->num - 1].wght); +} + +/* This function returns the average distance +** between two domains, which is extracted +** from the table. +*/ + +Anum +archDecoDomDist ( +const ArchDeco * const archptr, +const ArchDecoDom * const dom0ptr, +const ArchDecoDom * const dom1ptr) +{ + return (archDecoArchDistE (archptr, dom0ptr->num, dom1ptr->num)); +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archDecoDomFrst ( +const ArchDeco * const archptr, +ArchDecoDom * restrict const domptr) +{ + domptr->num = 1; + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archDecoDomLoad ( +const ArchDeco * const archptr, +ArchDecoDom * restrict const domptr, +FILE * restrict const stream) +{ + if ((intLoad (stream, &domptr->num) != 1) || + (domptr->num < 1) || (domptr->num > archptr->domvertnbr)) { + errorPrint ("archDecoDomLoad: bad input"); + return (1); + } + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archDecoDomSave ( +const ArchDeco * const archptr, +const ArchDecoDom * const domptr, +FILE * restrict const stream) +{ + if (fprintf (stream, ANUMSTRING " ", + (Anum) domptr->num) == EOF) { + errorPrint ("archDecoDomSave: bad output"); + return (1); + } + + return (0); +} + +/* This function tries to split a +** decomposition domain into two +** subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archDecoDomBipart ( +const ArchDeco * const archptr, +const ArchDecoDom * const domptr, +ArchDecoDom * restrict const dom0ptr, +ArchDecoDom * restrict const dom1ptr) +{ + if (archptr->domverttab[domptr->num - 1].size <= 1) /* Return if cannot bipartition more */ + return (1); + + dom0ptr->num = domptr->num << 1; /* Compute subdomain numbers from domain number */ + dom1ptr->num = dom0ptr->num + 1; + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archDecoDomIncl ( +const ArchDeco * const archptr, +const ArchDecoDom * const dom0ptr, +const ArchDecoDom * const dom1ptr) +{ + Anum dom0num; + Anum dom1num; + + for (dom1num = dom1ptr->num, dom0num = dom0ptr->num; dom1num != 0; dom1num >>= 1) + if (dom1num == dom0ptr->num) + return (1); + + return (0); +} + +/* This function creates the MPI_Datatype for +** decomposition-described domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archDecoDomMpiType ( +const ArchDeco * const archptr, +MPI_Datatype * const typeptr) +{ + *typeptr = ANUM_MPI; + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch_deco.h b/scotch_6.0.3/src/libscotch/arch_deco.h new file mode 100644 index 00000000..2f2273b9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_deco.h @@ -0,0 +1,160 @@ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_deco.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the decomposition-defined target **/ +/** architecture functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 24 jul 1995 **/ +/** # Version 3.1 : from : 20 jul 1996 **/ +/** to 20 jul 1996 **/ +/** # Version 3.2 : from : 11 sep 1996 **/ +/** to 28 sep 1998 **/ +/** # Version 4.0 : from : 29 nov 2003 **/ +/** to 14 jun 2004 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 27 sep 2008 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 01 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#ifndef ARCH_DECO_H_STRUCT +#define ARCH_DECO_H_STRUCT + +/*+ Decomposition architecture flags. +*/ + +#define ARCHDECONONE 0x0000 /*+ No options set +*/ + +#define ARCHDECOFREE 0x0001 /*+ Free arrays +*/ + +/* +** The type and structure definitions. +*/ + +/*+ The decomposition-described terminal vertex definition. +*/ + +typedef struct ArchDecoTermVert_ { + ArchDomNum labl; /*+ Number for terminals, or ARCHDOMNOTTERM +*/ + Anum wght; /*+ Weight of the domain (processor load) +*/ + Anum num; /*+ Number of the terminal +*/ +} ArchDecoTermVert; + +/*+ The decomposition-described architecture definitions. +*/ + +typedef struct ArchDecoVert_ { + ArchDomNum labl; /*+ Smallest number of included terminal +*/ + Anum size; /*+ Number of processors in the domain +*/ + Anum wght; /*+ Weight of the domain (processor load) +*/ +} ArchDecoVert; + +typedef struct ArchDeco_ { + int flagval; /*+ Flag value +*/ + Anum domtermnbr; /*+ Number of terminal domains +*/ + Anum domvertnbr; /*+ Number of domains +*/ + ArchDecoVert * domverttab; /*+ Table of domain "vertices" +*/ + Anum * domdisttab; /*+ Table of domain distances +*/ +} ArchDeco; + +typedef struct ArchDecoDom_ { + Anum num; /*+ Domain number in the decomposition +*/ +} ArchDecoDom; + +#endif /* ARCH_DECO_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_DECO_H_PROTO +#define ARCH_DECO_H_PROTO + +#ifndef ARCH_DECO +#define static +#endif + +int archDecoArchBuild (ArchDeco * const, const Anum, const Anum, const ArchDecoTermVert * const, const Anum * const); +int archDecoArchLoad (ArchDeco * const, FILE * restrict const); +int archDecoArchSave (const ArchDeco * const, FILE * restrict const); +int archDecoArchFree (ArchDeco * const); +Anum archDecoArchSize (ArchDeco * const, const Anum); +Anum archDecoArchDist (ArchDeco * const, const Anum, const Anum); +Anum archDecoArchDistE (ArchDeco * const, const Anum, const Anum); +ArchDomNum archDecoDomNum (const ArchDeco * const, const ArchDecoDom * const); +int archDecoDomTerm (const ArchDeco * const, ArchDecoDom * restrict const, const ArchDomNum); +Anum archDecoDomSize (const ArchDeco * const, const ArchDecoDom * const); +Anum archDecoDomWght (const ArchDeco * const, const ArchDecoDom * const); +Anum archDecoDomDist (const ArchDeco * const, const ArchDecoDom * const, const ArchDecoDom * const); +int archDecoDomFrst (const ArchDeco * const, ArchDecoDom * restrict const); +int archDecoDomLoad (const ArchDeco * const, ArchDecoDom * restrict const, FILE * restrict const); +int archDecoDomSave (const ArchDeco * const, const ArchDecoDom * const, FILE * restrict const); +int archDecoDomBipart (const ArchDeco * const, const ArchDecoDom * const, ArchDecoDom * restrict const, ArchDecoDom * restrict const); +int archDecoDomIncl (const ArchDeco * const, const ArchDecoDom * const, const ArchDecoDom * const); +#ifdef SCOTCH_PTSCOTCH +int archDecoDomMpiType (const ArchDeco * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +/* +** The macro definitions. +*/ + +#define archDecoArchSize(d,i) ((d)->domverttab[(i) - 1].size) +#define archDecoArchDist(d,i,j) ((d)->domdisttab[((i) >= (j)) ? (((i) - 1) * ((i) - 2)) / 2 + (j) - 1 \ + : (((j) - 1) * ((j) - 2)) / 2 + (i) - 1]) +#define archDecoArchDistE(d,i,j) (((i) == (j)) ? 0 : archDecoArchDist ((d), (i), (j))) + +#endif /* ARCH_DECO_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/arch_dist.c b/scotch_6.0.3/src/libscotch/arch_dist.c new file mode 100644 index 00000000..614721a4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_dist.c @@ -0,0 +1,321 @@ +/* Copyright 2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_dist.c **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the distance **/ +/** multiplicator pseudo-architecture **/ +/** functions. This pseudo-architecture is **/ +/** used by graph repartitioning routines **/ +/** to handle floating-point migration **/ +/** costs. **/ +/** **/ +/** DATES : # Version 6.0 : from : 14 fev 2011 **/ +/** to : 30 jun 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_DIST + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_dist.h" + +/**************************************/ +/* */ +/* These are the entry points for the */ +/* distance graph routines. They are */ +/* used only in debugging mode, to */ +/* provide breakpoints for routines */ +/* which are else implemented as */ +/* macros for the sake of efficiency. */ +/* */ +/**************************************/ + +/* This routine loads the distance +** graph architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archDistArchLoad ( +ArchDist * restrict const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if (sizeof (ArchDist) > sizeof (ArchDummy)) { + errorPrint ("archDistArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (intLoad (stream, &archptr->crloval) != 1) { + errorPrint ("archDistArchLoad: bad input"); + return (1); + } + + return (archLoad (archptr->archptr, stream)); /* Load sub-architecture */ +} + +/* This routine saves the +** distance graph architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archDistArchSave ( +const ArchDist * const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if (sizeof (ArchDist) > sizeof (ArchDummy)) { + errorPrint ("archDistArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING "\t", + (Anum) archptr->crloval) == EOF) { + errorPrint ("archDistArchSave: bad output"); + return (1); + } + + return (archSave (archptr->archptr, stream)); /* Save sub-architecture */ +} + +/* This routine build the +** distance graph architecture of +** an original one. +** It returns: +** - 0 : if the architecture has been successfully built. +** - !0 : on error. +*/ + +int +archDistArchBuild ( +Arch * const archptr, +Arch * const orgarchptr, +const Anum crloval) +{ + ArchDist * archdataptr; + + archInit (archptr); /* Initialize architecture body */ + archptr->class = archClass ("dist"); /* Set architecture class */ + archptr->flagval = orgarchptr->flagval; /* Set architecture flag */ + archdataptr = (ArchDist *) (void *) &archptr->data; + archdataptr->archptr = orgarchptr; + archdataptr->crloval = crloval; + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archDistDomNum ( +const ArchDist * const archptr, +const ArchDom * const domptr) +{ + return (archDomNum (archptr->archptr, domptr)); /* Call proper routine */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archDistDomTerm ( +const ArchDist * const archptr, +ArchDom * const domptr, +const ArchDomNum domnum) +{ + return (archDomTerm (archptr->archptr, domptr, domnum)); /* Call proper routine */ +} + +/* This function returns the number of +** elements in the distance domain. +*/ + +Anum +archDistDomSize ( +const ArchDist * const archptr, +const ArchDom * const domptr) +{ + return (archDomSize (archptr->archptr, domptr)); /* Call proper routine */ +} + +/* This function returns the weight of +** the given distance domain. +*/ + +Anum +archDistDomWght ( +const ArchDist * const archptr, +const ArchDom * const domptr) +{ + return (archDomWght (archptr->archptr, domptr)); /* Call proper routine */ +} + +/* This function returns the average +** distance between two distance +** subdomains. +*/ + +Anum +archDistDomDist ( +const ArchDist * const archptr, +const ArchDom * const dom0ptr, +const ArchDom * const dom1ptr) +{ + return (archptr->crloval * archDomDist (archptr->archptr, dom0ptr, dom1ptr)); +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archDistDomFrst ( +const ArchDist * const archptr, +ArchDom * restrict const domptr) +{ + return (archDomFrst (archptr->archptr, domptr)); /* Call proper routine */ +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archDistDomLoad ( +const ArchDist * const archptr, +ArchDom * restrict const domptr, +FILE * const stream) +{ + return (archDomLoad (archptr->archptr, domptr, stream)); /* Call proper routine */ +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archDistDomSave ( +const ArchDist * const archptr, +const ArchDom * const domptr, +FILE * const stream) +{ + return (archDomSave (archptr->archptr, domptr, stream)); /* Call proper routine */ +} + +/* This function tries to split a distance +** graph domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archDistDomBipart ( +const ArchDist * const archptr, +const ArchDom * const domptr, +ArchDom * restrict const dom0ptr, +ArchDom * restrict const dom1ptr) +{ + return (archDomBipart (archptr->archptr, domptr, dom0ptr, dom1ptr)); /* Call proper routine */ +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archDistDomIncl ( +const ArchDist * const archptr, +const ArchDom * const dom0ptr, +const ArchDom * const dom1ptr) +{ + return (archDomIncl (archptr->archptr, dom0ptr, dom1ptr)); /* Call proper routine */ +} + +/* This function creates the MPI_Datatype for +** distance graph domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archDistDomMpiType ( +const ArchDist * const archptr, +MPI_Datatype * const typeptr) +{ + return (archDomMpiType (archptr->archptr, typeptr)); /* Call proper routine as we don't add any parameter */ +} +#endif /* SCOTCH_PTSCOTCH */ + diff --git a/scotch_6.0.3/src/libscotch/arch_dist.h b/scotch_6.0.3/src/libscotch/arch_dist.h new file mode 100644 index 00000000..a140cf2a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_dist.h @@ -0,0 +1,101 @@ +/* Copyright 2011,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_dist.h **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the distance multiplicator pseudo- **/ +/** architecture functions. This pseudo- **/ +/** architecture is used by graph reparti- **/ +/** tioning routines to handle floating- **/ +/** point migration costs. **/ +/** **/ +/** DATES : # Version 6.0 : from : 14 fev 2011 **/ +/** to : 01 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +#ifndef ARCH_DIST_H_STRUCT +#define ARCH_DIST_H_STRUCT + +/*+ The distance graph definitions. +*/ + +typedef struct ArchDist_ { + struct Arch_ * archptr; /*+ Encapsulated architecture +*/ + Anum crloval; /*+ Coefficient load for regular edges +*/ +} ArchDist; + +#define ArchDistDom ArchDom /*+ Domain is the regular domain +*/ + +#endif /* ARCH_DIST_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_DIST_H_PROTO +#define ARCH_DIST_H_PROTO + +#ifndef ARCH_DIST +#define static +#endif + +int archDistArchLoad (ArchDist * restrict const, FILE * restrict const); +int archDistArchSave (const ArchDist * const, FILE * restrict const); +#define archDistArchFree NULL +int archDistArchBuild (struct Arch_ * const, struct Arch_ * const, const Anum); +ArchDomNum archDistDomNum (const ArchDist * const, const ArchDom * const); +int archDistDomTerm (const ArchDist * const, ArchDom * restrict const, const ArchDomNum); +Anum archDistDomSize (const ArchDist * const, const ArchDom * const); +Anum archDistDomWght (const ArchDist * const, const ArchDom * const); +Anum archDistDomDist (const ArchDist * const, const ArchDom * const, const ArchDom * const); +int archDistDomFrst (const ArchDist * const, ArchDom * const); +int archDistDomLoad (const ArchDist * const, ArchDom * const, FILE * const); +int archDistDomSave (const ArchDist * const, const ArchDom * const, FILE * const); +int archDistDomBipart (const ArchDist * const, const ArchDom * const, ArchDom * restrict const, ArchDom * restrict const); +int archDistDomIncl (const ArchDist * const, const ArchDom * const, const ArchDom * const); +#ifdef SCOTCH_PTSCOTCH +int archDistDomMpiType (const ArchDist * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +#endif /* ARCH_DIST_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/arch_hcub.c b/scotch_6.0.3/src/libscotch/arch_hcub.c new file mode 100644 index 00000000..52fdbb98 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_hcub.c @@ -0,0 +1,350 @@ +/* Copyright 2004,2007,2008,2010-2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_hcub.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the hypercube **/ +/** target architecture. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 23 dec 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 29 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 08 sep 1995 **/ +/** # Version 3.1 : from : 11 jun 1996 **/ +/** to 11 jun 1996 **/ +/** # Version 3.2 : from : 21 sep 1996 **/ +/** to 14 may 1998 **/ +/** # Version 4.0 : from : 11 nov 2003 **/ +/** to 10 mar 2005 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 14 fev 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_HCUB + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_hcub.h" + +/********************************************/ +/* */ +/* These are the binary hypercube routines. */ +/* */ +/********************************************/ + +/* This routine loads the binary +** hypercube architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archHcubArchLoad ( +ArchHcub * restrict const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchHcub) > sizeof (ArchDummy)) || + (sizeof (ArchHcubDom) > sizeof (ArchDomDummy))) { + errorPrint ("archHcubArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((intLoad (stream, &archptr->dimmax) != 1) || + (archptr->dimmax < 1) || + (archptr->dimmax > (sizeof (archptr->dimmax) << 3))) { + errorPrint ("archHcubArchLoad: bad input"); + return (1); + } + + return (0); +} + +/* This routine saves the +** binary hypercube architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archHcubArchSave ( +const ArchHcub * const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchHcub) > sizeof (ArchDummy)) || + (sizeof (ArchHcubDom) > sizeof (ArchDomDummy))) { + errorPrint ("archHcubArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING " ", (Anum) archptr->dimmax) == EOF) { + errorPrint ("archHcubArchSave: bad output"); + return (1); + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archHcubDomNum ( +const ArchHcub * const archptr, +const ArchHcubDom * const domptr) +{ + return (domptr->bitset); /* Return vertex number */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archHcubDomTerm ( +const ArchHcub * const archptr, +ArchHcubDom * const domptr, +const ArchDomNum domnum) +{ + if (domnum < (1 << archptr->dimmax)) { /* If valid label */ + domptr->dimcur = 0; /* Set the domain */ + domptr->bitset = domnum; + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the hypercube domain. +*/ + +Anum +archHcubDomSize ( +const ArchHcub * const archptr, +const ArchHcubDom * const domptr) +{ + return (1 << domptr->dimcur); +} + +/* This function returns the average distance +** between two sub-hypercubes. +*/ + +Anum +archHcubDomDist ( +const ArchHcub * const archptr, +const ArchHcubDom * const dom0ptr, +const ArchHcubDom * const dom1ptr) +{ + Anum i, j, k; + + if (dom0ptr->dimcur > dom1ptr->dimcur) { /* Get smallest set dimension value */ + i = dom0ptr->dimcur; + j = i - dom1ptr->dimcur; + } + else { + i = dom1ptr->dimcur; + j = i - dom0ptr->dimcur; + } + j /= 2; /* For set/unset bits, assume 1/2 difference */ + + for (k = (dom0ptr->bitset ^ dom1ptr->bitset) >> i, i = archptr->dimmax - i; + i > 0; + k >>= 1, i --) + j += (k & 1); /* Add Hamming difference on set dimensions */ + + return (j); +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archHcubDomFrst ( +const ArchHcub * const archptr, +ArchHcubDom * restrict const domptr) +{ + domptr->dimcur = archptr->dimmax; + domptr->bitset = 0; + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archHcubDomLoad ( +const ArchHcub * const archptr, +ArchHcubDom * restrict const domptr, +FILE * restrict const stream) +{ + if ((intLoad (stream, &domptr->dimcur) != 1) || + (intLoad (stream, &domptr->bitset) != 1) || + (domptr->dimcur > archptr->dimmax)) { + errorPrint ("archHcubDomLoad: bad input"); + return (1); + } + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archHcubDomSave ( +const ArchHcub * const archptr, +const ArchHcubDom * const domptr, +FILE * restrict const stream) +{ + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", + (Anum) domptr->dimcur, + (Anum) domptr->bitset) == EOF) { + errorPrint ("archHcubDomSave: bad output"); + return (1); + } + + return (0); +} + +/* This function tries to split a hypercube +** domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archHcubDomBipart ( +const ArchHcub * const archptr, +const ArchHcubDom * const domptr, +ArchHcubDom * restrict const dom0ptr, +ArchHcubDom * restrict const dom1ptr) +{ + if (domptr->dimcur <= 0) /* Return if cannot bipartition more */ + return (1); + + dom0ptr->dimcur = + dom1ptr->dimcur = domptr->dimcur - 1; + dom0ptr->bitset = domptr->bitset; + dom1ptr->bitset = domptr->bitset | (1 << dom1ptr->dimcur); + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archHcubDomIncl ( +const ArchHcub * const archptr, +const ArchHcubDom * const dom0ptr, +const ArchHcubDom * const dom1ptr) +{ + if ((dom0ptr->dimcur >= dom1ptr->dimcur) && + (((dom0ptr->bitset ^ dom1ptr->bitset) >> dom0ptr->dimcur) == 0)) + return (1); + + return (0); +} + +/* This function creates the MPI_Datatype for +** hypercube domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archHcubDomMpiType ( +const ArchHcub * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (2, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch_hcub.h b/scotch_6.0.3/src/libscotch/arch_hcub.h new file mode 100644 index 00000000..694cb33b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_hcub.h @@ -0,0 +1,119 @@ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_hcub.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the hypercube graph target **/ +/** architecture functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 09 aug 1995 **/ +/** # Version 3.1 : from : 11 jun 1996 **/ +/** to 11 jun 1996 **/ +/** # Version 3.2 : from : 21 sep 1996 **/ +/** to 13 may 1998 **/ +/** # Version 4.0 : from : 11 nov 2003 **/ +/** to 11 nov 2003 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 21 jan 2008 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 01 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +#ifndef ARCH_HCUB_H_STRUCT +#define ARCH_HCUB_H_STRUCT + +/*+ The binary hypercube definitions. +*/ + +typedef struct ArchHcub_ { + Anum dimmax; /*+ Number of hypercube dimensions +*/ +} ArchHcub; + +typedef struct ArchHcubDom_ { + Anum dimcur; /*+ Current dimension to be set +*/ + Anum bitset; /*+ Bit set of set dimensions +*/ +} ArchHcubDom; + +#endif /* ARCH_HCUB_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_HCUB_H_PROTO +#define ARCH_HCUB_H_PROTO + +#ifndef ARCH_HCUB +#define static +#endif + +int archHcubArchLoad (ArchHcub * restrict const, FILE * restrict const); +int archHcubArchSave (const ArchHcub * const, FILE * restrict const); +#define archHcubArchFree NULL +ArchDomNum archHcubDomNum (const ArchHcub * const, const ArchHcubDom * const); +int archHcubDomTerm (const ArchHcub * const, ArchHcubDom * restrict const, const ArchDomNum); +Anum archHcubDomSize (const ArchHcub * const, const ArchHcubDom * const); +#define archHcubDomWght archHcubDomSize +Anum archHcubDomDist (const ArchHcub * const, const ArchHcubDom * const, const ArchHcubDom * const); +int archHcubDomFrst (const ArchHcub * const, ArchHcubDom * restrict const); +int archHcubDomLoad (const ArchHcub * const, ArchHcubDom * restrict const, FILE * restrict const); +int archHcubDomSave (const ArchHcub * const, const ArchHcubDom * const, FILE * restrict const); +int archHcubDomBipart (const ArchHcub * const, const ArchHcubDom * const, ArchHcubDom * restrict const, ArchHcubDom * restrict const); +int archHcubDomIncl (const ArchHcub * const, const ArchHcubDom * const, const ArchHcubDom * const); +#ifdef SCOTCH_PTSCOTCH +int archHcubDomMpiType (const ArchHcub * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +#endif /* ARCH_HCUB_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/arch_mesh.c b/scotch_6.0.3/src/libscotch/arch_mesh.c new file mode 100644 index 00000000..058f1a2d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_mesh.c @@ -0,0 +1,775 @@ +/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_mesh.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the mesh graph **/ +/** target architectures. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 23 dec 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 29 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 08 sep 1995 **/ +/** # Version 3.1 : from : 22 jul 1996 **/ +/** to 23 jul 1996 **/ +/** # Version 3.2 : from : 16 oct 1996 **/ +/** to 14 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 09 jan 2004 **/ +/** to 10 mar 2005 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 14 fev 2011 **/ +/** **/ +/** NOTES : # The vertices of the (dX,dY) mesh are **/ +/** numbered as terminals so that **/ +/** t(0,0) = 0, t(1,0) = 1, **/ +/** t(dX - 1, 0) = dX - 1, t(0,1) = dX, **/ +/** and t(x,y) = (y * dX) + x. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_MESH + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_mesh.h" + +/***********************************************/ +/* */ +/* These are the 2-dimensional mesh routines. */ +/* */ +/***********************************************/ + +/* This routine loads the +** bidimensional mesh architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archMesh2ArchLoad ( +ArchMesh2 * restrict const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchMesh2) > sizeof (ArchDummy)) || + (sizeof (ArchMesh2Dom) > sizeof (ArchDomDummy))) { + errorPrint ("archMesh2ArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((intLoad (stream, &archptr->c[0]) != 1) || + (intLoad (stream, &archptr->c[1]) != 1) || + (archptr->c[0] < 1) || (archptr->c[1] < 1)) { + errorPrint ("archMesh2ArchLoad: bad input"); + return (1); + } + + return (0); +} + +/* This routine saves the +** bidimensional mesh architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archMesh2ArchSave ( +const ArchMesh2 * const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchMesh2) > sizeof (ArchDummy)) || + (sizeof (ArchMesh2Dom) > sizeof (ArchDomDummy))) { + errorPrint ("archMesh2ArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", + (Anum) archptr->c[0], + (Anum) archptr->c[1]) == EOF) { + errorPrint ("archMesh2ArchSave: bad output"); + return (1); + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archMesh2DomNum ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const domptr) +{ + return ((domptr->c[1][0] * archptr->c[0]) + domptr->c[0][0]); /* Return vertex number */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archMesh2DomTerm ( +const ArchMesh2 * const archptr, +ArchMesh2Dom * const domptr, +const ArchDomNum domnum) +{ + if (domnum < (archptr->c[0] * archptr->c[1])) { /* If valid label */ + domptr->c[0][0] = /* Set the domain */ + domptr->c[0][1] = domnum % archptr->c[0]; + domptr->c[1][0] = + domptr->c[1][1] = domnum / archptr->c[0]; + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the rectangular domain. +*/ + +Anum +archMesh2DomSize ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const domptr) +{ + return ((domptr->c[0][1] - domptr->c[0][0] + 1) * + (domptr->c[1][1] - domptr->c[1][0] + 1)); +} + +/* This function returns the average +** distance between two rectangular +** domains (in fact the distance between +** the centers of the domains). +*/ + +Anum +archMesh2DomDist ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const dom0ptr, +const ArchMesh2Dom * const dom1ptr) +{ + return (((abs (dom0ptr->c[0][0] + dom0ptr->c[0][1] - + dom1ptr->c[0][0] - dom1ptr->c[0][1]) + 1) / 2) + + ((abs (dom0ptr->c[1][0] + dom0ptr->c[1][1] - + dom1ptr->c[1][0] - dom1ptr->c[1][1]) + 1) / 2)); +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archMesh2DomFrst ( +const ArchMesh2 * const archptr, +ArchMesh2Dom * restrict const domptr) +{ + domptr->c[0][0] = + domptr->c[1][0] = 0; + domptr->c[0][1] = archptr->c[0] - 1; + domptr->c[1][1] = archptr->c[1] - 1; + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archMesh2DomLoad ( +const ArchMesh2 * const archptr, +ArchMesh2Dom * restrict const domptr, +FILE * restrict const stream) +{ + if ((intLoad (stream, &domptr->c[0][0]) != 1) || + (intLoad (stream, &domptr->c[1][0]) != 1) || + (intLoad (stream, &domptr->c[0][1]) != 1) || + (intLoad (stream, &domptr->c[1][1]) != 1)) { + errorPrint ("archMesh2DomLoad: bad input"); + return (1); + } + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** - 0 : on success. +** - !0 : on error. +*/ + +int +archMesh2DomSave ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const domptr, +FILE * restrict const stream) +{ + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", + (Anum) domptr->c[0][0], (Anum) domptr->c[1][0], + (Anum) domptr->c[0][1], (Anum) domptr->c[1][1]) == EOF) { + errorPrint ("archMesh2DomSave: bad output"); + return (1); + } + + return (0); +} + +/* These functions try to split a rectangular +** domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archMesh2DomBipart ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const domptr, +ArchMesh2Dom * restrict const dom0ptr, +ArchMesh2Dom * restrict const dom1ptr) +{ + Anum dimsiz[2]; + int dimval; /* Dimension along which to split */ + + dimsiz[0] = domptr->c[0][1] - domptr->c[0][0]; + dimsiz[1] = domptr->c[1][1] - domptr->c[1][0]; + + if ((dimsiz[0] | dimsiz[1]) == 0) /* Return if cannot bipartition more */ + return (1); + + dimval = 1; + if ((dimsiz[0] > dimsiz[1]) || /* Split domain in two along largest dimension */ + ((dimsiz[0] == dimsiz[1]) && (archptr->c[0] > archptr->c[1]))) + dimval = 0; + + if (dimval == 0) { /* Split across the X dimension */ + dom0ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; + dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; + dom1ptr->c[0][1] = domptr->c[0][1]; + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; + } + else { /* Split across the Y dimension */ + dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + dom0ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; + dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; + dom1ptr->c[1][1] = domptr->c[1][1]; + } + + return (0); +} + +int +archMesh2DomBipartO ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const domptr, +ArchMesh2Dom * restrict const dom0ptr, +ArchMesh2Dom * restrict const dom1ptr) +{ + if ((domptr->c[0][0] == domptr->c[0][1]) && /* Return if cannot bipartition more */ + (domptr->c[1][0] == domptr->c[1][1])) + return (1); + + if (domptr->c[1][1] == domptr->c[1][0]) { /* If the Y dimension cannot be cut */ + dom0ptr->c[0][0] = domptr->c[0][0]; /* Cut in the X dimension */ + dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; + dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; + dom1ptr->c[0][1] = domptr->c[0][1]; + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; + } + else { /* If the Y dimension can be cut, cut it */ + dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + dom0ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; + dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; + dom1ptr->c[1][1] = domptr->c[1][1]; + } + + return (0); +} + +int +archMesh2DomBipartU ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const domptr, +ArchMesh2Dom * restrict const dom0ptr, +ArchMesh2Dom * restrict const dom1ptr) +{ + if ((domptr->c[0][0] == domptr->c[0][1]) && /* Return if cannot bipartition more */ + (domptr->c[1][0] == domptr->c[1][1])) + return (1); + + if ((domptr->c[0][1] - domptr->c[0][0]) > /* Split domain unevenly along largest dimension */ + (domptr->c[1][1] - domptr->c[1][0])) { + dom0ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1] + domptr->c[0][1]) / 3; + dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; + dom1ptr->c[0][1] = domptr->c[0][1]; + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; + } + else { + dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + dom0ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1] + domptr->c[1][1]) / 3; + dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; + dom1ptr->c[1][1] = domptr->c[1][1]; + } + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archMesh2DomIncl ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const dom0ptr, +const ArchMesh2Dom * const dom1ptr) +{ + if ((dom0ptr->c[0][0] <= dom1ptr->c[0][0]) && + (dom0ptr->c[0][1] >= dom1ptr->c[0][1]) && + (dom0ptr->c[1][0] <= dom1ptr->c[1][0]) && + (dom0ptr->c[1][1] >= dom1ptr->c[1][1])) + return (1); + + return (0); +} + +/* This function creates the MPI_Datatype for +** 2D mesh domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archMesh2DomMpiType ( +const ArchMesh2 * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (4, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ + +/***********************************************/ +/* */ +/* These are the 3-dimensional mesh routines. */ +/* */ +/***********************************************/ + +/* This routine loads the +** tridimensional mesh architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archMesh3ArchLoad ( +ArchMesh3 * restrict const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchMesh3) > sizeof (ArchDummy)) || + (sizeof (ArchMesh3Dom) > sizeof (ArchDomDummy))) { + errorPrint ("archMesh3ArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((intLoad (stream, &archptr->c[0]) != 1) || + (intLoad (stream, &archptr->c[1]) != 1) || + (intLoad (stream, &archptr->c[2]) != 1) || + (archptr->c[0] < 1) || (archptr->c[1] < 1) || (archptr->c[2] < 1)) { + errorPrint ("archMesh3ArchLoad: bad input"); + return (1); + } + + return (0); +} + +/* This routine saves the +** tridimensional mesh architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archMesh3ArchSave ( +const ArchMesh3 * const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchMesh3) > sizeof (ArchDummy)) || + (sizeof (ArchMesh3Dom) > sizeof (ArchDomDummy))) { + errorPrint ("archMesh3ArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", + (Anum) archptr->c[0], (Anum) archptr->c[1], (Anum) archptr->c[2]) == EOF) { + errorPrint ("archMesh3ArchSave: bad output"); + return (1); + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archMesh3DomNum ( +const ArchMesh3 * const archptr, +const ArchMesh3Dom * const domptr) +{ + return ((((domptr->c[2][0] * archptr->c[1]) + /* Return the vertex number */ + domptr->c[1][0]) * archptr->c[0]) + + domptr->c[0][0]); +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archMesh3DomTerm ( +const ArchMesh3 * const archptr, +ArchMesh3Dom * const domptr, +const ArchDomNum domnum) +{ + if (domnum < (archptr->c[0] * archptr->c[1] * archptr->c[2])) { /* If valid label */ + domptr->c[0][0] = /* Set the domain */ + domptr->c[0][1] = domnum % archptr->c[0]; + domptr->c[1][0] = + domptr->c[1][1] = (domnum / archptr->c[0]) % archptr->c[1]; + domptr->c[2][0] = + domptr->c[2][1] = domnum / (archptr->c[0] * archptr->c[1]); + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the cubic domain. +*/ + +Anum +archMesh3DomSize ( +const ArchMesh3 * const archptr, +const ArchMesh3Dom * const domptr) +{ + return ((domptr->c[0][1] - domptr->c[0][0] + 1) * + (domptr->c[1][1] - domptr->c[1][0] + 1) * + (domptr->c[2][1] - domptr->c[2][0] + 1)); +} + +/* This function returns the average distance +** between two cubic domains (in fact the +** distance between the centers of the domains). +*/ + +Anum +archMesh3DomDist ( +const ArchMesh3 * const archptr, +const ArchMesh3Dom * const dom0ptr, +const ArchMesh3Dom * const dom1ptr) +{ + return (((abs (dom0ptr->c[0][0] + dom0ptr->c[0][1] - + dom1ptr->c[0][0] - dom1ptr->c[0][1]) + 1) / 2) + + ((abs (dom0ptr->c[1][0] + dom0ptr->c[1][1] - + dom1ptr->c[1][0] - dom1ptr->c[1][1]) + 1) / 2) + + ((abs (dom0ptr->c[2][0] + dom0ptr->c[2][1] - + dom1ptr->c[2][0] - dom1ptr->c[2][1]) + 1) / 2)); +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archMesh3DomFrst ( +const ArchMesh3 * const archptr, +ArchMesh3Dom * restrict const domptr) +{ + domptr->c[0][0] = + domptr->c[1][0] = + domptr->c[2][0] = 0; + domptr->c[0][1] = archptr->c[0] - 1; + domptr->c[1][1] = archptr->c[1] - 1; + domptr->c[2][1] = archptr->c[2] - 1; + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archMesh3DomLoad ( +const ArchMesh3 * const archptr, +ArchMesh3Dom * restrict const domptr, +FILE * restrict const stream) +{ + if ((intLoad (stream, &domptr->c[0][0]) != 1) || + (intLoad (stream, &domptr->c[1][0]) != 1) || + (intLoad (stream, &domptr->c[2][0]) != 1) || + (intLoad (stream, &domptr->c[0][1]) != 1) || + (intLoad (stream, &domptr->c[1][1]) != 1) || + (intLoad (stream, &domptr->c[2][1]) != 1)) { + errorPrint ("archMesh3DomLoad: bad input"); + return (1); + } + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archMesh3DomSave ( +const ArchMesh3 * const archptr, +const ArchMesh3Dom * const domptr, +FILE * restrict const stream) +{ + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", + (Anum) domptr->c[0][0], (Anum) domptr->c[1][0], (Anum) domptr->c[2][0], + (Anum) domptr->c[0][1], (Anum) domptr->c[1][1], (Anum) domptr->c[2][1]) == EOF) { + errorPrint ("archMesh3DomSave: bad output"); + return (1); + } + + return (0); +} + +/* This function tries to split a cubic +** domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archMesh3DomBipart ( +const ArchMesh3 * const archptr, +const ArchMesh3Dom * const domptr, +ArchMesh3Dom * restrict const dom0ptr, +ArchMesh3Dom * restrict const dom1ptr) +{ + Anum dimsiz[3]; + int dimtmp; + int dimval; + + dimsiz[0] = domptr->c[0][1] - domptr->c[0][0]; + dimsiz[1] = domptr->c[1][1] - domptr->c[1][0]; + dimsiz[2] = domptr->c[2][1] - domptr->c[2][0]; + + if ((dimsiz[0] | dimsiz[1] | dimsiz[2]) == 0) /* Return if cannot bipartition more */ + return (1); + + dimval = (archptr->c[1] > archptr->c[0]) ? 1 : 0; /* Assume all subdomain dimensions are equal */ + if (archptr->c[2] > archptr->c[dimval]) /* Find priviledged dimension */ + dimval = 2; + + dimtmp = dimval; /* Find best dimension */ + if (dimsiz[(dimtmp + 1) % 3] > dimsiz[dimval]) + dimval = (dimtmp + 1) % 3; + if (dimsiz[(dimtmp + 2) % 3] > dimsiz[dimval]) + dimval = (dimtmp + 2) % 3; + + if (dimval == 0) { /* Split domain in two along largest dimension */ + dom0ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; + dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; + dom1ptr->c[0][1] = domptr->c[0][1]; + + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; + + dom0ptr->c[2][0] = dom1ptr->c[2][0] = domptr->c[2][0]; + dom0ptr->c[2][1] = dom1ptr->c[2][1] = domptr->c[2][1]; + } + else if (dimval == 1) { + dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + + dom0ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; + dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; + dom1ptr->c[1][1] = domptr->c[1][1]; + + dom0ptr->c[2][0] = dom1ptr->c[2][0] = domptr->c[2][0]; + dom0ptr->c[2][1] = dom1ptr->c[2][1] = domptr->c[2][1]; + } + else { + dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; + + dom0ptr->c[2][0] = domptr->c[2][0]; + dom0ptr->c[2][1] = (domptr->c[2][0] + domptr->c[2][1]) / 2; + dom1ptr->c[2][0] = dom0ptr->c[2][1] + 1; + dom1ptr->c[2][1] = domptr->c[2][1]; + } + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archMesh3DomIncl ( +const ArchMesh3 * const archptr, +const ArchMesh3Dom * const dom0ptr, +const ArchMesh3Dom * const dom1ptr) +{ + if ((dom0ptr->c[0][0] <= dom1ptr->c[0][0]) && + (dom0ptr->c[0][1] >= dom1ptr->c[0][1]) && + (dom0ptr->c[1][0] <= dom1ptr->c[1][0]) && + (dom0ptr->c[1][1] >= dom1ptr->c[1][1]) && + (dom0ptr->c[2][0] <= dom1ptr->c[2][0]) && + (dom0ptr->c[2][1] >= dom1ptr->c[2][1])) + return (1); + + return (0); +} + +/* This function creates the MPI_Datatype for +** 3D mesh domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archMesh3DomMpiType ( +const ArchMesh3 * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (6, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch_mesh.h b/scotch_6.0.3/src/libscotch/arch_mesh.h new file mode 100644 index 00000000..3715927c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_mesh.h @@ -0,0 +1,150 @@ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_mesh.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the mesh graph target architecture **/ +/** functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 17 aug 1995 **/ +/** # Version 3.1 : from : 22 jul 1996 **/ +/** to 23 jul 1996 **/ +/** # Version 3.2 : from : 16 oct 1996 **/ +/** to 14 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 09 jan 2004 **/ +/** to 09 jan 2004 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 21 jan 2008 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 01 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +#ifndef ARCH_MESH_H_STRUCT +#define ARCH_MESH_H_STRUCT + +/*+ The 2D-mesh definitions. +*/ + +typedef struct ArchMesh2_ { + Anum c[2]; /*+ Mesh dimensions +*/ +} ArchMesh2; + +typedef struct ArchMesh2Dom_ { + Anum c[2][2]; /*+ Inclusive X and Y coordinates +*/ +} ArchMesh2Dom; + +/*+ The 3D-mesh definitions. +*/ + +typedef struct ArchMesh3_ { + Anum c[3]; /*+ Mesh dimensions +*/ +} ArchMesh3; + +typedef struct ArchMesh3Dom_ { + Anum c[3][2]; /*+ Inclusive X, Y, and Z coordinates +*/ +} ArchMesh3Dom; + +#endif /* ARCH_MESH_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_MESH_H_PROTO +#define ARCH_MESH_H_PROTO + +#ifndef ARCH_MESH +#define static +#endif + +int archMesh2ArchLoad (ArchMesh2 * restrict const, FILE * restrict const); +int archMesh2ArchSave (const ArchMesh2 * const, FILE * restrict const); +#define archMesh2ArchFree NULL +ArchDomNum archMesh2DomNum (const ArchMesh2 * const, const ArchMesh2Dom * const); +int archMesh2DomTerm (const ArchMesh2 * const, ArchMesh2Dom * restrict const, const ArchDomNum); +Anum archMesh2DomSize (const ArchMesh2 * const, const ArchMesh2Dom * const); +#define archMesh2DomWght archMesh2DomSize +Anum archMesh2DomDist (const ArchMesh2 * const, const ArchMesh2Dom * const, const ArchMesh2Dom * const); +int archMesh2DomFrst (const ArchMesh2 * const, ArchMesh2Dom * const); +int archMesh2DomLoad (const ArchMesh2 * const, ArchMesh2Dom * const, FILE * restrict const); +int archMesh2DomSave (const ArchMesh2 * const, const ArchMesh2Dom * const, FILE * restrict const); +int archMesh2DomBipart (const ArchMesh2 * const, const ArchMesh2Dom * const, ArchMesh2Dom * restrict const, ArchMesh2Dom * restrict const); +int archMesh2DomBipartO (const ArchMesh2 * const, const ArchMesh2Dom * const, ArchMesh2Dom * restrict const, ArchMesh2Dom * restrict const); +int archMesh2DomBipartU (const ArchMesh2 * const, const ArchMesh2Dom * const, ArchMesh2Dom * restrict const, ArchMesh2Dom * restrict const); +int archMesh2DomIncl (const ArchMesh2 * const, const ArchMesh2Dom * const, const ArchMesh2Dom * const); +#ifdef SCOTCH_PTSCOTCH +int archMesh2DomMpiType (const ArchMesh2 * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +int archMesh3ArchLoad (ArchMesh3 * restrict const, FILE * restrict const); +int archMesh3ArchSave (const ArchMesh3 * const, FILE * restrict const); +#define archMesh3ArchFree NULL +ArchDomNum archMesh3DomNum (const ArchMesh3 * const, const ArchMesh3Dom * const); +int archMesh3DomTerm (const ArchMesh3 * const, ArchMesh3Dom * restrict const, const ArchDomNum); +Anum archMesh3DomSize (const ArchMesh3 * const, const ArchMesh3Dom * const); +#define archMesh3DomWght archMesh3DomSize +Anum archMesh3DomDist (const ArchMesh3 * const, const ArchMesh3Dom * const, const ArchMesh3Dom * const); +int archMesh3DomFrst (const ArchMesh3 * const, ArchMesh3Dom * const); +int archMesh3DomLoad (const ArchMesh3 * const, ArchMesh3Dom * const, FILE * restrict const); +int archMesh3DomSave (const ArchMesh3 * const, const ArchMesh3Dom * const, FILE * restrict const); +int archMesh3DomBipart (const ArchMesh3 * const, const ArchMesh3Dom * const, ArchMesh3Dom * restrict const, ArchMesh3Dom * restrict const); +int archMesh3DomIncl (const ArchMesh3 * const, const ArchMesh3Dom * const, const ArchMesh3Dom * const); +#ifdef SCOTCH_PTSCOTCH +int archMesh3DomMpiType (const ArchMesh3 * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +#endif /* ARCH_MESH_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/arch_tleaf.c b/scotch_6.0.3/src/libscotch/arch_tleaf.c new file mode 100644 index 00000000..a337c9ed --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_tleaf.c @@ -0,0 +1,683 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_tleaf.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the tree-leaf **/ +/** target architecture. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 23 dec 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 29 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 08 sep 1995 **/ +/** # Version 3.1 : from : 20 jul 1996 **/ +/** to 20 jul 1996 **/ +/** # Version 3.2 : from : 10 oct 1996 **/ +/** to 14 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 07 jun 2001 **/ +/** to 07 jun 2001 **/ +/** # Version 4.0 : from : 10 dec 2003 **/ +/** to 10 mar 2005 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 01 jul 2012 **/ +/** **/ +/** NOTES : # The ltleaf architecture was proposed **/ +/** by Emmanuel Jeannot and Francois **/ +/** Tessier. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_TLEAF + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_tleaf.h" + +/*******************************************/ +/* */ +/* These are the tree-leaf graph routines. */ +/* */ +/*******************************************/ + +/* This routine loads the +** tree leaf architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archTleafArchLoad ( +ArchTleaf * restrict const archptr, +FILE * restrict const stream) +{ + Anum sizeval; + Anum levlnum; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchTleaf) > sizeof (ArchDummy)) || + (sizeof (ArchTleafDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTleafArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (intLoad (stream, &archptr->levlnbr) != 1) { + errorPrint ("archTleafArchLoad: bad input (1)"); + return (1); + } + + if ((archptr->sizetab = memAlloc ((archptr->levlnbr * 2 + 1) * sizeof (Anum))) == NULL) { /* TRICK: One more slot for linktab[-1] */ + errorPrint ("archTleafArchLoad: out of memory"); + return (1); + } + archptr->linktab = archptr->sizetab + archptr->levlnbr + 1; /* TRICK: One more slot */ + archptr->linktab[-1] = 0; /* Dummy slot for for level-0 communication */ + archptr->permtab = NULL; /* Assume no permutation array */ + + for (levlnum = 0, sizeval = 1; levlnum < archptr->levlnbr; levlnum ++) { + if ((intLoad (stream, &archptr->sizetab[levlnum]) != 1) || + (intLoad (stream, &archptr->linktab[levlnum]) != 1) || + (archptr->sizetab[levlnum] < 2) || + (archptr->linktab[levlnum] < 1)) { + errorPrint ("archTleafArchLoad: bad input (2)"); + return (1); + } + sizeval *= archptr->sizetab[levlnum]; + } + archptr->termnbr = sizeval; + + return (0); +} + +/* This routine frees the tree +** leaf architecture structures. +** It returns: +** - 0 : if the architecture has been successfully freed. +** - !0 : on error. +*/ + +int +archTleafArchFree ( +ArchTleaf * const archptr) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchTleaf) > sizeof (ArchDummy)) || + (sizeof (ArchTleafDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTleafArchFree: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + memFree (archptr->sizetab); /* Free group leader */ + if (archptr->permtab != NULL) + memFree (archptr->permtab); /* Free group leader */ + +#ifdef SCOTCH_DEBUG_ARCH2 + archptr->sizetab = + archptr->linktab = + archptr->permtab = NULL; +#endif /* SCOTCH_DEBUG_ARCH2 */ + + return (0); +} + +/* This routine saves the +** tree leaf architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archTleafArchSave ( +const ArchTleaf * const archptr, +FILE * restrict const stream) +{ + Anum levlnum; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchTleaf) > sizeof (ArchDummy)) || + (sizeof (ArchTleafDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTleafArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING, + (Anum) archptr->levlnbr) == EOF) { + errorPrint ("archTleafArchSave: bad output (1)"); + return (1); + } + + for (levlnum = 0; levlnum < archptr->levlnbr; levlnum ++) { + if (fprintf (stream, " " ANUMSTRING " " ANUMSTRING, + (Anum) archptr->sizetab[levlnum], + (Anum) archptr->linktab[levlnum]) == EOF) { + errorPrint ("archTleafArchSave: bad output (2)"); + return (1); + } + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archTleafDomNum ( +const ArchTleaf * const archptr, +const ArchTleafDom * const domnptr) +{ + Anum levlnum; + Anum sizeval; + + sizeval = 1; /* Compute size of blocks below */ + for (levlnum = domnptr->levlnum; levlnum < archptr->levlnbr; levlnum ++) + sizeval *= archptr->sizetab[levlnum]; + + return (domnptr->indxmin * sizeval); +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archTleafDomTerm ( +const ArchTleaf * const archptr, +ArchTleafDom * const domnptr, +const ArchDomNum domnnum) +{ +#ifdef SCOTCH_DEBUG_ARCH2 + if (domnnum < 0) { + errorPrint ("archTleafDomTerm: invalid parameter"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH2 */ + + if (domnnum < archptr->termnbr) { /* If valid label */ + domnptr->levlnum = archptr->levlnbr; /* Set the domain */ + domnptr->indxmin = domnnum; + domnptr->indxnbr = 1; + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the subtree domain. +*/ + +Anum +archTleafDomSize ( +const ArchTleaf * const archptr, +const ArchTleafDom * const domnptr) +{ + Anum levlnum; + Anum sizeval; + + sizeval = 1; /* Compute size of blocks below */ + for (levlnum = domnptr->levlnum; levlnum < archptr->levlnbr; levlnum ++) + sizeval *= archptr->sizetab[levlnum]; + + return (sizeval * domnptr->indxnbr); +} + +/* This function returns the average +** distance between two tree leaf +** subdomains. +*/ + +Anum +archTleafDomDist ( +const ArchTleaf * const archptr, +const ArchTleafDom * const dom0ptr, +const ArchTleafDom * const dom1ptr) +{ + Anum lev0num; + Anum lev1num; + Anum idx0min; + Anum idx1min; + Anum idx0nbr; + Anum idx1nbr; + Anum distval; + + const Anum * const sizetab = archptr->sizetab; + + lev0num = dom0ptr->levlnum; + lev1num = dom1ptr->levlnum; + idx0min = dom0ptr->indxmin; + idx1min = dom1ptr->indxmin; + idx0nbr = dom0ptr->indxnbr; + idx1nbr = dom1ptr->indxnbr; + + if (lev0num != lev1num) { + if (lev0num > lev1num) { + idx0nbr = 1; + do { + lev0num --; + idx0min /= sizetab[lev0num]; + } while (lev0num > lev1num); + } + else { + idx1nbr = 1; + do { + lev1num --; + idx1min /= sizetab[lev1num]; + } while (lev1num > lev0num); + } + } + + distval = archptr->linktab[lev0num - 1]; /* Get cost at this level */ + + return (((idx0min >= (idx1min + idx1nbr)) || /* If inclusion, only half of the distance */ + (idx1min >= (idx0min + idx0nbr))) ? distval : ((idx0nbr == idx1nbr) ? 0 : (distval >> 1))); +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archTleafDomFrst ( +const ArchTleaf * const archptr, +ArchTleafDom * restrict const domnptr) +{ + domnptr->levlnum = 0; + domnptr->indxmin = 0; + domnptr->indxnbr = 1; /* The root vertex is unique */ + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archTleafDomLoad ( +const ArchTleaf * const archptr, +ArchTleafDom * restrict const domnptr, +FILE * const stream) +{ + if ((intLoad (stream, &domnptr->levlnum) != 1) || + (intLoad (stream, &domnptr->indxmin) != 1) || + (intLoad (stream, &domnptr->indxnbr) != 1) || + (domnptr->levlnum < 0) || + (domnptr->levlnum > archptr->levlnbr)) { + errorPrint ("archTleafDomLoad: bad input"); + return (1); + } + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archTleafDomSave ( +const ArchTleaf * const archptr, +const ArchTleafDom * const domnptr, +FILE * const stream) +{ + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", + (Anum) domnptr->levlnum, + (Anum) domnptr->indxmin, + (Anum) domnptr->indxnbr) == EOF) { + errorPrint ("archTleafDomSave: bad output"); + return (1); + } + + return (0); +} + +/* This function tries to split a tree leaf +** domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archTleafDomBipart ( +const ArchTleaf * const archptr, +const ArchTleafDom * const domnptr, +ArchTleafDom * restrict const dom0ptr, +ArchTleafDom * restrict const dom1ptr) +{ + Anum sizeval; + + if (domnptr->indxnbr <= 1) { /* If dubdomain has only one node at this level */ + if (domnptr->levlnum >= archptr->levlnbr) /* Return if cannot bipartition more */ + return (1); + + sizeval = archptr->sizetab[domnptr->levlnum]; /* Partition all the vertices of a new level */ + + dom0ptr->levlnum = + dom1ptr->levlnum = domnptr->levlnum + 1; + dom0ptr->indxmin = domnptr->indxmin * sizeval; + } + else { /* Subdomain has several indices */ + sizeval = domnptr->indxnbr; /* Base on existing block size */ + + dom0ptr->levlnum = /* Stay at same level */ + dom1ptr->levlnum = domnptr->levlnum; + dom0ptr->indxmin = domnptr->indxmin; /* Start from the existing start index */ + } + + dom0ptr->indxnbr = (sizeval + 1) >> 1; /* Subdomain 0 is always the largest one */ + dom1ptr->indxmin = dom0ptr->indxmin + dom0ptr->indxnbr; + dom1ptr->indxnbr = sizeval - dom0ptr->indxnbr; + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archTleafDomIncl ( +const ArchTleaf * const archptr, +const ArchTleafDom * const dom0ptr, +const ArchTleafDom * const dom1ptr) +{ + Anum lev0num; + Anum lev1num; + Anum idx0min; + Anum idx1min; + Anum idx0nbr; + Anum idx1nbr; + + const Anum * const sizetab = archptr->sizetab; + + lev0num = dom0ptr->levlnum; + lev1num = dom1ptr->levlnum; + idx0min = dom0ptr->indxmin; + idx1min = dom1ptr->indxmin; + idx0nbr = dom0ptr->indxnbr; + idx1nbr = dom1ptr->indxnbr; + + if (lev0num != lev1num) { + if (lev1num > lev0num) { + idx1nbr = 1; + do { + lev1num --; + idx1min /= sizetab[lev1num]; + } while (lev1num > lev0num); + } + else + return (0); + } + + return (((idx0min >= (idx1min + idx1nbr)) || + (idx1min >= (idx0min + idx0nbr))) ? 0 : 1); +} + +/* This function creates the MPI_Datatype for +** tree-leaf domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archTleafDomMpiType ( +const ArchTleaf * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (3, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ + +/***********************************/ +/* */ +/* These are the labeled tree-leaf */ +/* graph routines. */ +/* */ +/***********************************/ + +/* This routine loads the labeled +** tree leaf architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archLtleafArchLoad ( +ArchTleaf * restrict const archptr, +FILE * restrict const stream) +{ + Anum sizeval; + Anum levlnum; + Anum permnum; + + if (archTleafArchLoad (archptr, stream) != 0) /* Read tree part */ + return (1); + + if ((intLoad (stream, &archptr->permnbr) != 1) || + (archptr->permnbr <= 0)) { + errorPrint ("archLtleafArchLoad: bad input (1)"); + return (1); + } + +#ifdef SCOTCH_DEBUG_ARCH2 + if (archptr->permnbr != 1) { /* Valid empty permutation is of size 1 */ + for (levlnum = archptr->levlnbr - 1, sizeval = archptr->sizetab[levlnum]; + sizeval != archptr->permnbr; levlnum --, sizeval *= archptr->sizetab[levlnum]) { + if (levlnum < 0) { + errorPrint ("archLtleafArchLoad: permutation size does not match level boundaries"); + return (1); + } + } + } +#endif /* SCOTCH_DEBUG_ARCH2 */ + + if ((archptr->permtab = memAlloc (archptr->permnbr * 2 * sizeof (Anum))) == NULL) { /* TRICK: space for peritab too */ + errorPrint ("archLtleafArchLoad: out of memory"); + return (1); + } + + for (permnum = 0; permnum < archptr->permnbr; permnum ++) { +#ifdef SCOTCH_DEBUG_ARCH2 + Anum permtmp; +#endif /* SCOTCH_DEBUG_ARCH2 */ + + if ((intLoad (stream, &archptr->permtab[permnum]) != 1) || + (archptr->permtab[permnum] < 0) || + (archptr->permtab[permnum] >= archptr->permnbr)) { + errorPrint ("archLtleafArchLoad: bad input (2)"); + return (1); + } +#ifdef SCOTCH_DEBUG_ARCH2 + for (permtmp = 0; permtmp < permnum; permtmp ++) { + if (archptr->permtab[permtmp] == archptr->permtab[permnum]) { + errorPrint ("archLtleafArchLoad: duplicate permutation index"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_ARCH2 */ + } + + archptr->peritab = archptr->permtab + archptr->permnbr; + for (permnum = 0; permnum < archptr->permnbr; permnum ++) /* Build inverse permutation */ + archptr->peritab[archptr->permtab[permnum]] = permnum; + + return (0); +} + +/* This routine saves the labeled +** tree leaf architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archLtleafArchSave ( +const ArchTleaf * const archptr, +FILE * restrict const stream) +{ + Anum permnum; + + if (archTleafArchSave (archptr, stream) != 0) /* Save tree part */ + return (1); + + if (fprintf (stream, ANUMSTRING, + (Anum) archptr->permnbr) == EOF) { + errorPrint ("archLtleafArchSave: bad output (1)"); + return (1); + } + + for (permnum = 0; permnum < archptr->permnbr; permnum ++) { + if (fprintf (stream, " " ANUMSTRING, + (Anum) archptr->permtab[permnum]) == EOF) { + errorPrint ("archLtleafArchSave: bad output (2)"); + return (1); + } + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archLtleafDomNum ( +const ArchTleaf * const archptr, +const ArchTleafDom * const domnptr) +{ + Anum levlnum; + Anum sizeval; + Anum domnnum; + Anum permnum; + + sizeval = 1; /* Compute size of blocks below */ + for (levlnum = domnptr->levlnum; levlnum < archptr->levlnbr; levlnum ++) + sizeval *= archptr->sizetab[levlnum]; + + domnnum = domnptr->indxmin * sizeval; + permnum = domnnum % archptr->permnbr; /* Get non permuted index as terminal domain */ + + return (domnnum - permnum + archptr->permtab[permnum]); /* Return permuted index */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archLtleafDomTerm ( +const ArchTleaf * const archptr, +ArchTleafDom * const domnptr, +const ArchDomNum domnnum) +{ +#ifdef SCOTCH_DEBUG_ARCH2 + if (domnnum < 0) { + errorPrint ("archLtleafDomTerm: invalid parameter"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH2 */ + + if (domnnum < archptr->termnbr) { /* If valid label */ + Anum permnum; + + permnum = domnnum % archptr->permnbr; /* Get permuted index as terminal domain */ + + domnptr->levlnum = archptr->levlnbr; /* Set the domain */ + domnptr->indxmin = domnnum - permnum + archptr->peritab[permnum]; + domnptr->indxnbr = 1; + + return (0); + } + + return (1); /* Cannot set domain */ +} diff --git a/scotch_6.0.3/src/libscotch/arch_tleaf.h b/scotch_6.0.3/src/libscotch/arch_tleaf.h new file mode 100644 index 00000000..d601e535 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_tleaf.h @@ -0,0 +1,152 @@ +/* Copyright 2004,2007,2008,2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_tleaf.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the tree-leaf pseudo-graph target **/ +/** architecture functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 16 aug 1995 **/ +/** # Version 3.1 : from : 20 jul 1996 **/ +/** to 23 jul 1996 **/ +/** # Version 3.2 : from : 10 oct 1996 **/ +/** to 14 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 10 dec 2003 **/ +/** to 10 dec 2003 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 24 jun 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 03 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +#ifndef ARCH_TLEAF_H_STRUCT +#define ARCH_TLEAF_H_STRUCT + +/** The Tree-Leaf graph definitions. **/ + +typedef struct ArchTleaf_ { + Anum termnbr; /*+ Number of terminal domains in architecture +*/ + Anum levlnbr; /*+ Number of levels +*/ + Anum * sizetab; /*+ Array of cluster sizes, per descending level +*/ + Anum * linktab; /*+ Value of extra-cluster link costs +*/ + Anum permnbr; /*+ Number of label permutation indices +*/ + Anum * permtab; /*+ Label permutation array +*/ + Anum * peritab; /*+ Invertse label permutation array +*/ +} ArchTleaf; + +typedef struct ArchTleafDom_ { + Anum levlnum; /*+ Current block level +*/ + Anum indxmin; /*+ Minimum index in level +*/ + Anum indxnbr; /*+ Number of indices in domain +*/ +} ArchTleafDom; + +#endif /* ARCH_TLEAF_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_TLEAF_H_PROTO +#define ARCH_TLEAF_H_PROTO + +#ifndef ARCH_TLEAF +#define static +#endif + +int archTleafArchLoad (ArchTleaf * restrict const, FILE * restrict const); +int archTleafArchFree (ArchTleaf * restrict const); +int archTleafArchSave (const ArchTleaf * const, FILE * restrict const); +ArchDomNum archTleafDomNum (const ArchTleaf * const, const ArchTleafDom * const); +int archTleafDomTerm (const ArchTleaf * const, ArchTleafDom * restrict const, const ArchDomNum); +Anum archTleafDomSize (const ArchTleaf * const, const ArchTleafDom * const); +#define archTleafDomWght archTleafDomSize +Anum archTleafDomDist (const ArchTleaf * const, const ArchTleafDom * const, const ArchTleafDom * const); +int archTleafDomFrst (const ArchTleaf * const, ArchTleafDom * restrict const); +int archTleafDomLoad (const ArchTleaf * const, ArchTleafDom * restrict const, FILE * restrict const); +int archTleafDomSave (const ArchTleaf * const, const ArchTleafDom * const, FILE * restrict const); +int archTleafDomBipart (const ArchTleaf * const, const ArchTleafDom * const, ArchTleafDom * restrict const, ArchTleafDom * restrict const); +int archTleafDomIncl (const ArchTleaf * const, const ArchTleafDom * const, const ArchTleafDom * const); +#ifdef SCOTCH_PTSCOTCH +int archTleafDomMpiType (const ArchTleaf * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +int archLtleafArchLoad (ArchTleaf * restrict const, FILE * restrict const); +int archLtleafArchSave (const ArchTleaf * const, FILE * restrict const); +ArchDomNum archLtleafDomNum (const ArchTleaf * const, const ArchTleafDom * const); +int archLtleafDomTerm (const ArchTleaf * const, ArchTleafDom * restrict const, const ArchDomNum); +#define archLtleafDomWght archLtleafDomSize + +#undef static + +/* +** The macro definitions. +*/ + +#define ArchLtleaf ArchTleaf +#define ArchLtleafDom ArchTleafDom + +#define archLtleafArchFree archTleafArchFree +#define archLtleafDomSize archTleafDomSize +#define archLtleafDomDist archTleafDomDist +#define archLtleafDomFrst archTleafDomFrst +#define archLtleafDomLoad archTleafDomLoad +#define archLtleafDomSave archTleafDomSave +#define archLtleafDomBipart archTleafDomBipart +#define archLtleafDomIncl archTleafDomIncl +#define archLtleafDomMpiType archTleafDomMpiType + +#endif /* ARCH_TLEAF_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/arch_torus.c b/scotch_6.0.3/src/libscotch/arch_torus.c new file mode 100644 index 00000000..c8a52537 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_torus.c @@ -0,0 +1,907 @@ +/* Copyright 2004,2007,2008,2010,2011,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_torus.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the torus graph **/ +/** target architectures. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 23 dec 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 29 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 08 sep 1995 **/ +/** # Version 3.1 : from : 07 may 1996 **/ +/** to 22 jul 1996 **/ +/** # Version 3.2 : from : 16 oct 1996 **/ +/** to 14 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 05 nov 2003 **/ +/** to 10 mar 2005 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 30 nov 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_TORUS + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_torus.h" + +/***********************************************/ +/* */ +/* These are the 2-dimensional torus routines. */ +/* */ +/***********************************************/ + +/* This routine loads the +** bidimensional torus architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archTorus2ArchLoad ( +ArchTorusX * restrict const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((ARCHTORUSDIMMAX < 2) || + (sizeof (ArchTorusX) > sizeof (ArchDummy)) || + (sizeof (ArchTorusXDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTorus2ArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((intLoad (stream, &archptr->c[0]) != 1) || + (intLoad (stream, &archptr->c[1]) != 1) || + (archptr->c[0] < 1) || (archptr->c[1] < 1)) { + errorPrint ("archTorus2ArchLoad: bad input"); + return (1); + } + + archptr->dimmax = 2; + + return (0); +} + +/* This routine saves the +** bidimensional torus architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archTorus2ArchSave ( +const ArchTorusX * const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((ARCHTORUSDIMMAX < 2) || + (sizeof (ArchTorusX) > sizeof (ArchDummy)) || + (sizeof (ArchTorusXDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTorus2ArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", + (Anum) archptr->c[0], + (Anum) archptr->c[1]) == EOF) { + errorPrint ("archTorus2ArchSave: bad output"); + return (1); + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archTorus2DomNum ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr) +{ + return ((domptr->c[1][0] * archptr->c[0]) + domptr->c[0][0]); /* Return vertex number */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archTorus2DomTerm ( +const ArchTorusX * const archptr, +ArchTorusXDom * const domptr, +const ArchDomNum domnum) +{ + if (domnum < (archptr->c[0] * archptr->c[1])) { /* If valid label */ + domptr->c[0][0] = /* Set the domain */ + domptr->c[0][1] = domnum % archptr->c[0]; + domptr->c[1][0] = + domptr->c[1][1] = domnum / archptr->c[0]; + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the rectangular domain. +*/ + +Anum +archTorus2DomSize ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr) +{ + return ((domptr->c[0][1] - domptr->c[0][0] + 1) * + (domptr->c[1][1] - domptr->c[1][0] + 1)); +} + +/* This function returns the average +** distance between two rectangular +** domains (in fact the distance between +** the centers of the domains). +*/ + +Anum +archTorus2DomDist ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const dom0ptr, +const ArchTorusXDom * const dom1ptr) +{ + Anum dc0, dc1; + Anum ds0, ds1; + + dc0 = abs (dom0ptr->c[0][0] + dom0ptr->c[0][1] - + dom1ptr->c[0][0] - dom1ptr->c[0][1]); + ds0 = (dc0 > archptr->c[0]) ? (2 * archptr->c[0] - dc0) : dc0; + + dc1 = abs (dom0ptr->c[1][0] + dom0ptr->c[1][1] - + dom1ptr->c[1][0] - dom1ptr->c[1][1]); + ds1 = (dc1 > archptr->c[1]) ? (2 * archptr->c[1] - dc1) : dc1; + + return ((ds0 + ds1) >> 1); +} + +/* This function tries to split a rectangular +** domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archTorus2DomBipart ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr, +ArchTorusXDom * restrict const dom0ptr, +ArchTorusXDom * restrict const dom1ptr) +{ + Anum dimsiz0; + Anum dimsiz1; + int dimnum; /* Dimension along which to split */ + + dimsiz0 = domptr->c[0][1] - domptr->c[0][0]; + dimsiz1 = domptr->c[1][1] - domptr->c[1][0]; + + if ((dimsiz0 | dimsiz1) == 0) /* Return if cannot bipartition more */ + return (1); + + dimnum = 1; + if ((dimsiz0 > dimsiz1) || /* Split domain in two along largest dimension */ + ((dimsiz0 == dimsiz1) && (archptr->c[0] > archptr->c[1]))) + dimnum = 0; + + dom0ptr->c[0][0] = domptr->c[0][0]; + dom1ptr->c[1][1] = domptr->c[1][1]; + if (dimnum == 0) { /* Split across the X dimension */ + dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; + dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; + dom1ptr->c[0][1] = domptr->c[0][1]; + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = domptr->c[1][1]; + } + else { /* Split across the Y dimension */ + dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + dom0ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; + dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; + } + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archTorus2DomIncl ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const dom0ptr, +const ArchTorusXDom * const dom1ptr) +{ + if ((dom0ptr->c[0][0] <= dom1ptr->c[0][0]) && + (dom0ptr->c[0][1] >= dom1ptr->c[0][1]) && + (dom0ptr->c[1][0] <= dom1ptr->c[1][0]) && + (dom0ptr->c[1][1] >= dom1ptr->c[1][1])) + return (1); + + return (0); +} + +/***********************************************/ +/* */ +/* These are the 3-dimensional torus routines. */ +/* */ +/***********************************************/ + +/* This routine loads the +** tridimensional torus architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archTorus3ArchLoad ( +ArchTorusX * restrict const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((ARCHTORUSDIMMAX < 3) || + (sizeof (ArchTorusX) > sizeof (ArchDummy)) || + (sizeof (ArchTorusXDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTorus3ArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((intLoad (stream, &archptr->c[0]) != 1) || + (intLoad (stream, &archptr->c[1]) != 1) || + (intLoad (stream, &archptr->c[2]) != 1) || + (archptr->c[0] < 1) || (archptr->c[1] < 1) || (archptr->c[2] < 1)) { + errorPrint ("archTorus3ArchLoad: bad input"); + return (1); + } + + archptr->dimmax = 3; + + return (0); +} + +/* This routine saves the +** tridimensional torus architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archTorus3ArchSave ( +const ArchTorusX * const archptr, +FILE * restrict const stream) +{ +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchTorusX) > sizeof (ArchDummy)) || + (sizeof (ArchTorusXDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTorus3ArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", + (Anum) archptr->c[0], (Anum) archptr->c[1], (Anum) archptr->c[2]) == EOF) { + errorPrint ("archTorus3ArchSave: bad output"); + return (1); + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archTorus3DomNum ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr) +{ + return ((((domptr->c[2][0] * archptr->c[1]) + /* Return vertex number */ + domptr->c[1][0]) * archptr->c[0]) + + domptr->c[0][0]); +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archTorus3DomTerm ( +const ArchTorusX * const archptr, +ArchTorusXDom * const domptr, +const ArchDomNum domnum) +{ + if (domnum < (archptr->c[0] * archptr->c[1] * archptr->c[2])) { /* If valid label */ + domptr->c[0][0] = /* Set the domain */ + domptr->c[0][1] = domnum % archptr->c[0]; + domptr->c[1][0] = + domptr->c[1][1] = (domnum / archptr->c[0]) % archptr->c[1]; + domptr->c[2][0] = + domptr->c[2][1] = domnum / (archptr->c[0] * archptr->c[1]); + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the cubic domain. +*/ + +Anum +archTorus3DomSize ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr) +{ + return ((domptr->c[0][1] - domptr->c[0][0] + 1) * + (domptr->c[1][1] - domptr->c[1][0] + 1) * + (domptr->c[2][1] - domptr->c[2][0] + 1)); +} + +/* This function returns the average distance +** between two cubic domains (in fact the +** distance between the centers of the domains). +*/ + +Anum +archTorus3DomDist ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const dom0ptr, +const ArchTorusXDom * const dom1ptr) +{ + Anum dc0, dc1, dc2; + Anum ds0, ds1, ds2; + + dc0 = abs (dom0ptr->c[0][0] + dom0ptr->c[0][1] - + dom1ptr->c[0][0] - dom1ptr->c[0][1]); + ds0 = (dc0 > archptr->c[0]) ? (2 * archptr->c[0] - dc0) : dc0; + + dc1 = abs (dom0ptr->c[1][0] + dom0ptr->c[1][1] - + dom1ptr->c[1][0] - dom1ptr->c[1][1]); + ds1 = (dc1 > archptr->c[1]) ? (2 * archptr->c[1] - dc1) : dc1; + + dc2 = abs (dom0ptr->c[2][0] + dom0ptr->c[2][1] - + dom1ptr->c[2][0] - dom1ptr->c[2][1]); + ds2 = (dc2 > archptr->c[2]) ? (2 * archptr->c[2] - dc2) : dc2; + + return ((ds0 + ds1 + ds2) >> 1); +} + +/* This function tries to split a cubic +** domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archTorus3DomBipart ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr, +ArchTorusXDom * restrict const dom0ptr, +ArchTorusXDom * restrict const dom1ptr) +{ + Anum dimsiz[3]; + int dimnum; + + dimsiz[0] = domptr->c[0][1] - domptr->c[0][0]; + dimsiz[1] = domptr->c[1][1] - domptr->c[1][0]; + dimsiz[2] = domptr->c[2][1] - domptr->c[2][0]; + + if ((dimsiz[0] | dimsiz[1] | dimsiz[2]) == 0) /* Return if cannot bipartition more */ + return (1); + + dimnum = ((dimsiz[1] > dimsiz[2]) || /* Find largest or priviledged subdomain dimension */ + ((dimsiz[1] == dimsiz[2]) && + (archptr->c[1] > archptr->c[2]))) ? 1 : 2; + if ((dimsiz[0] > dimsiz[dimnum]) || + ((dimsiz[0] == dimsiz[dimnum]) && + (archptr->c[0] > archptr->c[dimnum]))) + dimnum = 0; + + dom0ptr->c[0][0] = domptr->c[0][0]; + dom1ptr->c[2][1] = domptr->c[2][1]; + if (dimnum == 0) { /* Split domain in two along largest dimension */ + dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; + dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; + dom1ptr->c[0][1] = domptr->c[0][1]; + + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; + + dom0ptr->c[2][0] = dom1ptr->c[2][0] = domptr->c[2][0]; + dom0ptr->c[2][1] = domptr->c[2][1]; + } + else if (dimnum == 1) { + dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + + dom0ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; + dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; + dom1ptr->c[1][1] = domptr->c[1][1]; + + dom0ptr->c[2][0] = dom1ptr->c[2][0] = domptr->c[2][0]; + dom0ptr->c[2][1] = domptr->c[2][1]; + } + else { + dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; + + dom0ptr->c[2][0] = domptr->c[2][0]; + dom0ptr->c[2][1] = (domptr->c[2][0] + domptr->c[2][1]) / 2; + dom1ptr->c[2][0] = dom0ptr->c[2][1] + 1; + } + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archTorus3DomIncl ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const dom0ptr, +const ArchTorusXDom * const dom1ptr) +{ + if ((dom0ptr->c[0][0] <= dom1ptr->c[0][0]) && + (dom0ptr->c[0][1] >= dom1ptr->c[0][1]) && + (dom0ptr->c[1][0] <= dom1ptr->c[1][0]) && + (dom0ptr->c[1][1] >= dom1ptr->c[1][1]) && + (dom0ptr->c[2][0] <= dom1ptr->c[2][0]) && + (dom0ptr->c[2][1] >= dom1ptr->c[2][1])) + return (1); + + return (0); +} + +/***********************************************/ +/* */ +/* These are the x-dimensional torus routines. */ +/* */ +/***********************************************/ + +/* This routine loads the +** tridimensional torus architecture. +** It returns: +** - 0 : if the architecture has been successfully read. +** - !0 : on error. +*/ + +int +archTorusXArchLoad ( +ArchTorusX * restrict const archptr, +FILE * restrict const stream) +{ + Anum dimnum; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchTorusX) > sizeof (ArchDummy)) || + (sizeof (ArchTorusXDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTorusXArchLoad: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if ((intLoad (stream, &archptr->dimmax) != 1) || + (archptr->dimmax > ARCHTORUSDIMMAX)) { + errorPrint ("archTorusXArchLoad: bad input (1)"); + return (1); + } + + for (dimnum = 0; dimnum < archptr->dimmax; dimnum ++) { + if ((intLoad (stream, &archptr->c[dimnum]) != 1) || + (archptr->c[dimnum] < 1)) { + errorPrint ("archTorusXArchLoad: bad input (2)"); + return (1); + } + } + + return (0); +} + +/* This routine saves the +** tridimensional torus architecture. +** It returns: +** - 0 : if the architecture has been successfully written. +** - !0 : on error. +*/ + +int +archTorusXArchSave ( +const ArchTorusX * const archptr, +FILE * restrict const stream) +{ + Anum dimnum; + +#ifdef SCOTCH_DEBUG_ARCH1 + if ((sizeof (ArchTorusX) > sizeof (ArchDummy)) || + (sizeof (ArchTorusXDom) > sizeof (ArchDomDummy))) { + errorPrint ("archTorusXArchSave: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_ARCH1 */ + + if (fprintf (stream, ANUMSTRING " ", + (Anum) archptr->dimmax) == EOF) { + errorPrint ("archTorusXArchSave: bad output (1)"); + return (1); + } + + for (dimnum = 0; dimnum < archptr->dimmax; dimnum ++) { + if (fprintf (stream, ANUMSTRING " ", + (Anum) archptr->c[dimnum]) == EOF) { + errorPrint ("archTorusXArchSave: bad output (2)"); + return (1); + } + } + + return (0); +} + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archTorusXDomNum ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr) +{ + Anum dimnum; + Anum domnum; + + for (dimnum = archptr->dimmax - 2, domnum = domptr->c[archptr->dimmax - 1][0]; dimnum >= 0; dimnum --) + domnum = (domnum * archptr->c[dimnum]) + domptr->c[dimnum][0]; + + return (domnum); /* Return vertex number */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archTorusXDomTerm ( +const ArchTorusX * const archptr, +ArchTorusXDom * const domptr, +const ArchDomNum domnum) +{ + Anum dimnum; + Anum domtmp; + + for (dimnum = 0, domtmp = domnum; dimnum < archptr->dimmax; dimnum ++) { /* Set the domain */ + domptr->c[dimnum][0] = + domptr->c[dimnum][1] = domtmp % archptr->c[dimnum]; + domtmp /= archptr->c[dimnum]; + } + + if (domtmp > 0) /* If residual is not zero, terminal domain number is invalid since too high */ + return (1); + + return (0); +} + +/* This function returns the number of +** elements in the cubic domain. +*/ + +Anum +archTorusXDomSize ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr) +{ + Anum dimnum; + Anum domsiz; + + for (dimnum = 0, domsiz = 1; dimnum < archptr->dimmax; dimnum ++) + domsiz *= domptr->c[dimnum][1] - domptr->c[dimnum][0] + 1; + + return (domsiz); +} + +/* This function returns the average distance +** between two cubic domains (in fact the +** distance between the centers of the domains). +*/ + +Anum +archTorusXDomDist ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const dom0ptr, +const ArchTorusXDom * const dom1ptr) +{ + Anum dimnum; + Anum distval; + Anum disttmp; + + for (dimnum = 0, distval = 0; dimnum < archptr->dimmax; dimnum ++) { + disttmp = abs (dom0ptr->c[dimnum][0] + dom0ptr->c[dimnum][1] - + dom1ptr->c[dimnum][0] - dom1ptr->c[dimnum][1]); + distval += (disttmp > archptr->c[dimnum]) ? (2 * archptr->c[dimnum] - disttmp) : disttmp; + } + + return (distval >> 1); +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archTorusXDomFrst ( +const ArchTorusX * const archptr, +ArchTorusXDom * restrict const domptr) +{ + Anum dimnum; + + for (dimnum = 0; dimnum < archptr->dimmax; dimnum ++) { + domptr->c[dimnum][0] = 0; + domptr->c[dimnum][1] = archptr->c[dimnum] - 1; + } + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archTorusXDomLoad ( +const ArchTorusX * const archptr, +ArchTorusXDom * restrict const domptr, +FILE * restrict const stream) +{ + Anum dimnum; + + for (dimnum = 0; dimnum < archptr->dimmax; dimnum ++) { + if ((intLoad (stream, &domptr->c[dimnum][0]) != 1) || + (intLoad (stream, &domptr->c[dimnum][1]) != 1) || + (domptr->c[dimnum][0] > domptr->c[dimnum][1]) || + (domptr->c[dimnum][0] < 0)) { + errorPrint ("archTorusXDomLoad: bad input"); + return (1); + } + } + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archTorusXDomSave ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr, +FILE * restrict const stream) +{ + Anum dimnum; + + for (dimnum = 0; dimnum < archptr->dimmax; dimnum ++) { + if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", + (Anum) domptr->c[dimnum][0], + (Anum) domptr->c[dimnum][1]) == EOF) { + errorPrint ("archTorusXDomSave: bad output"); + return (1); + } + } + + return (0); +} + +/* This function tries to split a cubic +** domain into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 1 : if bipartitioning could not be performed. +** - 2 : on error. +*/ + +int +archTorusXDomBipart ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const domptr, +ArchTorusXDom * restrict const dom0ptr, +ArchTorusXDom * restrict const dom1ptr) +{ + Anum archdimsizmax; /* Maximum span on largest architecture dimension */ + Anum domndimsizmax; /* Maximum span on largest domain dimension */ + Anum domndimval; /* Dimension to be split */ + Anum domndimflg; /* Flag set if subdomain can be bipartitioned */ + Anum domndimtmp; + Anum dimnum; + + for (dimnum = domndimval = archptr->dimmax - 1, archdimsizmax = domndimflg = 0, domndimsizmax = -1; + dimnum >= 0; dimnum --) { + Anum archdimsiz; + Anum domndimsiz; + Anum domndim0; + Anum domndim1; + + dom0ptr->c[dimnum][0] = /* Set up subdomain data as copy of original domain data */ + dom1ptr->c[dimnum][0] = domndim0 = domptr->c[dimnum][0]; + dom0ptr->c[dimnum][1] = + dom1ptr->c[dimnum][1] = domndim1 = domptr->c[dimnum][1]; + + domndimsiz = domndim1 - domndim0; /* Span on current dimension */ + domndimflg |= domndimsiz; /* Flag set if at least one is not zero */ + + if (domndimsiz < domndimsizmax) /* If dimension is too small, skip it */ + continue; + archdimsiz = archptr->c[dimnum]; + if ((domndimsiz == domndimsizmax) && /* If dimension to split is not priviledged, skip it */ + (archdimsiz <= archdimsizmax)) + continue; + + archdimsizmax = archdimsiz; /* Record dimension to split */ + domndimsizmax = domndimsiz; + domndimval = dimnum; + } + + if (domndimflg == 0) /* Return if cannot bipartition more */ + return (1); + + domndimtmp = (domptr->c[domndimval][0] + domptr->c[domndimval][1]) / 2; + dom0ptr->c[domndimval][1] = domndimtmp; + dom1ptr->c[domndimval][0] = domndimtmp + 1; + + return (0); +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archTorusXDomIncl ( +const ArchTorusX * const archptr, +const ArchTorusXDom * const dom0ptr, +const ArchTorusXDom * const dom1ptr) +{ + Anum dimnum; + + for (dimnum = 0; dimnum < archptr->dimmax; dimnum ++) { + if ((dom1ptr->c[dimnum][0] < dom0ptr->c[dimnum][0]) || + (dom1ptr->c[dimnum][1] > dom1ptr->c[dimnum][1])) + return (0); + } + + return (1); +} + +/* This function creates the MPI_Datatype for +** xD torus domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archTorusXDomMpiType ( +const ArchTorusX * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (2 * archptr->dimmax, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch_torus.h b/scotch_6.0.3/src/libscotch/arch_torus.h new file mode 100644 index 00000000..7b3d8109 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_torus.h @@ -0,0 +1,174 @@ +/* Copyright 2004,2007,2008,2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_torus.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the tori graph target architecture **/ +/** functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 17 aug 1995 **/ +/** # Version 3.1 : from : 22 jul 1996 **/ +/** to 23 jul 1996 **/ +/** # Version 3.2 : from : 16 oct 1996 **/ +/** to 14 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 05 nov 2003 **/ +/** to 05 nov 2003 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 21 jan 2008 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 01 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#ifndef ARCH_TORUS_H_STRUCT +#define ARCH_TORUS_H_STRUCT + +/*+ Maximum dimension. +*/ + +#define ARCHTORUSDIMMAX 5 /* Maximum dimension (at least 3) */ + +/*+ Data structure equivalence for target architecture array. +*/ + +#ifdef ARCH +#define ArchTorus2Dom ArchTorusXDom +#define ArchTorus3Dom ArchTorusXDom +#endif /* ARCH */ + +/* +** The type and structure definitions. +*/ + +/*+ The xD-torus definitions. +*/ + +typedef struct ArchTorusX_ { + Anum dimmax; /*+ Number of torus dimensions +*/ + Anum c[ARCHTORUSDIMMAX]; /*+ Mesh dimensions +*/ +} ArchTorusX; + +typedef struct ArchTorusXDom_ { + Anum c[ARCHTORUSDIMMAX][2]; /*+ Inclusive X and Y coordinates +*/ +} ArchTorusXDom; + +#endif /* ARCH_TORUS_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_TORUS_H_PROTO +#define ARCH_TORUS_H_PROTO + +#ifndef ARCH_TORUS +#define static +#endif + +int archTorus2ArchLoad (ArchTorusX * restrict const, FILE * restrict const); +int archTorus2ArchSave (const ArchTorusX * const, FILE * restrict const); +#define archTorus2ArchFree NULL +ArchDomNum archTorus2DomNum (const ArchTorusX * const, const ArchTorusXDom * const); +int archTorus2DomTerm (const ArchTorusX * const, ArchTorusXDom * restrict const, const ArchDomNum); +Anum archTorus2DomSize (const ArchTorusX * const, const ArchTorusXDom * const); +#define archTorus2DomWght archTorus2DomSize +Anum archTorus2DomDist (const ArchTorusX * const, const ArchTorusXDom * const, const ArchTorusXDom * const); +#define archTorus2DomFrst archTorusXDomFrst +#define archTorus2DomLoad archTorusXDomLoad +#define archTorus2DomSave archTorusXDomSave +int archTorus2DomBipart (const ArchTorusX * const, const ArchTorusXDom * const, ArchTorusXDom * restrict const, ArchTorusXDom * restrict const); +int archTorus2DomBipartO (const ArchTorusX * const, const ArchTorusXDom * const, ArchTorusXDom * restrict const, ArchTorusXDom * restrict const); +int archTorus2DomBipartU (const ArchTorusX * const, const ArchTorusXDom * const, ArchTorusXDom * restrict const, ArchTorusXDom * restrict const); +int archTorus2DomIncl (const ArchTorusX * const, const ArchTorusXDom * const, const ArchTorusXDom * const); +#ifdef SCOTCH_PTSCOTCH +#define archTorus2DomMpiType archTorusXDomMpiType +#endif /* SCOTCH_PTSCOTCH */ + +int archTorus3ArchLoad (ArchTorusX * restrict const, FILE * restrict const); +int archTorus3ArchSave (const ArchTorusX * const, FILE * restrict const); +#define archTorus3ArchFree NULL +ArchDomNum archTorus3DomNum (const ArchTorusX * const, const ArchTorusXDom * const); +int archTorus3DomTerm (const ArchTorusX * const, ArchTorusXDom * restrict const, const ArchDomNum); +Anum archTorus3DomSize (const ArchTorusX * const, const ArchTorusXDom * const); +#define archTorus3DomWght archTorus3DomSize +Anum archTorus3DomDist (const ArchTorusX * const, const ArchTorusXDom * const, const ArchTorusXDom * const); +#define archTorus3DomFrst archTorusXDomFrst +#define archTorus3DomLoad archTorusXDomLoad +#define archTorus3DomSave archTorusXDomSave +int archTorus3DomBipart (const ArchTorusX * const, const ArchTorusXDom * const, ArchTorusXDom * restrict const, ArchTorusXDom * restrict const); +int archTorus3DomIncl (const ArchTorusX * const, const ArchTorusXDom * const, const ArchTorusXDom * const); +#ifdef SCOTCH_PTSCOTCH +#define archTorus3DomMpiType archTorusXDomMpiType +#endif /* SCOTCH_PTSCOTCH */ + +int archTorusXArchLoad (ArchTorusX * restrict const, FILE * restrict const); +int archTorusXArchSave (const ArchTorusX * const, FILE * restrict const); +#define archTorusXArchFree NULL +ArchDomNum archTorusXDomNum (const ArchTorusX * const, const ArchTorusXDom * const); +int archTorusXDomTerm (const ArchTorusX * const, ArchTorusXDom * restrict const, const ArchDomNum); +Anum archTorusXDomSize (const ArchTorusX * const, const ArchTorusXDom * const); +#define archTorusXDomWght archTorusXDomSize +Anum archTorusXDomDist (const ArchTorusX * const, const ArchTorusXDom * const, const ArchTorusXDom * const); +int archTorusXDomFrst (const ArchTorusX * const, ArchTorusXDom * const); +int archTorusXDomLoad (const ArchTorusX * const, ArchTorusXDom * const, FILE * restrict const); +int archTorusXDomSave (const ArchTorusX * const, const ArchTorusXDom * const, FILE * restrict const); +int archTorusXDomBipart (const ArchTorusX * const, const ArchTorusXDom * const, ArchTorusXDom * restrict const, ArchTorusXDom * restrict const); +int archTorusXDomIncl (const ArchTorusX * const, const ArchTorusXDom * const, const ArchTorusXDom * const); +#ifdef SCOTCH_PTSCOTCH +int archTorusXDomMpiType (const ArchTorusX * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +#endif /* ARCH_TORUS_H_PROTO */ +#endif /* ARCH_NOPROTO */ + diff --git a/scotch_6.0.3/src/libscotch/arch_vcmplt.c b/scotch_6.0.3/src/libscotch/arch_vcmplt.c new file mode 100644 index 00000000..54031e13 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_vcmplt.c @@ -0,0 +1,287 @@ +/* Copyright 2004,2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_vcmplt.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the variable-sized **/ +/** complete graph target architecture. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to : 24 mar 1993 **/ +/** # Version 1.2 : from : 04 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 1.3 : from : 20 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to : 23 dec 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to : 29 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 16 aug 1995 **/ +/** # Version 3.1 : from : 20 jul 1996 **/ +/** to 20 jul 1996 **/ +/** # Version 3.2 : from : 15 oct 1996 **/ +/** to 14 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 14 sep 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 05 nov 2003 **/ +/** to 05 nov 2003 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 26 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_VCMPLT + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_vcmplt.h" + +/*****************************************/ +/* */ +/* These are the variable-sized complete */ +/* graph handling routines. */ +/* */ +/*****************************************/ + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archVcmpltDomNum ( +const ArchVcmplt * const archptr, +const ArchVcmpltDom * const domptr) +{ + return (domptr->termnum); /* Return terminal number */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archVcmpltDomTerm ( +const ArchVcmplt * const archptr, +ArchVcmpltDom * const domptr, +const ArchDomNum domnum) +{ + Anum termnum; + Anum termlvl; + + if (domnum != ARCHDOMNOTTERM) { /* If valid label */ + if (domnum == 0) /* Not a legal domain */ + return (2); + + domptr->termnum = domnum; /* Set the domain */ + for (termnum = domnum, termlvl = 0; termnum > 1; termnum >>= 1, termlvl ++) ; /* Compute level */ + domptr->termlvl = termlvl; /* Set level */ + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the domain. +*/ + +Anum +archVcmpltDomSize ( +const ArchVcmplt * const archptr, +const ArchVcmpltDom * const domptr) +{ + return (1); /* All domains have same size for bipartitioning */ +} + +/* This function returns the average +** distance between two subdomains. +*/ + +Anum +archVcmpltDomDist ( +const ArchVcmplt * const archptr, +const ArchVcmpltDom * const dom0ptr, +const ArchVcmpltDom * const dom1ptr) +{ + return ((dom0ptr->termnum == dom1ptr->termnum) ? 0 : 1); /* All distinct terminals are at distance 1 */ +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archVcmpltDomFrst ( +const ArchVcmplt * const archptr, +ArchVcmpltDom * restrict const domptr) +{ + domptr->termlvl = 0; /* First terminal number */ + domptr->termnum = 1; + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archVcmpltDomLoad ( +const ArchVcmplt * const archptr, +ArchVcmpltDom * restrict const domptr, +FILE * const stream) +{ + Anum termnum; + Anum termlvl; + + if (intLoad (stream, &domptr->termnum) != 1) { + errorPrint ("archVcmpltDomLoad: bad input"); + return (1); + } + + for (termnum = domptr->termnum, termlvl = 0; termnum > 1; termnum >>= 1, termlvl ++) ; /* Compute level */ + domptr->termlvl = termlvl; + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archVcmpltDomSave ( +const ArchVcmplt * const archptr, +const ArchVcmpltDom * const domptr, +FILE * const stream) +{ + if (fprintf (stream, ANUMSTRING " ", + (Anum) domptr->termnum) == EOF) { + errorPrint ("archVcmpltDomSave: bad output"); + return (1); + } + + return (0); +} + +/* This function splits a domain +** into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 2 : on error. +*/ + +int +archVcmpltDomBipart ( +const ArchVcmplt * const archptr, +const ArchVcmpltDom * const domptr, +ArchVcmpltDom * restrict const dom0ptr, +ArchVcmpltDom * restrict const dom1ptr) +{ + dom0ptr->termlvl = /* Bipartition the domain */ + dom1ptr->termlvl = domptr->termlvl + 1; + dom0ptr->termnum = domptr->termnum << 1; + dom1ptr->termnum = dom0ptr->termnum + 1; + + return ((dom1ptr->termnum < domptr->termnum) ? 2 : 0); /* Return error on overflow */ +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archVcmpltDomIncl ( +const ArchVcmplt * const archptr, +const ArchVcmpltDom * const dom0ptr, +const ArchVcmpltDom * const dom1ptr) +{ + if ((dom1ptr->termlvl >= dom0ptr->termlvl) && + ((dom1ptr->termnum >> (dom1ptr->termlvl - dom0ptr->termlvl)) == dom0ptr->termnum)) + return (1); + + return (0); +} + +/* This function creates the MPI_Datatype for +** variable-sized complete graph domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archVcmpltDomMpiType ( +const ArchVcmplt * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (2, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch_vcmplt.h b/scotch_6.0.3/src/libscotch/arch_vcmplt.h new file mode 100644 index 00000000..1350efe9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_vcmplt.h @@ -0,0 +1,113 @@ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_vcmplt.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the variable-sized complete graph **/ +/** target architecture functions. **/ +/** **/ +/** DATES : # Version 3.0 : from : 01 jul 1995 **/ +/** to 09 aug 1995 **/ +/** # Version 3.1 : from : 20 jul 1996 **/ +/** to 20 jul 1996 **/ +/** # Version 3.2 : from : 15 oct 1996 **/ +/** to 14 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 08 nov 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 05 nov 2003 **/ +/** to 05 nov 2003 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 21 jan 2008 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 26 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +#ifndef ARCH_VCMPLT_H_STRUCT +#define ARCH_VCMPLT_H_STRUCT + +/*+ The variable-sized complete graph bipartitioning definitions. +*/ + +typedef struct ArchVcmplt_ { + int padding; /*+ No data needed +*/ +} ArchVcmplt; + +typedef struct ArchVcmpltDom_ { + Anum termlvl; /*+ Terminal depth +*/ + Anum termnum; /*+ Terminal number +*/ +} ArchVcmpltDom; + +#endif /* ARCH_VCMPLT_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_VCMPLT_H_PROTO +#define ARCH_VCMPLT_H_PROTO + +#ifndef ARCH_VCMPLT +#define static +#endif + +#define archVcmpltArchLoad NULL +#define archVcmpltArchSave NULL +#define archVcmpltArchFree NULL +ArchDomNum archVcmpltDomNum (const ArchVcmplt * const, const ArchVcmpltDom * const); +int archVcmpltDomTerm (const ArchVcmplt * const, ArchVcmpltDom * restrict const, const ArchDomNum); +Anum archVcmpltDomSize (const ArchVcmplt * const, const ArchVcmpltDom * const); +#define archVcmpltDomWght archVcmpltDomSize +Anum archVcmpltDomDist (const ArchVcmplt * const, const ArchVcmpltDom * const, const ArchVcmpltDom * const); +int archVcmpltDomFrst (const ArchVcmplt * const, ArchVcmpltDom * const); +int archVcmpltDomLoad (const ArchVcmplt * const, ArchVcmpltDom * const, FILE * const); +int archVcmpltDomSave (const ArchVcmplt * const, const ArchVcmpltDom * const, FILE * const); +int archVcmpltDomBipart (const ArchVcmplt * const, const ArchVcmpltDom * const, ArchVcmpltDom * restrict const, ArchVcmpltDom * restrict const); +int archVcmpltDomIncl (const ArchVcmplt * const, const ArchVcmpltDom * const, const ArchVcmpltDom * const); +#ifdef SCOTCH_PTSCOTCH +int archVcmpltDomMpiType (const ArchVcmplt * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +#endif /* ARCH_VCMPLT_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/arch_vhcub.c b/scotch_6.0.3/src/libscotch/arch_vhcub.c new file mode 100644 index 00000000..22db2fee --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_vhcub.c @@ -0,0 +1,287 @@ +/* Copyright 2004,2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_vhcub.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the variable-sized **/ +/** hypercube target architecture. **/ +/** **/ +/** DATES : # Version 3.4 : from : 08 nov 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 04 nov 2003 **/ +/** to 04 nov 2003 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 27 feb 2008 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 26 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ARCH_VHCUB + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "arch_vhcub.h" + +/********************************/ +/* */ +/* These are the variable-sized */ +/* hypercube handling routines. */ +/* */ +/********************************/ + +/* This function returns the smallest number +** of terminal domain included in the given +** domain. +*/ + +ArchDomNum +archVhcubDomNum ( +const ArchVhcub * const archptr, +const ArchVhcubDom * const domptr) +{ + return (domptr->termnum); /* Return terminal number */ +} + +/* This function returns the terminal domain associated +** with the given terminal number in the architecture. +** It returns: +** - 0 : if label is valid and domain has been updated. +** - 1 : if label is invalid. +** - 2 : on error. +*/ + +int +archVhcubDomTerm ( +const ArchVhcub * const archptr, +ArchVhcubDom * const domptr, +const ArchDomNum domnum) +{ + Anum termnum; + Anum termlvl; + + if (domnum != ARCHDOMNOTTERM) { /* If valid label */ + if (domnum == 0) /* Not a legal domain */ + return (2); + + domptr->termnum = domnum; /* Set the domain */ + for (termnum = domnum, termlvl = 0; termnum > 1; termnum >>= 1, termlvl ++) ; /* Compute level */ + domptr->termlvl = termlvl; /* Set level */ + + return (0); + } + + return (1); /* Cannot set domain */ +} + +/* This function returns the number of +** elements in the domain. +*/ + +Anum +archVhcubDomSize ( +const ArchVhcub * const archptr, +const ArchVhcubDom * const domptr) +{ + return (1); /* All domains have same size for bipartitioning */ +} + +/* This function returns the average +** distance between two subdomains. +*/ + +Anum +archVhcubDomDist ( +const ArchVhcub * const archptr, +const ArchVhcubDom * const dom0ptr, +const ArchVhcubDom * const dom1ptr) +{ + Anum dom0num; + Anum dom1num; + Anum distval; + + if (dom0ptr->termlvl > dom1ptr->termlvl) { + dom0num = dom0ptr->termnum >> (dom0ptr->termlvl - dom1ptr->termlvl); + dom1num = dom1ptr->termnum; + distval = (dom0ptr->termlvl - dom1ptr->termlvl) >> 1; /* One half of unknown bits */ + } + else { + dom0num = dom0ptr->termnum; + dom1num = dom1ptr->termnum >> (dom1ptr->termlvl - dom0ptr->termlvl); + distval = (dom1ptr->termlvl - dom0ptr->termlvl) >> 1; /* One half of unknown bits */ + } + + for (dom0num ^= dom1num; dom0num != 0; /* Compute Hamming distance */ + distval += (dom0num & 1), dom0num >>= 1) ; + + return (distval); +} + +/* This function sets the biggest +** domain available for this +** architecture. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archVhcubDomFrst ( +const ArchVhcub * const archptr, +ArchVhcubDom * restrict const domptr) +{ + domptr->termlvl = 0; /* First terminal number */ + domptr->termnum = 1; + + return (0); +} + +/* This routine reads domain information +** from the given stream. +** It returns: +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archVhcubDomLoad ( +const ArchVhcub * const archptr, +ArchVhcubDom * restrict const domptr, +FILE * const stream) +{ + Anum termnum; + Anum termlvl; + + if (intLoad (stream, &domptr->termnum) != 1) { + errorPrint ("archVhcubDomLoad: bad input"); + return (1); + } + + for (termnum = domptr->termnum, termlvl = 0; termnum > 1; termnum >>= 1, termlvl ++) ; /* Compute level */ + domptr->termlvl = termlvl; + + return (0); +} + +/* This routine saves domain information +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +archVhcubDomSave ( +const ArchVhcub * const archptr, +const ArchVhcubDom * const domptr, +FILE * const stream) +{ + if (fprintf (stream, ANUMSTRING " ", + (Anum) domptr->termnum) == EOF) { + errorPrint ("archVhcubDomSave: bad output"); + return (1); + } + + return (0); +} + +/* This function splits a domain +** into two subdomains. +** It returns: +** - 0 : if bipartitioning succeeded. +** - 2 : on error. +*/ + +int +archVhcubDomBipart ( +const ArchVhcub * const archptr, +const ArchVhcubDom * const domptr, +ArchVhcubDom * restrict const dom0ptr, +ArchVhcubDom * restrict const dom1ptr) +{ + dom0ptr->termlvl = /* Bipartition the domain */ + dom1ptr->termlvl = domptr->termlvl + 1; + dom0ptr->termnum = domptr->termnum << 1; + dom1ptr->termnum = dom0ptr->termnum + 1; + + return ((dom1ptr->termnum < domptr->termnum) ? 2 : 0); /* Return error on overflow */ +} + +/* This function checks if dom1 is +** included in dom0. +** It returns: +** - 0 : if dom1 is not included in dom0. +** - 1 : if dom1 is included in dom0. +** - 2 : on error. +*/ + +int +archVhcubDomIncl ( +const ArchVhcub * const archptr, +const ArchVhcubDom * const dom0ptr, +const ArchVhcubDom * const dom1ptr) +{ + if ((dom1ptr->termlvl >= dom0ptr->termlvl) && + ((dom1ptr->termnum >> (dom1ptr->termlvl - dom0ptr->termlvl)) == dom0ptr->termnum)) + return (1); + + return (0); +} + +/* This function creates the MPI_Datatype for +** variable-sized hypercube domains. +** It returns: +** - 0 : if type could be created. +** - 1 : on error. +*/ + +#ifdef SCOTCH_PTSCOTCH +int +archVhcubDomMpiType ( +const ArchVhcub * const archptr, +MPI_Datatype * const typeptr) +{ + MPI_Type_contiguous (2, ANUM_MPI, typeptr); + + return (0); +} +#endif /* SCOTCH_PTSCOTCH */ diff --git a/scotch_6.0.3/src/libscotch/arch_vhcub.h b/scotch_6.0.3/src/libscotch/arch_vhcub.h new file mode 100644 index 00000000..1080df5b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/arch_vhcub.h @@ -0,0 +1,106 @@ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : arch_vhcub.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the variable-sized hypercube **/ +/** target architecture functions. **/ +/** **/ +/** DATES : # Version 3.4 : from : 08 nov 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 04 nov 2003 **/ +/** to 04 nov 2003 **/ +/** # Version 5.1 : from : 21 jan 2008 **/ +/** to 21 jan 2008 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 01 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +#ifndef ARCH_VHCUB_H_STRUCT +#define ARCH_VHCUB_H_STRUCT + +/*+ The variable-sized hypercube bipartitioning definitions. +*/ + +typedef struct ArchVhcub_ { + int padding; /*+ No data needed +*/ +} ArchVhcub; + +typedef struct ArchVhcubDom_ { + Anum termlvl; /*+ Terminal depth +*/ + Anum termnum; /*+ Terminal number +*/ +} ArchVhcubDom; + +#endif /* ARCH_VHCUB_H_STRUCT */ + +/* +** The function prototypes. +*/ + +#ifndef ARCH_NOPROTO +#ifndef ARCH_VHCUB_H_PROTO +#define ARCH_VHCUB_H_PROTO + +#ifndef ARCH_VHCUB +#define static +#endif + +#define archVhcubArchLoad NULL +#define archVhcubArchSave NULL +#define archVhcubArchFree NULL +ArchDomNum archVhcubDomNum (const ArchVhcub * const, const ArchVhcubDom * const); +int archVhcubDomTerm (const ArchVhcub * const, ArchVhcubDom * restrict const, const ArchDomNum); +Anum archVhcubDomSize (const ArchVhcub * const, const ArchVhcubDom * const); +#define archVhcubDomWght archVhcubDomSize +Anum archVhcubDomDist (const ArchVhcub * const, const ArchVhcubDom * const, const ArchVhcubDom * const); +int archVhcubDomFrst (const ArchVhcub * const, ArchVhcubDom * const); +int archVhcubDomLoad (const ArchVhcub * const, ArchVhcubDom * const, FILE * const); +int archVhcubDomSave (const ArchVhcub * const, const ArchVhcubDom * const, FILE * const); +int archVhcubDomBipart (const ArchVhcub * const, const ArchVhcubDom * const, ArchVhcubDom * restrict const, ArchVhcubDom * restrict const); +int archVhcubDomIncl (const ArchVhcub * const, const ArchVhcubDom * const, const ArchVhcubDom * const); +#ifdef SCOTCH_PTSCOTCH +int archVhcubDomMpiType (const ArchVhcub * const, MPI_Datatype * const); +#endif /* SCOTCH_PTSCOTCH */ + +#undef static + +#endif /* ARCH_VHCUB_H_PROTO */ +#endif /* ARCH_NOPROTO */ diff --git a/scotch_6.0.3/src/libscotch/bdgraph.c b/scotch_6.0.3/src/libscotch/bdgraph.c new file mode 100644 index 00000000..52ad21d0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph.c @@ -0,0 +1,189 @@ +/* Copyright 2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the distributed **/ +/** bipartitioning graph data structure **/ +/** handling routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 sep 2007 **/ +/** to 14 apr 2011 **/ +/** # Version 6.0 : from : 11 sep 2011 **/ +/** to 31 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "dgraph.h" +#include "dmapping.h" +#include "bdgraph.h" + +/*************************************/ +/* */ +/* These routines handle distributed */ +/* bipartition graphs. */ +/* */ +/*************************************/ + +/* This routine builds the active graph +** corresponding to the given bipartitioning +** job parameters. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +bdgraphInit ( +Bdgraph * restrict const actgrafptr, /* Active graph */ +const Dgraph * restrict const indgrafptr, /* Induced source subdgraph */ +const Dgraph * restrict const srcgrafptr, /* Original source graph */ +const Arch * restrict const archptr, /* Current mapping of halo vertices */ +const ArchDom domnsubtab[]) /* Subdomains */ +{ + Anum domndist; /* Distance between both subdomains */ + Anum domnwght0; /* Processor workforce in each domain */ + Anum domnwght1; + + domndist = archDomDist (archptr, &domnsubtab[0], &domnsubtab[1]); /* Get distance between subdomains */ + domnwght0 = archDomWght (archptr, &domnsubtab[0]); /* Get weights of subdomains */ + domnwght1 = archDomWght (archptr, &domnsubtab[1]); + actgrafptr->s = *indgrafptr; /* Get source graph data */ + actgrafptr->s.flagval &= ~DGRAPHFREEALL; /* Do not free contents of separation graph */ + actgrafptr->s.vlblloctax = NULL; /* Never mind about vertex labels in the future */ + actgrafptr->veexloctax = NULL; /* No external gain (yet) */ + actgrafptr->veexglbsum = 0; + actgrafptr->partgsttax = NULL; /* Do not allocate frontier arrays yet */ + actgrafptr->fronloctab = NULL; + + bdgraphInit2 (actgrafptr, domndist, domnwght0, domnwght1); + +/* TODO: Compute external gains */ + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (actgrafptr) != 0) { + errorPrint ("bdgraphInit: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + return (0); +} + +void +bdgraphInit2 ( +Bdgraph * restrict const actgrafptr, /* Active graph */ +const Anum domndist, /* Distance between both subdomains */ +const Anum domnwght0, /* Processor workforce in each domain */ +const Anum domnwght1) +{ + actgrafptr->fronlocnbr = /* No frontier vertices */ + actgrafptr->fronglbnbr = 0; + actgrafptr->complocload0 = actgrafptr->s.velolocsum; + actgrafptr->compglbload0 = actgrafptr->s.veloglbsum; + actgrafptr->compglbload0min = 0; /* No external constraints on bipartition (yet) */ + actgrafptr->compglbload0max = actgrafptr->s.veloglbsum; + actgrafptr->compglbload0avg = (Gnum) (((double) actgrafptr->s.veloglbsum * (double) domnwght0) / (double) (domnwght0 + domnwght1)); + actgrafptr->compglbload0dlt = actgrafptr->s.veloglbsum - actgrafptr->compglbload0avg; + actgrafptr->complocsize0 = actgrafptr->s.vertlocnbr; + actgrafptr->compglbsize0 = actgrafptr->s.vertglbnbr; + actgrafptr->commglbload = 0; + actgrafptr->commglbloadextn0 = 0; + actgrafptr->commglbgainextn = 0; + actgrafptr->commglbgainextn0 = 0; + actgrafptr->bbalglbval = (double) actgrafptr->compglbload0dlt / (double) actgrafptr->compglbload0avg; + actgrafptr->domndist = domndist; + actgrafptr->domnwght[0] = domnwght0; + actgrafptr->domnwght[1] = domnwght1; + actgrafptr->levlnum = 0; +} + +/* This routine frees the contents +** of the given distributed active graph. +** It returns: +** - VOID : in all cases. +*/ + +void +bdgraphExit ( +Bdgraph * const grafptr) +{ + if (grafptr->partgsttax != NULL) + memFree (grafptr->partgsttax + grafptr->s.baseval); + if (grafptr->fronloctab != NULL) + memFree (grafptr->fronloctab); + if (grafptr->veexloctax != NULL) + memFree (grafptr->veexloctax + grafptr->s.baseval); + + dgraphExit (&grafptr->s); /* Free distributed source graph and its private data (flagval may be corrupted afterwards) */ + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + memSet (grafptr, ~0, sizeof (Bdgraph)); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ +} + +/* This routine moves all of the graph +** vertices to the first part. +** It returns: +** - VOID : in all cases. +*/ + +void +bdgraphZero ( +Bdgraph * const grafptr) +{ + if (grafptr->partgsttax != NULL) + memSet (grafptr->partgsttax + grafptr->s.baseval, 0, grafptr->s.vertgstnbr * sizeof (GraphPart)); /* Set all local and ghost vertices to part 0 */ + + grafptr->fronlocnbr = /* No frontier vertices */ + grafptr->fronglbnbr = 0; + grafptr->complocload0 = grafptr->s.velolocsum; + grafptr->compglbload0 = grafptr->s.veloglbsum; + grafptr->compglbload0dlt = grafptr->s.veloglbsum - grafptr->compglbload0avg; + grafptr->complocsize0 = grafptr->s.vertlocnbr; + grafptr->compglbsize0 = grafptr->s.vertglbnbr; + grafptr->commglbload = grafptr->commglbloadextn0; + grafptr->commglbgainextn = grafptr->commglbgainextn0; +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph.h b/scotch_6.0.3/src/libscotch/bdgraph.h new file mode 100644 index 00000000..4978835c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph.h @@ -0,0 +1,131 @@ +/* Copyright 2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for distributed edge bipartition- **/ +/** ing routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 sep 2007 **/ +/** to : 14 apr 2011 **/ +/** # Version 6.0 : from : 11 sep 2011 **/ +/** to : 31 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Graph option flags. +*/ + +#define BDGRAPHFREEFRON (DGRAPHBITSNOTUSED) /* Free part array */ +#define BDGRAPHFREEPART (DGRAPHBITSNOTUSED << 1) /* Free frontier array */ +#define BDGRAPHFREEVEEX (DGRAPHBITSNOTUSED << 2) /* Free external gain array */ + +/*+ Active graph structure. +*/ + +typedef struct Bdgraph_ { + Dgraph s; /*+ Distributed source graph +*/ + Gnum * veexloctax; /*+ Local vertex external gain array if moved to 1 +*/ + Gnum veexglbsum; /*+ Global sum of veexloctax array cells +*/ + GraphPart * partgsttax; /*+ Based local part array: 0,1: part +*/ + Gnum * fronloctab; /*+ Array of local frontier vertex numbers +*/ + Gnum fronlocnbr; /*+ Number of local frontier vertices +*/ + Gnum fronglbnbr; /*+ Number of global frontier vertices +*/ + Gnum complocload0; /*+ Local load of part 0 +*/ + Gnum compglbload0; /*+ Global load of part 0 +*/ + Gnum compglbload0min; /*+ Minimum allowed load in part 0 (strategy variable) +*/ + Gnum compglbload0max; /*+ Maximum allowed load in part 0 (strategy variable) +*/ + Gnum compglbload0avg; /*+ Global average load of part 0 +*/ + Gnum compglbload0dlt; /*+ Load difference from the average +*/ + Gnum complocsize0; /*+ Number of local vertices in part 0 +*/ + Gnum compglbsize0; /*+ Number of global vertices in part 0 +*/ + Gnum commglbload; /*+ Global communication load +*/ + Gnum commglbgainextn; /*+ Global external gain if all swapped +*/ + Gnum commglbloadextn0; /*+ Global communication load if all moved to part 0 +*/ + Gnum commglbgainextn0; /*+ Global external gain if all swapped from part 0 +*/ + double bbalglbval; /*+ Bipartitioning imbalance ratio (strategy variable) +*/ + Anum domndist; /*+ Distance between subdomains +*/ + Anum domnwght[2]; /*+ Weights for each subdomain +*/ + INT levlnum; /*+ Graph coarsening level +*/ +} Bdgraph; + +/*+ The distributed save graph structure. +*/ + +typedef struct BdgraphStore_ { + Gnum fronlocnbr; /*+ Number of local frontier vertices +*/ + Gnum fronglbnbr; /*+ Number of frontier vertices +*/ + Gnum complocload0; /*+ Local load in part 0 +*/ + Gnum compglbload0; /*+ Load in part 0 +*/ + Gnum compglbload0dlt; /*+ Difference from the average +*/ + Gnum complocsize0; /*+ Number of local vertices in part 0 +*/ + Gnum compglbsize0; /*+ Number of global vertices in part 0 +*/ + Gnum commglbload; + Gnum commglbgainextn; + byte * datatab; /*+ Variable-sized data array +*/ +} BdgraphStore; + +/* +** The function prototypes. +*/ + +#ifndef BDGRAPH +#define static +#endif + +#ifdef DMAPPING_H +int bdgraphInit (Bdgraph * const, const Dgraph * const, const Dgraph * const, const Arch * const, const ArchDom[]); +#endif /* DMAPPING_H */ +void bdgraphInit2 (Bdgraph * const, const Anum, const Anum, const Anum); +#ifdef DMAPPING_H +int bdgraphInit3 (Bdgraph * const, const Dgraph * const, const Dmapping * const, const ArchDom[]); +#endif /* DMAPPING_H */ +void bdgraphExit (Bdgraph * restrict const); +void bdgraphFree (Bdgraph * restrict const); +void bdgraphZero (Bdgraph * restrict const); +int bdgraphCheck (const Bdgraph * restrict const); +#ifdef BGRAPH_H +int bdgraphGatherAll (const Bdgraph * restrict const, Bgraph * restrict); +#endif /* BGRAPH_H */ + +int bdgraphStoreInit (const Bdgraph * const, BdgraphStore * const); +void bdgraphStoreExit (BdgraphStore * const); +void bdgraphStoreSave (const Bdgraph * const , BdgraphStore * const); +void bdgraphStoreUpdt (Bdgraph * const, const BdgraphStore * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_bd.c b/scotch_6.0.3/src/libscotch/bdgraph_bipart_bd.c new file mode 100644 index 00000000..db6ae4e6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_bd.c @@ -0,0 +1,453 @@ +/* Copyright 2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_bd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a bipartition of **/ +/** the given distributed separator graph **/ +/** by creating a band graph of given witdh **/ +/** around the current frontier, computing **/ +/** an improved bipartition of the band **/ +/** graph, and projecting back the obtained **/ +/** frontier to the original graph. **/ +/** **/ +/** DATES : # Version 5.1 : from : 11 nov 2007 **/ +/** to : 14 apr 2011 **/ +/** # Version 6.0 : from : 11 sep 2011 **/ +/** to : 31 aug 2014 **/ +/** **/ +/** NOTES : # Since only edges from local vertices **/ +/** to local anchors are created in **/ +/** dgraphBand(), the communication const **/ +/** might be wrong if a local vertex of **/ +/** the last layer is linked to a remote **/ +/** vertex of different part which was **/ +/** not in the band graph. Hence, commun- **/ +/** ication costs have to be recomputed **/ +/** from scratch. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH_BIPART_BD + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "arch.h" +#include "dgraph.h" +#include "dgraph_halo.h" +#include "bdgraph.h" +#include "bdgraph_bipart_bd.h" +#include "bdgraph_bipart_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes a distributed band graph +** of given width around the current frontier and +** applies distributed bipartitioning routines to it. +** The distributed graph is not guaranteed to be +** balanced at at all. +** It returns: +** - 0 : if the distributed band graph could be computed. +** - !0 : on error. +*/ + +int +bdgraphBipartBd ( +Bdgraph * const orggrafptr, /*+ Distributed graph +*/ +const BdgraphBipartBdParam * const paraptr) /*+ Method parameters +*/ +{ + Bdgraph bndgrafdat; /* Bipartitioning band graph structure */ + Gnum bndvertancnnd; /* End of local vertex array, without anchors */ + Gnum bndvertlocnbr1; /* Number of band graph vertices in part 1 except anchor 1 */ + Gnum bndvertlocnum; + Gnum bndvertlvlnum; /* Based number of first band vertex in last layer */ + Gnum bndvertlocancadj; /* Flag set when anchor(s) represent unexistent vertices */ + Gnum bndvertglbancadj; /* Global adjustment of anchor vertices */ + Gnum bndveexlocsum; /* Local sum of veexloctax array cells for band graph */ + Gnum bndveexlocsum0; /* Local sum of veexloctax array cells in part 0 for band graph */ + Gnum bndedlolocval; + Gnum bndfronlocnum; + Gnum orgfronlocnum; + int * restrict orgflagloctab; + Gnum orgvertlocnum; + Gnum orgedlolocval; + const int * restrict orgprocsidtab; + int orgprocsidnbr; + int orgprocsidnum; + int orgprocsidval; + Gnum complocsizeadj0; + Gnum commlocloadintn; + Gnum commlocloadintn2; /* Twice twice (4 times) the internal communication load of last layer */ + Gnum commlocloadextn; + Gnum commlocgainextn; + Gnum reduloctab[7]; + Gnum reduglbtab[7]; + DgraphHaloRequest requdat; + + if (orggrafptr->fronglbnbr == 0) /* If no separator vertices, apply strategy to full (original) graph */ + return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); + + if (dgraphBand (&orggrafptr->s, orggrafptr->fronlocnbr, orggrafptr->fronloctab, orggrafptr->partgsttax, + orggrafptr->complocload0, orggrafptr->s.velolocsum - orggrafptr->complocload0, paraptr->distmax, + &bndgrafdat.s, &bndgrafdat.fronloctab, &bndgrafdat.partgsttax, + &bndvertlvlnum, &bndvertlocnbr1, &bndvertlocancadj) != 0) { + errorPrint ("bdgraphBipartBd: cannot create band graph"); + return (1); + } + bndvertancnnd = bndgrafdat.s.vertlocnnd - 2; + + reduloctab[0] = 0; /* Assume no memory allocation problem */ + bndveexlocsum = + bndveexlocsum0 = 0; + bndgrafdat.veexloctax = NULL; /* Assume no external gains */ + if (orggrafptr->veexloctax != NULL) { + if ((bndgrafdat.veexloctax = memAlloc (bndgrafdat.s.vertlocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("bdgraphBipartBd: out of memory (1)"); + reduloctab[0] = 1; /* Memory error */ + } + else { + Gnum bndvertlocnum; + + bndgrafdat.veexloctax -= bndgrafdat.s.baseval; + + for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { + Gnum veexval; + + veexval = orggrafptr->veexloctax[bndgrafdat.s.vnumloctax[bndvertlocnum]]; + bndgrafdat.veexloctax[bndvertlocnum] = veexval; + bndveexlocsum += veexval; + bndveexlocsum0 += veexval & (((Gnum) bndgrafdat.partgsttax[bndvertlocnum]) - 1); + } + } + } + reduloctab[1] = bndgrafdat.s.vendloctax[bndvertancnnd] - bndgrafdat.s.vertloctax[bndvertancnnd] - (orggrafptr->s.procglbnbr - 1); /* Anchor degrees */ + reduloctab[2] = bndgrafdat.s.vendloctax[bndvertancnnd + 1] - bndgrafdat.s.vertloctax[bndvertancnnd + 1] - (orggrafptr->s.procglbnbr - 1); + + bndgrafdat.complocsize0 = bndgrafdat.s.vertlocnbr - (bndvertlocnbr1 + 1); /* Add 1 for anchor vertex 1 */ + complocsizeadj0 = orggrafptr->complocsize0 - bndgrafdat.complocsize0; /* -1 less because of anchor 0 */ + reduloctab[3] = bndgrafdat.complocsize0; + reduloctab[4] = bndvertlocancadj; /* Sum increases in size and load */ + reduloctab[5] = bndveexlocsum; + reduloctab[6] = bndveexlocsum0; + if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartBd: communication error (1)"); + return (1); + } + if (reduglbtab[0] != 0) { + bdgraphExit (&bndgrafdat); + return (1); + } + if ((reduglbtab[1] == 0) || /* If graph is too small to have any usable anchors */ + (reduglbtab[2] == 0)) { + bdgraphExit (&bndgrafdat); + return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); + } + + bndvertglbancadj = reduglbtab[4]; + bndgrafdat.veexglbsum = orggrafptr->veexglbsum; /* All external gains preserved */ + bndgrafdat.fronlocnbr = orggrafptr->fronlocnbr; /* All separator vertices are kept in band graph */ + bndgrafdat.fronglbnbr = orggrafptr->fronglbnbr; + bndgrafdat.complocload0 = orggrafptr->complocload0 + bndvertlocancadj; /* All loads are kept in band graph */ + bndgrafdat.compglbload0 = orggrafptr->compglbload0 + bndvertglbancadj; + bndgrafdat.compglbload0min = orggrafptr->compglbload0min + bndvertglbancadj; /* Tilt extrema loads according to adjustments */ + bndgrafdat.compglbload0max = orggrafptr->compglbload0max + bndvertglbancadj; + bndgrafdat.compglbload0avg = orggrafptr->compglbload0avg + bndvertglbancadj; /* Tilt average load according to adjustments */ + bndgrafdat.compglbload0dlt = orggrafptr->compglbload0dlt; + bndgrafdat.compglbsize0 = reduglbtab[3]; + bndgrafdat.commglbload = orggrafptr->commglbload; + bndgrafdat.commglbgainextn = orggrafptr->commglbgainextn; + bndgrafdat.commglbloadextn0 = orggrafptr->commglbloadextn0; + bndgrafdat.commglbgainextn0 = orggrafptr->commglbgainextn0; + bndgrafdat.bbalglbval = orggrafptr->bbalglbval; + bndgrafdat.domndist = orggrafptr->domndist; + bndgrafdat.domnwght[0] = orggrafptr->domnwght[0]; + bndgrafdat.domnwght[1] = orggrafptr->domnwght[1]; + bndgrafdat.levlnum = orggrafptr->levlnum; + + if (bndgrafdat.veexloctax != NULL) { + Gnum bndveexglbanc0; + Gnum bndveexglbanc1; + + bndveexglbanc0 = (orggrafptr->veexglbsum + orggrafptr->commglbgainextn) / 2 - reduglbtab[6]; /* Compute global external gains of anchors */ + bndveexglbanc1 = (orggrafptr->veexglbsum - bndveexglbanc0) - reduglbtab[5]; + + bndgrafdat.veexloctax[bndvertancnnd] = DATASIZE (bndveexglbanc0, bndgrafdat.s.procglbnbr, bndgrafdat.s.proclocnum); /* Spread gains across local anchors */ + bndgrafdat.veexloctax[bndvertancnnd + 1] = DATASIZE (bndveexglbanc1, bndgrafdat.s.procglbnbr, bndgrafdat.s.proclocnum); + } + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (&bndgrafdat) != 0) { + errorPrint ("bdgraphBipartBd: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + if (bdgraphBipartSt (&bndgrafdat, paraptr->stratbnd) != 0) { /* Separate distributed band graph */ + errorPrint ("bdgraphBipartBd: cannot separate band graph"); + bdgraphExit (&bndgrafdat); + return (1); + } + + reduloctab[0] = (Gnum) bndgrafdat.partgsttax[bndvertancnnd]; /* Check if anchor vertices remain in their parts */ + reduloctab[1] = (Gnum) bndgrafdat.partgsttax[bndvertancnnd + 1]; + reduloctab[2] = complocsizeadj0; + reduloctab[3] = 0; /* Assume memory allocation is all right */ + if ((orgflagloctab = memAlloc (flagSize (orggrafptr->s.vertlocnnd) * sizeof (int))) == NULL) { /* Eventually keep space for based indices */ + errorPrint ("bdgraphBipartBd: out of memory (2)"); + reduloctab[3] = 1; + } + + if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 4, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartBd: communication error (2)"); + return (1); + } + + if (((reduglbtab[0] + reduglbtab[1]) != orggrafptr->s.procglbnbr) || /* If not all anchors of initial same parts in same parts */ + ((reduglbtab[0] != 0) && (reduglbtab[0] != orggrafptr->s.procglbnbr)) || + (reduglbtab[3] != 0)) { + if (orgflagloctab != NULL) + memFree (orgflagloctab); + bdgraphExit (&bndgrafdat); /* Apply original strategy to full graph */ + return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); + } + + if (dgraphGhst (&bndgrafdat.s) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("bdgraphBipartBd: cannot compute ghost edge array"); + return (1); + } + + if (reduglbtab[0] == orggrafptr->s.procglbnbr) { /* If all anchors swapped parts, swap all parts of original vertices */ + Gnum orgvertnum; + + orggrafptr->complocsize0 = orggrafptr->s.vertlocnbr - reduloctab[2] - bndgrafdat.s.vertlocnbr + bndgrafdat.complocsize0; + orggrafptr->compglbsize0 = orggrafptr->s.vertglbnbr - reduglbtab[2] - bndgrafdat.s.vertglbnbr + bndgrafdat.compglbsize0; + + for (orgvertnum = orggrafptr->s.baseval; orgvertnum < orggrafptr->s.vertlocnnd; orgvertnum ++) + orggrafptr->partgsttax[orgvertnum] ^= 1; + } + else { + orggrafptr->complocsize0 = reduloctab[2] + bndgrafdat.complocsize0; + orggrafptr->compglbsize0 = reduglbtab[2] + bndgrafdat.compglbsize0; + } + + for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) /* Update part array of all vertices except anchors */ + orggrafptr->partgsttax[bndgrafdat.s.vnumloctax[bndvertlocnum]] = bndgrafdat.partgsttax[bndvertlocnum]; + + dgraphHaloAsync (&orggrafptr->s, (byte *) (orggrafptr->partgsttax + orggrafptr->s.baseval), GRAPHPART_MPI, &requdat); /* Share part array of full graph */ + + commlocloadintn = + commlocloadextn = + commlocgainextn = 0; + bndedlolocval = 1; /* Assume no edge loads */ + for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertlvlnum; bndvertlocnum ++) { /* For all vertices of band graph save for last layer */ + Gnum bndedgelocnum; + Gnum bndedgelocnnd; + Gnum bndpartval; + + bndpartval = (Gnum) bndgrafdat.partgsttax[bndvertlocnum]; + if (bndgrafdat.veexloctax != NULL) { + commlocloadextn += bndgrafdat.veexloctax[bndvertlocnum] * bndpartval; + commlocgainextn += bndgrafdat.veexloctax[bndvertlocnum] * (1 - bndpartval * 2); + } + for (bndedgelocnum = bndgrafdat.s.vertloctax[bndvertlocnum], bndedgelocnnd = bndgrafdat.s.vendloctax[bndvertlocnum]; + bndedgelocnum < bndedgelocnnd; bndedgelocnum ++) { + Gnum bndvertlocend; + Gnum bndpartend; + + bndvertlocend = bndgrafdat.s.edgegsttax[bndedgelocnum]; + bndpartend = bndgrafdat.partgsttax[bndvertlocend]; + + if (bndgrafdat.s.edloloctax != NULL) + bndedlolocval = bndgrafdat.s.edloloctax[bndedgelocnum]; + commlocloadintn += (bndpartval ^ bndpartend) * bndedlolocval; /* Internal load is accounted for twice */ + } + } + for ( ; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { /* For all vertices of last layer, remove internal loads to band vertices once */ + Gnum bndedgelocnum; + Gnum bndedgelocnnd; + Gnum bndpartval; + + bndpartval = (Gnum) bndgrafdat.partgsttax[bndvertlocnum]; + if (bndgrafdat.veexloctax != NULL) { + commlocloadextn += bndgrafdat.veexloctax[bndvertlocnum] * bndpartval; + commlocgainextn += bndgrafdat.veexloctax[bndvertlocnum] * (1 - bndpartval * 2); + } + for (bndedgelocnum = bndgrafdat.s.vertloctax[bndvertlocnum], bndedgelocnnd = bndgrafdat.s.vendloctax[bndvertlocnum] - 1; /* "-1" to avoid anchor edges */ + bndedgelocnum < bndedgelocnnd; bndedgelocnum ++) { + Gnum bndvertlocend; + Gnum bndpartend; + + bndvertlocend = bndgrafdat.s.edgegsttax[bndedgelocnum]; + bndpartend = bndgrafdat.partgsttax[bndvertlocend]; + + if (bndgrafdat.s.edloloctax != NULL) + bndedlolocval = bndgrafdat.s.edloloctax[bndedgelocnum]; + commlocloadintn -= (bndpartval ^ bndpartend) * bndedlolocval; /* Remove internal loads to band graph vertices once because afterwards they will be accounted for twice */ + } + } + + memSet (orgflagloctab, 0, flagSize (orggrafptr->s.vertlocnnd) * sizeof (int)); /* Set vertices as not already considered */ + + for (bndfronlocnum = orgfronlocnum = 0; bndfronlocnum < bndgrafdat.fronlocnbr; bndfronlocnum ++) { /* Project back separator except for last layer */ + Gnum bndvertlocnum; + + bndvertlocnum = bndgrafdat.fronloctab[bndfronlocnum]; + if (bndvertlocnum < bndvertlvlnum) { /* If vertex does not belong to last layer */ + Gnum orgvertlocnum; + + orgvertlocnum = bndgrafdat.s.vnumloctax[bndvertlocnum]; + flagSet (orgflagloctab, orgvertlocnum); /* Set vertex as processed */ + orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; + } + } + + if (dgraphHaloWait (&requdat) != 0) { + errorPrint ("bdgraphBipartBd: cannot complete asynchronous halo exchange"); + return (1); + } + + orgedlolocval = 1; /* Assume no edge loads */ + commlocloadintn2 = 0; + for (bndvertlocnum = bndvertlvlnum; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { /* For all vertices of last layer */ + Gnum orgedgelocnum; + Gnum orgedgelocnnd; + Gnum orgvertlocnum; + GraphPart orgpartval; + Gnum orgflagval; + + orgvertlocnum = bndgrafdat.s.vnumloctax[bndvertlocnum]; + orgpartval = bndgrafdat.partgsttax[bndvertlocnum]; + + orgflagval = 0; /* Assume vertex does not belong to the frontier */ + for (orgedgelocnum = orggrafptr->s.vertloctax[orgvertlocnum], orgedgelocnnd = orggrafptr->s.vendloctax[orgvertlocnum]; + orgedgelocnum < orgedgelocnnd; orgedgelocnum ++) { + Gnum orgvertlocend; + Gnum orgpartend; + Gnum orgflagtmp; + + orgvertlocend = orggrafptr->s.edgegsttax[orgedgelocnum]; + orgpartend = orggrafptr->partgsttax[orgvertlocend]; + + orgflagtmp = orgpartval ^ orgpartend; + if (bndgrafdat.s.edloloctax != NULL) + orgedlolocval = orggrafptr->s.edloloctax[orgedgelocnum]; + orgflagval |= orgflagtmp; + commlocloadintn2 += orgflagtmp * orgedlolocval; /* Internal load to band and original graph vertices are accounted for twice */ + if ((orgflagtmp != 0) && (orgvertlocend < orggrafptr->s.vertlocnnd) && (flagVal (orgflagloctab, orgvertlocend) == 0)) { + orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocend; + flagSet (orgflagloctab, orgvertlocend); + } + } + if ((orgflagval != 0) && (flagVal (orgflagloctab, orgvertlocnum) == 0)) + orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; + + flagSet (orgflagloctab, orgvertlocnum); /* Set vertex as processed anyway */ + } + commlocloadintn += 2 * commlocloadintn2; /* Add twice the internal load of original graph edges and once the one of band edges (one removed before) */ + + orggrafptr->complocload0 = bndgrafdat.complocload0 - bndvertlocancadj; + orggrafptr->compglbload0 = bndgrafdat.compglbload0 - bndvertglbancadj; + orggrafptr->compglbload0dlt = orggrafptr->compglbload0 - orggrafptr->compglbload0avg; + + orgprocsidnbr = orggrafptr->s.procsidnbr; + if (orgprocsidnbr == 0) + goto loop_exit; + orgvertlocnum = orggrafptr->s.baseval; + orgprocsidnum = 0; + orgprocsidtab = orggrafptr->s.procsidtab; + orgprocsidval = orgprocsidtab[orgprocsidnum ++]; + while (1) { /* Scan all vertices which have foreign neighbors */ + while (orgprocsidval < 0) { + orgvertlocnum -= (Gnum) orgprocsidval; + orgprocsidval = orgprocsidtab[orgprocsidnum ++]; + } + + if (flagVal (orgflagloctab, orgvertlocnum) == 0) { /* If vertex not already processed */ + Gnum orgedgelocnum; + Gnum orgedgelocnnd; + GraphPart orgpartval; + + orgpartval = orggrafptr->partgsttax[orgvertlocnum]; + for (orgedgelocnum = orggrafptr->s.vertloctax[orgvertlocnum], orgedgelocnnd = orggrafptr->s.vendloctax[orgvertlocnum]; + orgedgelocnum < orgedgelocnnd; orgedgelocnum ++) { + if (orggrafptr->partgsttax[orggrafptr->s.edgegsttax[orgedgelocnum]] != orgpartval) { + orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; + break; + } + } + } + + do { + if (orgprocsidnum >= orgprocsidnbr) + goto loop_exit; + } while ((orgprocsidval = orgprocsidtab[orgprocsidnum ++]) >= 0); + } +loop_exit : + memFree (orgflagloctab); + + reduloctab[0] = commlocloadintn; /* Twice the internal load; sum globally before dividing by two */ + reduloctab[1] = commlocloadextn; + reduloctab[2] = commlocgainextn; + reduloctab[3] = orgfronlocnum; + if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 4, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartBd: communication error (3)"); + return (1); + } + orggrafptr->fronlocnbr = orgfronlocnum; + orggrafptr->fronglbnbr = reduglbtab[3]; + orggrafptr->commglbload = (reduglbtab[0] / 2) * orggrafptr->domndist + reduglbtab[1]; + orggrafptr->commglbgainextn = reduglbtab[2]; + orggrafptr->bbalglbval = (double) ((orggrafptr->compglbload0dlt < 0) ? (- orggrafptr->compglbload0dlt) : orggrafptr->compglbload0dlt) / (double) orggrafptr->compglbload0avg; + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (orggrafptr) != 0) { + errorPrint ("bdgraphBipartBd: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + bdgraphExit (&bndgrafdat); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_bd.h b/scotch_6.0.3/src/libscotch/bdgraph_bipart_bd.h new file mode 100644 index 00000000..f7f7c85d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_bd.h @@ -0,0 +1,69 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_bd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the band graph bipartitioning **/ +/** routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.1 : from : 11 nov 2007 **/ +/** to : 15 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct BdgraphBipartBdParam_ { + INT distmax; /*+ Width of band surrounding the frontier +*/ + Strat * stratbnd; /*+ Strategy for band graph +*/ + Strat * stratorg; /*+ Strategy for original graph +*/ +} BdgraphBipartBdParam; + +/* +** The function prototypes. +*/ + +#ifndef BDGRAPH_BIPART_BD +#define static +#endif + +int bdgraphBipartBd (Bdgraph * const, const BdgraphBipartBdParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_df.c b/scotch_6.0.3/src/libscotch/bdgraph_bipart_df.c new file mode 100644 index 00000000..b5aad800 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_df.c @@ -0,0 +1,399 @@ +/* Copyright 2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_df.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a bipartition of **/ +/** the given distributed separator graph **/ +/** by applying a diffusion method to what **/ +/** is assumed to be a distributed band **/ +/** graph. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 nov 2007 **/ +/** to : 19 jul 2011 **/ +/** # Version 6.0 : from : 11 sep 2011 **/ +/** to : 31 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH_BIPART_DF + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "dgraph.h" +#include "bdgraph.h" +#include "bdgraph_bipart_df.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes a distributed bipartition +** by diffusion across what is assumed to be a +** distributed band graph. +** It returns: +** - 0 : if the bipartition could be computed. +** - !0 : on error. +*/ + +int +bdgraphBipartDf ( +Bdgraph * const grafptr, /*+ Distributed graph +*/ +const BdgraphBipartDfParam * const paraptr) /*+ Method parameters +*/ +{ + float * restrict ielsloctax; /* Inverse of degree array */ + float * restrict veexloctax; /* Veexval over domndist */ + float * restrict difogsttax; /* Old diffusion value array */ + float * restrict difngsttax; /* New diffusion value array */ + const Gnum * restrict edgegsttax; + Gnum fronlocnum; + Gnum veexlocnbr; + float vanclocval[2]; + float valolocval[2]; /* Fraction of load to remove from anchor vertices at each step */ + Gnum vanclocnnd; + Gnum vertlocnum; + Gnum complocload1; + Gnum complocsize1; + Gnum commlocloadintn; + Gnum commlocloadextn; + Gnum commlocgainextn; + Gnum reduloctab[6]; + Gnum reduglbtab[6]; + Gnum passnum; + float cdifval; + float cremval; + int ovflval; /* Overflow flag value */ + + const Gnum * restrict const veloloctax = grafptr->s.veloloctax; + const Gnum * restrict const edloloctax = grafptr->s.edloloctax; + + if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("bdgraphBipartDf: cannot compute ghost edge array"); + return (1); + } + + reduloctab[0] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 2] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 2] - (grafptr->s.procglbnbr - 1); /* Local degree of both anchor vertices, minus edges to other anchors */ + reduloctab[1] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 1] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 1] - (grafptr->s.procglbnbr - 1); /* Anchor edges have load 1 even for weighted graphs */ + if (grafptr->s.veloloctax == NULL) + reduloctab[2] = /* Weights of anchors */ + reduloctab[3] = 1; + else { + reduloctab[2] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 2]; + reduloctab[3] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 1]; + } + + veexlocnbr = (grafptr->veexloctax != NULL) ? grafptr->s.vertlocnbr : 0; + if (memAllocGroup ((void **) (void *) + &ielsloctax, (size_t) (grafptr->s.vertlocnbr * sizeof (float)), + &veexloctax, (size_t) (veexlocnbr * sizeof (float)), + &difogsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), + &difngsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), NULL) == NULL) { + errorPrint ("bdgraphBipartDf: out of memory"); + reduloctab[0] = -1; + } + ielsloctax -= grafptr->s.baseval; + difogsttax -= grafptr->s.baseval; + difngsttax -= grafptr->s.baseval; + veexloctax = (grafptr->veexloctax != NULL) ? (veexloctax - grafptr->s.baseval) : NULL; + + if (MPI_Allreduce (reduloctab, reduglbtab, 4, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartDf: communication error (1)"); + return (1); + } + + if (reduglbtab[0] < 0) { + if (ielsloctax != NULL) + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + return (1); + } + if ((reduglbtab[0] == 0) || /* If graph is too small to have any usable anchors, leave partition as is */ + (reduglbtab[1] == 0)) { + memFree (ielsloctax + grafptr->s.baseval); + + if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (grafptr->partgsttax + grafptr->s.baseval), GRAPHPART_MPI) != 0) { + errorPrint ("bdgraphBipartDf: cannot propagate part data (1)"); + return (1); + } + + return (0); + } + + vanclocval[0] = (float) ((paraptr->typeval == BDGRAPHBIPARTDFTYPEBAL) /* If balanced parts wanted */ + ? grafptr->compglbload0avg /* Target is average */ + : ( (grafptr->compglbload0 < grafptr->compglbload0min) ? grafptr->compglbload0min : /* Else keep load if not off balance */ + ((grafptr->compglbload0 > grafptr->compglbload0max) ? grafptr->compglbload0max : grafptr->compglbload0))); + vanclocval[1] = (float) grafptr->s.veloglbsum - vanclocval[0]; + vanclocval[0] = - vanclocval[0]; /* Part 0 holds negative values */ + valolocval[0] = (float) reduglbtab[2]; /* Compute values to remove from anchor vertices */ + valolocval[1] = (float) reduglbtab[3] - BDGRAPHBIPARTDFEPSILON; /* Slightly tilt value to add to part 1 */ + + vanclocnnd = grafptr->s.vertlocnnd - 2; /* Do not account for anchor vertices in diffusion computations */ + if (grafptr->s.edloloctax != NULL) { + for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { + Gnum edgelocnum; + Gnum edgelocnnd; + Gnum edlolocsum; + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if ((grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]) == 0) { + errorPrint ("bdgraphBipartDf: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + difogsttax[vertlocnum] = 0.0F; + for (edgelocnum = grafptr->s.vertloctax[vertlocnum], edgelocnnd = grafptr->s.vendloctax[vertlocnum], edlolocsum = 0; + edgelocnum < edgelocnnd; edgelocnum ++) + edlolocsum += grafptr->s.edloloctax[edgelocnum]; + + ielsloctax[vertlocnum] = 1.0F / (float) edlolocsum; + } + } + else { /* Graph has no edge loads */ + for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if ((grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]) == 0) { + errorPrint ("bdgraphBipartDf: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + ielsloctax[vertlocnum] = 1.0F / (float) (grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]); + difogsttax[vertlocnum] = 0.0F; + } + } + ielsloctax[vanclocnnd] = 1.0F / (float) reduglbtab[0]; + ielsloctax[vanclocnnd + 1] = 1.0F / (float) reduglbtab[1]; + difogsttax[vanclocnnd] = vanclocval[0] * ielsloctax[vanclocnnd]; /* Load anchor vertices for first pass */ + difogsttax[vanclocnnd + 1] = vanclocval[1] * ielsloctax[vanclocnnd + 1]; + difngsttax[vanclocnnd] = /* In case of isolated anchors, do not risk overflow because of NaN */ + difngsttax[vanclocnnd + 1] = 0.0F; + + if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { /* Perform initial diffusion (and build communication structures) */ + errorPrint ("bdgraphBipartDf: cannot propagate diffusion data (1)"); + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + return (1); + } + + ovflval = 0; + cdifval = paraptr->cdifval; + cremval = paraptr->cremval; + edgegsttax = grafptr->s.edgegsttax; + for (passnum = 0; ; ) { /* For all passes */ + if (ovflval == 0) { /* If no overflow occured */ + float * diftgsttax; /* Temporary swap value */ + Gnum vertlocnum; + float veloval; + + veloval = 1.0F; /* Assume no vertex loads */ + for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { + Gnum edgelocnum; + Gnum edgelocnnd; + float diffval; + + diffval = 0.0F; + edgelocnum = grafptr->s.vertloctax[vertlocnum]; + edgelocnnd = grafptr->s.vendloctax[vertlocnum]; + if (grafptr->s.edloloctax != NULL) + for ( ; edgelocnum < edgelocnnd; edgelocnum ++) + diffval += difogsttax[edgegsttax[edgelocnum]] * (float) grafptr->s.edloloctax[edgelocnum]; + else + for ( ; edgelocnum < edgelocnnd; edgelocnum ++) + diffval += difogsttax[edgegsttax[edgelocnum]]; + + diffval *= cdifval; + diffval += (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; + + if (grafptr->s.veloloctax != NULL) + veloval = (float) grafptr->s.veloloctax[vertlocnum]; + if (diffval >= 0.0F) { + diffval = (diffval - veloval) * ielsloctax[vertlocnum]; + if (diffval <= 0.0F) + diffval = +BDGRAPHBIPARTDFEPSILON; + } + else { + diffval = (diffval + veloval) * ielsloctax[vertlocnum]; + if (diffval >= 0.0F) + diffval = -BDGRAPHBIPARTDFEPSILON; + } + if (isnan (diffval)) { /* If overflow occured */ + ovflval = 1; /* We are in state of overflow */ + goto abort; /* Exit this loop without swapping arrays */ + } + difngsttax[vertlocnum] = diffval; + } + for ( ; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { /* For the two local anchor vertices */ + Gnum edgelocnum; + Gnum edgelocnnd; + float diffval; + + diffval = 0.0F; + edgelocnum = grafptr->s.vertloctax[vertlocnum] + grafptr->s.procglbnbr - 1; /* Skip links to other anchors */ + edgelocnnd = grafptr->s.vendloctax[vertlocnum]; + if (edgelocnum == edgelocnnd) /* If isolated anchor */ + continue; /* Barrel is empty */ + + for ( ; edgelocnum < edgelocnnd; edgelocnum ++) /* Anchor edges have load 1 even for weighted graphs */ + diffval += difogsttax[edgegsttax[edgelocnum]]; + + diffval *= cdifval; + diffval += vanclocval[vertlocnum - vanclocnnd] + (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; + if (diffval >= 0.0F) { + diffval = (diffval - valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; + if (diffval <= 0.0F) + diffval = +BDGRAPHBIPARTDFEPSILON; + } + else { + diffval = (diffval + valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; + if (diffval >= 0.0F) + diffval = -BDGRAPHBIPARTDFEPSILON; + } + if (isnan (diffval)) { /* If overflow occured */ + ovflval = 1; /* We are in state of overflow */ + goto abort; /* Exit this loop without swapping arrays */ + } + difngsttax[vertlocnum] = diffval; + } + + diftgsttax = (float *) difngsttax; /* Swap old and new diffusion arrays */ + difngsttax = (float *) difogsttax; /* Casts to prevent IBM compiler from yelling */ + difogsttax = (float *) diftgsttax; + } +abort : /* If overflow occured, resume here */ + if (++ passnum >= paraptr->passnbr) /* If maximum number of passes reached */ + break; /* Exit main loop */ + + if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { + errorPrint ("bdgraphBipartDf: cannot propagate diffusion data (2)"); + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + return (1); + } + } + + for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) /* Set new part distribution */ + grafptr->partgsttax[vertlocnum] = (difogsttax[vertlocnum] <= 0.0F) ? 0 : 1; + grafptr->partgsttax[vanclocnnd] = 0; /* Set up parts in case anchors are isolated */ + grafptr->partgsttax[vanclocnnd + 1] = 1; + + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + + if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (grafptr->partgsttax + grafptr->s.baseval), GRAPHPART_MPI) != 0) { + errorPrint ("bdgraphBipartDf: cannot propagate part data (2)"); + return (1); + } + + commlocloadintn = + commlocloadextn = + commlocgainextn = 0; + for (vertlocnum = grafptr->s.baseval, fronlocnum = complocsize1 = complocload1 = 0; + vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + Gnum edgelocnnd; + Gnum veloval; + Gnum partval; + Gnum flagval; + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (grafptr->partgsttax[vertlocnum] > 1) { + errorPrint ("bdgraphBipartDf: internal error (3)"); + break; /* Do not break upcoming collective communications */ + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + partval = (Gnum) grafptr->partgsttax[vertlocnum]; + veloval = (veloloctax != NULL) ? veloloctax[vertlocnum] : 1; + if (grafptr->veexloctax != NULL) { + commlocloadextn += grafptr->veexloctax[vertlocnum] * partval; + commlocgainextn += grafptr->veexloctax[vertlocnum] * (1 - partval * 2); + } + complocsize1 += partval; + complocload1 += partval * veloval; + + flagval = 0; + for (edgelocnum = grafptr->s.vertloctax[vertlocnum], edgelocnnd = grafptr->s.vendloctax[vertlocnum]; + edgelocnum < edgelocnnd; edgelocnum ++) { + Gnum edloval; + Gnum partend; + + partend = (Gnum) grafptr->partgsttax[edgegsttax[edgelocnum]]; +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (partend > 1) { + errorPrint ("bdgraphBipartDf: internal error (4)"); + vertlocnum = grafptr->s.vertlocnnd; + break; /* Do not break upcoming collective communications */ + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + edloval = (edloloctax != NULL) ? edloloctax[edgelocnum] : 1; + flagval |= partval ^ partend; + commlocloadintn += (partval ^ partend) * edloval; /* Internal load is accounted for twice */ + } + if (flagval != 0) /* If vertex has neighbors in other part */ + grafptr->fronloctab[fronlocnum ++] = vertlocnum; /* Record it as member of separator */ + } + grafptr->complocload0 = grafptr->s.velolocsum - complocload1; + grafptr->complocsize0 = grafptr->s.vertlocnbr - complocsize1; + grafptr->fronlocnbr = fronlocnum; + + reduloctab[0] = fronlocnum; + reduloctab[1] = grafptr->complocload0; + reduloctab[2] = grafptr->complocsize0; + reduloctab[3] = commlocloadintn; /* Twice the internal load; sum globally before dividing by two */ + reduloctab[4] = commlocloadextn; + reduloctab[5] = commlocgainextn; + if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 6, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartDf: communication error (2)"); + return (1); + } + grafptr->fronglbnbr = reduglbtab[0]; + grafptr->compglbload0 = reduglbtab[1]; + grafptr->compglbload0dlt = grafptr->compglbload0 - grafptr->compglbload0avg; + grafptr->compglbsize0 = reduglbtab[2]; + grafptr->commglbload = (reduglbtab[3] / 2) * grafptr->domndist + reduglbtab[4]; + grafptr->commglbgainextn = reduglbtab[5]; + grafptr->bbalglbval = (double) ((grafptr->compglbload0dlt < 0) ? (- grafptr->compglbload0dlt) : grafptr->compglbload0dlt) / (double) grafptr->compglbload0avg; + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (grafptr) != 0) { + errorPrint ("bdgraphBipartDf: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_df.h b/scotch_6.0.3/src/libscotch/bdgraph_bipart_df.h new file mode 100644 index 00000000..e76bbc1e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_df.h @@ -0,0 +1,89 @@ +/* Copyright 2007,2009,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_df.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the parallel diffusion bipartition- **/ +/** ing routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 nov 2007 **/ +/** to : 14 apr 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Small non-zero float value. +*/ + +#define BDGRAPHBIPARTDFEPSILON (1.0F / (float) (GNUMMAX)) + +/*+ Sign masking operator. +*/ + +#define BDGRAPHBIPARTDFGNUMSGNMSK(i) ((Gnum) 0 - (((Gunum) (i)) >> (sizeof (Gnum) * 8 - 1))) + +/* +** The type and structure definitions. +*/ + +/*+ Job selection policy types. +*/ + +typedef enum BdgraphBipartDfType_ { + BDGRAPHBIPARTDFTYPEBAL = 0, /*+ Balance to average +*/ + BDGRAPHBIPARTDFTYPEKEEP /*+ Preserve current imbalance +*/ +} BdgraphBipartDfType; + +/*+ Method parameters. +*/ + +typedef struct BdgraphBipartDfParam_ { + INT passnbr; /*+ Number of passes to do +*/ + double cdifval; /*+ Coefficient of diffused load +*/ + double cremval; /*+ Coefficient of remaining load +*/ + BdgraphBipartDfType typeval; /*+ Type of balance to reach +*/ +} BdgraphBipartDfParam; + +/* +** The function prototypes. +*/ + +#ifndef BDGRAPH_BIPART_DF +#define static +#endif + +int bdgraphBipartDf (Bdgraph * const, const BdgraphBipartDfParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_ex.c b/scotch_6.0.3/src/libscotch/bdgraph_bipart_ex.c new file mode 100644 index 00000000..109b4897 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_ex.c @@ -0,0 +1,503 @@ +/* Copyright 2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_ex.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module bipartitions a distributed **/ +/** active graph using a parallel gradient **/ +/** method to balance the two parts as **/ +/** evenly as possible. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 jul 2010 **/ +/** to : 15 apr 2011 **/ +/** # Version 6.0 : from : 11 sep 2011 **/ +/** to : 31 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH_BIPART_EX + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "arch.h" +#include "bdgraph.h" +#include "bdgraph_bipart_ex.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bdgraphBipartEx ( +Bdgraph * restrict const grafptr, /*+ Active graph +*/ +const BdgraphBipartExParam * restrict const paraptr) /*+ Method parameters +*/ +{ + int sbbtnbr; /* Number of subbits */ + Gnum sbbtmsk; /* Subbit mask */ + int gainsiz; /* Size of gain array */ + int gainidx; + Gnum * restrict gainloctab; + Gnum * restrict gainglbtab; + Gnum * restrict frstloctab; + Gnum * restrict nextloctab; + Gnum * restrict loadglbtab; + const Gnum * restrict edgegsttax; + Gnum edlolocval; + Gnum fronlocnum; + Gnum vertgstnum; + Gnum vertlocnnd; + Gnum complocsizedlt; /* Count of vertices moved locally */ + Gnum complocloaddlt; /* Load of vertices moved locally */ + Gnum compglbloaddlt; + Gnum compglbloaddltmax; + Gnum compglbloaddltmat; + Gnum commlocgain; + Gnum commlocgainextn; + Gnum fronlocnbr; + int * restrict movegsttab; + int * restrict flagloctab; + int cheklocval; + int chekglbval; + BdgraphBipartExSort * sorttab; + size_t sortsiz; + Gnum reduloctab[5]; + Gnum reduglbtab[5]; + Gnum domndist; + Gnum partval; + + const Gnum * restrict const vertloctax = grafptr->s.vertloctax; /* Fast accesses */ + const Gnum * restrict const vendloctax = grafptr->s.vendloctax; + const Gnum * restrict const veloloctax = grafptr->s.veloloctax; + const Gnum * restrict const veexloctax = grafptr->veexloctax; + const Gnum * restrict const edloloctax = grafptr->s.edloloctax; + Gnum * restrict const fronloctab = grafptr->fronloctab; + GraphPart * restrict const partgsttax = grafptr->partgsttax; + + partval = (grafptr->compglbload0dlt > 0) ? 1 : 0; /* Get number of underloaded part to receive vertices */ + + compglbloaddltmax = (Gnum) ((double) grafptr->compglbload0avg * paraptr->deltval); + compglbloaddltmat = (partval == 0) + ? (grafptr->compglbload0avg - grafptr->compglbload0min) + : (grafptr->compglbload0max - grafptr->compglbload0avg); + if (compglbloaddltmax > compglbloaddltmat) + compglbloaddltmax = compglbloaddltmat; + + if ((abs (grafptr->compglbload0dlt) < compglbloaddltmax) || /* If nothing to do */ + (grafptr->fronglbnbr == 0)) /* Or if no current frontier */ + return (0); /* This algorithm is useless */ + + if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("bdgraphBipartEx: cannot compute ghost edge array"); + return (1); + } + + sbbtnbr = (int) paraptr->sbbtnbr; + sbbtmsk = (1 << sbbtnbr) - 1; + gainsiz = ((sizeof (Gnum) << 3) - sbbtnbr) << (sbbtnbr + 1); /* Compute gain array size */ + sortsiz = MAX ((grafptr->s.procglbnbr * sizeof (BdgraphBipartExSort)), /* TRICK: recycle */ + (grafptr->fronlocnbr * sizeof (BdgraphBipartExMove))); + + cheklocval = 0; + if (memAllocGroup ((void **) (void *) + &gainglbtab, (size_t) (gainsiz * sizeof (Gnum)), + &gainloctab, (size_t) (gainsiz * sizeof (Gnum)), + &frstloctab, (size_t) (gainsiz * sizeof (Gnum)), + &nextloctab, (size_t) (grafptr->fronlocnbr * sizeof (Gnum)), + &loadglbtab, (size_t) (grafptr->s.procglbnbr * sizeof (Gnum)), + &movegsttab, (size_t) (flagSize (grafptr->s.vertgstnbr + grafptr->s.baseval) * sizeof (int)), /* TRICK: use based vertices as flag array indices */ + &flagloctab, (size_t) (flagSize (grafptr->s.vertlocnbr + grafptr->s.baseval) * sizeof (int)), + &sorttab, (size_t) (sortsiz), NULL) == NULL) { + errorPrint ("bdgraphBipartEx: out of memory"); + cheklocval = 1; + } + else { + memSet (gainloctab, 0, gainsiz * sizeof (Gnum)); /* Initialize gain array */ + memSet (frstloctab, ~0, gainsiz * sizeof (Gnum)); /* Initialize linked list */ + memSet (nextloctab, ~0, grafptr->fronlocnbr * sizeof (Gnum)); + memSet (movegsttab, 0, flagSize (grafptr->s.vertgstnbr + grafptr->s.baseval) * sizeof (int)); /* TRICK: based sizes */ + memSet (flagloctab, 0, flagSize (grafptr->s.vertlocnbr + grafptr->s.baseval) * sizeof (int)); + } + +#ifdef SCOTCH_DEBUG_BDGRAPH1 + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartEx: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + if (chekglbval != 0) { + if (gainglbtab != NULL) + memFree (gainglbtab); /* Free group leader */ + return (1); + } + + domndist = (Gnum) grafptr->domndist; + + edgegsttax = grafptr->s.edgegsttax; + edlolocval = 1; /* Assume no edge loads */ + for (fronlocnum = 0; fronlocnum < grafptr->fronlocnbr; fronlocnum ++) { + Gnum vertlocnum; + Gnum velolocval; + Gnum edgelocnum; + Gnum commgain; + int gainidx; + int i; + Gnum j; + + vertlocnum = fronloctab[fronlocnum]; + + if ((Gnum) partgsttax[vertlocnum] == partval) /* If vertex belongs to lighter part, skip it */ + continue; + + for (edgelocnum = vertloctax[vertlocnum], commgain = 0; + edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { + Gnum vertlocend; + Gnum partend; + Gnum partdlt; + + vertlocend = edgegsttax[edgelocnum]; + partend = (Gnum) partgsttax[vertlocend]; + if (edloloctax != NULL) + edlolocval = edloloctax[edgelocnum]; + + partdlt = partval ^ partend; /* Inverse of partdlt, because "partval" is the opposite */ + commgain += (2 * partdlt - 1) * edlolocval; /* Since partdlt has reversed meaning, reverse gain too */ + } + commgain *= domndist; /* Adjust internal gains with respect to external gains */ + if (veexloctax != NULL) + commgain += (2 * partval - 1) * veexloctax[vertlocnum]; /* Partval has reversed meaning */ + + velolocval = (veloloctax != NULL) ? veloloctax[vertlocnum] : 1; + + if (commgain >= 0) { /* Compute table entry for gain */ + for (i = 0, j = commgain; j > sbbtmsk; i ++, j >>= 1) ; + i = (i << sbbtnbr) + (int) j; + } + else { + for (i = 0, j = - (commgain + 1); j > sbbtmsk; i ++, j >>= 1) ; + i = - ((i << sbbtnbr) + (int) j + 1); + } + + gainidx = (gainsiz >> 1) + i; +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if ((gainidx < 0) || (gainidx >= gainsiz)) { + errorPrint ("bdgraphBipartEx: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + gainloctab[gainidx] += velolocval; /* Accumulate gain in proper cell */ + nextloctab[fronlocnum] = frstloctab[gainidx]; /* Chain frontier vertex in gain list */ + frstloctab[gainidx] = fronlocnum; + } + + if (MPI_Allreduce (gainloctab, gainglbtab, gainsiz, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartEx: communication error (2)"); + return (1); + } + + complocloaddlt = 0; /* No moved vertices yet */ + compglbloaddlt = abs (grafptr->compglbload0dlt); /* We want to reduce the absolute value of imbalance */ + for (gainidx = 0; gainidx < gainsiz; gainidx ++) { + Gnum compglbloadtmp; + Gnum gainglbval; + Gnum fronlocnum; + + gainglbval = gainglbtab[gainidx]; + if (gainglbval <= 0) + continue; + + compglbloadtmp = compglbloaddlt - gainglbval; + if (compglbloadtmp < compglbloaddltmax) + break; + + compglbloaddlt = compglbloadtmp; + complocloaddlt += gainloctab[gainidx]; /* We moved that much load locally */ + + for (fronlocnum = frstloctab[gainidx]; fronlocnum != ~0; /* For all vertices in swapped gain slot */ + fronlocnum = nextloctab[fronlocnum]) + partgsttax[fronloctab[fronlocnum]] = (GraphPart) (partval | 2); /* Swap vertex part and flag vertex */ + } + + if ((gainidx < gainsiz) && /* If we can make further adjustments */ + (compglbloaddlt > compglbloaddltmax)) { /* And if there are some to make */ + Gnum loadglbmax; + int procglbnbr; + int proclocnum; + int procnum; + int procmax; + int sortnbr; + int sortnum; + + if (MPI_Allgather (gainloctab + gainidx, 1, GNUM_MPI, + loadglbtab, 1, GNUM_MPI, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartEx: communication error (3)"); + return (1); + } + + for (procnum = procmax = sortnbr = 0, loadglbmax = 0; /* For all potential contributions */ + procnum < grafptr->s.procglbnbr; procnum ++) { + if (loadglbtab[procnum] > 0) { + if (loadglbtab[procnum] > loadglbmax) { /* Find maximum contribution index as starting point */ + loadglbmax = loadglbtab[procnum]; + procmax = procnum; + } + sorttab[sortnbr].veloval = loadglbtab[procnum]; + sorttab[sortnbr].procnum = (Gnum) procnum; + sortnbr ++; + } + } + + procglbnbr = grafptr->s.procglbnbr; + for (sortnum = 0; sortnum < sortnbr; sortnum ++) /* Increase priority value from found maximum */ + sorttab[sortnum].prioval = (sorttab[sortnum].procnum + procglbnbr - procmax) % procglbnbr; + + intSort3asc2 (sorttab, sortnbr); /* Sort contributions array unambiguously */ + + proclocnum = grafptr->s.proclocnum; + for (sortnum = sortnbr - 1; sortnum >= 0; sortnum --) { /* Process contributions by descending load */ + Gnum compglbloadtmp; + + compglbloadtmp = compglbloaddlt - sorttab[sortnum].veloval; + if (compglbloadtmp < compglbloaddltmax) { /* If entire move would cause imbalance */ + Gnum fronlocnum; + BdgraphBipartExMove * movetab; + Gnum movenbr; + Gnum movenum; + + if (sorttab[sortnum].procnum != proclocnum) /* If this is not our job to handle it */ + break; /* Nothing more to do for us */ + + movetab = (BdgraphBipartExMove *) sorttab; /* TRICK: recycle sorttab array as move array */ + + for (fronlocnum = frstloctab[gainidx], movenbr = 0; /* For all vertices in swapped gain slot */ + fronlocnum != ~0; fronlocnum = nextloctab[fronlocnum], movenbr ++) { + Gnum vertlocnum; + + vertlocnum = fronloctab[fronlocnum]; + movetab[movenbr].veloval = (veloloctax != NULL) ? veloloctax[vertlocnum] : 1; + movetab[movenbr].vertnum = vertlocnum; + } + + intSort2asc1 (movetab, movenbr); /* Sort local moves by ascending load order */ + + for (movenum = movenbr - 1; movenum >= 0; movenum --) { /* For all potential moves by descending weight */ + Gnum compglbloadtmp; + + compglbloadtmp = compglbloaddlt - movetab[movenum].veloval; + if (compglbloadtmp >= compglbloaddltmax) { /* If move reduces imbalance */ + partgsttax[movetab[movenum].vertnum] = (GraphPart) (partval | 2); /* Swap vertex part and flag vertex */ + compglbloaddlt = compglbloadtmp; + complocloaddlt += movetab[movenum].veloval; /* We moved that much load locally */ + if (compglbloaddlt <= compglbloaddltmax) /* If nothing more to do, exit loop */ + break; + } + } + + break; /* Nothing more to do */ + } + + compglbloaddlt = compglbloadtmp; /* Accept move entirely */ + + if (sorttab[sortnum].procnum == proclocnum) { /* If we are the process to do it */ + Gnum fronlocnum; + + complocloaddlt += sorttab[sortnum].veloval; /* We moved all of our local load for this gain */ + + for (fronlocnum = frstloctab[gainidx]; fronlocnum != ~0; /* For all vertices in swapped gain slot */ + fronlocnum = nextloctab[fronlocnum]) + partgsttax[fronloctab[fronlocnum]] = (GraphPart) (partval | 2); /* Swap vertex part and flag vertex */ + + break; /* We did our job; don't care about the rest */ + } + } + } + grafptr->complocload0 -= (2 * partval - 1) * complocloaddlt; /* Update according to load of moved vertices */ + + if (dgraphHaloSync (&grafptr->s, partgsttax + grafptr->s.baseval, GRAPHPART_MPI) != 0) { + errorPrint ("bdgraphBipartEx: communication error (4)"); + return (1); + } + + for (vertgstnum = grafptr->s.vertlocnnd; /* For all received ghosts */ + vertgstnum < grafptr->s.vertgstnnd; vertgstnum ++) { + if ((partgsttax[vertgstnum] & 2) != 0) { /* If ghost vertex changed part */ + partgsttax[vertgstnum] &= 1; /* Put it back in normal state */ + flagSet (movegsttab, vertgstnum); /* While recording state change */ + } + } + + complocsizedlt = 0; /* No difference to number of vertices yet */ + for (fronlocnum = 0, fronlocnbr = grafptr->fronlocnbr; + fronlocnum < fronlocnbr; fronlocnum ++) { + Gnum vertlocnum; + + vertlocnum = fronloctab[fronlocnum]; + + flagSet (flagloctab, vertlocnum); /* Record vertex as already seen */ + if ((partgsttax[vertlocnum] & 2) != 0) { /* If frontier vertex changed part */ + partgsttax[vertlocnum] &= 1; /* Put it back in normal state */ + flagSet (movegsttab, vertlocnum); /* While recording state change */ + complocsizedlt ++; /* One more vertex changed of part */ + } + } + grafptr->complocsize0 -= (2 * partval - 1) * complocsizedlt; /* Update according to number of moved vertices */ + + if (grafptr->s.procsidnbr != 0) { /* Add potential new frontiers to frontier array */ + Gnum vertlocnum; + Gnum procsidnbr; + Gnum procsidnum; + int procsidval; + + const int * restrict const procsidtab = grafptr->s.procsidtab; + + vertlocnum = grafptr->s.baseval; + procsidnbr = grafptr->s.procsidnbr; + procsidnum = 0; + procsidval = procsidtab[procsidnum ++]; + + while (1) { /* Scan all vertices which have foreign neighbors */ + while (procsidval < 0) { + vertlocnum -= (Gnum) procsidval; + procsidval = procsidtab[procsidnum ++]; + } + + if (flagVal (flagloctab, vertlocnum) == 0) { /* If vertex not already processed */ + flagSet (flagloctab, vertlocnum); + fronloctab[fronlocnbr ++] = vertlocnum; /* Record candidate frontier vertex */ + } + + do { + if (procsidnum >= procsidnbr) + goto loop_exit; + } while ((procsidval = procsidtab[procsidnum ++]) >= 0); + } +loop_exit : ; + } + + edlolocval = 1; /* Assume no edge loads */ + commlocgain = + commlocgainextn = 0; + for (fronlocnum = 0, vertlocnnd = grafptr->s.vertlocnnd; /* For all potential frontier vertices */ + fronlocnum < fronlocnbr; ) { + Gnum vertlocnum; + Gnum edgelocnum; + Gnum commcut; + Gnum flagval; + + vertlocnum = fronloctab[fronlocnum]; + partval = partgsttax[vertlocnum]; + flagval = flagVal (movegsttab, vertlocnum); + + for (edgelocnum = vertloctax[vertlocnum], commcut = 0; + edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { + Gnum vertlocend; + Gnum flagend; + Gnum partend; + Gnum partdlt; + + vertlocend = edgegsttax[edgelocnum]; + partend = (Gnum) partgsttax[vertlocend]; + flagend = (Gnum) flagVal (movegsttab, vertlocend); + if (edloloctax != NULL) + edlolocval = edloloctax[edgelocnum]; + + partdlt = partval ^ partend; /* Compute difference between new parts */ + commcut |= partdlt; /* Accumulate difference */ + + if ((partdlt != 0) && /* If vertices belong to different parts */ + (vertlocend < vertlocnnd) && /* And end vertex is local */ + (flagVal (flagloctab, vertlocend) == 0)) { /* And end vertex not already queued */ + fronloctab[fronlocnbr ++] = vertlocend; /* Add end vertex to frontier queue */ + flagSet (flagloctab, vertlocend); /* Flag it to avoid multiple insertions */ + } + + commlocgain += (((- partdlt) & edlolocval) - /* Compute difference between new and old communication loads */ + ((- (partdlt ^ flagval ^ flagend)) & edlolocval)); + } + + if (veexloctax != NULL) + commlocgainextn += (partval - (partval ^ flagval)) * veexloctax[vertlocnum]; /* Compute half of difference in external load */ + + if (commcut == 0) { /* If vertex no longer belongs to frontier */ + fronloctab[fronlocnum] = fronloctab[-- fronlocnbr]; /* Replace it by another one */ + continue; /* Process replacement vertex */ + } + + fronlocnum ++; /* Process next vertex */ + } + grafptr->fronlocnbr = fronlocnbr; /* Set new number of frontier vertices */ + + memFree (gainglbtab); /* Free group leader */ + + reduloctab[0] = grafptr->fronlocnbr; + reduloctab[1] = grafptr->complocload0; + reduloctab[2] = grafptr->complocsize0; + reduloctab[3] = commlocgain * domndist; /* Send internal gain */ + reduloctab[4] = commlocgainextn * 2; /* Send external gain */ + if (MPI_Allreduce (reduloctab, reduglbtab, 5, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartEx: communication error (5)"); + return (1); + } + grafptr->fronglbnbr = reduglbtab[0]; + grafptr->compglbload0 = reduglbtab[1]; + grafptr->compglbload0dlt = reduglbtab[1] - grafptr->compglbload0avg; + grafptr->compglbsize0 = reduglbtab[2]; + grafptr->commglbload += reduglbtab[3] / 2 + reduglbtab[4]; /* Add modifications, counted twice for internal gain */ + grafptr->commglbgainextn -= reduglbtab[4]; /* Account for modifications in external gain */ + grafptr->bbalglbval = (double) ((grafptr->compglbload0dlt < 0) ? (- grafptr->compglbload0dlt) : grafptr->compglbload0dlt) / (double) grafptr->compglbload0avg; + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (grafptr) != 0) { + errorPrint ("bdgraphBipartEx: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_ex.h b/scotch_6.0.3/src/libscotch/bdgraph_bipart_ex.h new file mode 100644 index 00000000..a60ef21e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_ex.h @@ -0,0 +1,85 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_ex.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the parallel load imbalance **/ +/** minimization bipartitioning routine **/ +/** for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.1 : from : 14 jul 2010 **/ +/** to : 14 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct BdgraphBipartExParam_ { + INT sbbtnbr; /*+ Number of sub-bits in the distributed gain structure +*/ + double deltval; /*+ Maximum weight imbalance ratio +*/ +} BdgraphBipartExParam; + +/* Sort structure for local vertices. First + element used for intSort2asc1. */ + +typedef struct BdgraphBipartExSort_ { + Gnum veloval; /* Load per process; TRICK: FIRST */ + Gnum prioval; /* Priority value, not to sort by process rank */ + Gnum procnum; /* Process number; TRICK: (Gnum) for sorting */ +} BdgraphBipartExSort; + +/* Sort structure for individual moves. */ + +typedef struct BdgraphBipartExMove_ { + Gnum veloval; /* Load per process; TRICK: FIRST */ + Gnum vertnum; /* Vertex number */ +} BdgraphBipartExMove; + +/* +** The function prototypes. +*/ + +#ifndef BDGRAPH_BIPART_EX +#define static +#endif + +int bdgraphBipartEx (Bdgraph * restrict const, const BdgraphBipartExParam * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_ml.c b/scotch_6.0.3/src/libscotch/bdgraph_bipart_ml.c new file mode 100644 index 00000000..2cc144fd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_ml.c @@ -0,0 +1,824 @@ +/* Copyright 2007-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_ml.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module bipartitions a distributed **/ +/** graph using a multi-level scheme. **/ +/** **/ +/** DATES : # Version 5.1 : from : 30 oct 2007 **/ +/** to : 14 apr 2011 **/ +/** : # Version 6.0 : from : 11 sep 2011 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH_BIPART_ML + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "arch.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "bdgraph.h" +#include "bdgraph_bipart_ml.h" +#include "bdgraph_bipart_st.h" + +/*********************************************/ +/* */ +/* The coarsening and uncoarsening routines. */ +/* */ +/*********************************************/ + +/* This routine builds a coarser graph from the +** Dgraph that is given on input. The coarser +** Dgraphs differ at this stage from classical +** active Dgraphs as their internal gains are not +** yet computed. +** It returns: +** - 0 : if the coarse Dgraph has been built. +** - 1 : if threshold reached or on error. +*/ + +static +int +bdgraphBipartMlCoarsen ( +Bdgraph * restrict const finegrafptr, /*+ Finer graph +*/ +Bdgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ +DgraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ +const BdgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ +{ + int foldval; + + switch (paraptr->foldval) { + case 0 : + foldval = DGRAPHCOARSENNONE; + break; + case 1 : + foldval = DGRAPHCOARSENFOLD; + break; + case 2 : + foldval = DGRAPHCOARSENFOLDDUP; + break; +#ifdef SCOTCH_DEBUG_BGRAPH2 + default : + errorPrint ("bdgraphBipartMlCoarsen: invalid parameter"); + return (1); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + } + if ((finegrafptr->s.vertglbnbr / finegrafptr->s.procglbnbr) > paraptr->foldmax) /* If no need to fold */ + foldval = DGRAPHCOARSENNONE; + + *coarmultptr = NULL; /* Let the routine create the multinode array */ + dgraphInit (&coargrafptr->s, finegrafptr->s.proccomm); /* Re-use fine graph communicator */ + if (dgraphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, paraptr->passnbr, + paraptr->coarnbr, paraptr->coarrat, foldval) != 0) + return (1); /* Return if coarsening failed */ + + *coarmultptr -= coargrafptr->s.baseval; /* Base pointer to multinode array */ + coargrafptr->partgsttax = NULL; /* Do not allocate partition data yet */ + coargrafptr->fronloctab = NULL; + coargrafptr->fronglbnbr = 0; + + if (coargrafptr->s.procglbnbr == 0) { /* Not owner of graph */ + coargrafptr->veexloctax = NULL; + return (0); + } + + if (finegrafptr->veexloctax != NULL) { /* Merge external gains for coarsened vertices */ + DgraphCoarsenMulti * restrict coarmulttax; + Gnum * restrict coarveexloctax; + Gnum coarvertlocnum; + + if ((coarveexloctax = (Gnum *) memAlloc (coargrafptr->s.vertlocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("bdgraphBipartMlCoarsen: out of memory"); + dgraphExit (&coargrafptr->s); /* Only free Dgraph since veexloctax not allocated */ + memFree (*coarmultptr + coargrafptr->s.baseval); + return (1); + } + coarveexloctax -= coargrafptr->s.baseval; + coargrafptr->veexloctax = coarveexloctax; + coarmulttax = *coarmultptr; + + for (coarvertlocnum = coargrafptr->s.baseval; coarvertlocnum < coargrafptr->s.vertlocnnd; coarvertlocnum++) { + Gnum finevertnum0; /* First multinode vertex */ + Gnum finevertnum1; /* Second multinode vertex */ + + finevertnum0 = coarmulttax[coarvertlocnum].vertglbnum[0]; + finevertnum1 = coarmulttax[coarvertlocnum].vertglbnum[1]; + coarveexloctax[coarvertlocnum] = (finevertnum0 != finevertnum1) + ? finegrafptr->veexloctax[finevertnum0] + finegrafptr->veexloctax[finevertnum1] + : finegrafptr->veexloctax[finevertnum0]; + } + } + else /* If fine graph does not have external gains */ + coargrafptr->veexloctax = NULL; /* Coarse graph does not have external gains */ + + coargrafptr->veexglbsum = finegrafptr->veexglbsum; + coargrafptr->compglbload0min = finegrafptr->compglbload0min; /* Only set constant partition parameters as others will be set on uncoarsening */ + coargrafptr->compglbload0max = finegrafptr->compglbload0max; + coargrafptr->compglbload0avg = finegrafptr->compglbload0avg; + coargrafptr->commglbloadextn0 = finegrafptr->commglbloadextn0; + coargrafptr->commglbgainextn0 = finegrafptr->commglbgainextn0; + coargrafptr->domndist = finegrafptr->domndist; + coargrafptr->domnwght[0] = finegrafptr->domnwght[0]; + coargrafptr->domnwght[1] = finegrafptr->domnwght[1]; + coargrafptr->levlnum = finegrafptr->levlnum + 1; + + return (0); +} + +/* This routine is the reduction-loc operator which +** returns in inout[2] the rank of the process which +** holds the best partition. +** It returns: +** - void : in all cases. +*/ + +static +void +bdgraphBipartMlOpBest ( +const Gnum * const in, /* First operand */ +Gnum * const inout, /* Second and output operand */ +const int * const len, /* Number of instances ; should be 1, not used */ +const MPI_Datatype * const typedat) /* MPI datatype ; not used */ +{ + inout[5] |= in[5]; /* Memory error flag */ + + if (inout[0] == 1) { /* Handle cases when at least one of them is erroneous */ + if (in[0] == 1) { + if (inout[1] > in[1]) /* To enforce commutativity, always keep smallest process number */ + inout[1] = in[1]; + inout[2] = in[2]; + return; + } + + inout[0] = in[0]; /* Validity flag */ + inout[1] = in[1]; /* Lead process rank */ + inout[2] = in[2]; /* Lead process color */ + inout[3] = in[3]; /* Communication load */ + inout[4] = in[4]; /* Load imbalance */ + return; + } + else if (in[0] == 1) + return; + + if ((in[3] < inout[3]) || /* Select best partition */ + ((in[3] == inout[3]) && ((in[4] < inout[4]) || + ((in[4] == inout[4]) && (in[1] < inout[1]))))) { + inout[1] = in[1]; + inout[2] = in[2]; + inout[3] = in[3]; + inout[4] = in[4]; + } +} + +/* This routine propagates the bipartitioning of the +** coarser graph back to the finer graph, according +** to the multinode table of collapsed vertices. +** After the bipartitioning is propagated, it finishes +** to compute the parameters of the finer graph that +** were not computed at the coarsening stage. +** It returns: +** - 0 : if coarse graph data has been propagated to fine graph. +** - !0 : on error. +*/ + +static +int +bdgraphBipartMlUncoarsen ( +Bdgraph * restrict finegrafptr, /*+ Finer graph +*/ +const Bdgraph * restrict const coargrafptr, /*+ Coarser graph +*/ +const DgraphCoarsenMulti * restrict const coarmulttax) /*+ Multinode array +*/ +{ + Gnum baseval; + Gnum finefronlocnbr; + Gnum finefronlocnum; + Gnum fineedlolocval; + Gnum finevertlocadj; /* Global vertex adjustment */ + Gnum finevertlocnum; + Gnum finevertlocnnd; /* Index for frontier array fronloctab */ + Gnum finecomplocsize1; + Gnum finecomplocload1; + Gnum finecommlocloadintn; + Gnum finecommlocloadextn; + Gnum finecommlocgainextn; + int vrcvdspnbr; + int vsnddspnbr; + int * restrict vrcvcnttab; + int * restrict vsndcnttab; + int * restrict vrcvdsptab; + int * restrict vsnddsptab; + Gnum * restrict vrcvdattab; + Gnum * restrict vsnddattab; + Gnum * restrict vsndidxtab; + BdgraphBipartMlSort * restrict sortloctab; /* Array of vertices to send to their owner */ + Gnum sortlocnbr; + Gnum sortlocnum; + int procnum; + MPI_Datatype besttypedat; /* Data type for finding best bipartition */ + MPI_Op bestoperdat; /* Handle of MPI operator for finding best bipartition */ + Gnum reduloctab[6]; /* "6": both for selecting best and propagating data */ + Gnum reduglbtab[6]; + const Gnum * restrict coarfronloctab; + GraphPart * restrict coarpartgsttax; + GraphPart * restrict finepartgsttax; + Gnum * restrict finefronloctab; + + const int fineprocglbnbr = finegrafptr->s.procglbnbr; + const Gnum * restrict const fineprocvrttab = finegrafptr->s.procvrttab; + const Gnum * restrict const fineedgegsttax = finegrafptr->s.edgegsttax; + const Gnum * restrict const finevertloctax = finegrafptr->s.vertloctax; + const Gnum * restrict const finevendloctax = finegrafptr->s.vendloctax; + const Gnum * restrict const fineveloloctax = finegrafptr->s.veloloctax; + const Gnum * restrict const fineveexloctax = finegrafptr->veexloctax; + const Gnum * restrict const fineedloloctax = finegrafptr->s.edloloctax; + + reduloctab[5] = 0; /* Assume everything is fine */ + if (finegrafptr->partgsttax == NULL) { /* If partition array not yet allocated */ + if (dgraphGhst (&finegrafptr->s) != 0) { /* Create ghost edge array and compute vertgstnbr */ + errorPrint ("bdgraphBipartMlUncoarsen: cannot compute ghost edge array"); + reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ + } + else if ((finegrafptr->partgsttax = (GraphPart *) memAlloc (finegrafptr->s.vertgstnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("bdgraphBipartMlUncoarsen: out of memory (1)"); + reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ + } + else if (finegrafptr->partgsttax -= finegrafptr->s.baseval, + (finegrafptr->fronloctab = (Gnum *) memAlloc (finegrafptr->s.vertlocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("bdgraphBipartMlUncoarsen: out of memory (2)"); + reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ + } + } + + if (coargrafptr == NULL) { /* If coarser graph not provided */ +#ifdef SCOTCH_DEBUG_BDGRAPH1 /* Communication cannot be overlapped by a useful one */ + if (MPI_Allreduce (&reduloctab[5], &reduglbtab[5], 1, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartMlUncoarsen: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + reduglbtab[5] = reduloctab[5]; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + if (reduglbtab[5] != 0) + return (1); + + bdgraphZero (finegrafptr); /* Assign all vertices to part 0 */ + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (finegrafptr) != 0) { + errorPrint ("bdgraphBipartMlUncoarsen: inconsistent graph data (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + return (0); + } + + if (coargrafptr->s.procglbnbr <= 0) { /* If unused folded coargrafptr */ + reduloctab[0] = 1; /* Set it as invalid */ + reduloctab[1] = 0; /* Useless rank */ + reduloctab[2] = 1; /* Color is not the one of folded */ + reduloctab[3] = /* Prevent Valgrind from yelling */ + reduloctab[4] = 0; + } + else { + reduloctab[0] = ((coargrafptr->compglbload0 == 0) || /* Empty subdomains are deemed invalid */ + (coargrafptr->compglbload0 == coargrafptr->s.veloglbsum)) ? 1 : 0; + reduloctab[1] = finegrafptr->s.proclocnum; /* Set rank and color key according to coarse graph (sub)communicator */ + reduloctab[2] = finegrafptr->s.prockeyval; + reduloctab[3] = coargrafptr->commglbload; + reduloctab[4] = coargrafptr->compglbload0dlt; + } + + if ((MPI_Type_contiguous (6, GNUM_MPI, &besttypedat) != MPI_SUCCESS) || + (MPI_Type_commit (&besttypedat) != MPI_SUCCESS) || + (MPI_Op_create ((MPI_User_function *) bdgraphBipartMlOpBest, 1, &bestoperdat) != MPI_SUCCESS)) { + errorPrint ("bdgraphBipartMlUncoarsen: communication error (2)"); + return (1); + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 1, besttypedat, bestoperdat, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartMlUncoarsen: communication error (3)"); + return (1); + } + + if ((MPI_Op_free (&bestoperdat) != MPI_SUCCESS) || + (MPI_Type_free (&besttypedat) != MPI_SUCCESS)) { + errorPrint ("bdgraphBipartMlUncoarsen: communication error (4)"); + return (1); + } + + if (reduglbtab[5] != 0) /* If memory error, return */ + return (1); + + if (reduglbtab[0] == 1) { /* If all possible partitions are invalid */ +#ifdef SCOTCH_DEBUG_BDGRAPH2 + errorPrintW ("bdgraphBipartMlUncoarsen: no valid partition"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + return (1); /* All invalid partitions will lead to low method be applied at upper level */ + } + + if (memAllocGroup ((void **) (void *) + &vrcvcnttab, (size_t) (fineprocglbnbr * sizeof (int)), + &vrcvdsptab, (size_t) (fineprocglbnbr * sizeof (int)), + &vsnddsptab, (size_t) (fineprocglbnbr * sizeof (int)), + &vsndcnttab, (size_t) (fineprocglbnbr * sizeof (int)), + &vsndidxtab, (size_t) (fineprocglbnbr * sizeof (Gnum) * 4), /* TRICK: sortloctab after vsndidxtab after vsndcnttab */ + &sortloctab, (size_t) (2 * coargrafptr->s.vertlocnbr * sizeof (BdgraphBipartMlSort)), NULL) == NULL) { + errorPrint ("bdgraphBipartMlUncoarsen: out of memory (3)"); + reduloctab[5] = 1; + } +#ifdef SCOTCH_DEBUG_BDGRAPH1 /* Communication cannot be overlapped by a useful one */ + if (MPI_Allreduce (&reduloctab[5], &reduglbtab[5], 1, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartMlUncoarsen: communication error (5)"); + return (1); + } +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + reduglbtab[5] = reduloctab[5]; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + if (reduglbtab[5] != 0) { + if (vrcvcnttab != NULL) + memFree (vrcvcnttab); + return (1); + } + + memSet (vsndcnttab, 0, ((byte *) sortloctab) - ((byte *) vsndcnttab)); /* TRICK: sortloctab after vsndidxtab after vsndcnttab */ + + baseval = finegrafptr->s.baseval; + coarfronloctab = coargrafptr->fronloctab; + coarpartgsttax = coargrafptr->partgsttax; + finepartgsttax = finegrafptr->partgsttax; + finevertlocnnd = finegrafptr->s.vertlocnnd; + finevertlocadj = finegrafptr->s.procvrttab[finegrafptr->s.proclocnum] - baseval; + finefronloctab = finegrafptr->fronloctab; + + finecomplocsize1 = 0; + finecomplocload1 = 0; + finecommlocloadextn = 0; + finecommlocgainextn = 0; + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + memSet (finepartgsttax + baseval, ~0, finegrafptr->s.vertgstnbr * sizeof (GraphPart)); /* All vertices are unvisited */ +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + finefronlocnbr = 0; + sortlocnbr = 0; + if (reduglbtab[2] == (Gnum) coargrafptr->s.prockeyval) { /* If we belong to the group of the lead process, we must browse and send local data */ + Gnum coarfronlocnum; + Gnum coarvertlocnum; + + for (coarfronlocnum = 0; coarfronlocnum < coargrafptr->fronlocnbr; coarfronlocnum ++) + coarpartgsttax[coarfronloctab[coarfronlocnum]] |= 2; /* Flag vertex as belonging to frontier */ + + for (coarvertlocnum = baseval; coarvertlocnum < coargrafptr->s.vertlocnnd; coarvertlocnum ++) { + GraphPart coarpartval; + Gnum coarpartmsk; + Gnum finevertglbnum; + Gnum finevertlocnum; + int i; + + coarpartval = coarpartgsttax[coarvertlocnum]; + coarpartmsk = (Gnum) (coarpartval & 1); + + i = 0; + do { + finevertglbnum = coarmulttax[coarvertlocnum].vertglbnum[i]; + finevertlocnum = finevertglbnum - finevertlocadj; + + if ((finevertlocnum >= baseval) && /* If vertex is local */ + (finevertlocnum < finevertlocnnd)) { +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (finepartgsttax[finevertlocnum] != ((GraphPart) ~0)) { + errorPrint ("bdgraphBipartMlUncoarsen: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + finepartgsttax[finevertlocnum] = (coarpartval & 1); + finecomplocsize1 += coarpartmsk; /* One extra vertex created in part 1 if (coarpartval == 1) */ + + if ((coarpartval & 2) != 0) /* If coarse frontier vertex, add fine vertex to fine frontier */ + finefronloctab[finefronlocnbr ++] = finevertlocnum; + + if (fineveloloctax != NULL) { + Gnum veloval; + + veloval = fineveloloctax[finevertlocnum]; + finecomplocload1 += veloval & (- coarpartmsk); + } + if (fineveexloctax != NULL) { + Gnum veexval; + + veexval = fineveexloctax[finevertlocnum]; + finecommlocloadextn += veexval * coarpartmsk; + finecommlocgainextn += veexval * (1 - 2 * coarpartmsk); + } + } + else { + int procngbnum; + int procngbmax; + + procngbnum = 0; + procngbmax = fineprocglbnbr; + while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (fineprocvrttab[procngbmed] > finevertglbnum) + procngbmax = procngbmed; + else + procngbnum = procngbmed; + } + + vsndidxtab[4 * procngbnum + coarpartval] ++; /* One of four counters per process number will be incremented */ + sortloctab[sortlocnbr].vertnum = finevertglbnum; + sortloctab[sortlocnbr].procnum = ((procngbnum + (fineprocglbnbr * coarpartmsk)) ^ (- (Gnum) (coarpartval >> 1))); /* Embed part and frontier information */ + sortlocnbr ++; + } + + i ++; /* Process next multinode vertex */ + } while (finevertglbnum != coarmulttax[coarvertlocnum].vertglbnum[1]); /* If not single node */ + } + + for (procnum = 0; procnum < fineprocglbnbr; procnum ++) { /* Aggregate data to be sent */ + vsndcnttab[procnum] = vsndidxtab[4 * procnum] + vsndidxtab[4 * procnum + 1] + + vsndidxtab[4 * procnum + 2] + vsndidxtab[4 * procnum + 3]; + + if (vsndcnttab[procnum] != 0) /* If we will send data to neighbor */ + vsndcnttab[procnum] += 3; /* Add control data to message size */ + } + } + + if (MPI_Alltoall (vsndcnttab, 1, MPI_INT, vrcvcnttab, 1, MPI_INT, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartMlUncoarsen: communication error (3)"); + return (1); + } + + for (procnum = 0, vrcvdspnbr = vsnddspnbr = 0; /* Build communication index arrays */ + procnum < fineprocglbnbr; procnum ++) { + vrcvdsptab[procnum] = vrcvdspnbr; + vsnddsptab[procnum] = vsnddspnbr; + vrcvdspnbr += vrcvcnttab[procnum]; + vsnddspnbr += vsndcnttab[procnum]; + } + + if (memAllocGroup ((void **) (void *) + &vrcvdattab, (size_t) (vrcvdspnbr * sizeof (Gnum)), + &vsnddattab, (size_t) (vsnddspnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("bdgraphBipartMlUncoarsen: out of memory (4)"); + reduloctab[5] = 1; + } +#ifdef SCOTCH_DEBUG_BDGRAPH1 /* Communication cannot be overlapped by a useful one */ + if (MPI_Allreduce (&reduloctab[5], &reduglbtab[5], 1, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartMlUncoarsen: communication error (4)"); + return (1); + } +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + reduglbtab[5] = reduloctab[5]; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + if (reduglbtab[5] != 0) { + if (vrcvdattab != NULL) + memFree (vrcvdattab); + if (vrcvcnttab != NULL) + memFree (vrcvcnttab); + return (1); + } + + for (procnum = 0; procnum < fineprocglbnbr; procnum ++) { + Gnum vsnddspval; + + vsnddspval = vsnddsptab[procnum]; + if (vsndcnttab[procnum] != 0) { + Gnum vsndidxnum; + + vsnddattab[vsnddspval] = vsndidxtab[4 * procnum]; + vsnddattab[vsnddspval + 1] = vsndidxtab[4 * procnum + 1]; + vsnddattab[vsnddspval + 2] = vsndidxtab[4 * procnum + 2]; + + vsnddspval += 3; /* Compute sub-array indices to pack vertices to be sent */ + vsndidxnum = vsndidxtab[4 * procnum]; + vsndidxtab[4 * procnum] = vsnddspval; + vsnddspval += vsndidxnum; + vsndidxnum = vsndidxtab[4 * procnum + 1]; + vsndidxtab[4 * procnum + 1] = vsnddspval; + vsnddspval += vsndidxnum; + vsndidxnum = vsndidxtab[4 * procnum + 2]; + vsndidxtab[4 * procnum + 2] = vsnddspval; + vsnddspval += vsndidxnum; + vsndidxtab[4 * procnum + 3] = vsnddspval; + } + } + + for (sortlocnum = 0; sortlocnum < sortlocnbr; sortlocnum ++) { /* For all vertices to send */ + Gnum vertglbend; + Gnum procngbnum; + int partval; + + vertglbend = sortloctab[sortlocnum].vertnum; + procngbnum = sortloctab[sortlocnum].procnum; + + partval = 0; /* Extract frontier and part data from process number */ + if (procngbnum < 0) { + partval = 2; + procngbnum ^= (Gnum) -1; + } + if (procngbnum >= fineprocglbnbr) { + partval |= 1; + procngbnum -= fineprocglbnbr; + } + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (((partval < 3) && (vsndidxtab[4 * procngbnum + partval] >= vsndidxtab[4 * procngbnum + partval + 1])) || + (vsndidxtab[4 * procngbnum + partval] >= (vsnddsptab[procngbnum] + vsndcnttab[procngbnum]))) { + errorPrint ("bdgraphBipartMlUncoarsen: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + vsnddattab[vsndidxtab[4 * procngbnum + partval] ++] = vertglbend; /* Pack vertex in proper sub-array */ + } + + if (MPI_Alltoallv (vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, + vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartMlUncoarsen: communication error (5)"); + return (1); + } + + for (procnum = 0; procnum < fineprocglbnbr; ++ procnum) { /* Update local ones from the buffer for receiving data */ + Gnum vrcvidxnum; + Gnum vrcvidxnnd; + + if (vrcvcnttab[procnum] == 0) /* If nothing received from this process, skip it */ + continue; + + finecomplocsize1 += (vrcvcnttab[procnum] - 3) - vrcvdattab[vrcvdsptab[procnum]] - vrcvdattab[vrcvdsptab[procnum] + 2]; + + for (vrcvidxnum = vrcvdsptab[procnum] + 3, vrcvidxnnd = vrcvidxnum + vrcvdattab[vrcvdsptab[procnum]]; /* Vertices in sub-array 0 */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum finevertlocnum; + + finevertlocnum = vrcvdattab[vrcvidxnum] - finevertlocadj; +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if ((finevertlocnum < baseval) || (finevertlocnum >= finevertlocnnd)) { + errorPrint ("bdgraphBipartMlUncoarsen: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + finepartgsttax[finevertlocnum] = 0; + } + + for (vrcvidxnnd = vrcvidxnum + vrcvdattab[vrcvdsptab[procnum] + 1]; /* Vertices in sub-array 1 */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum finevertlocnum; + + finevertlocnum = vrcvdattab[vrcvidxnum] - finevertlocadj; +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if ((finevertlocnum < baseval) || (finevertlocnum >= finevertlocnnd)) { + errorPrint ("bdgraphBipartMlUncoarsen: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + finepartgsttax[finevertlocnum] = 1; + if (fineveloloctax != NULL) + finecomplocload1 += fineveloloctax[finevertlocnum]; + if (fineveexloctax != NULL) { + Gnum veexval; + + veexval = fineveexloctax[finevertlocnum]; + finecommlocloadextn += veexval; + finecommlocgainextn -= veexval; + } + } + + for (vrcvidxnnd = vrcvidxnum + vrcvdattab[vrcvdsptab[procnum] + 2]; /* Vertices in sub-array 2 */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum finevertlocnum; + + finevertlocnum = vrcvdattab[vrcvidxnum] - finevertlocadj; +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if ((finevertlocnum < baseval) || (finevertlocnum >= finevertlocnnd)) { + errorPrint ("bdgraphBipartMlUncoarsen: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + finepartgsttax[finevertlocnum] = 0; + finefronloctab[finefronlocnbr ++] = finevertlocnum; + } + + for (vrcvidxnnd = vrcvdsptab[procnum] + vrcvcnttab[procnum]; /* Vertices in sub-array 3 */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum finevertlocnum; + + finevertlocnum = vrcvdattab[vrcvidxnum] - finevertlocadj; +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if ((finevertlocnum < baseval) || (finevertlocnum >= finevertlocnnd)) { + errorPrint ("bdgraphBipartMlUncoarsen: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + finepartgsttax[finevertlocnum] = 1; + finefronloctab[finefronlocnbr ++] = finevertlocnum; + if (fineveloloctax != NULL) + finecomplocload1 += fineveloloctax[finevertlocnum]; + + if (fineveexloctax != NULL) { + Gnum veexval; + + veexval = fineveexloctax[finevertlocnum]; + finecommlocloadextn += veexval; + finecommlocgainextn -= veexval; + } + } + } +#ifdef SCOTCH_DEBUG_BDGRAPH2 + for (finevertlocnum = baseval; finevertlocnum < finevertlocnnd; finevertlocnum ++) { + if (finepartgsttax[finevertlocnum] == ((GraphPart) ~0)) { + errorPrint ("bdgraphBipartMlUncoarsen: internal error (8)"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + if (dgraphHaloSync (&finegrafptr->s, (byte *) (finepartgsttax + baseval), GRAPHPART_MPI) != 0) { + errorPrint ("bdgraphBipartMlUncoarsen: cannot perform halo exchange"); + return (1); + } + + finecommlocloadintn = 0; + fineedlolocval = 1; /* Assume edges are not weighted */ + for (finefronlocnum = 0; finefronlocnum < finefronlocnbr; finefronlocnum ++) { + Gnum finevertlocnum; + Gnum fineedgelocnum; + Gnum partval; + Gnum commcut; + + finevertlocnum = finefronloctab[finefronlocnum]; + partval = finepartgsttax[finevertlocnum]; + for (fineedgelocnum = finevertloctax[finevertlocnum], commcut = 0; + fineedgelocnum < finevendloctax[finevertlocnum]; fineedgelocnum ++) { + Gnum partdlt; + + partdlt = partval ^ finepartgsttax[fineedgegsttax[fineedgelocnum]]; + commcut += partdlt; + if (fineedloloctax != NULL) + fineedlolocval = fineedloloctax[fineedgelocnum]; + finecommlocloadintn += partdlt * fineedlolocval; /* Counted in both part, should be divided by 2 in summing up phase */ + } + if (commcut == 0) /* If vertex does not really belong to frontier */ + finefronloctab[finefronlocnum --] = finefronloctab[-- finefronlocnbr]; /* Replace vertex and redo */ + } + + memFree (vrcvdattab); /* Free group leaders */ + memFree (vrcvcnttab); + + finegrafptr->fronlocnbr = finefronlocnbr; + finegrafptr->complocsize0 = finegrafptr->s.vertlocnbr - finecomplocsize1; + finegrafptr->complocload0 = (fineveloloctax == NULL) ? finegrafptr->complocsize0 : (finegrafptr->s.velolocsum - finecomplocload1); + + reduloctab[0] = finegrafptr->complocload0; + reduloctab[1] = finegrafptr->complocsize0; + reduloctab[2] = finegrafptr->fronlocnbr; + reduloctab[3] = finecommlocloadintn; + reduloctab[4] = finecommlocloadextn; + reduloctab[5] = finecommlocgainextn; + MPI_Allreduce (reduloctab, reduglbtab, 6, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm); + + finegrafptr->compglbload0 = reduglbtab[0]; + finegrafptr->compglbload0dlt = finegrafptr->compglbload0 - finegrafptr->compglbload0avg; + finegrafptr->compglbsize0 = reduglbtab[1]; + finegrafptr->fronglbnbr = reduglbtab[2]; + finegrafptr->commglbload = ((reduglbtab[3] / 2) * finegrafptr->domndist + reduglbtab[4] + finegrafptr->commglbloadextn0); + finegrafptr->commglbgainextn = reduglbtab[5]; + finegrafptr->bbalglbval = coargrafptr->bbalglbval; + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (finegrafptr) != 0) { + errorPrint ("bdgraphBipartMlUncoarsen: inconsistent graph data (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + return (0); +} + +/* This routine performs the +** bipartitioning recursion. +** It returns: +** - 0 : if bipartitioning could be computed. +** - !0 : on error. +*/ + +static +int +bdgraphBipartMl2 ( +Bdgraph * restrict const grafptr, /* Active graph */ +const BdgraphBipartMlParam * const paraptr) /* Method parameters */ +{ + Bdgraph coargrafdat; + DgraphCoarsenMulti * restrict coarmulttax; + int o; + + if (grafptr->s.procglbnbr <= 1) { /* Enter into sequential mode */ + if (((o = bdgraphBipartMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ + ((o = bdgraphBipartSt (grafptr, paraptr->stratseq)) != 0)) { +#ifdef SCOTCH_DEBUG_BDGRAPH2 + errorPrintW ("bdgraphBipartMl2: cannot apply sequential strategy"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + } + return (o); + } + + coarmulttax = NULL; /* Assume multinode array is not allocated */ + if (bdgraphBipartMlCoarsen (grafptr, &coargrafdat, &coarmulttax, paraptr) == 0) { + o = (coargrafdat.s.procglbnbr == 0) ? 0 : bdgraphBipartMl2 (&coargrafdat, paraptr); /* Apply recursion on coarsened graph if it exists */ + + if ((o == 0) && + ((o = bdgraphBipartMlUncoarsen (grafptr, &coargrafdat, coarmulttax)) == 0) && + ((o = bdgraphBipartSt (grafptr, paraptr->stratasc)) != 0)) { /* Apply ascending strategy if uncoarsening worked */ +#ifdef SCOTCH_DEBUG_BDGRAPH2 + errorPrintW ("bdgraphBipartMl2: cannot apply ascending strategy"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + } + + bdgraphExit (&coargrafdat); + if (coarmulttax != NULL) /* If multinode array has been allocated */ + memFree (coarmulttax + grafptr->s.baseval); /* Free array */ + + if (o == 0) /* If multi-level failed, apply low strategy as fallback */ + return (o); + } + + if (((o = bdgraphBipartMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ + ((o = bdgraphBipartSt (grafptr, paraptr->stratlow)) != 0)) { /* Apply low strategy */ +#ifdef SCOTCH_DEBUG_BDGRAPH2 + errorPrintW ("bdgraphBipartMl2: cannot apply low strategy"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + } + + return (o); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the muti-level bipartitioning. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bdgraphBipartMl ( +Bdgraph * const grafptr, /*+ Active graph +*/ +const BdgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum levlnum; /* Save value for graph level */ + int o; + + levlnum = grafptr->levlnum; /* Save graph level */ + grafptr->levlnum = 0; /* Initialize coarsening level */ + o = bdgraphBipartMl2 (grafptr, paraptr); /* Perform multi-level bipartitioning */ + grafptr->levlnum = levlnum; /* Restore graph level */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_ml.h b/scotch_6.0.3/src/libscotch/bdgraph_bipart_ml.h new file mode 100644 index 00000000..3c8c22a6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_ml.h @@ -0,0 +1,86 @@ +/* Copyright 2007-2009,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_ml.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the multi-level bipartition **/ +/** routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.1 : from : 30 oct 2007 **/ +/** to : 29 oct 2009 **/ +/** # Version 6.0 : from : 28 sep 2014 **/ +/** to 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct BdgraphBipartMlParam_ { + INT passnbr; /*+ Number of coarsening passes to go +*/ + INT foldmax; /*+ Maximum number of vertices per processor to do folding +*/ + int foldval; /*+ Type of folding +*/ + INT coarnbr; /*+ Minimum number of vertices +*/ + double coarrat; /*+ Coarsening ratio +*/ + Strat * stratlow; /*+ Strategy at lowest level +*/ + Strat * stratasc; /*+ Strategy at ascending levels +*/ + Strat * stratseq; /*+ Strategy when running on a single processor +*/ +} BdgraphBipartMlParam; + +typedef struct BdgraphBipartMlSort_ { + Gnum vertnum; /*+ Global vertex index for uncoarsening +*/ + Gnum procnum; /*+ Gnum to have same type +*/ +} BdgraphBipartMlSort; + +/* +** The function prototypes. +*/ + +#ifndef BDGRAPH_BIPART_ML +#define static +#endif + +static int bdgraphBipartMlCoarsen (Bdgraph * const, Bdgraph * const, DgraphCoarsenMulti * restrict * const, const BdgraphBipartMlParam * const); +static int bdgraphBipartMlUncoarsen (Bdgraph *, const Bdgraph * const, const DgraphCoarsenMulti * restrict const); +static void bdgraphBipartMlOpBest (const Gnum * const, Gnum * const, const int * const, const MPI_Datatype * const); +int bdgraphBipartMl (Bdgraph * const, const BdgraphBipartMlParam * const); +static int bdgraphBipartMl2 (Bdgraph * const, const BdgraphBipartMlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_sq.c b/scotch_6.0.3/src/libscotch/bdgraph_bipart_sq.c new file mode 100644 index 00000000..78942bc0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_sq.c @@ -0,0 +1,296 @@ +/* Copyright 2007,2008,2010,2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_sq.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a bipartition of a **/ +/** given bipartitioned distributed graph **/ +/** by moving all (interesting) vertices of **/ +/** the given graph to every processor, **/ +/** executing a sequential bipartition **/ +/** routine, and projecting back the best **/ +/** result obtained. **/ +/** **/ +/** DATES : # Version 5.1 : from : 27 dec 2007 **/ +/** to 14 apr 2011 **/ +/** # Version 6.0 : from : 27 dec 2007 **/ +/** to 31 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH_BIPART_SQ + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "arch.h" +#include "parser.h" +#include "graph.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "dgraph.h" +#include "bdgraph.h" +#include "bdgraph_bipart_sq.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine is the reduction-loc operator which +** returns in inout[2] the rank of the process which +** holds the best partition. +** It returns: +** - void : in all cases. +*/ + +static +void +bdgraphBipartSqOpBest ( +const Gnum * const in, /* First operand */ +Gnum * const inout, /* Second and output operand */ +const int * const len, /* Number of instances; should be 1, not used */ +const MPI_Datatype * const typedat) /* MPI datatype; not used */ +{ + inout[5] |= in[5]; /* Propagate errors */ + + inout[4] += in[4]; /* Count cases for which a bipartitioning error occured */ + if (inout[3] == 1) { /* Handle cases when at least one of them is erroneous */ + if (in[3] == 1) + return; + + inout[0] = in[0]; + inout[1] = in[1]; + inout[2] = in[2]; + inout[3] = in[3]; + return; + } + else if (in[3] == 1) + return; + + if ((in[0] < inout[0]) || /* Select best partition */ + ((in[0] == inout[0]) && + ((in[1] < inout[1]) || + ((in[1] == inout[1]) && (in[2] < inout[2]))))) { + inout[0] = in[0]; + inout[1] = in[1]; + inout[2] = in[2]; + } +} + +/* This routine computes a partition of the +** given distributed graph by gathering as many +** copies of the graph as there are processes +** sharing the distributed graph, running a +** sequential algorithm on them, and collecting +** the best solution found. +** It returns: +** - 0 : if the bipartition could be computed. +** - !0 : on error. +*/ + +int +bdgraphBipartSq ( +Bdgraph * const dgrfptr, /*+ Distributed graph +*/ +const BdgraphBipartSqParam * const paraptr) /*+ Method parameters +*/ +{ + Bgraph cgrfdat; /* Centralized bipartitioned graph structure */ + Gnum reduloctab[6]; /* Local array for best bipartition data (7 for Bcast) */ + Gnum reduglbtab[6]; /* Global array for best bipartition data */ + MPI_Datatype besttypedat; /* Data type for finding best bipartition */ + MPI_Op bestoperdat; /* Handle of MPI operator for finding best bipartition */ + int bestprocnum; /* Rank of process holding best partition */ + Gnum * restrict vnumloctax; + Gnum vertlocnum; + Gnum complocsize1; + Gnum complocload1; + Gnum fronlocnbr; + int o; + + if ((MPI_Type_contiguous (6, GNUM_MPI, &besttypedat) != MPI_SUCCESS) || + (MPI_Type_commit (&besttypedat) != MPI_SUCCESS) || + (MPI_Op_create ((MPI_User_function *) bdgraphBipartSqOpBest, 1, &bestoperdat) != MPI_SUCCESS)) { + errorPrint ("bdgraphBipartSq: communication error (1)"); + return (1); + } + + reduloctab[0] = /* In case of error, maximum communication load */ + reduloctab[1] = GNUMMAX; /* And maximum load imbalance */ + reduloctab[2] = dgrfptr->s.proclocnum; + reduloctab[3] = /* Assume sequential bipartioning went fine */ + reduloctab[4] = 0; + reduloctab[5] = 0; /* Assume no errors */ + + vnumloctax = dgrfptr->s.vnumloctax; /* No need for vertex number array when centralizing graph */ + dgrfptr->s.vnumloctax = NULL; + o = bdgraphGatherAll (dgrfptr, &cgrfdat); + dgrfptr->s.vnumloctax = vnumloctax; /* Restore vertex number array */ + if (o != 0) { + errorPrint ("bdgraphBipartSq: cannot build centralized graph"); + return (1); + } + + if (bgraphBipartSt (&cgrfdat, paraptr->strat) != 0) { /* Bipartition centralized graph */ + errorPrint ("bdgraphBipartSq: cannot bipartition centralized graph"); + reduloctab[3] = + reduloctab[4] = 1; + } + else { /* Fill local array with local bipartition data */ + reduloctab[0] = ((cgrfdat.fronnbr != 0) || ((cgrfdat.compsize0 != 0) && ((cgrfdat.s.vertnbr - cgrfdat.compsize0) != 0))) + ? cgrfdat.commload + : GNUMMAX; /* Partitions with empty bipartitions unwanted if they are completely unbalanced */ + reduloctab[1] = cgrfdat.compload0dlt; + } + + if (dgrfptr->partgsttax == NULL) { + if (dgraphGhst (&dgrfptr->s) != 0) { /* Compute ghost edge array if not already present, before copying graph fields */ + errorPrint ("bdgraphBipartSq: cannot compute ghost edge array"); + reduloctab[5] = 1; + } + else { + if ((dgrfptr->partgsttax = (GraphPart *) memAlloc (dgrfptr->s.vertgstnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("bdgraphBipartSq: out of memory (1)"); + reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ + } + dgrfptr->partgsttax -= dgrfptr->s.baseval; + } + if ((dgrfptr->fronloctab = (Gnum *) memAlloc (dgrfptr->s.vertlocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("bdgraphBipartSq: out of memory (2)"); + reduloctab[5] = 1; + } + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 1, besttypedat, bestoperdat, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartSq: communication error (2)"); + return (1); + } + if ((reduloctab[4] != 0) && (reduloctab[4] != dgrfptr->s.procglbnbr)) { + errorPrint ("bdgraphBipartSq: internal error"); + return (1); + } + + if ((MPI_Op_free (&bestoperdat) != MPI_SUCCESS) || + (MPI_Type_free (&besttypedat) != MPI_SUCCESS)) { + errorPrint ("bdgraphBipartSq: communication error (3)"); + return (1); + } + + if (reduglbtab[3] != 0) { /* If none of the sequential methods succeeded */ + bgraphExit (&cgrfdat); + return (1); + } + + bestprocnum = (int) reduglbtab[2]; + if (dgrfptr->s.proclocnum == bestprocnum) { /* If process holds best partition */ + reduloctab[0] = cgrfdat.compload0; /* Global values to share */ + reduloctab[1] = cgrfdat.compsize0; + reduloctab[2] = cgrfdat.commload; + reduloctab[3] = cgrfdat.commgainextn; + reduloctab[4] = cgrfdat.fronnbr; + } + if (MPI_Bcast (reduloctab, 5, GNUM_MPI, bestprocnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartSq: communication error (4)"); + return (1); + } + dgrfptr->compglbload0 = reduloctab[0]; + dgrfptr->compglbload0dlt = reduloctab[0] - dgrfptr->compglbload0avg; + dgrfptr->compglbsize0 = reduloctab[1]; + dgrfptr->commglbload = reduloctab[2]; + dgrfptr->commglbgainextn = reduloctab[3]; + dgrfptr->fronglbnbr = reduloctab[4]; + + if (commScatterv (cgrfdat.parttax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GRAPHPART_MPI, /* No base for sending as procdsptab holds based values */ + dgrfptr->partgsttax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GRAPHPART_MPI, + bestprocnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphBipartSq: communication error (5)"); + return (1); + } + + if (dgraphHaloSync (&dgrfptr->s, (byte *) (dgrfptr->partgsttax + dgrfptr->s.baseval), GRAPHPART_MPI) != 0) { + errorPrint ("bdgraphBipartSq: cannot perform halo exchange"); + return (1); + } + + complocsize1 = + complocload1 = 0; + for (vertlocnum = dgrfptr->s.baseval, fronlocnbr = 0; + vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { + int partval; + Gnum partval1; + Gnum commcut; + Gnum edgelocnum; + + partval = dgrfptr->partgsttax[vertlocnum]; + partval1 = partval & 1; + complocsize1 += partval1; /* Superscalar update */ + if (dgrfptr->s.veloloctax != NULL) { + Gnum veloval; + + veloval = dgrfptr->s.veloloctax[vertlocnum]; + complocload1 += (-partval1) & veloval; /* Superscalar update */ + } + for (edgelocnum = dgrfptr->s.vertloctax[vertlocnum], commcut = 0; + edgelocnum < dgrfptr->s.vendloctax[vertlocnum]; edgelocnum ++) { /* Build local frontier */ + int partend; + int partdlt; + + partend = dgrfptr->partgsttax[dgrfptr->s.edgegsttax[edgelocnum]]; + partdlt = partval ^ partend; + commcut |= partdlt; + } + if (commcut != 0) + dgrfptr->fronloctab[fronlocnbr ++] = vertlocnum; + } + dgrfptr->fronlocnbr = fronlocnbr; + dgrfptr->complocsize0 = dgrfptr->s.vertlocnbr - complocsize1; + dgrfptr->complocload0 = (dgrfptr->s.veloloctax != NULL) ? (dgrfptr->s.velolocsum - complocload1) : dgrfptr->complocsize0; + + bgraphExit (&cgrfdat); + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (dgrfptr) != 0) { + errorPrint ("bdgraphBipartSq: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_sq.h b/scotch_6.0.3/src/libscotch/bdgraph_bipart_sq.h new file mode 100644 index 00000000..c5bdb83d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_sq.h @@ -0,0 +1,69 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_sq.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the sequential bipartitioning **/ +/** routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.1 : from : 19 nov 2007 **/ +/** to : 20 nov 2007 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct BdgraphBipartSqParam_ { + Strat * strat; /*+ Sequential bipartitioning strategy used +*/ +} BdgraphBipartSqParam; + +/* +** The function prototypes. +*/ + +#ifndef BDGRAPH_BIPART_SQ +#define static +#endif + +int bdgraphBipartSq (Bdgraph * const, const BdgraphBipartSqParam * const); + +static void bdgraphBipartSqOpBest (const Gnum * const, Gnum * const, const int * const, const MPI_Datatype * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_st.c b/scotch_6.0.3/src/libscotch/bdgraph_bipart_st.c new file mode 100644 index 00000000..f925bf04 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_st.c @@ -0,0 +1,390 @@ +/* Copyright 2007-2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_st.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the strategy and **/ +/** method tables for distributed graph **/ +/** bipartitioning methods. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 sep 2007 **/ +/** to : 15 apr 2011 **/ +/** # Version 6.0 : from : 11 sep 2011 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH_BIPART_ST + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "bdgraph.h" +#include "bdgraph_bipart_bd.h" +#include "bdgraph_bipart_df.h" +#include "bdgraph_bipart_ex.h" +#include "bdgraph_bipart_ml.h" +#include "bdgraph_bipart_sq.h" +#include "bdgraph_bipart_st.h" +#include "bdgraph_bipart_zr.h" + +/* +** The static and global variables. +*/ + +static Bdgraph bdgraphdummy; /* Dummy distributed bipartitioned graph for offset computations */ + +static union { + BdgraphBipartBdParam param; + StratNodeMethodData padding; +} bdgraphbipartstdefaultbd = { { 3, &stratdummy } }; + +static union { + BdgraphBipartDfParam param; + StratNodeMethodData padding; +} bdgraphbipartstdefaultdf = { { 500, 1.0, 0.0, BDGRAPHBIPARTDFTYPEBAL } }; + +static union { + BdgraphBipartExParam param; + StratNodeMethodData padding; +} bdgraphbipartstdefaultex = { { 5, 0.005 } }; + +static union { + BdgraphBipartMlParam param; + StratNodeMethodData padding; +} bdgraphbipartstdefaultml = { { 5, 1000, 2, 10000, 0.8L, &stratdummy, &stratdummy, &stratdummy} }; + +static union { + BdgraphBipartSqParam param; + StratNodeMethodData padding; +} bdgraphbipartstdefaultsq = { { &stratdummy } }; + +static StratMethodTab bdgraphbipartstmethtab[] = { /* Bipartitioning methods array */ + { BDGRAPHBIPARTSTMETHBD, "b", bdgraphBipartBd, &bdgraphbipartstdefaultbd }, + { BDGRAPHBIPARTSTMETHDF, "d", bdgraphBipartDf, &bdgraphbipartstdefaultdf }, + { BDGRAPHBIPARTSTMETHEX, "x", bdgraphBipartEx, &bdgraphbipartstdefaultex }, + { BDGRAPHBIPARTSTMETHML, "m", bdgraphBipartMl, &bdgraphbipartstdefaultml }, + { BDGRAPHBIPARTSTMETHSQ, "q", bdgraphBipartSq, &bdgraphbipartstdefaultsq }, + { BDGRAPHBIPARTSTMETHZR, "z", bdgraphBipartZr, NULL }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab bdgraphbipartstparatab[] = { /* Method parameter list */ + { BDGRAPHBIPARTSTMETHBD, STRATPARAMINT, "width", + (byte *) &bdgraphbipartstdefaultbd.param, + (byte *) &bdgraphbipartstdefaultbd.param.distmax, + NULL }, + { BDGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "bnd", + (byte *) &bdgraphbipartstdefaultbd.param, + (byte *) &bdgraphbipartstdefaultbd.param.stratbnd, + (void *) &bdgraphbipartststratab }, + { BDGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "org", + (byte *) &bdgraphbipartstdefaultbd.param, + (byte *) &bdgraphbipartstdefaultbd.param.stratorg, + (void *) &bdgraphbipartststratab }, + { BDGRAPHBIPARTSTMETHDF, STRATPARAMINT, "pass", + (byte *) &bdgraphbipartstdefaultdf.param, + (byte *) &bdgraphbipartstdefaultdf.param.passnbr, + NULL }, + { BDGRAPHBIPARTSTMETHDF, STRATPARAMDOUBLE, "dif", + (byte *) &bdgraphbipartstdefaultdf.param, + (byte *) &bdgraphbipartstdefaultdf.param.cdifval, + NULL }, + { BDGRAPHBIPARTSTMETHDF, STRATPARAMDOUBLE, "rem", + (byte *) &bdgraphbipartstdefaultdf.param, + (byte *) &bdgraphbipartstdefaultdf.param.cremval, + NULL }, + { BDGRAPHBIPARTSTMETHDF, STRATPARAMCASE, "type", + (byte *) &bdgraphbipartstdefaultdf.param, + (byte *) &bdgraphbipartstdefaultdf.param.typeval, + (void *) "bk" }, + { BDGRAPHBIPARTSTMETHEX, STRATPARAMINT, "sbbt", + (byte *) &bdgraphbipartstdefaultex.param, + (byte *) &bdgraphbipartstdefaultex.param.sbbtnbr, + NULL }, + { BDGRAPHBIPARTSTMETHEX, STRATPARAMDOUBLE, "bal", + (byte *) &bdgraphbipartstdefaultex.param, + (byte *) &bdgraphbipartstdefaultex.param.deltval, + NULL }, + { BDGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "asc", + (byte *) &bdgraphbipartstdefaultml.param, + (byte *) &bdgraphbipartstdefaultml.param.stratasc, + (void *) &bdgraphbipartststratab }, + { BDGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "low", + (byte *) &bdgraphbipartstdefaultml.param, + (byte *) &bdgraphbipartstdefaultml.param.stratlow, + (void *) &bdgraphbipartststratab }, + { BDGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "seq", + (byte *) &bdgraphbipartstdefaultml.param, + (byte *) &bdgraphbipartstdefaultml.param.stratseq, + (void *) &bdgraphbipartststratab }, + { BDGRAPHBIPARTSTMETHML, STRATPARAMINT, "pass", + (byte *) &bdgraphbipartstdefaultml.param, + (byte *) &bdgraphbipartstdefaultml.param.passnbr, + NULL }, + { BDGRAPHBIPARTSTMETHML, STRATPARAMINT, "vert", + (byte *) &bdgraphbipartstdefaultml.param, + (byte *) &bdgraphbipartstdefaultml.param.coarnbr, + NULL }, + { BDGRAPHBIPARTSTMETHML, STRATPARAMINT, "dvert", + (byte *) &bdgraphbipartstdefaultml.param, + (byte *) &bdgraphbipartstdefaultml.param.foldmax, + NULL }, + { BDGRAPHBIPARTSTMETHML, STRATPARAMCASE, "fold", + (byte *) &bdgraphbipartstdefaultml.param, + (byte *) &bdgraphbipartstdefaultml.param.foldval, + (void *) "nfd" }, + { BDGRAPHBIPARTSTMETHML, STRATPARAMDOUBLE, "rat", + (byte *) &bdgraphbipartstdefaultml.param, + (byte *) &bdgraphbipartstdefaultml.param.coarrat, + NULL }, + { BDGRAPHBIPARTSTMETHSQ, STRATPARAMSTRAT, "strat", + (byte *) &bdgraphbipartstdefaultsq.param, + (byte *) &bdgraphbipartstdefaultsq.param.strat, + (void *) &bgraphbipartststratab }, + { BDGRAPHBIPARTSTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab bdgraphbipartstcondtab[] = { /* Active graph condition parameter table */ + { STRATNODECOND, STRATPARAMDOUBLE, "bal", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.bbalglbval, + NULL }, + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.s.edgeglbnbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "lmin0", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.compglbload0min, + NULL }, + { STRATNODECOND, STRATPARAMINT, "lmax0", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.compglbload0max, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.s.veloglbsum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load0", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.compglbload0, + NULL }, + { STRATNODECOND, STRATPARAMINT, "proc", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.s.procglbnbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "rank", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.s.proclocnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vert", + (byte *) &bdgraphdummy, + (byte *) &bdgraphdummy.s.vertglbnbr, + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab bdgraphbipartststratab = { /* Strategy tables for graph bipartitioning methods */ + bdgraphbipartstmethtab, + bdgraphbipartstparatab, + bdgraphbipartstcondtab }; + +/***********************************************/ +/* */ +/* This is the generic bipartitioning routine. */ +/* */ +/***********************************************/ + +/* This routine performs the bipartitioning of +** the given active graph according to the +** given strategy. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bdgraphBipartSt ( +Bdgraph * restrict const grafptr, /*+ Active graph to bipartition +*/ +const Strat * restrict const strat) /*+ Bipartitioning strategy +*/ +{ + StratTest val; /* Result of condition evaluation */ + BdgraphStore savetab[2]; /* Results of the two strategies */ + int o; + int o2; +#ifdef SCOTCH_DEBUG_BDGRAPH2 + MPI_Comm proccommold; /*Save area for old communicator */ +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (sizeof (Gnum) != sizeof (INT)) { + errorPrint ("bdgraphBipartSt: invalid type specification for parser variables"); + return (1); + } + if (/*(sizeof (BdgraphBipartFmParam) > sizeof (StratNodeMethodData)) || + (sizeof (BdgraphBipartGgParam) > sizeof (StratNodeMethodData)) ||*/ + (sizeof (BdgraphBipartMlParam) > sizeof (StratNodeMethodData))) { + errorPrint ("bdgraphBipartSt: invalid type specification"); + return (1); + } /* TODO REMOVE */ +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ +#ifdef SCOTCH_DEBUG_BDGRAPH1 + if ((strat->tabl != &bdgraphbipartststratab) && + (strat != &stratdummy)) { + errorPrint ("bdgraphBipartSt: invalid parameter (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + o = bdgraphBipartSt (grafptr, strat->data.concat.strat[0]); /* Apply the first strategy */ + if (o == 0) /* If it worked all right */ + o |= bdgraphBipartSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ + break; + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if ((val.typetest != STRATTESTVAL) || + (val.typenode != STRATPARAMLOG)) { + errorPrint ("bdgraphBipartSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = bdgraphBipartSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = bdgraphBipartSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + break; + case STRATNODESELECT : + if (((bdgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ + ((bdgraphStoreInit (grafptr, &savetab[1])) != 0)) { + errorPrint ("bdgraphBipartSt: out of memory"); + bdgraphStoreExit (&savetab[0]); + return (1); + } + + bdgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */ + o = bdgraphBipartSt (grafptr, strat->data.select.strat[0]); /* Apply first strategy */ + bdgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ + bdgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ + o2 = bdgraphBipartSt (grafptr, strat->data.select.strat[1]); /* Apply second strategy */ + + if ((o == 0) || (o2 == 0)) { /* If at least one method did bipartition */ + Gnum compglbload0; + int b0; + int b1; + + compglbload0 = grafptr->compglbload0avg + savetab[0].compglbload0dlt; + b0 = ((compglbload0 < grafptr->compglbload0min) || + (compglbload0 > grafptr->compglbload0max)) ? 1 : o; + compglbload0 = grafptr->compglbload0avg + savetab[1].compglbload0dlt; + b1 = ((compglbload0 < grafptr->compglbload0min) || + (compglbload0 > grafptr->compglbload0max)) ? 1 : o2; + + do { /* Do we want to restore partition 0 ? */ + if (b0 > b1) + break; + if (b0 == b1) { /* If both are valid or invalid */ + if (b0 == 0) { /* If both are valid */ + if ( (savetab[0].commglbload > grafptr->commglbload) || /* Compare on cut */ + ((savetab[0].commglbload == grafptr->commglbload) && + (abs (savetab[0].compglbload0dlt) > abs (grafptr->compglbload0dlt)))) + break; + } + else { /* If both are invalid */ + if ( (abs (savetab[0].compglbload0dlt) > abs (grafptr->compglbload0dlt)) || /* Compare on imbalance */ + ((abs (savetab[0].compglbload0dlt) == abs (grafptr->compglbload0dlt)) && + (savetab[0].commglbload > grafptr->commglbload))) + break; + } + } + + bdgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ + } while (0); + } + if (o2 < o) /* o = min(o,o2): if one biparts, then bipart */ + o = o2; /* Else if one stops, then stop, else error */ + + bdgraphStoreExit (&savetab[0]); /* Free both save areas */ + bdgraphStoreExit (&savetab[1]); + break; +#ifdef SCOTCH_DEBUG_BDGRAPH1 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + default : +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ +#ifdef SCOTCH_DEBUG_BDGRAPH2 + proccommold = grafptr->s.proccomm; /* Create new communicator to isolate method communications */ + MPI_Comm_dup (proccommold, &grafptr->s.proccomm); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + o = (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_BDGRAPH2 + MPI_Comm_free (&grafptr->s.proccomm); /* Restore old communicator */ + grafptr->s.proccomm = proccommold; +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ +#ifdef SCOTCH_DEBUG_BDGRAPH1 + break; + default : + errorPrint ("bdgraphBipartSt: invalid parameter (2)"); + return (1); +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_st.h b/scotch_6.0.3/src/libscotch/bdgraph_bipart_st.h new file mode 100644 index 00000000..249f7765 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_st.h @@ -0,0 +1,82 @@ +/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_st.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the strategy and method **/ +/** tables and the generic entry point for **/ +/** the distributed graph bipartitioning **/ +/** methods. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 sep 2007 **/ +/** to 16 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum BdgraphBipartStMethodType_ { + BDGRAPHBIPARTSTMETHBD = 0, /*+ Band (strategy) +*/ + BDGRAPHBIPARTSTMETHDF, /*+ Diffusion +*/ + BDGRAPHBIPARTSTMETHEX, /*+ Exactifier +*/ + BDGRAPHBIPARTSTMETHML, /*+ Multi-level (strategy) +*/ + BDGRAPHBIPARTSTMETHSQ, /*+ Sequential Method +*/ + BDGRAPHBIPARTSTMETHZR, /*+ Move all to part zero +*/ + BDGRAPHBIPARTSTMETHNBR /*+ Number of methods +*/ +} BdgraphBipartStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab bdgraphbipartststratab; + +/* +** The function prototypes. +*/ + +#ifndef BDGRAPH_BIPART_ST +#define static +#endif + +int bdgraphBipartSt (Bdgraph * const, const Strat * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_zr.c b/scotch_6.0.3/src/libscotch/bdgraph_bipart_zr.c new file mode 100644 index 00000000..88a12d23 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_zr.c @@ -0,0 +1,88 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_zr.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : This module moves all of the vertices **/ +/** to the first subdomain of the **/ +/** bipartition. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 sep 2007 **/ +/** to 26 oct 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH_BIPART_ZR + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "dgraph.h" +#include "bdgraph.h" +#include "bdgraph_bipart_zr.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine moves all of the graph vertices +** to the first part of the partition. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +bdgraphBipartZr ( +Bdgraph * const grafptr) /*+ Active graph +*/ +{ + if (grafptr->compglbload0 != grafptr->s.veloglbsum) /* If not all vertices already in part zero */ + bdgraphZero (grafptr); + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (grafptr) != 0) { + errorPrint ("bdgraphBipartZr: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_bipart_zr.h b/scotch_6.0.3/src/libscotch/bdgraph_bipart_zr.h new file mode 100644 index 00000000..0bd2fed2 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_bipart_zr.h @@ -0,0 +1,58 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_bipart_zr.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : Part of a static mapper. **/ +/** These lines are the data declarations **/ +/** for the move-all-to-first-subdomain **/ +/** distributed bipartitioning module. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 sep 2007 **/ +/** to 26 oct 2007 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef BDGRAPH_BIPART_ZR +#define static +#endif + +int bdgraphBipartZr (Bdgraph * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bdgraph_check.c b/scotch_6.0.3/src/libscotch/bdgraph_check.c new file mode 100644 index 00000000..2abe8ee0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_check.c @@ -0,0 +1,327 @@ +/* Copyright 2007,2008,2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_check.c **/ +/** **/ +/** AUTHORS : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the distributed **/ +/** bipartition graph consistency checking **/ +/** routine. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 sep 2007 **/ +/** to 22 jul 2008 **/ +/** # Version 6.0 : from : 03 sep 2011 **/ +/** to 31 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "dgraph.h" +#include "bdgraph.h" + +int +bdgraphCheck ( +const Bdgraph * restrict const grafptr) +{ + Dgraph grafdat; /* Dummy graph for ghost edge array */ + MPI_Comm proccomm; /* Graph communicator */ + int * restrict flagloctax; /* Frontier flag array */ + GraphPart * restrict partgsttax; + Gnum fronlocnum; + Gnum vertlocnum; /* Number of current vertex */ + Gnum complocload[2]; + Gnum complocsize[2]; + Gnum commcut[2]; + Gnum commlocloadintn; + Gnum commlocloadextn; + Gnum commlocgainextn; + Gnum edlolocval; + Gnum reduloctab[21]; /* Arrays for reductions */ + Gnum reduglbtab[21]; + int chekglbval; /* Global consistency flag */ + int cheklocval; /* Local consistency flag */ + + proccomm = grafptr->s.proccomm; + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize */ + errorPrint ("bdgraphCheck: communication error (1)"); + return (1); + } + + cheklocval = 0; /* Assume everything is all right */ + if ((grafptr->compglbload0min < 0) || + (grafptr->compglbload0max > grafptr->s.veloglbsum)) { + errorPrint ("bdgraphCheck: invalid extrema loads"); + cheklocval = 1; + } + + if (grafptr->compglbload0 != (grafptr->compglbload0avg + grafptr->compglbload0dlt)) { + errorPrint ("bdgraphCheck: invalid global balance"); + cheklocval |= 2; + } + + if ((grafptr->fronlocnbr < 0) || + (grafptr->fronlocnbr > grafptr->s.vertlocnbr)) { + errorPrint ("bdgraphCheck: invalid number of local frontier vertices"); + cheklocval |= 4; + } + + if (grafptr->partgsttax != NULL) { + for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { + if ((grafptr->partgsttax[vertlocnum] | 1) != 1) { /* If part is neither 0 nor 1 */ + errorPrint ("bdgraphCheck: invalid local part array"); + cheklocval |= 8; + break; + } + } + } + + grafdat = grafptr->s; /* Copy minimal distributed graph data */ + if (dgraphGhst (&grafdat) != 0) { /* Create ghost edge array if did not exist */ + errorPrint ("bdgraphCheck: cannot compute ghost edge array"); + cheklocval |= 16; + } + + if (memAllocGroup ((void **) (void *) + &partgsttax, (size_t) (grafdat.vertgstnbr * sizeof (GraphPart)), + &flagloctax, (size_t) (grafptr->s.vertlocnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("bdgraphCheck: out of memory"); + cheklocval |= 32; + } + else { + memSet (flagloctax, ~0, grafptr->s.vertlocnbr * sizeof (int)); + flagloctax -= grafptr->s.baseval; + + for (fronlocnum = 0; fronlocnum < grafptr->fronlocnbr; fronlocnum ++) { + Gnum vertlocnum; + + vertlocnum = grafptr->fronloctab[fronlocnum]; + if ((vertlocnum < grafptr->s.baseval) || (vertlocnum >= grafptr->s.vertlocnnd)) { + errorPrint ("bdgraphCheck: invalid vertex index in frontier array"); + cheklocval |= 64; + break; + } + if (flagloctax[vertlocnum] != ~0) { + errorPrint ("bdgraphCheck: duplicate vertex in frontier array"); + cheklocval |= 128; + break; + } + flagloctax[vertlocnum] = 0; + } + } + + reduloctab[0] = grafptr->commglbload; + reduloctab[1] = - grafptr->commglbload; + reduloctab[2] = grafptr->compglbload0; + reduloctab[3] = - grafptr->compglbload0; + reduloctab[4] = grafptr->s.veloglbsum - grafptr->compglbload0; + reduloctab[5] = - grafptr->s.veloglbsum + grafptr->compglbload0; + reduloctab[6] = grafptr->compglbsize0; + reduloctab[7] = - grafptr->compglbsize0; + reduloctab[8] = grafptr->s.vertglbnbr - grafptr->compglbsize0; + reduloctab[9] = - grafptr->s.vertglbnbr + grafptr->compglbsize0; + reduloctab[10] = grafptr->commglbgainextn; + reduloctab[11] = - grafptr->commglbgainextn; + reduloctab[12] = grafptr->commglbgainextn0; + reduloctab[13] = - grafptr->commglbgainextn0; + reduloctab[14] = grafptr->commglbloadextn0; + reduloctab[15] = - grafptr->commglbloadextn0; + reduloctab[16] = grafptr->fronglbnbr; + reduloctab[17] = - grafptr->fronglbnbr; + reduloctab[18] = grafptr->levlnum; + reduloctab[19] = - grafptr->levlnum; + reduloctab[20] = cheklocval; + + if (MPI_Allreduce (reduloctab, reduglbtab, 21, GNUM_MPI, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphCheck: communication error (2)"); + return (1); + } + + if (reduglbtab[20] != 0) { /* Exit and Return information of previous errors */ + if (partgsttax != NULL) + memFree (partgsttax); /* Free yet unbased group leader */ + return ((int) reduglbtab[20]); + } + + if ((reduglbtab[1] != - reduglbtab[0]) || + (reduglbtab[3] != - reduglbtab[2]) || + (reduglbtab[5] != - reduglbtab[4]) || + (reduglbtab[7] != - reduglbtab[6]) || + (reduglbtab[9] != - reduglbtab[8]) || + (reduglbtab[11] != - reduglbtab[10]) || + (reduglbtab[13] != - reduglbtab[12]) || + (reduglbtab[15] != - reduglbtab[14]) || + (reduglbtab[17] != - reduglbtab[16]) || + (reduglbtab[19] != - reduglbtab[18])) { + errorPrint ("bdgraphCheck: inconsistent global graph data"); + return (1); + } + + if (grafptr->partgsttax != NULL) + memCpy (partgsttax, grafptr->partgsttax + grafptr->s.baseval, grafptr->s.vertlocnbr * sizeof (GraphPart)); /* Copy local part data */ + else + memSet (partgsttax, 0, grafptr->s.vertlocnbr * sizeof (GraphPart)); + dgraphHaloSync (&grafdat, partgsttax, GRAPHPART_MPI); /* Spread yet unbased halo part data across neighboring processes */ + partgsttax -= grafptr->s.baseval; + cheklocval = 0; + + for (fronlocnum = 0; fronlocnum < grafptr->fronlocnbr; fronlocnum ++) { + Gnum vertlocnum; + Gnum edgelocnum; + GraphPart commcut; + GraphPart partval; + + vertlocnum = grafptr->fronloctab[fronlocnum]; + partval = partgsttax[vertlocnum]; + + for (edgelocnum = grafptr->s.vertloctax[vertlocnum], commcut = 0; + edgelocnum < grafptr->s.vendloctax[vertlocnum]; edgelocnum ++) { + GraphPart partdlt; + + partdlt = partgsttax[grafdat.edgegsttax[edgelocnum]] ^ partval; + commcut |= partdlt; + } + if (commcut == 0) { + errorPrint ("bdgraphCheck: invalid vertex in frontier array"); + cheklocval |= 1; + break; + } + } + + complocload[0] = + complocload[1] = 0; + complocsize[0] = + complocsize[1] = 0; + commlocloadintn = 0; + commlocloadextn = 0; + commlocgainextn = 0; + edlolocval = 1; /* Assume edges are not weighted */ + for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { + Gnum partval; /* Part of current vertex */ + Gnum edgelocnum; /* Number of current edge */ + + partval = (Gnum) partgsttax[vertlocnum]; + if (grafptr->veexloctax != NULL) { + Gnum veexval; + + veexval = grafptr->veexloctax[vertlocnum]; + commlocloadextn += veexval * partval; + commlocgainextn += veexval * (1 - 2 * partval); + } + + complocload[partval] += (grafptr->s.veloloctax == NULL) ? 1 : grafptr->s.veloloctax[vertlocnum]; + complocsize[partval] ++; + + commcut[0] = + commcut[1] = 0; + for (edgelocnum = grafptr->s.vertloctax[vertlocnum]; edgelocnum < grafptr->s.vendloctax[vertlocnum]; edgelocnum ++) { + int partend; + int partdlt; + + if (grafptr->s.edloloctax != NULL) + edlolocval = grafptr->s.edloloctax[edgelocnum]; + partend = partgsttax[grafdat.edgegsttax[edgelocnum]]; + partdlt = partval ^ partend; + commcut[partend] ++; + commlocloadintn += partdlt * edlolocval; /* Internal load is accounted for twice */ + } + + if ((commcut[0] != 0) && (commcut[1] != 0) && /* If vertex should be in separator */ + (flagloctax[vertlocnum] != 0)) { + errorPrint ("bdgraphCheck: vertex should be in separator"); + cheklocval |= 2; + } + } + + if (grafptr->s.edgegsttax != grafdat.edgegsttax) /* If ghost edge array was allocated here, free it manually */ + memFree (grafdat.edgegsttax + grafptr->s.baseval); + if (grafptr->s.procsidtab != grafdat.procsidtab) /* The same for procsidtab */ + memFree (grafdat.procsidtab); + memFree (partgsttax + grafptr->s.baseval); /* Free group leader */ + + if ((cheklocval == 0) && + ((complocsize[0] != grafptr->complocsize0) || + (complocsize[1] != (grafptr->s.vertlocnbr - grafptr->complocsize0)))) { + errorPrint ("bdgraphCheck: invalid local part size"); + cheklocval |= 4; + } + + reduloctab[0] = complocload[0]; + reduloctab[1] = complocsize[0]; + reduloctab[2] = commlocloadintn; /* Twice the internal load; sum globally before dividing by two */ + reduloctab[3] = commlocloadextn; + reduloctab[4] = commlocgainextn; + reduloctab[5] = cheklocval; + + if (MPI_Allreduce (reduloctab, reduglbtab, 6, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphCheck: communication error (3)"); + return (1); + } + + if (reduglbtab[5] != 0) /* Return from previous errors */ + return (1); + + if (grafptr->compglbload0 != reduglbtab[0]) { + errorPrint ("bdgraphCheck: invalid global part loads"); + cheklocval |= 8; + } + + if (grafptr->compglbsize0 != reduglbtab[1]) { + errorPrint ("bdgraphCheck: invalid global part sizes"); + cheklocval |= 16; + } + + if (grafptr->commglbload != ((reduglbtab[2] / 2) * grafptr->domndist + reduglbtab[3] + grafptr->commglbloadextn0)) { + errorPrint ("bdgraphCheck: invalid global communication loads"); + cheklocval |= 32; + } + + if (grafptr->commglbgainextn != reduglbtab[4]) { + errorPrint ("bdgraphCheck: invalid global communication gains"); + cheklocval |= 64; + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphCheck: communication error (4)"); + return (1); + } + + return (chekglbval); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_gather_all.c b/scotch_6.0.3/src/libscotch/bdgraph_gather_all.c new file mode 100644 index 00000000..130629df --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_gather_all.c @@ -0,0 +1,262 @@ +/* Copyright 2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_gather_all.c **/ +/** **/ +/** AUTHORS : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the routine which **/ +/** builds a centralized Bgraph on all **/ +/** processors by gathering the pieces of **/ +/** a distributed Bdgraph. **/ +/** **/ +/** DATES : # Version 5.1 : from : 21 dec 2007 **/ +/** to 14 apr 2011 **/ +/** # Version 6.0 : from : 29 aug 2014 **/ +/** to 31 aug 2014 **/ +/** **/ +/** NOTES : # The definitions of MPI_Gather and **/ +/** MPI_Gatherv indicate that elements in **/ +/** the receive array should not be **/ +/** written more than once. Great care **/ +/** should be taken to enforce this rule, **/ +/** especially when the number of **/ +/** vertices in the centralized graph is **/ +/** smaller than the number of **/ +/** processors. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "arch.h" +#include "graph.h" +#include "bgraph.h" +#include "dgraph.h" +#include "bdgraph.h" + +/* This function gathers on all processors +** the pieces of a distributed Bdgraph to +** build a centralized Bgraph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +bdgraphGatherAll ( +const Bdgraph * restrict const dgrfptr, /* Distributed graph */ +Bgraph * restrict cgrfptr) /* Centralized graph */ +{ + int * restrict froncnttab; /* Count array for gather operations */ + int * restrict fronvrttab; /* Displacement array for gather operations */ + int fronlocnbr; /* Also int to enforce MPI standard */ + int cheklocval; +#ifdef SCOTCH_DEBUG_BDGRAPH1 + int chekglbval; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + int procnum; + + cheklocval = 0; +#ifdef SCOTCH_DEBUG_BDGRAPH1 + if (cgrfptr == NULL) /* Centralized graphs should be provided by all */ + cheklocval = 1; + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphGatherAll: communication error (1)"); + return (1); + } + if (chekglbval != 0) { + errorPrint ("bdgraphGatherAll: centralized graphs should be provided on every process"); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + + if (dgraphGatherAll (&dgrfptr->s, &cgrfptr->s) != 0) { + errorPrint ("bdgraphGatherAll: cannot build centralized graph"); + return (1); + } + + cgrfptr->s.flagval |= BGRAPHFREEFRON | BGRAPHFREEPART | BGRAPHFREEVEEX; + cgrfptr->veextax = NULL; /* In case of error */ + cgrfptr->parttax = NULL; + cgrfptr->frontab = NULL; + if ((cgrfptr->frontab = (Gnum *) memAlloc (cgrfptr->s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("bdgraphGatherAll: out of memory (1)"); +#ifndef SCOTCH_DEBUG_BDGRAPH1 + bgraphExit (cgrfptr); + return (1); +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + cheklocval = 1; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + } + else if ((cgrfptr->parttax = (GraphPart *) memAlloc (cgrfptr->s.vertnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("bdgraphGatherAll: out of memory (2)"); +#ifndef SCOTCH_DEBUG_BDGRAPH1 + bgraphExit (cgrfptr); + return (1); +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + cheklocval = 1; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + } + else { + cgrfptr->parttax -= cgrfptr->s.baseval; + + if (dgrfptr->veexloctax != NULL) { + if ((cgrfptr->veextax = (Gnum *) memAlloc (cgrfptr->s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("bdgraphGatherAll: out of memory (3)"); +#ifndef SCOTCH_DEBUG_BDGRAPH1 + bgraphExit (cgrfptr); + return (1); +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + cheklocval = 1; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + } + else + cgrfptr->veextax -= cgrfptr->s.baseval; + } + } + +#ifdef SCOTCH_DEBUG_BDGRAPH1 + if (cheklocval == 0) { +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + if (memAllocGroup ((void **) (void *) /* Allocate tempory arrays to gather frontiers */ + &froncnttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), + &fronvrttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("bdgraphGatherAll: out of memory (4)"); +#ifndef SCOTCH_DEBUG_BDGRAPH1 + bgraphExit (cgrfptr); + return (1); + } +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + cheklocval = 1; + } + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphGatherAll: communication error (2)"); + return (1); + } + if (chekglbval != 0) { + if (froncnttab != NULL) + memFree (froncnttab); /* Free group leader */ + bgraphExit (cgrfptr); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + + cgrfptr->compload0min = dgrfptr->compglbload0min; /* Set constant fields of the centralized graph as those of the distibuted graph */ + cgrfptr->compload0max = dgrfptr->compglbload0max; + cgrfptr->compload0avg = dgrfptr->compglbload0avg; + cgrfptr->commloadextn0 = dgrfptr->commglbloadextn0; + cgrfptr->commgainextn0 = dgrfptr->commglbgainextn0; + cgrfptr->domndist = dgrfptr->domndist; + cgrfptr->domnwght[0] = dgrfptr->domnwght[0]; + cgrfptr->domnwght[1] = dgrfptr->domnwght[1]; + cgrfptr->vfixload[0] = /* Fixed vertices will soon be available in PT-Scotch */ + cgrfptr->vfixload[1] = 0; + cgrfptr->levlnum = dgrfptr->levlnum; + + if (dgrfptr->partgsttax == NULL) { /* If distributed graph does not have a part array yet */ + bgraphZero (cgrfptr); + memFree (froncnttab); /* Free group leader */ + return (0); + } + + if (commAllgatherv (dgrfptr->partgsttax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GRAPHPART_MPI, /* Get parttax of distributed graph */ + cgrfptr->parttax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GRAPHPART_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphGatherAll: communication error (4)"); + return (1); + } + + if (dgrfptr->veexloctax != NULL) { + if (commAllgatherv (dgrfptr->veexloctax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GNUM_MPI, /* Get veextax of distributed graph */ + cgrfptr->veextax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphGatherAll: communication error (5)"); + return (1); + } + } + + fronlocnbr = (int) dgrfptr->fronlocnbr; + if (MPI_Allgather (&fronlocnbr, 1, MPI_INT, /* Compute how frontiers are distributed */ + froncnttab, 1, MPI_INT, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphGatherAll: communication error (6)"); + return (1); + } + fronvrttab[0] = 0; /* Offset 0 for first process */ + for (procnum = 1; procnum < dgrfptr->s.procglbnbr; procnum ++) /* Adjust index sub-arrays for all processors except the first one */ + fronvrttab[procnum] = fronvrttab[procnum - 1] + froncnttab[procnum - 1]; + + if (MPI_Allgatherv (dgrfptr->fronloctab, (int) dgrfptr->fronlocnbr, GNUM_MPI, /* Gather frontiers */ + cgrfptr->frontab, froncnttab, fronvrttab, GNUM_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("bdgraphGatherAll: communication error (7)"); + return (1); + } + + for (procnum = 1; procnum < dgrfptr->s.procglbnbr; procnum ++) { /* Adjust index sub-arrays for all processors except the first one */ + Gnum vertnum; + Gnum vertnnd; + + for (vertnum = (Gnum) fronvrttab[procnum], vertnnd = (Gnum) fronvrttab[procnum] + (Gnum) froncnttab[procnum]; + vertnum < vertnnd; vertnum ++) + cgrfptr->frontab[vertnum] += (Gnum) dgrfptr->s.procdsptab[procnum] - dgrfptr->s.baseval; + } + + memFree (froncnttab); /* Free group leader */ + + for (procnum = 0; procnum < dgrfptr->s.proclocnum; procnum ++) /* Desynchronize random generators across processes */ + cheklocval = intRandVal (2); + intPerm (cgrfptr->frontab, dgrfptr->fronglbnbr); /* Compute permutation of frontier array to have different solutions on every process */ + + cgrfptr->compload0 = dgrfptr->compglbload0; /* Update other fields */ + cgrfptr->compload0dlt = dgrfptr->compglbload0dlt; + cgrfptr->compsize0 = dgrfptr->compglbsize0; + cgrfptr->commload = dgrfptr->commglbload; + cgrfptr->commgainextn = dgrfptr->commglbgainextn; + cgrfptr->commgainextn0 = dgrfptr->commglbgainextn0; + cgrfptr->fronnbr = dgrfptr->fronglbnbr; + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bgraphCheck (cgrfptr) != 0) { + errorPrint ("bdgraphGatherAll: internal error"); + bgraphExit (cgrfptr); + return (1); + } +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bdgraph_store.c b/scotch_6.0.3/src/libscotch/bdgraph_store.c new file mode 100644 index 00000000..af1a666f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bdgraph_store.c @@ -0,0 +1,197 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bdgraph_store.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the save data **/ +/** structure handling routines for dis- **/ +/** tributed bipartition graphs. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 sep 2007 **/ +/** to 22 oct 2008 **/ +/** # Version 6.0 : from : 11 sep 2011 **/ +/** to 11 sep 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BDGRAPH_STORE + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "dgraph.h" +#include "bdgraph.h" + +/**********************************/ +/* */ +/* Store graph handling routines. */ +/* */ +/**********************************/ + +/* This routine builds a save structure +** for the given active graph. +** It returns: +** - 0 : if allocation succeeded. +** - !0 : on error. +*/ + +int +bdgraphStoreInit ( +const Bdgraph * restrict const grafptr, +BdgraphStore * restrict const storptr) +{ + Gnum savsize; + + savsize = grafptr->s.vertlocnbr * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ + + if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ + errorPrint ("bdgraphStoreInit: out of memory"); + return (1); + } + + return (0); +} + +/* This routine frees a save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +bdgraphStoreExit ( +BdgraphStore * const storptr) +{ + memFree (storptr->datatab); +#ifdef SCOTCH_DEBUG_BDGRAPH2 + storptr->datatab = NULL; +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ +} + +/* This routine saves partition data from the +** given active graph to the given save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +bdgraphStoreSave ( +const Bdgraph * const grafptr, +BdgraphStore * const storptr) +{ + byte * partloctab; /* Pointer to part data save area */ + byte * fronloctab; /* Pointer to frontier data save area */ + + storptr->fronlocnbr = grafptr->fronlocnbr; /* Save partition parameters */ + storptr->fronglbnbr = grafptr->fronglbnbr; + storptr->complocload0 = grafptr->complocload0; + storptr->compglbload0 = grafptr->compglbload0; + storptr->compglbload0dlt = grafptr->compglbload0dlt; + storptr->complocsize0 = grafptr->complocsize0; + storptr->compglbsize0 = grafptr->compglbsize0; + storptr->commglbload = grafptr->commglbload; + storptr->commglbgainextn = grafptr->commglbgainextn; + + fronloctab = storptr->datatab; /* Compute data offsets within save structure */ + partloctab = fronloctab + grafptr->fronlocnbr * sizeof (Gnum); + + if (grafptr->fronloctab != NULL) /* If frontier array allocated */ + memCpy (fronloctab, grafptr->fronloctab, grafptr->fronlocnbr * sizeof (Gnum)); +#ifdef SCOTCH_DEBUG_BDGRAPH2 + else if (grafptr->fronglbnbr != 0) + errorPrint ("bdgraphStoreSave: inconsistent graph data (1)"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + if (grafptr->partgsttax != NULL) + memCpy (partloctab, grafptr->partgsttax + grafptr->s.baseval, grafptr->s.vertlocnbr * sizeof (GraphPart)); + else { +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (grafptr->compglbload0 != grafptr->s.veloglbsum) + errorPrint ("bdgraphStoreSave: inconsistent graph data (2)"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + memSet (partloctab, 0, grafptr->s.vertlocnbr * sizeof (GraphPart)); /* In case part array is allocated before update */ + } +} + +/* This routine updates partition data of the +** given active graph, using the given save graph. +** It returns: +** - VOID : in all cases. +*/ + +void +bdgraphStoreUpdt ( +Bdgraph * const grafptr, +const BdgraphStore * const storptr) +{ + byte * fronloctab; /* Pointer to frontier data save area */ + byte * partloctab; /* Pointer to part data save area */ + + grafptr->fronlocnbr = storptr->fronlocnbr; /* Save partition parameters */ + grafptr->fronglbnbr = storptr->fronglbnbr; + grafptr->complocload0 = storptr->complocload0; + grafptr->compglbload0 = storptr->compglbload0; + grafptr->compglbload0dlt = storptr->compglbload0dlt; + grafptr->complocsize0 = storptr->complocsize0; + grafptr->compglbsize0 = storptr->compglbsize0; + grafptr->commglbload = storptr->commglbload; + grafptr->commglbgainextn = storptr->commglbgainextn; + grafptr->bbalglbval = (double) ((grafptr->compglbload0dlt < 0) ? (- grafptr->compglbload0dlt) : grafptr->compglbload0dlt) / (double) grafptr->compglbload0avg; + + fronloctab = storptr->datatab; /* Compute data offsets within save structure */ + partloctab = fronloctab + grafptr->fronlocnbr * sizeof (Gnum); + + if (grafptr->fronloctab != NULL) + memCpy (grafptr->fronloctab, fronloctab, grafptr->fronlocnbr * sizeof (Gnum)); +#ifdef SCOTCH_DEBUG_BDGRAPH2 + else if (grafptr->fronglbnbr != 0) + errorPrint ("bdgraphStoreUpdt: inconsistent graph data (1)"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + + if (grafptr->partgsttax != NULL) + memCpy (grafptr->partgsttax + grafptr->s.baseval, partloctab, grafptr->s.vertlocnbr * sizeof (GraphPart)); +#ifdef SCOTCH_DEBUG_BDGRAPH2 + else if (grafptr->compglbload0 != grafptr->s.veloglbsum) + errorPrint ("bdgraphStoreUpdt: inconsistent graph data (2)"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + +#ifdef SCOTCH_DEBUG_BDGRAPH2 + if (bdgraphCheck (grafptr) != 0) + errorPrint ("bdgraphStoreUpdt: inconsistent graph data (3)"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ +} diff --git a/scotch_6.0.3/src/libscotch/bgraph.c b/scotch_6.0.3/src/libscotch/bgraph.c new file mode 100644 index 00000000..059d57b7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph.c @@ -0,0 +1,255 @@ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the bipartition **/ +/** graph data structure handling **/ +/** routines. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to 12 may 1993 **/ +/** # Version 1.3 : from : 06 apr 1994 **/ +/** to 09 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 01 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 15 aug 1995 **/ +/** # Version 3.1 : from : 15 nov 1995 **/ +/** to 16 nov 1995 **/ +/** # Version 3.2 : from : 24 aug 1996 **/ +/** to : 14 oct 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 19 oct 1998 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 31 aug 2004 **/ +/** # Version 5.0 : from : 17 dec 2006 **/ +/** to 10 sep 2007 **/ +/** # Version 5.1 : from : 08 oct 2008 **/ +/** to 18 mar 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 25 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "bgraph.h" + +/*************************/ +/* */ +/* These routines handle */ +/* bipartition graphs. */ +/* */ +/*************************/ + +/* This routine builds the active graph +** corresponding to the given bipartitioning +** job parameters. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +bgraphInit ( +Bgraph * restrict const actgrafptr, /*+ Active graph +*/ +const Graph * restrict const srcgrafptr, /*+ Source graph +*/ +const Arch * restrict const archptr, /*+ Target architecture +*/ +const ArchDom * restrict const domnsubtab, /*+ Array of the two subdomains +*/ +const Gnum * restrict const vflowgttab) /*+ Array of vertex weight biases +*/ +{ + Anum domndist; /* Distance between both subdomains */ + Anum domnwght0; /* Processor workforce in each domain */ + Anum domnwght1; + + domndist = archDomDist (archptr, &domnsubtab[0], &domnsubtab[1]); /* Get distance between subdomains */ + domnwght0 = archDomWght (archptr, &domnsubtab[0]); /* Get weights of subdomains */ + domnwght1 = archDomWght (archptr, &domnsubtab[1]); + + actgrafptr->s = *srcgrafptr; /* Get source graph data */ + actgrafptr->s.flagval = ((srcgrafptr->flagval & GRAPHBITSUSED) & ~GRAPHFREETABS) | BGRAPHFREEFRON | BGRAPHFREEPART; /* Graph is a clone with own grouped bipartitioning arrays */ + actgrafptr->s.vlbltax = NULL; /* Remove vertex labels */ + actgrafptr->veextax = NULL; /* No external gains (yet) */ + + if (((actgrafptr->parttax = memAlloc (actgrafptr->s.vertnbr * sizeof (GraphPart))) == NULL) || + ((actgrafptr->frontab = memAlloc (actgrafptr->s.vertnbr * sizeof (Gnum))) == NULL)) { + errorPrint ("bgraphInit: out of memory"); + if (actgrafptr->parttax != NULL) + memFree (actgrafptr->parttax); + return (1); + } + actgrafptr->parttax -= actgrafptr->s.baseval; + + bgraphInit2 (actgrafptr, domndist, domnwght0, domnwght1, vflowgttab[0], vflowgttab[1]); + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (actgrafptr) != 0) { + errorPrint ("bgraphInit: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + return (0); +} + +/* This routine fills the internal fields of +** the given active graph. +** It returns: +** - void : in all cases. +*/ + +void +bgraphInit2 ( +Bgraph * restrict const grafptr, /*+ Active graph +*/ +const Anum domndist, /*+ Distance between both subdomains +*/ +const Anum domnwght0, /*+ Processor workforce in each domain +*/ +const Anum domnwght1, +const Gnum vfixload0, /*+ Fixed load in each subdomain +*/ +const Gnum vfixload1) +{ + grafptr->fronnbr = 0; /* No frontier vertices */ + grafptr->compload0min = 0; /* No external constraints on bipartition (yet) */ + grafptr->compload0max = grafptr->s.velosum; + grafptr->compload0avg = (Gnum) (((double) (grafptr->s.velosum + vfixload0 + vfixload1) * (double) domnwght0) / (double) (domnwght0 + domnwght1)) - vfixload0; + grafptr->compload0dlt = grafptr->s.velosum - grafptr->compload0avg; + grafptr->compload0 = grafptr->s.velosum; + grafptr->compsize0 = grafptr->s.vertnbr; /* Size does not account for fixed vertices */ + grafptr->commload = 0; + grafptr->commloadextn0 = 0; + grafptr->commgainextn = 0; + grafptr->commgainextn0 = 0; + grafptr->domndist = domndist; + grafptr->domnwght[0] = domnwght0; + grafptr->domnwght[1] = domnwght1; + grafptr->vfixload[0] = vfixload0; + grafptr->vfixload[1] = vfixload1; + grafptr->bbalval = (double) grafptr->compload0dlt / (double) grafptr->compload0avg; + grafptr->levlnum = 0; + + memSet (grafptr->parttax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ +} + +/* This routine frees the contents +** of the given active graph. +** It returns: +** - void : in all cases. +*/ + +void +bgraphExit ( +Bgraph * restrict const grafptr) +{ + if ((grafptr->veextax != NULL) && /* External gain array is private */ + ((grafptr->s.flagval & BGRAPHFREEVEEX) != 0)) + memFree (grafptr->veextax + grafptr->s.baseval); + if ((grafptr->frontab != NULL) && + ((grafptr->s.flagval & BGRAPHFREEFRON) != 0)) + memFree (grafptr->frontab); + if ((grafptr->parttax != NULL) && + ((grafptr->s.flagval & BGRAPHFREEPART) != 0)) + memFree (grafptr->parttax + grafptr->s.baseval); + + graphExit (&grafptr->s); /* Free re-allocated arrays of cloned source graph, if any */ + +#ifdef SCOTCH_DEBUG_BGRAPH2 + memSet (grafptr, ~0, sizeof (Bgraph)); +#endif /* SCOTCH_DEBUG_BGRAPH2 */ +} + +/* This routine swaps all of the graph +** vertices from one part to another, and +** recomputes the resulting gains. +** It returns: +** - void : in all cases. +*/ + +void +bgraphSwal ( +Bgraph * restrict const grafptr) +{ + Gnum vertnnd; + Gnum vertnum; + Gnum comploadsum; + + GraphPart * restrict const parttax = grafptr->parttax; + + for (vertnum = grafptr->s.baseval, vertnnd = grafptr->s.vertnnd; vertnum < vertnnd; vertnum ++) + parttax[vertnum] ^= 1; + + comploadsum = grafptr->s.velosum + grafptr->vfixload[0] + grafptr->vfixload[1]; /* Overall load sum, including fixed vertex loads */ + grafptr->compload0 = comploadsum - grafptr->compload0; + grafptr->compload0dlt = comploadsum - grafptr->compload0dlt - 2 * grafptr->compload0avg; + grafptr->compsize0 = grafptr->s.vertnbr - grafptr->compsize0; /* Size does not account for fixed vertices */ + grafptr->commload += grafptr->commgainextn; + grafptr->commgainextn = - grafptr->commgainextn; +} + +/* This routine moves all of the graph +** vertices to the first part, and +** computes the resulting gains. +** It returns: +** - void : in all cases. +*/ + +void +bgraphZero ( +Bgraph * restrict const grafptr) +{ + Gnum compload0; + + compload0 = grafptr->s.velosum + grafptr->vfixload[0]; + grafptr->fronnbr = 0; /* No frontier vertices */ + grafptr->compload0dlt = compload0 - grafptr->compload0avg; + grafptr->compload0 = compload0; + grafptr->compsize0 = grafptr->s.vertnbr; + grafptr->commload = grafptr->commloadextn0; /* Initialize communication load */ + grafptr->commgainextn = grafptr->commgainextn0; + grafptr->bbalval = (double) grafptr->compload0dlt / (double) grafptr->compload0avg; + + memSet (grafptr->parttax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ +} diff --git a/scotch_6.0.3/src/libscotch/bgraph.h b/scotch_6.0.3/src/libscotch/bgraph.h new file mode 100644 index 00000000..c36a4bc0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph.h @@ -0,0 +1,139 @@ +/* Copyright 2004,2007,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the job control routines of the **/ +/** Dual Recursive Bipartitioning method. **/ +/** **/ +/** DATES : # Version 0.0 : from : 23 mar 1993 **/ +/** to 12 may 1993 **/ +/** # Version 1.3 : from : 06 apr 1994 **/ +/** to 09 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 04 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 15 nov 1995 **/ +/** to 15 nov 1995 **/ +/** # Version 3.2 : from : 24 aug 1996 **/ +/** to 03 nov 1997 **/ +/** # Version 3.3 : from : 01 dec 1998 **/ +/** to 02 dec 1998 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 05 may 2006 **/ +/** # Version 5.0 : from : 30 nov 2006 **/ +/** to 30 nov 2006 **/ +/** # Version 5.1 : from : 08 jan 2008 **/ +/** to 18 mar 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 08 aug 2014 **/ +/** **/ +/************************************************************/ + +#define BGRAPH_H + +/* +** The type and structure definitions. +*/ + +/*+ Graph option flags. +*/ + +#define BGRAPHFREEFRON (GRAPHBITSNOTUSED) /* Free frontier array */ +#define BGRAPHFREEPART (GRAPHBITSNOTUSED << 1) /* Free part array */ +#define BGRAPHFREEVEEX (GRAPHBITSNOTUSED << 2) /* Free external gain array */ +#define BGRAPHHASANCHORS (GRAPHBITSNOTUSED << 3) /* If graph has anchor vertices */ + +/*+ The bipartition graph structure. +*/ + +typedef struct Bgraph_ { + Graph s; /*+ Source graph data +*/ + Gnum * veextax; /*+ Array of vertex external gain if moved to part 1 +*/ + GraphPart * parttax; /*+ Array of parts for every vertex +*/ + Gnum * frontab; /*+ Array of frontier vertex numbers +*/ + Gnum fronnbr; /*+ Number of frontier vertices +*/ + Gnum compload0min; /*+ Minimum allowed load in part 0 (strategy variable) +*/ + Gnum compload0max; /*+ Maximum allowed load in part 0 (strategy variable) +*/ + Gnum compload0avg; /*+ Average load of part 0 +*/ + Gnum compload0dlt; /*+ Difference from the average +*/ + Gnum compload0; /*+ Load in part 0 (strategy variable) +*/ + Gnum compsize0; /*+ Number of vertices in part 0 +*/ + Gnum commload; /*+ Communication load +*/ + Gnum commloadextn0; /*+ Communication load if all moved to part 0 +*/ + Gnum commgainextn0; /*+ External gain if all swapped from part 0 +*/ + Gnum commgainextn; /*+ External gain if all swapped +*/ + double bbalval; /*+ Bipartitioning imbalance ratio (strategy variable) +*/ + Anum domndist; /*+ Distance between subdomains +*/ + Gnum domnwght[2]; /*+ Weights of the two subdomains +*/ + Gnum vfixload[2]; /*+ Vertex load biases of the two subdomains +*/ + INT levlnum; /*+ Coarsening level +*/ +} Bgraph; + +/*+ The save graph structure. +*/ + +typedef struct BgraphStore_ { + Gnum fronnbr; /*+ Number of frontier nodes +*/ + Gnum compload0dlt; /*+ Difference from the average +*/ + Gnum compsize0; /*+ Number of vertices in part 0 +*/ + Gnum commload; /*+ Communication load +*/ + Gnum commgainextn; /*+ External gain if all swapped +*/ + byte * datatab; /*+ Variable-sized data array +*/ +} BgraphStore; + +/* +** The function prototypes. +*/ + +#ifndef BGRAPH +#define static +#endif + +int bgraphInit (Bgraph * restrict const, const Graph * restrict const, const Arch * restrict const, const ArchDom * restrict const, const Gnum * restrict const); +void bgraphInit2 (Bgraph * restrict const, const Anum, const Anum, const Anum, const Gnum, const Gnum); +void bgraphExit (Bgraph * restrict const); +void bgraphSwal (Bgraph * restrict const); +void bgraphZero (Bgraph * restrict const); +int bgraphCheck (const Bgraph * restrict const); + +int bgraphStoreInit (const Bgraph * const, BgraphStore * const); +void bgraphStoreExit (BgraphStore * const); +void bgraphStoreSave (const Bgraph * const, BgraphStore * const); +void bgraphStoreUpdt (Bgraph * const, const BgraphStore * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_bd.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_bd.c new file mode 100644 index 00000000..59308584 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_bd.c @@ -0,0 +1,599 @@ +/* Copyright 2004,2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_bd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module builds a band graph around **/ +/** the frontier in order to decrease **/ +/** problem size for the strategy to be **/ +/** applied. **/ +/** **/ +/** DATES : # Version 5.0 : from : 27 nov 2006 **/ +/** to : 23 dec 2007 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to : 26 mar 2011 **/ +/** # Version 6.0 : from : 07 nov 2011 **/ +/** to : 08 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_BIPART_BD + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_bd.h" +#include "bgraph_bipart_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +int +bgraphBipartBd ( +Bgraph * restrict const orggrafptr, /*+ Active graph +*/ +const BgraphBipartBdParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum * restrict queutab; + Gnum queuheadval; + Gnum queutailval; + Gnum distmax; /* Maximum distance allowed */ + Gnum * restrict orgindxtax; /* Based access to index array for original graph */ + Gnum orgfronnum; + Gnum ancfronnum; + Gnum bndfronnum; + Bgraph bndgrafdat; /* Band graph structure */ + Gnum bndvertnbr; /* Number of regular vertices in band graph (without anchors) */ + Gnum bndvertnnd; + const Gnum * restrict bndvnumtax; /* Band vertex number array, recycling queutab */ + Gnum * restrict bndveextax; /* External gain array of band graph, if present */ + Gnum bndveexnbr; /* Number of external array vertices */ + Gnum bndvelosum; /* Load of regular vertices in band graph */ + Gnum bndedlosum; /* Sum of edge loads */ + Gnum bndcompsize1; /* Number of regular vertices in part 1 of band graph */ + Gnum bndcompload1; /* Load of regular vertices in part 1 */ + Gnum bndvlvlnum; /* Index of first band graph vertex to belong to the last layer */ + Gnum bndvertnum; + Gnum bndeancnbr; /* Number of anchor edges */ + Gnum bndedgenbr; /* Upper bound on the number of edges, including anchor edges */ + Gnum bndedgenum; + Gnum * restrict bndedgetax; + Gnum * restrict bndedlotax; + Gnum bndedgetmp; + Gnum bnddegrmax; + Gnum bndcommgainextn; /* Sum of all external gains in band graph */ + Gnum bndcommgainextn1; /* Sum of external gains accounted for in load, since in part 1 */ + size_t bndedlooftval; /* Offset of edge load array with respect to edge array */ + const Gnum * restrict const orgverttax = orggrafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const orgvendtax = orggrafptr->s.vendtax; + const Gnum * restrict const orgvelotax = orggrafptr->s.velotax; + const Gnum * restrict const orgedgetax = orggrafptr->s.edgetax; + const Gnum * restrict const orgedlotax = orggrafptr->s.edlotax; + GraphPart * restrict const orgparttax = orggrafptr->parttax; + Gnum * restrict const orgfrontab = orggrafptr->frontab; + + if (orggrafptr->fronnbr == 0) /* If no separator vertices, apply strategy to full (original) graph */ + return (bgraphBipartSt (orggrafptr, paraptr->stratorg)); + + distmax = (Gnum) paraptr->distmax; + if (distmax < 1) /* Always at least one layer of vertices around separator */ + distmax = 1; + + if (memAllocGroup ((void **) (void *) + &queutab, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), + &orgindxtax, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("bgraphBipartBd: out of memory (1)"); + return (1); + } + memSet (orgindxtax, ~0, orggrafptr->s.vertnbr * sizeof (Gnum)); /* Initialize index array */ + orgindxtax -= orggrafptr->s.baseval; + + queuheadval = orggrafptr->fronnbr; /* First layer is vertices in frontier array */ + for (orgfronnum = 0, bndvertnnd = orggrafptr->s.baseval; /* Flag vertices belonging to frontier as band vertices */ + orgfronnum < queuheadval; orgfronnum ++) { + Gnum orgvertnum; + + orgvertnum = orgfrontab[orgfronnum]; + orgindxtax[orgvertnum] = bndvertnnd ++; + queutab[orgfronnum] = orgvertnum; /* Copy frontier array in queue array */ + } + + bndvelosum = 0; + bndedgenbr = 0; /* Estimate upper bound on the number of edges */ + bndcompsize1 = 0; + bndcompload1 = 0; + queutailval = 0; + bndvlvlnum = 0; /* Assume first layer is last layer */ + while (distmax -- > 0) { /* For all passes except the last one */ + Gnum orgvertnum; + Gnum orgdistval; + + bndvlvlnum = queuheadval; /* Record start of last layer */ + while (queutailval < bndvlvlnum) { /* For all vertices in queue */ + Gnum orgvertnum; + Gnum orgedgenum; + Gnum orgpartval; + + orgvertnum = queutab[queutailval ++]; +#ifdef SCOTCH_DEBUG_BGRAPH2 + if ((orgvertnum < orggrafptr->s.baseval) || (orgvertnum >= orggrafptr->s.vertnnd)) { + errorPrint ("bgraphBipartBd: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + bndedgenbr += orgvendtax[orgvertnum] - orgverttax[orgvertnum]; /* Exact number of edges */ + orgpartval = orgparttax[orgvertnum]; + bndcompsize1 += orgpartval; /* Count vertices in part 1 */ + if (orgvelotax != NULL) { + Gnum orgveloval; + + orgveloval = orgvelotax[orgvertnum]; + bndvelosum += orgveloval; + bndcompload1 += orgveloval * orgpartval; + } + + for (orgedgenum = orgverttax[orgvertnum]; + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { + Gnum orgvertend; + + orgvertend = orgedgetax[orgedgenum]; + if (orgindxtax[orgvertend] == ~0) { /* If vertex not visited yet */ + orgindxtax[orgvertend] = bndvertnnd ++; /* Flag it as enqueued */ + queutab[queuheadval ++] = orgvertend; /* Enqueue it */ + } + } + } + } + bndedgenbr += queuheadval - queutailval; /* As many edges from anchors as remaining vertices */ + while (queutailval < queuheadval) { /* Process vertices in last layer */ + Gnum orgvertnum; + Gnum orgpartval; + + orgvertnum = queutab[queutailval ++]; +#ifdef SCOTCH_DEBUG_BGRAPH2 + if ((orgvertnum < orggrafptr->s.baseval) || (orgvertnum >= orggrafptr->s.vertnnd)) { + errorPrint ("bgraphBipartBd: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + bndedgenbr += orgvendtax[orgvertnum] - orgverttax[orgvertnum]; /* Upper bound on number of edges, including anchor edge */ + orgpartval = orgparttax[orgvertnum]; + bndcompsize1 += orgpartval; /* Count vertices in part 1 */ + if (orgvelotax != NULL) { + Gnum orgveloval; + + orgveloval = orgvelotax[orgvertnum]; + bndvelosum += orgveloval; + bndcompload1 += orgveloval * orgpartval; + } + } + bndvertnbr = bndvertnnd - orggrafptr->s.baseval; + if (orgvelotax == NULL) { + bndvelosum = bndvertnbr; + bndcompload1 = bndcompsize1; + } + + if ((bndcompsize1 >= (orggrafptr->s.vertnbr - orggrafptr->compsize0)) || /* If either part has all of its vertices in band, use plain graph instead */ + ((bndvertnbr - bndcompsize1) >= orggrafptr->compsize0)) { + memFree (queutab); + return (bgraphBipartSt (orggrafptr, paraptr->stratorg)); + } /* TRICK: since always at least one missing vertex per part, there is room for anchor vertices */ + + queutab[bndvertnbr] = /* Anchor vertices do not have original vertex numbers */ + queutab[bndvertnbr + 1] = -1; + + memSet (&bndgrafdat, 0, sizeof (Bgraph)); + bndgrafdat.s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP | BGRAPHHASANCHORS; /* All Bgraph arrays are non-freeable by bgraphExit() */ + bndgrafdat.s.baseval = orggrafptr->s.baseval; + bndgrafdat.s.vertnbr = bndvertnbr += 2; /* "+ 2" for anchor vertices */ + bndgrafdat.s.vertnnd = bndvertnnd + 2; + + bndveexnbr = (orggrafptr->veextax != NULL) ? bndvertnbr : 0; + if (memAllocGroup ((void **) (void *) /* Do not allocate vnumtax but keep queutab instead */ + &bndgrafdat.s.verttax, (size_t) ((bndvertnbr + 1) * sizeof (Gnum)), + &bndgrafdat.s.velotax, (size_t) (bndvertnbr * sizeof (Gnum)), + &bndveextax, (size_t) (bndveexnbr * sizeof (Gnum)), + &bndgrafdat.frontab, (size_t) (bndvertnbr * sizeof (Gnum)), + &bndgrafdat.parttax, (size_t) (bndvertnbr * sizeof (GraphPart)), NULL) == NULL) { + errorPrint ("bgraphBipartBd: out of memory (2)"); + memFree (queutab); + return (1); + } + bndgrafdat.parttax -= orggrafptr->s.baseval; /* From now on we should free a Bgraph and not a Graph */ + bndgrafdat.s.verttax -= orggrafptr->s.baseval; + bndgrafdat.s.vendtax = bndgrafdat.s.verttax + 1; /* Band graph is compact */ + bndgrafdat.s.velotax -= orggrafptr->s.baseval; + bndgrafdat.s.vnumtax = queutab - orggrafptr->s.baseval; /* TRICK: re-use queue array as vertex number array since vertices taken in queue order; will not be freed as graph vertex arrays are said to be grouped */ + bndgrafdat.s.velosum = orggrafptr->s.velosum; + bndgrafdat.s.velotax[bndvertnnd] = orggrafptr->compload0 - (bndvelosum - bndcompload1); /* Set loads of anchor vertices */ + bndgrafdat.s.velotax[bndvertnnd + 1] = orggrafptr->s.velosum - orggrafptr->compload0 - bndcompload1; + if (bndveexnbr != 0) { + bndveextax -= orggrafptr->s.baseval; + bndgrafdat.veextax = bndveextax; + } + else + bndveextax = NULL; + + if (memAllocGroup ((void **) (void *) + &bndgrafdat.s.edgetax, (size_t) (bndedgenbr * sizeof (Gnum)), + &bndgrafdat.s.edlotax, (size_t) (bndedgenbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("bgraphBipartBd: out of memory (3)"); + bgraphExit (&bndgrafdat); + memFree (queutab); + return (1); + } + bndgrafdat.s.edgetax -= orggrafptr->s.baseval; + bndgrafdat.s.edlotax -= orggrafptr->s.baseval; + bndedgetax = bndgrafdat.s.edgetax; + bndedlotax = bndgrafdat.s.edlotax; + bndvnumtax = bndgrafdat.s.vnumtax; + + for (bndvertnum = bndedgenum = orggrafptr->s.baseval, bnddegrmax = bndedlosum = bndcommgainextn = bndcommgainextn1 = 0; + bndvertnum < bndvlvlnum; bndvertnum ++) { /* Fill index array for vertices not belonging to last level */ + Gnum orgvertnum; + GraphPart orgpartval; + Gnum orgedgenum; + Gnum orgedloval; + Gnum bnddegrval; + + orgvertnum = bndvnumtax[bndvertnum]; + orgpartval = orgparttax[orgvertnum]; + bndgrafdat.s.verttax[bndvertnum] = bndedgenum; + bndgrafdat.s.velotax[bndvertnum] = (orgvelotax != NULL) ? orgvelotax[orgvertnum] : 1; + bndgrafdat.parttax[bndvertnum] = orgpartval; + if (bndveextax != NULL) { + Gnum orgveexval; + + orgveexval = orggrafptr->veextax[orgvertnum]; + bndveextax[bndvertnum] = orgveexval; + bndcommgainextn += orgveexval; + bndcommgainextn1 += orgveexval * (Gnum) orgpartval; + } + orgedloval = 1; /* Assume unity edge loads if not present */ + for (orgedgenum = orgverttax[orgvertnum]; /* All edges of first levels are kept */ + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++, bndedgenum ++) { + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if ((bndedgenum >= (bndedgenbr + orggrafptr->s.baseval)) || + (orgindxtax[orgedgetax[orgedgenum]] < 0)) { + errorPrint ("bgraphBipartBd: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + if (orgedlotax != NULL) + orgedloval = orgedlotax[orgedgenum]; + bndedlosum += orgedloval; + bndedgetax[bndedgenum] = orgindxtax[orgedgetax[orgedgenum]]; + bndedlotax[bndedgenum] = orgedloval; + } + + bnddegrval = bndedgenum - bndgrafdat.s.verttax[bndvertnum]; + if (bnddegrmax < bnddegrval) + bnddegrmax = bnddegrval; + } + bndeancnbr = 0; + for ( ; bndvertnum < bndvertnnd; bndvertnum ++) { /* Fill index array for vertices belonging to last level */ + Gnum orgvertnum; + Gnum orgedgenum; + GraphPart orgpartval; + Gnum bnddegrval; + Gnum orgedloval; + Gnum ancedloval; /* Accumulated edge load for anchor edge */ + + orgvertnum = bndvnumtax[bndvertnum]; + orgpartval = orgparttax[orgvertnum]; + bndgrafdat.s.verttax[bndvertnum] = bndedgenum; + bndgrafdat.s.velotax[bndvertnum] = (orgvelotax != NULL) ? orgvelotax[orgvertnum] : 1; + bndgrafdat.parttax[bndvertnum] = orgpartval; /* Record part for vertices of last level */ + if (bndveextax != NULL) { + Gnum orgveexval; + + orgveexval = orggrafptr->veextax[orgvertnum]; + bndveextax[bndvertnum] = orgveexval; + bndcommgainextn += orgveexval; + bndcommgainextn1 += orgveexval * (Gnum) orgpartval; + } + + ancedloval = 0; + orgedloval = 1; /* Assume unity edge loads if not present */ + for (orgedgenum = orgverttax[orgvertnum]; /* Keep only band edges */ + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { + Gnum bndvertend; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bndedgenum >= (bndedgenbr + orggrafptr->s.baseval)) { + errorPrint ("bgraphBipartBd: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + if (orgedlotax != NULL) + orgedloval = orgedlotax[orgedgenum]; + bndedlosum += orgedloval; /* Normal arcs are accounted for twice; anchor arcs only once */ + bndvertend = orgindxtax[orgedgetax[orgedgenum]]; + if (bndvertend != ~0) { + bndedgetax[bndedgenum] = bndvertend; + bndedlotax[bndedgenum ++] = orgedloval; + } + else + ancedloval += orgedloval; /* Accumulate loads of edges linking to anchor vertex */ + } + + bndedlosum += ancedloval; /* Account for anchor edges a second time */ + if (ancedloval > 0) { /* If vertex is connected to rest of part */ + bndedlotax[bndedgenum] = ancedloval; + bndedgetax[bndedgenum ++] = bndvertnnd + (Gnum) orgpartval; /* Add anchor edge to proper anchor vertex */ + bndeancnbr ++; + } + bnddegrval = bndedgenum - bndgrafdat.s.verttax[bndvertnum]; + if (bnddegrmax < bnddegrval) + bnddegrmax = bnddegrval; + } + bndgrafdat.parttax[bndvertnnd] = 0; /* Set parts of anchor vertices */ + bndgrafdat.parttax[bndvertnnd + 1] = 1; + + bndgrafdat.s.edlosum = bndedlosum; + bndgrafdat.s.verttax[bndvertnnd] = bndedgenum; /* Mark end of regular edge array and start of first anchor edge array */ + bndedgetmp = bndedgenum + bndeancnbr; +#ifdef SCOTCH_DEBUG_BGRAPH2 + if ((bndedgetmp - 1) >= (bndedgenbr + orggrafptr->s.baseval)) { + errorPrint ("bgraphBipartBd: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + bndgrafdat.s.edgenbr = bndedgetmp - orggrafptr->s.baseval; + bndgrafdat.s.verttax[bndvertnnd + 2] = bndedgetmp; /* Mark end of edge array with anchor vertices */ + for (bndvertnum = bndvlvlnum; bndvertnum < bndvertnnd; bndvertnum ++) { /* Fill anchor edge arrays */ + Gnum orgvertnum; + + orgvertnum = bndvnumtax[bndvertnum]; + if (bndgrafdat.s.verttax[bndvertnum + 1] > bndgrafdat.s.verttax[bndvertnum]) { /* If vertex is not isolated */ + Gnum bndedgelst; /* Number of last edge */ + Gnum bndvertend; + + bndedgelst = bndgrafdat.s.verttax[bndvertnum + 1] - 1; + bndvertend = bndedgetax[bndedgelst]; /* Get last neighbor of its edge sub-array */ + if (bndvertend >= bndvertnnd) { /* If it is an anchor */ + Gnum bndedloval; + + bndedloval = bndedlotax[bndedgelst]; + bndedlosum += bndedloval; + if (bndvertend == bndvertnnd) { /* Add edge from proper anchor */ + bndedgetax[bndedgenum] = bndvertnum; + bndedlotax[bndedgenum ++] = bndedloval; + } + else { + bndedgetax[-- bndedgetmp] = bndvertnum; + bndedlotax[bndedgetmp] = bndedloval; + } + } + } + } + bndgrafdat.s.verttax[bndvertnnd + 1] = bndedgenum; /* Mark end of edge array of first anchor and start of second */ +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bndedgenum != bndedgetmp) { + errorPrint ("bgraphBipartBd: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + if ((bndedgenum == bndgrafdat.s.verttax[bndvertnnd]) || /* If any of the anchor edges is isolated */ + (bndedgenum == bndgrafdat.s.verttax[bndvertnnd + 2])) { + bgraphExit (&bndgrafdat); /* Free all band graph related data */ + memFree (queutab); + return (bgraphBipartSt (orggrafptr, paraptr->stratorg)); /* Work on original graph */ + } + + if (bnddegrmax < (bndgrafdat.s.verttax[bndvertnnd + 1] - bndgrafdat.s.verttax[bndvertnnd])) + bnddegrmax = (bndgrafdat.s.verttax[bndvertnnd + 1] - bndgrafdat.s.verttax[bndvertnnd]); + if (bnddegrmax < (bndgrafdat.s.verttax[bndvertnnd + 2] - bndgrafdat.s.verttax[bndvertnnd + 1])) + bnddegrmax = (bndgrafdat.s.verttax[bndvertnnd + 2] - bndgrafdat.s.verttax[bndvertnnd + 1]); + bndgrafdat.s.degrmax = bnddegrmax; + + bndedlooftval = bndedlotax - bndedgetax; + bndgrafdat.s.edgetax = (Gnum *) memRealloc (bndedgetax + bndgrafdat.s.baseval, (bndedlooftval + bndgrafdat.s.edgenbr) * sizeof (Gnum)) - bndgrafdat.s.baseval; + bndgrafdat.s.edlotax = bndgrafdat.s.edgetax + bndedlooftval; /* Use old index into old array as new index */ + bndedgetax = bndgrafdat.s.edgetax; + bndedlotax = bndgrafdat.s.edlotax; + + for (bndfronnum = 0, bndvertnum = orggrafptr->s.baseval; /* Fill band frontier array with first vertex indices as they make the separator */ + bndfronnum < orggrafptr->fronnbr; bndfronnum ++, bndvertnum ++) + bndgrafdat.frontab[bndfronnum] = bndvertnum; + + if (bndveextax != NULL) { + Gnum bndcommloadintn; + Gnum bndfronnnd; + Gnum bndvertnum; + Gnum bndedgenum; + Gnum bndedloval; + + bndedloval = 1; /* Assume unity edge weights */ + bndcommloadintn = 0; + for (bndvertnum = orggrafptr->s.baseval, bndfronnnd = bndvertnum + orggrafptr->fronnbr; /* Compute communication load at frontier */ + bndvertnum < bndfronnnd; bndvertnum ++) { + Gnum bndpartval; + + bndpartval = (Gnum) bndgrafdat.parttax[bndvertnum]; + if (bndpartval != 0) /* Process only frontier vertices in part 0 */ + continue; + + for (bndedgenum = bndgrafdat.s.verttax[bndvertnum]; bndedgenum < bndgrafdat.s.vendtax[bndvertnum]; bndedgenum ++) { + Gnum bndpartend; + + bndpartend = (Gnum) bndgrafdat.parttax[bndedgetax[bndedgenum]]; + bndedloval = bndedlotax[bndedgenum]; + bndcommloadintn += bndedloval * bndpartend; + } + } + + bndcommloadintn *= orggrafptr->domndist; + bndveextax[bndvertnnd + 1] = (orggrafptr->commload - orggrafptr->commloadextn0 - bndcommloadintn) - bndcommgainextn1; + bndveextax[bndvertnnd] = (orggrafptr->commload - orggrafptr->commloadextn0 - bndcommloadintn) - bndcommgainextn + bndcommgainextn1 + orggrafptr->commgainextn; + } + + bndgrafdat.fronnbr = orggrafptr->fronnbr; + bndgrafdat.compload0 = orggrafptr->compload0; + bndgrafdat.compload0min = orggrafptr->compload0min; + bndgrafdat.compload0max = orggrafptr->compload0max; + bndgrafdat.compload0avg = orggrafptr->compload0avg; + bndgrafdat.compload0dlt = orggrafptr->compload0dlt; + bndgrafdat.compsize0 = bndvertnbr - bndcompsize1 - 1; /* "- 1" for anchor vertex in part 0 */ + bndgrafdat.commload = orggrafptr->commload; + bndgrafdat.commloadextn0 = orggrafptr->commloadextn0; + bndgrafdat.commgainextn = orggrafptr->commgainextn; + bndgrafdat.commgainextn0 = orggrafptr->commgainextn0; + bndgrafdat.domndist = orggrafptr->domndist; + bndgrafdat.domnwght[0] = orggrafptr->domnwght[0]; + bndgrafdat.domnwght[1] = orggrafptr->domnwght[1]; + bndgrafdat.vfixload[0] = orggrafptr->vfixload[0]; + bndgrafdat.vfixload[1] = orggrafptr->vfixload[1]; + bndgrafdat.bbalval = orggrafptr->bbalval; + bndgrafdat.levlnum = orggrafptr->levlnum; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if ((graphCheck (&bndgrafdat.s) != 0) || /* Check band graph consistency */ + (bgraphCheck (&bndgrafdat) != 0)) { + errorPrint ("bgraphBipartBd: inconsistent band graph data"); + bgraphExit (&bndgrafdat); + memFree (queutab); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + if (bgraphBipartSt (&bndgrafdat, paraptr->stratbnd) != 0) { /* Apply strategy to band graph */ + errorPrint ("bgraphBipartBd: cannot bipartition band graph"); + bgraphExit (&bndgrafdat); + memFree (queutab); + return (1); + } + if (bndgrafdat.parttax[bndvertnnd] == /* If band graph was too small and anchors went to the same part, apply strategy on full graph */ + bndgrafdat.parttax[bndvertnnd + 1]) { + bgraphExit (&bndgrafdat); + memFree (queutab); + return (bgraphBipartSt (orggrafptr, paraptr->stratorg)); + } + + orggrafptr->compload0 = bndgrafdat.compload0; + orggrafptr->compload0dlt = bndgrafdat.compload0dlt; + orggrafptr->commload = bndgrafdat.commload; + orggrafptr->commgainextn = bndgrafdat.commgainextn; + orggrafptr->bbalval = bndgrafdat.bbalval; + + if (bndgrafdat.parttax[bndvertnnd] != 0) { /* If anchors swapped parts, swap all parts of original vertices */ + Gnum orgvertnum; + + orggrafptr->compsize0 = orggrafptr->s.vertnbr - orggrafptr->compsize0 - bndcompsize1 + bndgrafdat.compsize0 - 1; /* "- 1" for anchor 0 */ + + for (orgvertnum = orggrafptr->s.baseval; orgvertnum < orggrafptr->s.vertnnd; orgvertnum ++) + orgparttax[orgvertnum] ^= 1; + } + else + orggrafptr->compsize0 = orggrafptr->compsize0 - (bndvertnbr - bndcompsize1) + bndgrafdat.compsize0 + 1; /* "+ 1" for anchor 0 */ + + for (bndvertnum = bndgrafdat.s.baseval; bndvertnum < bndvertnnd; bndvertnum ++) /* Update part array of full graph */ + orgparttax[bndvnumtax[bndvertnum]] = bndgrafdat.parttax[bndvertnum]; + + for (bndfronnum = orgfronnum = ancfronnum = 0; /* Update frontier array of full graph */ + bndfronnum < bndgrafdat.fronnbr; bndfronnum ++) { + Gnum bndvertnum; + Gnum orgvertnum; + + bndvertnum = bndgrafdat.frontab[bndfronnum]; + orgvertnum = bndvnumtax[bndvertnum]; + if (orgvertnum != -1) /* If frontier vertex is not an anchor vertex */ + orgfrontab[orgfronnum ++] = orgvertnum; /* Record it as original frontier vertex */ + else + bndgrafdat.frontab[ancfronnum ++] = bndvertnum; /* Else record it for future processing */ + } + + while (ancfronnum > 0) { /* For all recorded frontier anchor vertices */ + Gnum bndvertnum; /* Index of frontier anchor vertex in band graph */ + GraphPart ancpartval; + + bndvertnum = bndgrafdat.frontab[-- ancfronnum]; + ancpartval = bndgrafdat.parttax[bndvertnum]; + + for (bndedgenum = bndgrafdat.s.verttax[bndvertnum]; + bndedgenum < bndgrafdat.s.vendtax[bndvertnum]; bndedgenum ++) { + Gnum bndvertend; /* Index of neighbor of anchor vertex in band graph */ + Gnum orgvertnum; /* Index of neighbor of anchor vertex in original graph */ + Gnum orgedgenum; + + bndvertend = bndedgetax[bndedgenum]; + if (bndgrafdat.parttax[bndvertend] == ancpartval) /* If neighbor is in same part as anchor, skip to next */ + continue; + + orgvertnum = bndvnumtax[bndvertend]; + + for (orgedgenum = orgverttax[orgvertnum]; /* For all neighbors of neighbor */ + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { + Gnum orgvertend; + + orgvertend = orgedgetax[orgedgenum]; /* Get end vertex in original graph */ + if (orgindxtax[orgvertend] == ~0) { /* If vertex never considered before */ +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (orgparttax[orgvertend] != ancpartval) { /* Original vertex should always be in same part as anchor */ + errorPrint ("bgraphBipartBd: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + orggrafptr->frontab[orgfronnum ++] = orgvertend; /* Add vertex to frontier array */ + orgindxtax[orgvertend] = 0; /* Flag vertex as already enqueued */ + } + } + } + } + orggrafptr->fronnbr = orgfronnum; + + bgraphExit (&bndgrafdat); /* Free band graph structures */ + memFree (queutab); + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (orggrafptr) != 0) { + errorPrint ("bgraphBipartBd: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_bd.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_bd.h new file mode 100644 index 00000000..c1c2e008 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_bd.h @@ -0,0 +1,67 @@ +/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_bd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the bipartition graph banding **/ +/** module. **/ +/** **/ +/** DATES : Version 5.0 : from : 27 nov 2006 **/ +/** to : 29 may 2007 **/ +/** Version 5.1 : from : 04 nov 2010 **/ +/** to : 04 nov 2010 **/ +/** Version 6.0 : from : 07 nov 2011 **/ +/** to : 07 nov 2011 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct BgraphBipartBdParam_ { + Gnum distmax; /*+ Maximum distance to separator +*/ + Strat * stratbnd; /*+ Strategy for band graph +*/ + Strat * stratorg; /*+ Strategy for original graph +*/ +} BgraphBipartBdParam; + +/* +** The function prototypes. +*/ + +int bgraphBipartBd (Bgraph * restrict const, const BgraphBipartBdParam * restrict const); diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_df.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_df.c new file mode 100644 index 00000000..0e553630 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_df.c @@ -0,0 +1,303 @@ +/* Copyright 2004,2007,2008,2011-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_df.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a bipartition of **/ +/** a bipartition graph by using a **/ +/** diffusion scheme. **/ +/** **/ +/** NOTES : # This algorithm has been designed to **/ +/** work on band graphs only, for which **/ +/** the two anchor vertices are the two **/ +/** last vertices, the before-last as **/ +/** anchor of part 0, and the last as **/ +/** anchor of part 1. **/ +/** **/ +/** DATES : # Version 5.0 : from : 09 jan 2007 **/ +/** to 10 sep 2007 **/ +/** # Version 5.1 : from : 29 oct 2007 **/ +/** to 27 mar 2011 **/ +/** # Version 6.0 : from : 07 nov 2011 **/ +/** to 08 aug 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_BIPART_DF + +#ifdef SCOTCH_PTHREAD +#define BGRAPHBIPARTDFTHREAD +#endif /* SCOTCH_PTHREAD */ + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_df.h" + +/************************************/ +/* */ +/* The threaded reduction routines. */ +/* */ +/************************************/ + +#ifdef BGRAPHBIPARTDFTHREAD + +static +void +bgraphBipartDfReduceVanc ( +BgraphBipartDfThread * restrict const tlocptr, /* Pointer to local thread */ +void * restrict const vlocptr, /* Pointer to local value */ +void * restrict const vremptr) /* Pointer to remote value */ +{ + BgraphBipartDfThread * restrict const tremptr = (BgraphBipartDfThread *) vremptr; + + tlocptr->vanctab[0] += tremptr->vanctab[0]; /* Accumulate external gains */ + tlocptr->vanctab[1] += tremptr->vanctab[1]; +} + +static +void +bgraphBipartDfReduceVeex ( +BgraphBipartDfThread * restrict const tlocptr, /* Pointer to local thread */ +void * restrict const vlocptr, /* Pointer to local value */ +void * restrict const vremptr) /* Pointer to remote value */ +{ + BgraphBipartDfThread * restrict const tremptr = (BgraphBipartDfThread *) vremptr; + + tlocptr->veexsum += tremptr->veexsum; /* Accumulate external gains */ + tlocptr->veexsum1 += tremptr->veexsum1; +} + +#endif /* BGRAPHBIPARTDFTHREAD */ + +/********************************/ +/* */ +/* The sequential loop routine. */ +/* */ +/********************************/ + +#define BGRAPHBIPARTDFLOOPNAME bgraphBipartDfSeq +#include "bgraph_bipart_df_loop.c" +#undef BGRAPHBIPARTDFLOOPNAME + +/******************************/ +/* */ +/* The threaded loop routine. */ +/* */ +/******************************/ + +#ifdef BGRAPHBIPARTDFTHREAD + +#define BGRAPHBIPARTDFLOOPTHREAD +#define BGRAPHBIPARTDFLOOPNAME bgraphBipartDfThr +#include "bgraph_bipart_df_loop.c" +#undef BGRAPHBIPARTDFLOOPNAME +#undef BGRAPHMAPARTDFLOOPTHREAD + +#endif /* BGRAPHBIPARTDFTHREAD */ + +/******************************/ +/* */ +/* The threaded join routine. */ +/* */ +/******************************/ + +#ifdef BGRAPHBIPARTDFTHREAD + +int +bgraphBipartDfJoin ( +BgraphBipartDfThread * tlocptr, +BgraphBipartDfThread * tremptr) +{ + BgraphBipartDfData * restrict const loopptr = (BgraphBipartDfData *) tlocptr->thrddat.grouptr; + Bgraph * restrict const grafptr = loopptr->grafptr; + Gnum * restrict const frontab = grafptr->frontab; + Gnum fronnbr; + + fronnbr = tremptr->fronnnd - (tremptr->vertbas - grafptr->s.baseval); + memMov (frontab + tlocptr->fronnnd, /* Aggregate frontier array; TODO: we should do differently for large number of threads */ + frontab + (tremptr->vertbas - grafptr->s.baseval), fronnbr * sizeof (Gnum)); + tlocptr->fronnnd += fronnbr; /* Accumulate frontier vertices */ + tlocptr->compload1 += tremptr->compload1; /* Accumulate graph properties */ + tlocptr->compsize1 += tremptr->compsize1; + tlocptr->commloadextn += tremptr->commloadextn; + tlocptr->commloadintn += tremptr->commloadintn; + tlocptr->commgainextn += tremptr->commgainextn; + + return (0); +} + +#endif /* BGRAPHBIPARTDFTHREAD */ + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bgraphBipartDf ( +Bgraph * restrict const grafptr, /*+ Active graph +*/ +const BgraphBipartDfParam * const paraptr) /*+ Method parameters +*/ +{ + BgraphBipartDfData loopdat; + Gnum compload0; + Gnum compload1; + Gnum compsize1; + Gnum commloadintn; + Gnum commloadextn; + Gnum commgainextn; +#ifdef BGRAPHBIPARTDFTHREAD /* Threads can be accepted even when SCOTCH_DETERMINISTIC set */ + int thrdnbr; +#endif /* BGRAPHBIPARTDFTHREAD */ + Gnum fronnbr; + +#ifdef SCOTCH_DEBUG_BGRAPH1 + if ((grafptr->s.flagval & BGRAPHHASANCHORS) == 0) { /* Method valid only if graph has anchors */ + errorPrint ("bgraphBipartDf: graph does not have anchors"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH1 */ + + if (memAllocGroup ((void **) (void *) + &loopdat.difotax, (size_t) (grafptr->s.vertnbr * sizeof (float)), + &loopdat.difntax, (size_t) (grafptr->s.vertnbr * sizeof (float)), NULL) == NULL) { + errorPrint ("bgraphBipartDf: out of memory (1)"); + return (1); + } + + loopdat.grafptr = grafptr; + loopdat.difotax -= grafptr->s.baseval; + loopdat.difntax -= grafptr->s.baseval; + loopdat.passnbr = paraptr->passnbr; + + compload0 = (paraptr->typeval == BGRAPHBIPARTDFTYPEBAL) /* If balanced parts wanted */ + ? grafptr->compload0avg /* Target is average */ + : ( (grafptr->compload0 < grafptr->compload0min) ? grafptr->compload0min : /* Else keep load if not off balance */ + ((grafptr->compload0 > grafptr->compload0max) ? grafptr->compload0max : grafptr->compload0)); + loopdat.vanctab[0] = (float) - compload0; /* Values to be injected to anchor vertices at every iteration */ + loopdat.vanctab[1] = (float) (grafptr->s.velosum - compload0)- BGRAPHBIPARTDFEPSILON; /* Slightly tilt value to add to part 1 */ + +#ifdef BGRAPHBIPARTDFTHREAD /* Threads can be accepted even when SCOTCH_DETERMINISTIC set */ + thrdnbr = SCOTCH_PTHREAD_NUMBER; + + loopdat.abrtval = 0; /* No one wants to abort yet */ + + if (thrdnbr > 1) { + BgraphBipartDfThread * restrict thrdtab; + int thrdnum; + Gnum vertbas; + + if ((thrdtab = memAlloc (thrdnbr * sizeof (BgraphBipartDfThread))) == NULL) { + errorPrint ("bgraphBipartDf: out of memory (2)"); + memFree (loopdat.difotax + grafptr->s.baseval); + return (1); + } + + for (thrdnum = 0, vertbas = grafptr->s.baseval; /* For all threads except the last one */ + thrdnum < (thrdnbr - 1); thrdnum ++) { + thrdtab[thrdnum].vertbas = vertbas; + thrdtab[thrdnum].vertnnd = vertbas += DATASIZE ((grafptr->s.vertnbr - 2), thrdnbr, thrdnum); /* Do not count anchors in distribution */ + } + thrdtab[thrdnum].vertbas = vertbas; + thrdtab[thrdnum].vertnnd = grafptr->s.vertnnd; /* Both anchors will always be on the same thread */ + + threadLaunch (&loopdat, thrdtab, sizeof (BgraphBipartDfThread), + (ThreadLaunchStartFunc) bgraphBipartDfThr, + (ThreadLaunchJoinFunc) bgraphBipartDfJoin, thrdnbr, THREADCANBARRIER | THREADCANREDUCE); + + fronnbr = thrdtab[0].fronnnd; + compload1 = thrdtab[0].compload1; + compsize1 = thrdtab[0].compsize1; + commloadextn = thrdtab[0].commloadextn; + commloadintn = thrdtab[0].commloadintn; + commgainextn = thrdtab[0].commgainextn; + + memFree (thrdtab); /* Free group leader */ + } + else +#endif /* BGRAPHBIPARTDFTHREAD */ + { + BgraphBipartDfThread thrddat; + + thrddat.thrddat.grouptr = &loopdat; + thrddat.vertbas = grafptr->s.baseval; /* Process all vertices, including both anchors */ + thrddat.vertnnd = grafptr->s.vertnnd; +#ifdef BGRAPHBIPARTDFTHREAD + loopdat.thrddat.thrdnbr = 1; /* Thread is thread 0 of 1 */ + thrddat.thrddat.thrdnum = 0; +#endif /* BGRAPHBIPARTDFTHREAD */ + + bgraphBipartDfSeq (&thrddat); + + fronnbr = thrddat.fronnnd; + compload1 = thrddat.compload1; + compsize1 = thrddat.compsize1; + commloadextn = thrddat.commloadextn; + commloadintn = thrddat.commloadintn; + commgainextn = thrddat.commgainextn; + } + + memFree (loopdat.difotax + grafptr->s.baseval); /* Free group leader */ + + grafptr->fronnbr = fronnbr; + grafptr->compload0 = grafptr->s.velosum - compload1; + grafptr->compload0dlt = grafptr->compload0 - grafptr->compload0avg; + grafptr->compsize0 = grafptr->s.vertnbr - compsize1; + grafptr->commload = commloadextn + (commloadintn / 2) * grafptr->domndist; + grafptr->commgainextn = commgainextn; + grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (grafptr) != 0) { + errorPrint ("bgraphBipartDf: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_df.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_df.h new file mode 100644 index 00000000..19a640ea --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_df.h @@ -0,0 +1,126 @@ +/* Copyright 2004,2007,2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_df.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the function **/ +/** declarations for the diffusion scheme **/ +/** bipartitioning method. **/ +/** **/ +/** DATES : # Version 5.0 : from : 09 jan 2007 **/ +/** to 28 may 2007 **/ +/** # Version 5.1 : from : 29 oct 2007 **/ +/** to 28 mar 2011 **/ +/** # Version 6.0 : from : 08 nov 2011 **/ +/** to 20 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/* Small non-zero float value. */ + +#define BGRAPHBIPARTDFEPSILON (1.0F / (float) (GNUMMAX)) + +/*+ Sign masking operator. +*/ + +#define BGRAPHBIPARTDFGNUMSGNMSK(i) (- (Gnum) (((Gunum) (i)) >> (sizeof (Gnum) * 8 - 1))) + +/* +** The type and structure definitions. +*/ + +/*+ Job selection policy types. +*/ + +typedef enum BgraphBipartDfType_ { + BGRAPHBIPARTDFTYPEBAL = 0, /*+ Balance to average +*/ + BGRAPHBIPARTDFTYPEKEEP /*+ Preserve current imbalance +*/ +} BgraphBipartDfType; + +/*+ Method parameters. +*/ + +typedef struct BgraphBipartDfParam_ { + INT passnbr; /*+ Number of passes to do +*/ + BgraphBipartDfType typeval; /*+ Type of balance to reach +*/ +} BgraphBipartDfParam; + +/*+ The loop routine parameter + structure. It contains the + thread-independent data. +*/ + +typedef struct BgraphBipartDfData_ { + ThreadGroupHeader thrddat; + Bgraph * grafptr; /*+ Graph to work on +*/ + float * difntax; /*+ New diffusion value array +*/ + float * difotax; /*+ Old diffusion value array +*/ + INT passnbr; /*+ Number of passes +*/ + Gnum vanctab[2]; /*+ Anchor load arrays +*/ +#ifdef BGRAPHBIPARTDFTHREAD + int abrtval; /*+ Abort value +*/ +#endif /* BGRAPHBIPARTDFTHREAD */ +} BgraphBipartDfData; + +/*+ The thread-specific data block. +*/ + +typedef struct BgraphBipartDfThread_ { + ThreadHeader thrddat; /*+ Thread management data +*/ + Gnum vertbas; /*+ Minimum regular vertex index +*/ + Gnum vertnnd; /*+ After-last regular vertex index +*/ + Gnum fronnnd; /*+ After-last frontier vertex index +*/ + Gnum compload1; /*+ State return values to aggregate +*/ + Gnum compsize1; + Gnum commloadextn; + Gnum commloadintn; + Gnum commgainextn; + float vanctab[2]; /*+ Area for (reducing) contributions to anchors +*/ +#ifdef BGRAPHBIPARTDFTHREAD + Gnum veexsum; /*+ Area for reducing sums of external gains +*/ + Gnum veexsum1; +#endif /* BGRAPHBIPARTDFTHREAD */ +} BgraphBipartDfThread; + +/* +** The function prototypes. +*/ + +#ifndef BGRAPH_BIPART_DF +#define static +#endif + +int bgraphBipartDf (Bgraph * restrict const, const BgraphBipartDfParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_df_loop.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_df_loop.c new file mode 100644 index 00000000..2d0327f2 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_df_loop.c @@ -0,0 +1,371 @@ +/* Copyright 2004,2007,2008,2011-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_df_loop.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a bipartition of **/ +/** a bipartition graph by using a **/ +/** diffusion scheme. **/ +/** **/ +/** NOTES : # This algorithm has been designed to **/ +/** work on band graphs only, for which **/ +/** the two anchor vertices are the two **/ +/** last vertices, the before-last as **/ +/** anchor of part 0, and the last as **/ +/** anchor of part 1. **/ +/** **/ +/** DATES : # Version 5.0 : from : 09 jan 2007 **/ +/** to 10 sep 2007 **/ +/** # Version 5.1 : from : 29 oct 2007 **/ +/** to 27 mar 2011 **/ +/** # Version 6.0 : from : 07 nov 2011 **/ +/** to : 08 aug 2014 **/ +/** **/ +/************************************************************/ + +/****************************/ +/* */ +/* The diffusion subroutine */ +/* pattern. */ +/* */ +/****************************/ + +/* This routine computes the diffusion of two +** liquids on the given part of the bipartition +** graph. +** It returns: +** - void : in all cases +*/ + +static +int +BGRAPHBIPARTDFLOOPNAME ( +BgraphBipartDfThread * restrict thrdptr) /* Thread-dependent data */ +{ + float * restrict ielstax; /* Inverse of edge load sum array */ + float * restrict difotax; /* Old diffusion value array */ + float * restrict difntax; /* New diffusion value array */ + Gnum vertnum; + Gnum fronnum; + Gnum compload0; + Gnum compload1; + Gnum compsize1; + Gnum commloadintn; + Gnum commloadextn; + Gnum commgainextn; + Gnum veexnbr; + Gnum veexval; + Gnum veexval1; /* Negative external gain to part 1 */ + Gnum veexsum; + Gnum veexsum1; /* Sum of negative external gains */ + Gnum veloval; + float velfval; + INT passnum; + Anum distval; + + BgraphBipartDfData * restrict const loopptr = (BgraphBipartDfData *) thrdptr->thrddat.grouptr; + Bgraph * restrict const grafptr = loopptr->grafptr; + const Gnum vertbas = thrdptr->vertbas; + const Gnum vertnnd = thrdptr->vertnnd; + const Gnum vancnnd = MIN (vertnnd, grafptr->s.vertnnd - 2); /* End of regular vertices */ + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const Gnum * restrict const veextax = grafptr->veextax; + GraphPart * restrict const parttax = grafptr->parttax; +#ifdef BGRAPHBIPARTDFLOOPTHREAD + const int thrdlst = loopptr->thrddat.thrdnbr - 1; +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + + + difotax = loopptr->difotax; + difntax = loopptr->difntax; + + if ((ielstax = memAlloc ((vertnnd - vertbas) * sizeof (float))) == NULL) { /* Allocate here for memory affinity as it is a private array */ + errorPrint (STRINGIFY (BGRAPHBIPARTDFLOOPNAME) ": out of memory"); +#ifdef BGRAPHBIPARTDFLOOPTHREAD + loopptr->abrtval = 1; +#else /* BGRAPHBIPARTDFLOOPTHREAD */ + return (1); +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + } + else { + ielstax -= vertbas; /* Base access to local part of edge load sum array */ + + distval = grafptr->domndist; + veexval = /* Assume no external gains */ + veexval1 = 0; + veexsum = + veexsum1 = 0; + for (vertnum = vertbas; vertnum < vertnnd; vertnum ++) { /* Process all vertices, including anchors */ + Gnum edlosum; + + if (edlotax == NULL) /* If graph doesn't have edge weights */ + edlosum = vendtax[vertnum] - verttax[vertnum]; + else { + Gnum edgenum; + Gnum edgennd; + + for (edgenum = verttax[vertnum], edgennd = vendtax[vertnum], edlosum = 0; + edgenum < edgennd; edgenum ++) + edlosum += edlotax[edgenum]; + } + edlosum *= distval; + + if (veextax != NULL) { + veexval = veextax[vertnum]; + veexval1 = veexval & BGRAPHBIPARTDFGNUMSGNMSK (veexval); /* Get negative external gain only, by superscalar update */ +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (((veexval >= 0) && (veexval1 != 0)) || + ((veexval < 0) && (veexval1 != veexval))) { + errorPrint (STRINGIFY (BGRAPHBIPARTDFLOOPNAME) ": internal error"); +#ifdef BGRAPHBIPARTDFLOOPTHREAD + loopptr->abrtval = 1; +#else /* BGRAPHBIPARTDFLOOPTHREAD */ + return (1); +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + veexsum += veexval; /* Sum all external gains, positive and negative */ + veexsum1 += veexval1; /* Sum all negative gains */ + } + + difotax[vertnum] = 0.0; + ielstax[vertnum] = 1.0F / (float) (edlosum + veexval - 2 * veexval1); /* Add absolute value of veexval */ + } + if (veextax != NULL) { +#ifdef BGRAPHBIPARTDFLOOPTHREAD + thrdptr->veexsum = veexsum; + thrdptr->veexsum1 = veexsum1; + threadReduce (thrdptr, thrdptr, (ThreadReduceFunc) bgraphBipartDfReduceVeex, thrdlst); + veexsum = thrdptr->veexsum; /* Will be useful for thread (thrdlst) only */ + veexsum1 = thrdptr->veexsum1; + + if (thrdptr->thrddat.thrdnum == thrdlst) /* Last thread will handle anchors as root of reduction */ +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + { + ielstax[vertnnd - 2] = 1.0F / (1.0F / ielstax[vertnnd - 2] + (float) (veexsum - veexsum1)); + ielstax[vertnnd - 1] = 1.0F / (1.0F / ielstax[vertnnd - 1] - (float) veexsum1); + } + } +#ifdef BGRAPHBIPARTDFLOOPTHREAD + if (thrdptr->thrddat.thrdnum == thrdlst) /* Last thread will handle anchors as root of reduction */ +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + { + difotax[vertnnd - 2] = loopptr->vanctab[0] * ielstax[vertnnd - 2]; /* Load anchor vertices for first pass */ + difotax[vertnnd - 1] = loopptr->vanctab[1] * ielstax[vertnnd - 1]; + } + } + +#ifdef BGRAPHBIPARTDFLOOPTHREAD + threadBarrier (thrdptr); /* Wait until all array values have been computed */ + + if (loopptr->abrtval == 1) { /* If process alone or some decided to quit */ + if (ielstax != NULL) /* Free local array if necessary */ + memFree (ielstax + vertbas); + return (1); + } +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + + velfval = 1.0F; /* Assume no vertex loads */ + for (passnum = loopptr->passnbr; passnum > 0; passnum --) { /* For all passes */ + Gnum vertnum; + Gnum vancnnt; + float vancval; /* Value to load vertex with if anchor */ + float * difttax; /* Temporary swap value */ + float vancold0 = difotax[grafptr->s.vertnnd - 2]; /* Get for all threads */ + float vancold1 = difotax[grafptr->s.vertnnd - 1]; + float vancval0; /* External gain contributions from regular vertices to anchors */ + float vancval1; + + vancval0 = + vancval1 = 0.0F; + vancval = 0.0F; /* At first vertices are not anchors */ + vertnum = vertbas; /* Start processing regular vertices, then see */ + vancnnt = vancnnd; /* Loop until end of (regular) vertex block */ + while (1) { + for ( ; vertnum < vancnnt; vertnum ++) { + Gnum edgenum; + Gnum edgennd; + float diffval; + + edgenum = verttax[vertnum]; + edgennd = vendtax[vertnum]; + diffval = 0.0F; + if (edlotax != NULL) + for ( ; edgenum < edgennd; edgenum ++) + diffval += difotax[edgetax[edgenum]] * (float) edlotax[edgenum]; + else + for ( ; edgenum < edgennd; edgenum ++) + diffval += difotax[edgetax[edgenum]]; + + diffval *= (float) distval; + + if (veextax != NULL) { + Gnum veexval; + + veexval = veextax[vertnum]; + if (veexval != 0) { + float veextmp; + float vanctmp; + + veextmp = (float) veexval; + vanctmp = veextmp * difotax[vertnum]; + + if (veexval > 0) { /* If external gain links to part 0 */ + diffval += veextmp * vancold0; /* Spread contribution from anchor 0 */ + vancval0 += vanctmp; + } + else { /* If external gain links to part 1 */ + diffval -= veextmp * vancold1; /* Take opposite of negative value */ + vancval1 -= vanctmp; + } + } + } + + diffval += vancval; /* Add anchor contribution if anchor vertex */ + + if (velotax != NULL) + velfval = (float) velotax[vertnum]; + if (diffval >= 0.0F) { + diffval -= velfval; + if (diffval <= 0.0F) + diffval = +BGRAPHBIPARTDFEPSILON; + } + else { + diffval += velfval; + if (diffval >= 0.0F) + diffval = -BGRAPHBIPARTDFEPSILON; + } + if (isnan (diffval)) { /* If overflow occured (because of avalanche process) */ +#ifdef SCOTCH_DEBUG_BGRAPH2 + errorPrintW (STRINGIFY (BGRAPHBIPARTDFLOOPNAME) ": overflow"); +#endif /* SCOTCH_DEBUG_BGRAPH2 */ +#ifdef BGRAPHBIPARTDFLOOPTHREAD + loopptr->abrtval = 1; /* Threads need to halt */ + vertnum = vancnnt; /* Skip regular computations but synchronize */ +#else /* BGRAPHBIPARTDFLOOPTHREAD */ + goto abort; /* Exit this loop without swapping arrays */ +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + } + + difntax[vertnum] = diffval * ielstax[vertnum]; + } + if (vertnum == vancnnd) { /* If first time we reach the end of regular vertices */ + thrdptr->vanctab[0] = vancval0; + thrdptr->vanctab[1] = vancval1; +#ifdef BGRAPHBIPARTDFLOOPTHREAD + if (veextax != NULL) + threadReduce (thrdptr, thrdptr, (ThreadReduceFunc) bgraphBipartDfReduceVanc, thrdlst); +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + } + + if (vertnum >= vertnnd) /* If all vertices processed in range array, exit intermediate infinite loop */ + break; + + vancnnt ++; /* Prepare to go only for one more run, to be done twice */ + vancval = loopptr->vanctab[vertnum - vancnnd] + thrdptr->vanctab[vertnum - vancnnd]; /* Load variable with anchor value */ + } + + difttax = (float *) difntax; /* Swap old and new diffusion arrays */ + difntax = (float *) difotax; /* Casts to prevent IBM compiler from yelling */ + difotax = (float *) difttax; +#ifdef BGRAPHBIPARTDFLOOPTHREAD + threadBarrier (thrdptr); + + if (loopptr->abrtval == 1) { /* If all threads need to abort */ + difotax = (float *) difntax; /* Roll-back to keep last valid array */ + break; + } +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + } +abort : ; + + for (vertnum = vertbas; vertnum < vertnnd; vertnum ++) /* Update part according to diffusion state */ + parttax[vertnum] = (difotax[vertnum] <= 0.0F) ? 0 : 1; + +#ifdef BGRAPHBIPARTDFLOOPTHREAD + threadBarrier (thrdptr); +#endif /* BGRAPHBIPARTDFLOOPTHREAD */ + + veloval = 1; + veexval = 0; + for (vertnum = vertbas, fronnum = vertbas - grafptr->s.baseval, + commloadextn = commgainextn = commloadintn = compload1 = compsize1 = 0; + vertnum < vertnnd; vertnum ++) { + Gnum edgenum; + Gnum partval; + Gnum commload; /* Vertex internal communication load */ + + partval = (Gnum) parttax[vertnum]; + if (velotax != NULL) + veloval = velotax[vertnum]; + if (veextax != NULL) + veexval = veextax[vertnum]; + compsize1 += partval; + compload1 += partval * veloval; + commloadextn += partval * veexval; + commgainextn += (1 - 2 * partval) * veexval; + commload = 0; + if (edlotax != NULL) { + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum partend; + + partend = (Gnum) parttax[edgetax[edgenum]]; + commload += (partval ^ partend) * edlotax[edgenum]; + } + } + else { + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) + commload += partval ^ (Gnum) parttax[edgetax[edgenum]]; + } + commloadintn += commload; /* Internal loads will be added twice */ + if (commload != 0) /* If end vertex is in the other part */ + grafptr->frontab[fronnum ++] = vertnum; /* Then it belongs to the frontier */ + } + thrdptr->fronnnd = fronnum; /* Save state */ + thrdptr->compload1 = compload1; + thrdptr->compsize1 = compsize1; + thrdptr->commloadextn = commloadextn; + thrdptr->commloadintn = commloadintn; + thrdptr->commgainextn = commgainextn; + + memFree (ielstax + vertbas); /* Free local part of (local part of) edge load sum array */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_ex.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_ex.c new file mode 100644 index 00000000..90307f2e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_ex.c @@ -0,0 +1,121 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_ex.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tries to balance the **/ +/** subgraphs of the partition as best as **/ +/** it can. **/ +/** **/ +/** DATES : # Version 2.0 : from : 25 oct 1994 **/ +/** to 03 nov 1994 **/ +/** # Version 3.0 : from : 18 nov 1995 **/ +/** to 18 nov 1995 **/ +/** # Version 3.1 : from : 20 nov 1995 **/ +/** to 29 nov 1995 **/ +/** # Version 3.2 : from : 15 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 01 jun 2001 **/ +/** # Version 4.0 : from : 11 dec 2003 **/ +/** to 11 dec 2003 **/ +/** # Version 5.1 : from : 30 nov 2007 **/ +/** to 30 nov 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes +*/ + +#define BGRAPH_BIPART_EX + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_ex.h" +#include "bgraph_bipart_fm.h" +#include "bgraph_bipart_gg.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bgraphBipartEx ( +Bgraph * restrict const grafptr) +{ + BgraphBipartFmParam parafmdat; /* Parameter area for the Fiduccia-Mattheyses algorithm */ + + if (grafptr->compload0dlt == 0) /* Return if nothing to do */ + return (0); + + parafmdat.movenbr = grafptr->s.vertnbr; + parafmdat.passnbr = ~0; + parafmdat.deltval = 0.0L; /* Exact balance required */ + if (bgraphBipartFm (grafptr, ¶fmdat) != 0) /* Return if error */ + return (1); + + if ((grafptr->s.vertnbr > 1) && /* If graph has several vertices but is completely imbalanced */ + ((grafptr->compload0 == 0) || (grafptr->compload0 == grafptr->s.velosum))) { + BgraphBipartGgParam paraggdat; /* Parameter area for the Greedy Graph Growing algorithm */ + + paraggdat.passnbr = 4; + if (bgraphBipartGg (grafptr, ¶ggdat) != 0) /* Return if error */ + return (1); + } + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (grafptr) != 0) { + errorPrint ("bgraphBipartEx: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_ex.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_ex.h new file mode 100644 index 00000000..bb845973 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_ex.h @@ -0,0 +1,79 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_ex.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the exact-balance post-processing **/ +/** module. **/ +/** **/ +/** DATES : # Version 2.0 : from : 25 oct 1994 **/ +/** to 26 oct 1994 **/ +/** # Version 3.0 : from : 18 nov 1995 **/ +/** to 20 nov 1995 **/ +/** # Version 3.1 : from : 20 nov 1995 **/ +/** to 20 nov 1995 **/ +/** # Version 3.2 : from : 15 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 11 dec 2003 **/ +/** to 11 dec 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ System-defined constants. +*/ + +#define BGRAPHBIPARTEXGAINTABLSUBBITS 1 + +#define BGRAPHBIPARTEXSTATEFREE ((GainLink *) 0) /*+ Vertex in initial state (TRICK: must be 0) +*/ +#define BGRAPHBIPARTEXSTATEUSED ((GainLink *) 1) /*+ Swapped vertex +*/ +#define BGRAPHBIPARTEXSTATELINK ((GainLink *) 2) /*+ Currently in gain table if higher +*/ + +/* +** The function prototypes. +*/ + +#ifndef BGRAPH_BIPART_EX +#define static +#endif + +int bgraphBipartEx (Bgraph * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_fm.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_fm.c new file mode 100644 index 00000000..e3e4e5b7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_fm.c @@ -0,0 +1,1094 @@ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_fm.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module bipartitions an active **/ +/** graph using our improvements of the **/ +/** Fiduccia-Mattheyses heuristics. **/ +/** **/ +/** DATES : # Version 1.0 : from : 30 sep 1993 **/ +/** to 09 oct 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.2 : from : 07 feb 1994 **/ +/** to 15 feb 1994 **/ +/** # Version 1.3 : from : 06 apr 1994 **/ +/** to 30 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 03 nov 1994 **/ +/** # Version 3.1 : from : 06 nov 1995 **/ +/** to 07 jun 1996 **/ +/** # Version 3.2 : from : 21 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 12 mar 1999 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 01 jun 2001 **/ +/** # Version 4.0 : from : 20 dec 2003 **/ +/** to 05 may 2006 **/ +/** # Version 5.0 : from : 24 mar 2008 **/ +/** to : 22 may 2008 **/ +/** # Version 5.1 : from : 30 oct 2008 **/ +/** to : 14 apr 2011 **/ +/** # Version 6.0 : from : 23 fev 2011 **/ +/** to 09 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_BIPART_FM + +#define SCOTCH_TABLE_GAIN + +#include "module.h" +#include "common.h" +#include "fibo.h" +#include "gain.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_fm.h" +#include "bgraph_bipart_gg.h" + +/*********************************/ +/* */ +/* Gain table handling routines. */ +/* */ +/*********************************/ + +#ifdef SCOTCH_TABLE_GAIN + +/* This routine returns the vertex of best gain +** whose swap will keep the balance correct. +** It returns: +** - !NULL : pointer to the vertex. +** - NULL : if no more vertices available. +*/ + +static +BgraphBipartFmVertex * +bgraphBipartFmTablGet ( +BgraphBipartFmTabl * restrict const gainptr, /*+ Gain table +*/ +const Gnum deltcur, /*+ Current imbalance +*/ +const Gnum deltmin, /*+ Minimum imbalance +*/ +const Gnum deltmax) /*+ Maximum imbalance +*/ +{ + GainTabl * tablptr; + BgraphBipartFmVertex * vexxptr; + BgraphBipartFmVertex * vertbest; + Gnum gainbest; + const GainEntr * tablbest; + Gnum deltbest; + + tablptr = *gainptr; + tablbest = tablptr->tend; /* Assume no candidate vertex found yet */ + gainbest = GAINMAX; + vertbest = NULL; + deltbest = deltmax; + + for (vexxptr = (BgraphBipartFmVertex *) gainTablFrst (tablptr); /* Select candidate vertices */ + (vexxptr != NULL) && (vexxptr->gainlink.tabl < tablbest); + vexxptr = (BgraphBipartFmVertex *) gainTablNext (tablptr, &vexxptr->gainlink)) { + Gnum deltnew; + + deltnew = deltcur + vexxptr->compgain; + if ((deltnew >= deltmin) && /* If vertex enforces balance */ + (deltnew <= deltmax)) { + deltnew = abs (deltnew); + if ((vexxptr->commgain < gainbest) || /* And if it gives better gain */ + ((vexxptr->commgain == gainbest) && /* Or if it gives better load */ + (deltnew < deltbest))) { + tablbest = vexxptr->gainlink.tabl; /* Select it */ + gainbest = vexxptr->commgain; + vertbest = vexxptr; + deltbest = deltnew; + } + } + } + + return (vertbest); +} + +#else /* SCOTCH_TABLE_GAIN */ + +/* bgraphBipartFmCmpFunc(a,b) must return a negative +** number if a is "better" than b. The smaller, the +** better. +*/ + +static +int +bgraphBipartFmCmpFunc ( +const FiboNode * const data0ptr, /* TRICK: BgraphBipartFmLink is FIRST in BgraphBipartFmVertex */ +const FiboNode * const data1ptr) +{ + const BgraphBipartFmVertex * const node0ptr = (BgraphBipartFmVertex *) data0ptr; + const BgraphBipartFmVertex * const node1ptr = (BgraphBipartFmVertex *) data1ptr; + + if (node0ptr->commgain < node1ptr->commgain) + return (-1); + if (node0ptr->commgain > node1ptr->commgain) + return (1); + return (0); +} + +static +BgraphBipartFmVertex * +bgraphBipartFmTablGet ( +BgraphBipartFmTabl * restrict const tablptr, /*+ Gain table +*/ +const Gnum deltcur, /*+ Current imbalance +*/ +const Gnum deltmin, /*+ Minimum imbalance +*/ +const Gnum deltmax) /*+ Maximum imbalance +*/ +{ + FiboNode * remoptr; /* List of removed links */ + BgraphBipartFmVertex * vexxptr; + BgraphBipartFmVertex * vertbest; + Gnum gainbest; + Gnum deltbest; + FiboNode * linkptr; /* Pointer to current gain link */ + + gainbest = GAINMAX; + vertbest = NULL; + deltbest = deltmax; + remoptr = NULL; + + while ((linkptr = fiboTreeMin (tablptr)) != NULL) { /* Select candidate vertices */ + Gnum deltnew; + Gnum gainval; /* Separator gain of current link */ + + vexxptr = (BgraphBipartFmVertex *) linkptr; + gainval = vexxptr->commgain; + if (gainval > gainbest) /* If no more interesting vertices, stop searching */ + break; + + fiboTreeDel (tablptr, linkptr); /* Remove vertex link from table */ + linkptr->linkdat.prevptr = remoptr; /* Node has been removed but is not kept */ + remoptr = linkptr; /* It will be chained back afterwards */ + + deltnew = deltcur + vexxptr->compgain; + if ((deltnew >= deltmin) && /* If vertex enforces balance */ + (deltnew <= deltmax)) { + deltnew = abs (deltnew); + if (deltnew <= deltbest) { /* If vertex enforces balance */ + vertbest = vexxptr; + gainbest = gainval; + deltbest = deltnew; + } + } + } + + while (remoptr != NULL) { /* Put back all temporarily removed nodes */ + FiboNode * tempptr; + + tempptr = remoptr; /* Get pointer to node */ + remoptr = remoptr->linkdat.prevptr; /* Find next node */ + fiboTreeAdd (tablptr, tempptr); /* Re-link node */ + } + + return (vertbest); +} + +#endif /* SCOTCH_TABLE_GAIN */ + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bgraphBipartFm ( +Bgraph * restrict const grafptr, /*+ Active graph +*/ +const BgraphBipartFmParam * const paraptr) /*+ Method parameters +*/ +{ + BgraphBipartFmTabl tabldat; /* Gain table */ + BgraphBipartFmTabl * tablptr; /* Pointer to gain table */ + INT passnbr; /* Maximum number of passes to go */ + BgraphBipartFmSave * restrict savetab; /* Pointer to move array */ + Gnum movenbr; /* Number of uneffective moves done */ + Gnum savenbr; /* Number of recorded backtrack moves */ + Gnum mswpnum; /* Current number of recording sweep */ + int moveflag; /* Flag set if useful moves made */ + int swapval; /* Flag set if global swap performed */ + int swapvalbst; /* Recorded swap value for best position */ + Gnum hashsiz; /* Size of hash table */ + Gnum hashmsk; /* Mask for access to hash table */ + Gnum hashnum; /* Hash value */ + BgraphBipartFmVertex * lockptr; /* Linked list of locked vertices */ + BgraphBipartFmVertex * restrict hashtab; /* Extended vertex array */ + Gnum hashmax; + Gnum hashnbr; + void * hashtmp; /* Temporary variable to avoid "restrict" */ + Gnum comploadsum; /* Overall vertex load sum, including fixed */ + Gnum compload0dltmit; /* Theoretical smallest imbalance allowed */ + Gnum compload0dltmat; /* Theoretical largest imbalance allowed */ + Gnum compload0dltmin; /* Smallest imbalance allowed */ + Gnum compload0dltmax; /* Largest imbalance allowed */ + Gnum compload0dltbst; /* Best imbalance value found to date */ + Gnum compload0dlt; /* Current imbalance */ + Gnum compsize0dlt; /* Update of size of part 0 */ + Gnum commgainextn; /* Current external communication gain */ + Gnum commgainextnbst; /* External gain of best recorded position */ + Gnum commload; /* Communication load of current position */ + Gnum commloadbst; /* Best communication load to date */ + Gnum domndist; /* Distance between the two subdomains */ + Gnum fronnbr; + Gnum fronnum; + BgraphBipartFmType typeval; + + const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const Gnum * restrict const veextax = grafptr->veextax; + + comploadsum = grafptr->s.velosum + grafptr->vfixload[0] + grafptr->vfixload[1]; + compload0dltmat = (paraptr->deltval <= 0.0L) ? 0 + : ((Gnum) ((double) comploadsum * paraptr->deltval / + (double) MAX (grafptr->domnwght[0], grafptr->domnwght[1])) + 1); + compload0dltmit = MAX ((grafptr->compload0min - grafptr->compload0avg), - compload0dltmat); + compload0dltmat = MIN ((grafptr->compload0max - grafptr->compload0avg), compload0dltmat); + compload0dltmin = MIN (grafptr->compload0dlt, compload0dltmit); /* Set current maximum distance */ + compload0dltmax = MAX (grafptr->compload0dlt, compload0dltmat); + + typeval = BGRAPHBIPARTFMTYPEBOUNDARY; /* Start by using boundary moves only */ + + if (grafptr->fronnbr == 0) { /* If no current frontier */ + if ((grafptr->compload0dlt >= compload0dltmit) && /* If balance is correct */ + (grafptr->compload0dlt <= compload0dltmat)) + return (0); /* Nothing to do */ + else { /* Imbalance must be fought */ + BgraphBipartGgParam paradat; + + paradat.passnbr = 4; /* Use a standard algorithm */ + if (bgraphBipartGg (grafptr, ¶dat) != 0) /* Return if error */ + return (1); + if (grafptr->fronnbr == 0) /* If new partition has no frontier */ + return (0); /* This algorithm is still useless */ + compload0dltmin = MIN (compload0dltmit, grafptr->compload0dlt); + compload0dltmax = MAX (compload0dltmat, grafptr->compload0dlt); + typeval = BGRAPHBIPARTFMTYPEALL; + } + } + +#ifdef SCOTCH_DEBUG_BGRAPH2 + hashnbr = 2 * grafptr->fronnbr + 1; /* Ensure resizing will be performed, for maximum code coverage */ +#else /* SCOTCH_DEBUG_BGRAPH2 */ + hashnbr = 4 * (grafptr->fronnbr + paraptr->movenbr + grafptr->s.degrmax); +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + if (hashnbr > grafptr->s.vertnbr) + hashnbr = grafptr->s.vertnbr; + + if (typeval == BGRAPHBIPARTFMTYPEALL) /* Take maximum space so that hashmax will fit */ + hashnbr = grafptr->s.vertnbr * 4; + + for (hashsiz = 256; hashsiz < hashnbr; hashsiz <<= 1) ; /* Get upper power of two */ + hashmsk = hashsiz - 1; + hashmax = hashsiz >> 2; + + if (bgraphBipartFmTablInit (&tabldat) != 0) { + errorPrint ("bgraphBipartFm: internal error (1)"); /* Unable to do proper initialization */ + bgraphBipartFmTablExit (&tabldat); + return (1); + } + + tablptr = &tabldat; + if (memAllocGroup ((void **) (void *) + &hashtmp, (size_t) (hashsiz * sizeof (BgraphBipartFmVertex)), + &savetab, (size_t) (hashsiz * sizeof (BgraphBipartFmSave)), NULL) == NULL) { + errorPrint ("bgraphBipartFm: out of memory (1)"); + bgraphBipartFmTablExit (tablptr); + return (1); + } + hashtab = hashtmp; + memSet (hashtab, ~0, hashsiz * sizeof (BgraphBipartFmVertex)); /* Set all vertex numbers to ~0 */ + + domndist = grafptr->domndist; + + if (typeval == BGRAPHBIPARTFMTYPEALL) { + Gnum vertnum; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { /* Set initial gains */ + Gnum veloval; + Gnum hashnum; + Gnum edgenum; + Gnum edloval; + Gnum commcut; + Gnum commgain; + int partval; + int partdlt; + + partval = grafptr->parttax[vertnum]; + + for (edgenum = verttax[vertnum], commcut = commgain = 0, edloval = 1; + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + int partend; + int partdlt; + + vertend = edgetax[edgenum]; + partend = grafptr->parttax[vertend]; + if (edlotax != NULL) + edloval = edlotax[edgenum]; + + partdlt = partval ^ partend; + commcut += partdlt; + commgain += (1 - 2 * partdlt) * edloval; + } + commgain *= domndist; /* Adjust internal gains with respect to external gains */ + partdlt = 2 * partval - 1; + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + + for (hashnum = (vertnum * BGRAPHBIPARTFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != ~0; hashnum = (hashnum + 1) & hashmsk) ; + + hashtab[hashnum].vertnum = vertnum; /* Implicitely set slot as used */ + hashtab[hashnum].partval = partval; + hashtab[hashnum].compgain = partdlt * veloval; + hashtab[hashnum].commgain = (veextax == NULL) ? commgain : (commgain - partdlt * veextax[vertnum]); + hashtab[hashnum].commcut = commcut; + hashtab[hashnum].mswpnum = 0; /* Implicitely set slot as used */ + bgraphBipartFmTablAdd (tablptr, &hashtab[hashnum]); + } + } + else { + for (fronnum = 0, hashnbr = grafptr->fronnbr; /* Set initial gains */ + fronnum < hashnbr; fronnum ++) { + Gnum vertnum; + Gnum veloval; + Gnum hashnum; + Gnum edgenum; + Gnum edloval; + Gnum commcut; + Gnum commgain; + int partval; + int partdlt; + + vertnum = grafptr->frontab[fronnum]; + partval = grafptr->parttax[vertnum]; + + for (edgenum = verttax[vertnum], commcut = commgain = 0, edloval = 1; + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + int partend; + int partdlt; + + vertend = edgetax[edgenum]; + partend = grafptr->parttax[vertend]; + if (edlotax != NULL) + edloval = edlotax[edgenum]; + + partdlt = partval ^ partend; + commcut += partdlt; + commgain += (1 - 2 * partdlt) * edloval; + } + commgain *= domndist; /* Adjust internal gains with respect to external gains */ + partdlt = 2 * partval - 1; + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + + for (hashnum = (vertnum * BGRAPHBIPARTFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != ~0; hashnum = (hashnum + 1) & hashmsk) ; + + hashtab[hashnum].vertnum = vertnum; /* Implicitely set slot as used */ + hashtab[hashnum].partval = partval; + hashtab[hashnum].compgain = partdlt * veloval; + hashtab[hashnum].commgain = (veextax == NULL) ? commgain : (commgain - partdlt * veextax[vertnum]); + hashtab[hashnum].commcut = commcut; + hashtab[hashnum].mswpnum = 0; /* Implicitely set slot as used */ + bgraphBipartFmTablAdd (tablptr, &hashtab[hashnum]); + } + } + + compload0dltbst = grafptr->compload0dlt; + commloadbst = grafptr->commload; + commgainextnbst = grafptr->commgainextn; + swapvalbst = 0; /* No global swap performed yet */ + +#ifdef SCOTCH_DEBUG_BGRAPH2 +#ifdef SCOTCH_DEBUG_BGRAPH3 + if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, 0, compload0dltbst, commloadbst, commgainextnbst) != 0) { + errorPrint ("bgraphBipartFm: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH3 */ +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + passnbr = paraptr->passnbr; /* Set remaining number of passes */ + savenbr = 0; /* For empty backtrack of first pass */ + mswpnum = 0; /* Will be incremented afterwards */ + lockptr = NULL; /* Locked list is empty */ + + do { /* As long as there are improvements */ + BgraphBipartFmVertex * vexxptr; + + while (savenbr -- > 0) { /* Delete exceeding moves */ + Gnum hashnum; + int partval; + + hashnum = savetab[savenbr].hashnum; + partval = savetab[savenbr].partval; + hashtab[hashnum].partval = partval; /* Restore vertex data */ + hashtab[hashnum].compgain = savetab[savenbr].compgain; + hashtab[hashnum].commgain = savetab[savenbr].commgain; + hashtab[hashnum].commcut = savetab[savenbr].commcut; + + if (bgraphBipartFmIsTabl (&hashtab[hashnum])) { /* If vertex is linked */ + bgraphBipartFmTablDel (tablptr, &hashtab[hashnum]); /* Unlink it */ + bgraphBipartFmSetFree (&hashtab[hashnum]); /* Set it as free */ + } + if (bgraphBipartFmIsFree (&hashtab[hashnum]) && (partval == 2)) /* If vertex not locked and in separator */ + bgraphBipartFmTablAdd (tablptr, &hashtab[hashnum]); /* Re-link it */ + } + compload0dlt = compload0dltbst; /* Restore best separator parameters */ + commload = commloadbst; + commgainextn = commgainextnbst; + swapval = swapvalbst; + mswpnum ++; /* Forget all recorded moves */ + +#ifdef SCOTCH_DEBUG_BGRAPH2 +#ifdef SCOTCH_DEBUG_BGRAPH3 + if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, swapval, compload0dlt, commload, commgainextn) != 0) { + errorPrint ("bgraphBipartFm: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH3 */ +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + while (lockptr != NULL) { /* For all vertices in locked list */ + BgraphBipartFmVertex * vexxptr; + + vexxptr = lockptr; /* Unlink vertex from list */ + lockptr = bgraphBipartFmChainNext (vexxptr); + + if ((typeval == BGRAPHBIPARTFMTYPEALL) || (vexxptr->commcut > 0)) /* If vertex has cut edges or should be put anyway */ + bgraphBipartFmTablAdd (tablptr, vexxptr); /* Put it in table */ + else + bgraphBipartFmSetFree (vexxptr); /* Set it free anyway */ + } + + moveflag = 0; /* No useful moves made */ + movenbr = 0; /* No uneffective moves recorded yet */ + savenbr = 0; /* Back up to beginning of table */ + + while ((movenbr < paraptr->movenbr) && /* As long as we can find effective vertices */ + ((vexxptr = (BgraphBipartFmVertex *) bgraphBipartFmTablGet (tablptr, compload0dlt, compload0dltmin, compload0dltmax)) != NULL)) { + Gnum vertnum; /* Number of current vertex */ + int partval; /* Part of current vertex */ + Gnum edgenum; + Gnum edloval; + + bgraphBipartFmTablDel (tablptr, vexxptr); /* Remove it from table */ + bgraphBipartFmSetUsed (vexxptr); /* Mark it as used */ + bgraphBipartFmChain (&lockptr, vexxptr); /* Lock it */ + + vertnum = vexxptr->vertnum; + partval = vexxptr->partval; + + if (vexxptr->mswpnum != mswpnum) { /* If vertex data not yet recorded */ + vexxptr->mswpnum = mswpnum; + savetab[savenbr].hashnum = vexxptr - hashtab; + savetab[savenbr].partval = partval; + savetab[savenbr].compgain = vexxptr->compgain; + savetab[savenbr].commgain = vexxptr->commgain; + savetab[savenbr].commcut = vexxptr->commcut; + savenbr ++; /* One more move recorded */ + } + movenbr ++; /* One more move done */ + + commload += vexxptr->commgain; + compload0dlt += vexxptr->compgain; + if (veextax != NULL) + commgainextn += 2 * (2 * partval - 1) * veextax[vertnum]; + + vexxptr->partval = partval ^ 1; /* Swap vertex first in case neighbors are added */ + vexxptr->compgain = - vexxptr->compgain; + vexxptr->commgain = - vexxptr->commgain; + vexxptr->commcut = vendtax[vertnum] - verttax[vertnum] - vexxptr->commcut; + + edloval = 1; + for (edgenum = verttax[vertnum]; /* (Re-)link neighbors */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* Number of current end neighbor vertex */ + Gnum hashnum; + + vertend = edgetax[edgenum]; + if (edlotax != NULL) + edloval = edlotax[edgenum]; + + for (hashnum = (vertend * BGRAPHBIPARTFMHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + if (hashtab[hashnum].vertnum == vertend) { /* If hash slot found */ + int partdlt; + + if (hashtab[hashnum].mswpnum != mswpnum) { /* If vertex data not yet recorded */ + savetab[savenbr].hashnum = hashnum; /* Record them */ + savetab[savenbr].partval = hashtab[hashnum].partval; + savetab[savenbr].compgain = hashtab[hashnum].compgain; + savetab[savenbr].commgain = hashtab[hashnum].commgain; + savetab[savenbr].commcut = hashtab[hashnum].commcut; + hashtab[hashnum].mswpnum = mswpnum; + savenbr ++; + } + + partdlt = 2 * (partval ^ hashtab[hashnum].partval) - 1; + hashtab[hashnum].commgain += (domndist * 2) * edloval * partdlt; + hashtab[hashnum].commcut -= partdlt; + + if (! bgraphBipartFmIsUsed(&hashtab[hashnum])) { /* If vertex is of use */ + if (bgraphBipartFmIsTabl(&hashtab[hashnum])) { /* If vertex is linked */ + bgraphBipartFmTablDel (tablptr, &hashtab[hashnum]); /* Remove it from table */ + bgraphBipartFmSetFree (&hashtab[hashnum]); /* Mark it as free anyway */ + } + if (hashtab[hashnum].commcut > 0) /* If vertex belongs to the frontier */ + bgraphBipartFmTablAdd (tablptr, &hashtab[hashnum]); /* Re-link it */ + } + break; + } + if (hashtab[hashnum].vertnum == ~0) { /* If hash slot empty */ + Gnum commgain; /* Communication gain of current vertex */ + Gnum commgainold; /* Old communication gain of current vertex */ + Gnum veloval; + Gnum veexval; + int partold; + int partdlt; + + if (hashnbr >= hashmax) { /* If extended vertex table is already full */ + if (bgraphBipartFmResize (&hashtab, &hashmax, &hashmsk, &savetab, savenbr, tablptr, &lockptr) != 0) { + errorPrint ("bgraphBipartFm: out of memory (2)"); + memFree (hashtab); /* Free group leader */ + bgraphBipartFmTablExit (tablptr); + } + for (hashnum = (vertend * BGRAPHBIPARTFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != ~0; hashnum = (hashnum + 1) & hashmsk) ; /* Search for new first free slot */ + } + + if (edlotax != NULL) { /* If graph edges are weighted */ + Gnum edgeend; + + for (edgeend = verttax[vertend], commgainold = 0; /* Compute neighbor edge load sum */ + edgeend < vendtax[vertend]; edgeend ++) + commgainold += edlotax[edgeend]; + commgain = commgainold - 2 * edloval; + } + else { /* Graph edges are not weighted */ + commgainold = vendtax[vertend] - verttax[vertend]; + commgain = commgainold - 2; + } + + veloval = 1; + if (velotax != NULL) + veloval = velotax[vertend]; + veexval = 0; + if (veextax != NULL) + veexval = veextax[vertend]; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (grafptr->parttax[vertend] != (partval ^ swapval)) { + errorPrint ("bgraphBipartFm: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + partold = partval ^ swapval ^ swapvalbst; /* Get part of vertex as in latest accepted configuration */ + partdlt = 2 * partold - 1; /* Compute values to fill save table according to last stable configuration */ + savetab[savenbr].hashnum = hashnum; /* Record initial state of new vertex */ + savetab[savenbr].partval = partold; + savetab[savenbr].compgain = partdlt * veloval; + savetab[savenbr].commgain = commgainold * domndist - (partdlt * veexval); + savetab[savenbr].commcut = 0; + savenbr ++; + + partdlt = 2 * partval - 1; /* Compute values to fill hash table according to current configuration */ + hashtab[hashnum].vertnum = vertend; + hashtab[hashnum].partval = partval; /* It was a neighbor of the moved vertex, in current global swap state */ + hashtab[hashnum].compgain = partdlt * veloval; + hashtab[hashnum].commgain = commgain * domndist - (partdlt * veexval); + hashtab[hashnum].commcut = 1; + hashtab[hashnum].mswpnum = mswpnum; /* Vertex has just been saved */ + hashnbr ++; /* One more vertex in hash table */ + + bgraphBipartFmTablAdd (tablptr, &hashtab[hashnum]); + break; + } + } + } + + if (commload < commloadbst) { /* If move improves the cost */ + compload0dltbst = compload0dlt; /* This move was effective */ + commloadbst = commload; + commgainextnbst = commgainextn; + swapvalbst = swapval; + moveflag = 1; + movenbr = + savenbr = 0; + mswpnum ++; + } else if (commload == commloadbst) { + if (abs (compload0dlt) < abs (compload0dltbst)) { + compload0dltbst = compload0dlt; /* This move was effective */ + commgainextnbst = commgainextn; + swapvalbst = swapval; + moveflag = 1; + movenbr = + savenbr = 0; + mswpnum ++; + } + else if (abs (compload0dlt) == abs (compload0dltbst)) { + compload0dltbst = compload0dlt; /* Forget backtracking */ + commgainextnbst = commgainextn; + swapvalbst = swapval; + savenbr = 0; + mswpnum ++; + } + } + if ((compload0dltmin < compload0dltmit) || /* If must restrict distance bounds */ + (compload0dltmax > compload0dltmat)) { + if ((compload0dlt > compload0dltmin) && /* If we have done something useful */ + (compload0dlt < compload0dltmax)) { + compload0dltmin = MIN (compload0dltmit, compload0dlt); /* Update bounds */ + compload0dltmax = MAX (compload0dltmat, compload0dlt); + compload0dltbst = compload0dlt; /* Record best move done */ + commloadbst = commload; + commgainextnbst = commgainextn; + swapvalbst = swapval; + moveflag = 1; + movenbr = + savenbr = 0; + mswpnum ++; + } + } +#ifdef SCOTCH_DEBUG_BGRAPH2 +#ifdef SCOTCH_DEBUG_BGRAPH3 + if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, swapval, compload0dlt, commload, commgainextn) != 0) { + errorPrint ("bgraphBipartFm: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH3 */ +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + if (commgainextn < 0) { /* If global swap improves gain */ + Gnum compload0dlttmp; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (veextax == NULL) { /* commgainextn should always be 0 if (veextab == NULL) */ + errorPrint ("bgraphBipartFm: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + compload0dlttmp = grafptr->s.velosum - compload0dlt - 2 * grafptr->compload0avg; + if (abs (compload0dlttmp) <= compload0dltmax) { /* If still within bounds, perform actual swapping */ + Gnum hashnum; + + commload += commgainextn; /* Perform global swap */ + commgainextn = - commgainextn; + compload0dlt = compload0dlttmp; + swapval ^= 1; + + for (hashnum = 0; hashnum <= hashmsk; hashnum ++) { /* hashsiz no longer valid after resizing, so use hashmsk */ + Gnum commgain; + + if (hashtab[hashnum].mswpnum == ~0) /* If hash slot not used, skip it */ + continue; + + if (hashtab[hashnum].mswpnum != mswpnum) { /* And vertex data not yet recorded */ + hashtab[hashnum].mswpnum = mswpnum; /* Record them */ + savetab[savenbr].hashnum = hashnum; + savetab[savenbr].partval = hashtab[hashnum].partval; + savetab[savenbr].compgain = hashtab[hashnum].compgain; + savetab[savenbr].commgain = hashtab[hashnum].commgain; + savetab[savenbr].commcut = hashtab[hashnum].commcut; + savenbr ++; + } + + hashtab[hashnum].partval ^= 1; /* Swap the vertex */ + hashtab[hashnum].compgain = - hashtab[hashnum].compgain; + + commgain = veextax[hashtab[hashnum].vertnum]; + if (commgain != 0) { /* If vertex has external cocycle edges */ + hashtab[hashnum].commgain += 2 * (1 - 2 * hashtab[hashnum].partval) * commgain; /* Compute new gain */ + if (bgraphBipartFmIsTabl (&hashtab[hashnum])) { /* If vertex is linked */ + bgraphBipartFmTablDel (tablptr, &hashtab[hashnum]); /* Remove it from table */ + bgraphBipartFmTablAdd (tablptr, &hashtab[hashnum]); /* Re-link it */ + } + } + } + + if ((commload < commloadbst) || /* If move improves cost */ + ((commload == commloadbst) && + (abs (compload0dlt) < abs (compload0dltbst)))) { + compload0dltbst = compload0dlt; /* Then record best move done */ + commloadbst = commload; + commgainextnbst = commgainextn; + swapvalbst = swapval; + moveflag = 1; + movenbr = + savenbr = 0; + mswpnum ++; + } + +#ifdef SCOTCH_DEBUG_BGRAPH2 +#ifdef SCOTCH_DEBUG_BGRAPH3 + if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, swapval, compload0dlt, commload, commgainextn) != 0) { + errorPrint ("bgraphBipartFm: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH3 */ +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + } + } + } + } while ((moveflag != 0) && /* As long as vertices are moved */ + (-- passnbr != 0)); /* And we are allowed to loop (TRICK for negative values) */ + +#ifdef SCOTCH_DEBUG_BGRAPH2 +#ifdef SCOTCH_DEBUG_BGRAPH3 + if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, swapval, compload0dlt, commload, commgainextn) != 0) { + errorPrint ("bgraphBipartFm: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH3 */ +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + compsize0dlt = 0; /* No difference to number of vertices yet */ + if (swapvalbst != 0) { /* If global swap needed */ + Gnum vertnum; + + compsize0dlt = grafptr->s.vertnbr - 2 * grafptr->compsize0; /* Set difference so as to swap all vertices */ + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) /* Swap all vertices in part array */ + grafptr->parttax[vertnum] ^= 1; + } + + while (savenbr -- > 0) { /* Delete exceeding moves */ + Gnum hashnum; + + hashnum = savetab[savenbr].hashnum; + hashtab[hashnum].partval = savetab[savenbr].partval; /* Restore vertex data */ + hashtab[hashnum].commcut = savetab[savenbr].commcut; + } + compload0dlt = compload0dltbst; /* Restore best separator parameters */ + commload = commloadbst; + commgainextn = commgainextnbst; + + for (hashnum = fronnbr = 0; /* Build new frontier */ + hashnum <= hashmsk; hashnum ++) { /* hashsiz no longer valid after resizing, so use hashmsk */ + Gnum vertnum; + int partval; + + vertnum = hashtab[hashnum].vertnum; /* Get vertex data from slot */ + if (vertnum == ~0) + continue; + + partval = hashtab[hashnum].partval; + + if (grafptr->parttax[vertnum] != partval) { /* If vertex part changed */ + grafptr->parttax[vertnum] = partval; /* Set new part value */ + compsize0dlt += (1 - 2 * partval); /* Adjust size of part 0 accordingly */ + } + if (hashtab[hashnum].commcut > 0) /* If vertex belongs to cut */ + grafptr->frontab[fronnbr ++] = vertnum; /* Add vertex to frontier */ + } + grafptr->fronnbr = fronnbr; + grafptr->compload0 = compload0dlt + grafptr->compload0avg; + grafptr->compload0dlt = compload0dlt; + grafptr->compsize0 += compsize0dlt; + grafptr->commload = commload; + grafptr->commgainextn = commgainextn; + grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (grafptr) != 0) { + errorPrint ("bgraphBipartFm: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + memFree (hashtab); /* Free group leader */ + bgraphBipartFmTablExit (tablptr); + + return (0); +} + +/* This routine doubles the size all of the arrays +** involved in handling the hash table and hash +** vertex arrays. +** It returns: +** - 0 : if resizing succeeded. +** - !0 : if out of memory. +*/ + +static +int +bgraphBipartFmResize ( +BgraphBipartFmVertex * restrict * hashtabptr, /*+ Extended vertex array +*/ +Gnum * restrict const hashmaxptr, /*+ Size of vertex array +*/ +Gnum * const hashmskptr, /*+ Pointer to hash table mask +*/ +BgraphBipartFmSave * restrict * savetabptr, /*+ Move array +*/ +const Gnum savenbr, /*+ Number of moves recorded +*/ +BgraphBipartFmTabl * tablptr, /*+ Gain table +*/ +BgraphBipartFmVertex ** const lockptr) /*+ Pointer to locked list +*/ +{ + BgraphBipartFmVertex * restrict hashtab; /* Extended vertex array */ + BgraphBipartFmSave * savetab; /* Move backtracking array */ + BgraphBipartFmSave * saveold; /* Pointer to translated old save array */ + Gnum savenum; + Gnum hashold; /* Size of old hash table (half of new) */ + Gnum hashsiz; + Gnum hashmax; + Gnum hashmsk; + Gnum hashsta; /* Start index of range of hash indices to move */ + Gnum hashend; /* End index of range of hash indices to move */ + Gnum hashnum; + + hashmax = *hashmaxptr << 1; /* Compute new sizes */ + hashold = *hashmaxptr << 2; + hashsiz = *hashmaxptr << 3; + hashmsk = hashsiz - 1; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (sizeof (BgraphBipartFmVertex) < sizeof (BgraphBipartFmSave)) { /* Should always be true */ + errorPrint ("bgraphBipartFmResize: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + if (memReallocGroup ((void *) *hashtabptr, + &hashtab, (size_t) (hashsiz * sizeof (BgraphBipartFmVertex)), + &savetab, (size_t) (hashsiz * sizeof (BgraphBipartFmSave)), NULL) == NULL) { + errorPrint ("bgraphBipartFmResize: out of memory"); + return (1); + } + + saveold = (BgraphBipartFmSave *) ((byte *) hashtab + ((byte *) *savetabptr - (byte *) *hashtabptr)); + for (savenum = savenbr - 1; savenum >= 0; savenum --) { /* Move save array, in reverse order */ + savetab[savenum].commcut = saveold[savenum].commcut; + savetab[savenum].commgain = saveold[savenum].commgain; + savetab[savenum].compgain = saveold[savenum].compgain; + savetab[savenum].partval = saveold[savenum].partval; + savetab[savenum].hashnum = hashtab[saveold[savenum].hashnum].vertnum; /* Temporarily translate from hash index to number */ + } + + *hashtabptr = hashtab; + *hashmaxptr = hashmax; + *hashmskptr = hashmsk; + *savetabptr = savetab; + + memSet (hashtab + hashold, ~0, hashold * sizeof (BgraphBipartFmVertex)); + + bgraphBipartFmTablFree (tablptr); /* Reset gain table */ + *lockptr = NULL; /* Rebuild lock list */ + + for (hashsta = hashold - 1; hashtab[hashsta].vertnum != ~0; hashsta --) ; /* Start index of first segment to reconsider is last empty slot */ + hashend = hashold; /* First segment to reconsider ends at the end of the old array */ + while (hashend != hashsta) { /* For each of the two segments to consider */ + for (hashnum = hashsta; hashnum < hashend; hashnum ++) { /* Re-compute position of vertices in new table */ + Gnum vertnum; + + vertnum = hashtab[hashnum].vertnum; + if (vertnum != ~0) { /* If hash slot used */ + Gnum hashnew; + + for (hashnew = (vertnum * BGRAPHBIPARTFMHASHPRIME) & hashmsk; ; hashnew = (hashnew + 1) & hashmsk) { + if (hashnew == hashnum) /* If hash slot is the same */ + break; /* There is nothing to do */ + if (hashtab[hashnew].vertnum == ~0) { /* If new slot is empty */ +#ifdef SCOTCH_DEBUG_BGRAPH2 + if ((hashnew > hashnum) && (hashnew < hashend)) { /* If vertex is not moved either before its old position or after the end of the segment */ + errorPrint ("bgraphBipartFmResize: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + hashtab[hashnew] = hashtab[hashnum]; /* Copy data to new slot */ + hashtab[hashnum].mswpnum = ~0; /* TRICK: not tested at creation */ + hashtab[hashnum].vertnum = ~0; /* Make old slot empty */ + break; + } + } + + if (bgraphBipartFmIsTabl (&hashtab[hashnew])) /* If vertex was linked, re-link it */ + bgraphBipartFmTablAdd (tablptr, &hashtab[hashnew]); + else if (bgraphBipartFmIsUsed (&hashtab[hashnew])) /* Re-lock used vertices */ + bgraphBipartFmChain (lockptr, &hashtab[hashnew]); /* Lock it */ + } + } + + hashend = hashsta; /* End of second segment to consider is start of first one */ + hashsta = 0; /* Start of second segment is beginning of array */ + } /* After second segment, hashsta = hashend = 0 and loop stops */ + + for (savenum = 0; savenum < savenbr; savenum ++) { + Gnum vertnum; + Gnum hashnum; + + vertnum = savetab[savenum].hashnum; /* Get vertex number temporarily saved */ + for (hashnum = (vertnum * BGRAPHBIPARTFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != vertnum; hashnum = (hashnum + 1) & hashmsk) { +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (hashtab[hashnum].vertnum == ~0) { + errorPrint ("bgraphBipartFmResize: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + } + savetab[savenum].hashnum = hashnum; /* Set new hash table index */ + } + + return (0); +} + +/* This routine checks the consistency of +** the hash structures. +** It returns: +** - 0 : in case of success. +** - !0 : in case of error. +*/ + +#ifdef SCOTCH_DEBUG_BGRAPH3 +static +int +bgraphBipartFmCheck ( +const Bgraph * restrict const grafptr, +const BgraphBipartFmVertex * restrict const hashtab, +const Gnum hashmsk, +const int swapval, +const Gnum compload0dlt, +const Gnum commload, +const Gnum commgainextn) +{ + Gnum domndist; + Gnum hashnum; + Gnum compload0tmp; + Gnum commloaddlttmp; /* Difference between old and current communication load */ + Gnum commloadextndlttmp; + Gnum commgainextntmp; + + domndist = grafptr->domndist; + compload0tmp = (swapval == 0) ? grafptr->compload0 : (grafptr->s.velosum - grafptr->compload0); + commloaddlttmp = 0; /* No difference yet */ + commloadextndlttmp = swapval * grafptr->commgainextn; + commgainextntmp = (1 - 2 * swapval) * grafptr->commgainextn; + for (hashnum = 0; hashnum <= hashmsk; hashnum ++) { /* For all vertex slots */ + Gnum vertnum; + Gnum veloval; + Gnum veexval; + Gnum edgenum; + int partval; + int partold; + Gnum commcut; + Gnum commgain; + Gnum commgainextn; + + vertnum = hashtab[hashnum].vertnum; + if (vertnum == ~0) /* If unallocated slot */ + continue; /* Skip to next slot */ + + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + partval = hashtab[hashnum].partval; + if ((partval < 0) || (partval > 1)) { + errorPrint ("bgraphBipartFmCheck: invalid vertex part value"); + return (1); + } + if (hashtab[hashnum].compgain != (2 * partval - 1) * veloval) { + errorPrint ("bgraphBipartFmCheck: invalid vertex computation gain"); + return (1); + } + partold = grafptr->parttax[vertnum] ^ swapval; + veexval = (veextax != NULL) ? veextax[vertnum] : 0; + + compload0tmp += (partval ^ partold) * (1 - 2 * partval) * veloval; + commgainextn = (1 - 2 * partval) * veexval; + commgainextntmp += (partval ^ partold) * commgainextn * 2; + commloadextndlttmp -= (partval ^ partold) * commgainextn; + + commcut = + commgain = 0; + for (edgenum = verttax[vertnum]; /* For all neighbors */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum edloval; + Gnum vertend; + Gnum hashend; + int partend; + int partond; + int partdlt; + + vertend = edgetax[edgenum]; + partond = grafptr->parttax[vertend] ^ swapval; + edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; + + for (hashend = (vertend * BGRAPHBIPARTFMHASHPRIME) & hashmsk; ; hashend = (hashend + 1) & hashmsk) { + if (hashtab[hashend].vertnum == vertend) { /* If end vertex found */ + partend = hashtab[hashend].partval; + break; + } + if (hashtab[hashend].vertnum == ~0) { /* If end vertex not present */ + partend = partond; /* Keep old end part */ + break; + } + } + partdlt = partval ^ partend; + commcut += partdlt; + commgain += (1 - 2 * partdlt) * edloval; + commloaddlttmp += (partdlt - (partold ^ partond)) * edloval; /* Will account twice for difference of edge loads */ + } + if (commcut != hashtab[hashnum].commcut) { + errorPrint ("bgraphBipartFmCheck: invalid vertex cut value"); + return (1); + } + if ((commgain * domndist + commgainextn) != hashtab[hashnum].commgain) { + errorPrint ("bgraphBipartFmCheck: invalid vertex communication gain value"); + return (1); + } + } + if ((compload0tmp - grafptr->compload0avg) != compload0dlt) { + errorPrint ("bgraphBipartFmCheck: invalid computation load"); + return (1); + } + if ((grafptr->commload + (commloaddlttmp / 2) * domndist) != (commload - commloadextndlttmp)) { + errorPrint ("bgraphBipartFmCheck: invalid communication load"); + return (1); + } + if (commgainextntmp != commgainextn) { + errorPrint ("bgraphBipartFmCheck: invalid external communication gain"); + return (1); + } + + return (0); +} +#endif /* SCOTCH_DEBUG_BGRAPH3 */ diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_fm.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_fm.h new file mode 100644 index 00000000..617edccc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_fm.h @@ -0,0 +1,218 @@ +/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_fm.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for our Improved Fiduccia-Mattheyses **/ +/** bipartitioning algorithm. **/ +/** **/ +/** DATES : # Version 1.0 : from : 30 sep 1993 **/ +/** to 09 oct 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.3 : from : 06 apr 1994 **/ +/** to 13 apr 1994 **/ +/** # Version 2.0 : from : 04 jul 1994 **/ +/** to 25 nov 1994 **/ +/** # Version 3.0 : from : 06 jul 1995 **/ +/** to 06 jul 1995 **/ +/** # Version 3.1 : from : 06 nov 1995 **/ +/** to 07 jun 1996 **/ +/** # Version 3.2 : from : 21 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 12 mar 1999 **/ +/** # Version 4.0 : from : 27 aug 2004 **/ +/** to 27 aug 2004 **/ +/** # Version 6.0 : from : 23 fev 2011 **/ +/** to 05 sep 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Prime number for hashing vertex numbers. +*/ + +#define BGRAPHBIPARTFMHASHPRIME 17 /*+ Prime number for hashing +*/ + +/* +** The type and structure definitions. +*/ + +/*+ Move type. +*/ + +typedef enum BgraphBipartFmType_ { + BGRAPHBIPARTFMTYPEALL, /*+ All vertices +*/ + BGRAPHBIPARTFMTYPEBOUNDARY /*+ Boundary vertices only +*/ +} BgraphBipartFmType; + +/*+ This structure holds the method parameters. +*/ + +typedef struct BgraphBipartFmParam_ { + INT movenbr; /*+ Maximum number of uneffective moves that can be done +*/ + INT passnbr; /*+ Number of passes to be performed (-1 : infinite) +*/ + double deltval; /*+ Maximum weight imbalance ratio +*/ + BgraphBipartFmType typeval; /*+ Whether considered vertices are boundary or all +*/ +} BgraphBipartFmParam; + +#ifdef BGRAPH_BIPART_FM /* Private part of the module */ + +/*+ The hash vertex structure. For trick + reasons, the gain table data structure + must be the first field of the structure. +*/ + +#ifdef SCOTCH_TABLE_GAIN + +typedef GainTabl * BgraphBipartFmTabl; +typedef GainLink BgraphBipartFmLink; + +#else /* SCOTCH_TABLE_GAIN */ + +typedef FiboTree BgraphBipartFmTabl; +typedef FiboNode BgraphBipartFmLink; + +#endif /* SCOTCH_TABLE_GAIN */ + +typedef struct BgraphBipartFmVertex_ { + BgraphBipartFmLink gainlink; /*+ Gain link: FIRST +*/ + Gnum vertnum; /*+ Number of vertex +*/ + int partval; /*+ Vertex part +*/ + Gnum compgain; /*+ Computation gain +*/ + Gnum commgain; /*+ Communication gain +*/ + Gnum commcut; /*+ Cut edges +*/ + Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ +} BgraphBipartFmVertex; + +/*+ The move recording structure. +*/ + +typedef struct BgraphBipartFmSave_ { + Gnum hashnum; /*+ Number of vertex slot +*/ + int partval; /*+ Vertex part +*/ + Gnum compgain; /*+ Computation gain +*/ + Gnum commgain; /*+ Communication gain +*/ + Gnum commcut; /*+ Cut edges +*/ +} BgraphBipartFmSave; + +/* +** The function prototypes. +*/ + +static BgraphBipartFmVertex * bgraphBipartFmTablGet (BgraphBipartFmTabl * restrict const, const Gnum, const Gnum, const Gnum); + +static int bgraphBipartFmResize (BgraphBipartFmVertex * restrict *, Gnum * restrict const, Gnum * const, BgraphBipartFmSave * restrict *, const Gnum, BgraphBipartFmTabl * const, BgraphBipartFmVertex ** const); +#ifdef SCOTCH_DEBUG_BGRAPH3 +static int bgraphBipartFmCheck (const Bgraph * restrict const, const BgraphBipartFmVertex * restrict const, const Gnum, const int, const Gnum, const Gnum, const Gnum); +#endif /* SCOTCH_DEBUG_BGRAPH3 */ + +#endif /* BGRAPH_BIPART_FM */ + +int bgraphBipartFm (Bgraph * restrict const, const BgraphBipartFmParam * const); + +/* +** The macro definitions. +*/ + +#ifdef SCOTCH_TABLE_GAIN + +/*+ Gain table subbits. +*/ + +#define BGRAPHBIPARTFMSUBBITS 4 + +/** Gain table vertex status. **/ + +#define BGRAPHBIPARTFMSTATEFREE ((GainLink *) 0) /*+ Vertex in initial state +*/ +#define BGRAPHBIPARTFMSTATEUSED ((GainLink *) 1) /*+ Swapped vertex +*/ +#define BGRAPHBIPARTFMSTATELINK ((GainLink *) 2) /*+ Currently in gain table if higher +*/ + +/*+ Service routines. +*/ + +#define bgraphBipartFmTablInit(t) (((*(t)) = gainTablInit (GAINMAX, BGRAPHBIPARTFMSUBBITS)) == NULL) +#define bgraphBipartFmTablFree(t) gainTablFree (*(t)) +#define bgraphBipartFmTablExit(t) do { \ + if (*(t) != NULL) \ + gainTablExit (*(t)); \ + } while (0) +#define bgraphBipartFmTablAdd(t,v) gainTablAdd ((*(t)), &(v)->gainlink, (v)->commgain) +#define bgraphBipartFmTablDel(t,v) gainTablDel ((*(t)), &(v)->gainlink) +#define bgraphBipartFmIsFree(v) ((v)->gainlink.next == BGRAPHBIPARTFMSTATEFREE) +#define bgraphBipartFmIsTabl(v) ((v)->gainlink.next >= BGRAPHBIPARTFMSTATELINK) +#define bgraphBipartFmIsUsed(v) ((v)->gainlink.next == BGRAPHBIPARTFMSTATEUSED) +#define bgraphBipartFmSetFree(v) do { \ + (v)->gainlink.next = BGRAPHBIPARTFMSTATEFREE; \ + } while (0) +#define bgraphBipartFmSetUsed(v) do { \ + (v)->gainlink.next = BGRAPHBIPARTFMSTATEUSED; \ + } while (0) +#define bgraphBipartFmChain(l,v) do { \ + (v)->gainlink.prev = (GainLink *) *(l); \ + *(l) = (v); \ + } while (0) +#define bgraphBipartFmChainNext(v) ((BgraphBipartFmVertex *) (v)->gainlink.prev) + +#else /* SCOTCH_TABLE_GAIN */ + +/** Gain table vertex status. **/ + +#define BGRAPHBIPARTFMSTATEFREE ((FiboNode *) 0) /*+ Vertex in initial state +*/ +#define BGRAPHBIPARTFMSTATEUSED ((FiboNode *) 1) /*+ Swapped vertex +*/ +#define BGRAPHBIPARTFMSTATELINK ((FiboNode *) 2) /*+ Currently in gain table if higher +*/ + +/*+ Service routines. +*/ + +#define bgraphBipartFmTablInit(t) (fiboTreeInit ((t), bgraphBipartFmCmpFunc)) +#define bgraphBipartFmTablFree(t) fiboTreeFree (t) +#define bgraphBipartFmTablExit(t) fiboTreeExit (t) +#define bgraphBipartFmTablAdd(t,v) fiboTreeAdd ((t), &(v)->gainlink) +#define bgraphBipartFmTablDel(t,v) fiboTreeDel ((t), &(v)->gainlink) +#define bgraphBipartFmIsFree(v) ((v)->gainlink.linkdat.nextptr == BGRAPHBIPARTFMSTATEFREE) +#define bgraphBipartFmIsTabl(v) ((v)->gainlink.linkdat.nextptr >= BGRAPHBIPARTFMSTATELINK) +#define bgraphBipartFmIsUsed(v) ((v)->gainlink.linkdat.nextptr == BGRAPHBIPARTFMSTATEUSED) +#define bgraphBipartFmSetFree(v) do { \ + (v)->gainlink.linkdat.nextptr = BGRAPHBIPARTFMSTATEFREE; \ + } while (0) +#define bgraphBipartFmSetUsed(v) do { \ + (v)->gainlink.linkdat.nextptr = BGRAPHBIPARTFMSTATEUSED; \ + } while (0) +#define bgraphBipartFmChain(l,v) do { \ + (v)->gainlink.linkdat.prevptr = (FiboNode *) *(l); \ + *(l) = (v); \ + } while (0) +#define bgraphBipartFmChainNext(v) ((BgraphBipartFmVertex *) (v)->gainlink.linkdat.prevptr) + +#endif /* SCOTCH_TABLE_GAIN */ diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_gg.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_gg.c new file mode 100644 index 00000000..3b60e955 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_gg.c @@ -0,0 +1,369 @@ +/* Copyright 2004,2007,2009,2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_gg.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Luca SCARANO (v3.1) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module computes a bipartition of **/ +/** a bipartition graph by multiple runs of **/ +/** the greedy graph growing algorithm. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 jan 1996 **/ +/** to 07 jun 1996 **/ +/** # Version 3.2 : from : 20 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 01 jun 2001 **/ +/** # Version 4.0 : from : 09 jan 2004 **/ +/** to 01 sep 2004 **/ +/** # Version 5.0 : from : 02 jan 2007 **/ +/** to 04 feb 2007 **/ +/** # Version 5.1 : from : 21 nov 2007 **/ +/** to 22 feb 2011 **/ +/** # Version 6.0 : from : 23 fev 2011 **/ +/** to 08 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_BIPART_GG + +#define SCOTCH_TABLE_GAIN + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "fibo.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_gg.h" + +/* +** The static variables. +*/ + +static const Gnum bgraphbipartggloadone = 1; +static const Gnum bgraphbipartggloadzero = 0; + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +#ifndef SCOTCH_TABLE_GAIN + +/* bgraphBipartFmCmpFunc(a,b) must return a negative +** number if a is "better" than b. The smaller, the +** better. +*/ + +static +int +bgraphBipartGgCmpFunc ( +const FiboNode * const data0ptr, /* TRICK: BgraphBipartFmLink is FIRST in BgraphBipartFmVertex */ +const FiboNode * const data1ptr) +{ + const BgraphBipartGgVertex * const node0ptr = (BgraphBipartGgVertex *) data0ptr; + const BgraphBipartGgVertex * const node1ptr = (BgraphBipartGgVertex *) data1ptr; + + if (node0ptr->commgain < node1ptr->commgain) + return (-1); + if (node0ptr->commgain > node1ptr->commgain) + return (1); + return (0); +} + +#endif /* SCOTCH_TABLE_GAIN */ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bgraphBipartGg ( +Bgraph * restrict const grafptr, /*+ Active graph +*/ +const BgraphBipartGgParam * const paraptr) /*+ Method parameters +*/ +{ + BgraphBipartGgTabl tabldat; /* Gain table */ + BgraphBipartGgVertex * vexxtax; /* Extended vertex array [norestrict] */ + BgraphBipartGgVertex * vexxptr; /* Pointer to current vertex to swap */ + const Gnum * restrict veexptr; /* Pointer to external gain of current vertex */ + Gnum * restrict permtab; /* Permutation table for finding new roots */ + Gnum permnum; /* Current permutation index */ + const Gnum * restrict velobax; /* Data for handling of optional arrays */ + Gnum velomsk; + const byte * restrict veexbab; /* Un-based array for external gains */ + int veexsiz; + const Gnum * edlobax; /* Pointer to array or dummy value [norestrict] */ + Gnum edlomsk; + byte * restrict flagtax; + Gnum vertnum; + Gnum fronnum; + Gnum compsize1; + Gnum commgainextn; + unsigned int passnum; + Anum domndist; + Anum domndist2; /* Two times domndist */ + + const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * const edlotax = grafptr->s.edlotax; /* [norestrict] */ + const Gnum * restrict const veextax = grafptr->veextax; + + if ((bgraphBipartGgTablInit (&tabldat) != 0) || + ((vexxtax = (BgraphBipartGgVertex *) memAlloc (grafptr->s.vertnbr * sizeof (BgraphBipartGgVertex))) == NULL)) { + errorPrint ("bgraphBipartGg: out of memory (1)"); + bgraphBipartGgTablExit (&tabldat); + return (1); + } + vexxtax -= grafptr->s.baseval; /* Base access to vexxtax */ + permtab = NULL; /* Do not allocate permutation array yet */ + + domndist = grafptr->domndist; + domndist2 = grafptr->domndist * 2; + + if (edlotax == NULL) { /* If graph has no edge weights */ + Gnum vertnum; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum commload; + + commload = (vendtax[vertnum] - verttax[vertnum]) * domndist; + vexxtax[vertnum].commgain0 = (veextax == NULL) ? commload : commload + veextax[vertnum]; + } + + edlobax = &bgraphbipartggloadone; + edlomsk = 0; + } + else { /* Graph has edge weights */ + Gnum vertnum; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum commload; + Gnum edgenum; + + for (edgenum = verttax[vertnum], commload = 0; + edgenum < vendtax[vertnum]; edgenum ++) + commload += edlotax[edgenum]; + commload *= domndist; + + vexxtax[vertnum].commgain0 = (veextax == NULL) ? commload : commload + veextax[vertnum]; + } + + edlobax = edlotax; + edlomsk = ~((Gnum) 0); /* TRICK: assume that ~0 is -1 */ + } + if (grafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ + velobax = &bgraphbipartggloadone; /* In case vertices not weighted (least often) */ + velomsk = 0; + } + else { + velobax = grafptr->s.velotax; + velomsk = ~((Gnum) 0); + } + if (veextax == NULL) { + veexbab = (byte *) &bgraphbipartggloadzero; + veexsiz = 0; + } + else { + veexbab = (byte *) (veextax + grafptr->s.baseval); + veexsiz = sizeof (Gnum); + } + + for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { /* For all passes */ + Gnum vertnum; + Gnum commload; + Gnum compload0dlt; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { /* Reset extended vertex array */ + bgraphBipartGgSetFree (&vexxtax[vertnum]); + vexxtax[vertnum].commgain = vexxtax[vertnum].commgain0; + } + bgraphBipartGgTablFree (&tabldat); /* Reset gain table */ + permnum = 0; /* No permutation built yet */ + compload0dlt = grafptr->s.velosum - grafptr->compload0avg; /* Reset bipartition parameters */ + commload = grafptr->commloadextn0; + + vexxptr = vexxtax + (grafptr->s.baseval + intRandVal (grafptr->s.vertnbr)); /* Randomly select first root vertex */ + + do { /* For all root vertices, till balance */ +#ifdef SCOTCH_TABLE_GAIN + vexxptr->gainlink.next = /* TRICK: allow deletion of root vertex */ + vexxptr->gainlink.prev = (GainLink *) vexxptr; +#ifdef SCOTCH_DEBUG_BGRAPH2 + vexxptr->gainlink.tabl = NULL; +#endif /* SCOTCH_DEBUG_BGRAPH2 */ +#endif /* SCOTCH_TABLE_GAIN */ + + do { /* As long as vertices can be retrieved */ + const Gnum * restrict edgeptr; /* Pointer to current end vertex index */ + const Gnum * restrict edgetnd; /* Pointer to end of edge array */ + const Gnum * restrict edloptr; /* Pointer to current edge load */ + Gnum vertnum; /* Number of current vertex */ + Gnum veloval; /* Load of selected vertex */ + +#ifndef SCOTCH_TABLE_GAIN + if (bgraphBipartGgIsTabl (vexxptr)) +#endif /* SCOTCH_TABLE_GAIN */ + bgraphBipartGgTablDel (&tabldat, vexxptr); /* Remove vertex from table */ + + vertnum = vexxptr - vexxtax; /* Get number of selected vertex */ + veloval = velobax[vertnum & velomsk]; + + if (abs (compload0dlt - veloval) >= abs (compload0dlt)) { /* If swapping would cause imbalance */ +#ifndef SCOTCH_TABLE_GAIN + bgraphBipartGgNext (vexxptr) = BGRAPHBIPARTGGSTATELINK; /* Vertex belongs to frontier of part 0 */ +#endif /* SCOTCH_TABLE_GAIN */ + permnum = grafptr->s.vertnbr; /* Terminate swapping process */ + vexxptr = NULL; + break; + } + + bgraphBipartGgSetUsed (vexxptr); /* Mark it as swapped */ + compload0dlt -= veloval; /* Update partition parameters */ + commload += vexxptr->commgain; + for (edgeptr = edgetax + verttax[vertnum], /* (Re-)link neighbors */ + edgetnd = edgetax + vendtax[vertnum], + edloptr = edlobax + (verttax[vertnum] & edlomsk); + edgeptr < edgetnd; edgeptr ++, edloptr -= edlomsk) { /* TRICK: assume that ~0 is -1 */ + BgraphBipartGgVertex * vexxend; /* Pointer to end vertex of current edge */ + + vexxend = vexxtax + *edgeptr; /* Point to end vertex */ + if (! bgraphBipartGgIsUsed (vexxend)) { /* If vertex needs to be updated */ + vexxend->commgain -= *edloptr * domndist2; /* Adjust gain value */ + if (bgraphBipartGgIsTabl (vexxend)) /* If vertex is linked */ + bgraphBipartGgTablDel (&tabldat, vexxend); /* Remove it from table */ + bgraphBipartGgTablAdd (&tabldat, vexxend); /* (Re-)link vertex in table */ + } + } + } while ((vexxptr = (BgraphBipartGgVertex *) bgraphBipartGgTablFrst (&tabldat)) != NULL); + + if (permnum == 0) { /* If permutation has not been built yet */ + if (permtab == NULL) { /* If permutation array not allocated yet */ + if ((permtab = (Gnum *) memAlloc (grafptr->s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("bgraphBipartGg: out of memory (3)"); + memFree (vexxtax + grafptr->s.baseval); + bgraphBipartGgTablExit (&tabldat); + return (1); + } + intAscn (permtab, grafptr->s.vertnbr, grafptr->s.baseval); /* Initialize based permutation array */ + } + intPerm (permtab, grafptr->s.vertnbr); /* Build random permutation */ + } + for ( ; permnum < grafptr->s.vertnbr; permnum ++) { /* Find next root vertex */ + if (bgraphBipartGgIsFree (&vexxtax[permtab[permnum]])) { + vexxptr = vexxtax + permtab[permnum ++]; + break; + } + } + } while (vexxptr != NULL); + + if ((passnum == 0) || /* If first try */ + ( (grafptr->commload > commload) || /* Or if better solution reached */ + ((grafptr->commload == commload) && + (abs (grafptr->compload0dlt) > abs (compload0dlt))))) { + Gnum vertnum; + + grafptr->compload0dlt = compload0dlt; /* Set graph parameters */ + grafptr->commload = commload; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) /* Copy bipartition state with flag 2 for tabled vertices */ + grafptr->parttax[vertnum] = (bgraphBipartGgIsTabl (&vexxtax[vertnum])) ? 2 : (GraphPart) ((intptr_t) bgraphBipartGgNext (&vexxtax[vertnum])); + } + } + + flagtax = (byte *) (vexxtax + grafptr->s.baseval) - grafptr->s.baseval; /* Re-use extended vertex array for flag array */ + memSet (flagtax + grafptr->s.baseval, ~0, grafptr->s.vertnbr * sizeof (byte)); + for (vertnum = grafptr->s.baseval, veexptr = (Gnum *) veexbab, fronnum = 0, compsize1 = 0, commgainextn = grafptr->commgainextn0; + vertnum < grafptr->s.vertnnd; vertnum ++, veexptr = (Gnum *) ((byte *) veexptr + veexsiz)) { + int partval; + + partval = grafptr->parttax[vertnum]; + if (partval > 1) { /* If vertex belongs to frontier of part 0 */ + Gnum edgenum; + Gnum frontmp; /* Temporary count value for frontier */ + + grafptr->frontab[fronnum ++] = vertnum; /* Then it belongs to the frontier */ + grafptr->parttax[vertnum] = 0; /* And it belongs to part 0 */ + for (edgenum = verttax[vertnum], frontmp = 1; + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = edgetax[edgenum]; + if (grafptr->parttax[vertend] == 1) { /* If vertex belongs to other part */ + frontmp = 0; /* Then first frontier vertex was useful */ + if (flagtax[vertend] != 0) { /* If vertex has not yet been flagged */ + grafptr->frontab[fronnum ++] = vertend; /* Then add it to the frontier */ + flagtax[vertend] = 0; /* Flag it */ + } + } + } + fronnum -= frontmp; /* Remove vertex from frontier if it was useless */ + } + partval &= 1; + compsize1 += partval; + commgainextn -= partval * 2 * *veexptr; + } + grafptr->fronnbr = fronnum; + grafptr->compload0 = grafptr->compload0avg + grafptr->compload0dlt; + grafptr->compsize0 = grafptr->s.vertnbr - compsize1; + grafptr->commgainextn = commgainextn; + grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; + + if (permtab != NULL) /* Free work arrays */ + memFree (permtab); + memFree (vexxtax + grafptr->s.baseval); + bgraphBipartGgTablExit (&tabldat); + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (grafptr) != 0) { + errorPrint ("bgraphBipartGg: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_gg.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_gg.h new file mode 100644 index 00000000..e8ce06e6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_gg.h @@ -0,0 +1,162 @@ +/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_gg.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Luca SCARANO (v3.1) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the function **/ +/** declarations for the greedy graph **/ +/** growing bipartitioning method. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 jan 1996 **/ +/** to 29 apr 1996 **/ +/** # Version 3.2 : from : 20 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 09 jan 2004 **/ +/** to 09 jan 2004 **/ +/** # Version 6.0 : from : 23 fev 2011 **/ +/** to 09 nov 2011 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/** Method parameters. **/ + +typedef struct BgraphBipartGgParam_ { + INT passnbr; /*+ Number of passes to do +*/ +} BgraphBipartGgParam; + +#ifdef BGRAPH_BIPART_GG /* Private part of the module */ + +/*+ The complementary vertex structure. For + trick reasons, the gain table data structure + must be the first field of the structure. +*/ + +#ifdef SCOTCH_TABLE_GAIN + +typedef GainTabl * BgraphBipartGgTabl; +typedef GainLink BgraphBipartGgLink; + +#else /* SCOTCH_TABLE_GAIN */ + +typedef FiboTree BgraphBipartGgTabl; +typedef FiboNode BgraphBipartGgLink; + +#endif /* SCOTCH_TABLE_GAIN */ + +typedef struct BgraphBipartGgVertex_ { + BgraphBipartGgLink gainlink; /*+ Gain link: FIRST +*/ + Gnum commgain0; /*+ Gain if vertex and neighbors in part 0 +*/ + Gnum commgain; /*+ Gain value +*/ +} BgraphBipartGgVertex; + +#endif /* BGRAPH_BIPART_GG */ + +/* +** The function prototypes. +*/ + +#ifndef BGRAPH_BIPART_GG +#define static +#endif + +int bgraphBipartGg (Bgraph * restrict const, const BgraphBipartGgParam * const); + +#undef static + +/* +** The macro definitions. +*/ + +#ifdef SCOTCH_TABLE_GAIN + +/*+ Gain table subbits. +*/ + +#define BGRAPHBIPARTGGGAINTABLSUBBITS 1 + +/** Gain table vertex status. **/ + +#define BGRAPHBIPARTGGSTATEFREE ((GainLink *) 0) /*+ Vertex in initial state (TRICK: must be 0) +*/ +#define BGRAPHBIPARTGGSTATEUSED ((GainLink *) 1) /*+ Swapped vertex +*/ +#define BGRAPHBIPARTGGSTATELINK ((GainLink *) 2) /*+ Currently in gain table if higher +*/ + +/*+ Service routines. +*/ + +#define bgraphBipartGgTablInit(t) (((*(t)) = gainTablInit (GAIN_LINMAX, BGRAPHBIPARTGGGAINTABLSUBBITS)) == NULL) +#define bgraphBipartGgTablFree(t) gainTablFree (*(t)) +#define bgraphBipartGgTablExit(t) do { \ + if (*(t) != NULL) \ + gainTablExit (*(t)); \ + } while (0) +#define bgraphBipartGgTablAdd(t,v) gainTablAdd ((*(t)), &(v)->gainlink, (v)->commgain) +#define bgraphBipartGgTablDel(t,v) gainTablDel ((*(t)), &(v)->gainlink) +#define bgraphBipartGgTablFrst(t) gainTablFrst (*(t)) +#define bgraphBipartGgIsFree(v) ((v)->gainlink.next == BGRAPHBIPARTGGSTATEFREE) +#define bgraphBipartGgIsTabl(v) ((v)->gainlink.next >= BGRAPHBIPARTGGSTATELINK) +#define bgraphBipartGgIsUsed(v) ((v)->gainlink.next == BGRAPHBIPARTGGSTATEUSED) +#define bgraphBipartGgSetFree(v) ((v)->gainlink.next = BGRAPHBIPARTGGSTATEFREE) +#define bgraphBipartGgSetUsed(v) ((v)->gainlink.next = BGRAPHBIPARTGGSTATEUSED) +#define bgraphBipartGgNext(v) ((v)->gainlink.next) + +#else /* SCOTCH_TABLE_GAIN */ + +/*+ Gain table vertex status. +*/ + +#define BGRAPHBIPARTGGSTATEFREE ((FiboNode *) 0) /*+ Vertex in initial state (TRICK: must be 0) +*/ +#define BGRAPHBIPARTGGSTATEUSED ((FiboNode *) 1) /*+ Swapped vertex +*/ +#define BGRAPHBIPARTGGSTATELINK ((FiboNode *) 2) /*+ Currently in gain table if higher +*/ + +/*+ Service routines. +*/ + +#define bgraphBipartGgTablInit(t) (fiboTreeInit ((t), bgraphBipartGgCmpFunc)) +#define bgraphBipartGgTablFree(t) fiboTreeFree (t) +#define bgraphBipartGgTablExit(t) fiboTreeExit (t) +#define bgraphBipartGgTablAdd(t,v) fiboTreeAdd ((t), &(v)->gainlink) +#define bgraphBipartGgTablDel(t,v) fiboTreeDel ((t), &(v)->gainlink) +#define bgraphBipartGgTablFrst(t) fiboTreeMin ((t)) +#define bgraphBipartGgIsFree(v) ((v)->gainlink.linkdat.nextptr == BGRAPHBIPARTGGSTATEFREE) +#define bgraphBipartGgIsTabl(v) ((v)->gainlink.linkdat.nextptr >= BGRAPHBIPARTGGSTATELINK) +#define bgraphBipartGgIsUsed(v) ((v)->gainlink.linkdat.nextptr == BGRAPHBIPARTGGSTATEUSED) +#define bgraphBipartGgSetFree(v) ((v)->gainlink.linkdat.nextptr = BGRAPHBIPARTGGSTATEFREE) +#define bgraphBipartGgSetUsed(v) ((v)->gainlink.linkdat.nextptr = BGRAPHBIPARTGGSTATEUSED) +#define bgraphBipartGgNext(v) ((v)->gainlink.linkdat.nextptr) + +#endif /* SCOTCH_TABLE_GAIN */ diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_gp.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_gp.c new file mode 100644 index 00000000..9e54cf37 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_gp.c @@ -0,0 +1,264 @@ +/* Copyright 2004,2007,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bipart_gp.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module bipartitions an active **/ +/** graph using the Gibbs, Poole, and **/ +/** Stockmeyer algorithm. **/ +/** **/ +/** DATES : # Version 2.0 : from : 02 jun 1994 **/ +/** to 05 oct 1994 **/ +/** # Version 3.1 : from : 02 may 1996 **/ +/** to 02 may 1996 **/ +/** # Version 3.2 : from : 21 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 01 jun 2001 **/ +/** # Version 4.0 : from : 04 nov 2003 **/ +/** to 27 nov 2006 **/ +/** # Version 5.0 : from : 10 sep 2007 **/ +/** to 22 feb 2011 **/ +/** # Version 6.0 : from : 08 aug 2014 **/ +/** to 08 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_BIPART_GP + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_gp.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bgraphBipartGp ( +Bgraph * restrict const grafptr, +const BgraphBipartGpParam * const paraptr) /*+ Method parameters +*/ +{ + BgraphBipartGpQueue queudat; /* Neighbor queue */ + BgraphBipartGpVertex * restrict vexxtax; /* Complementary vertex array */ + Gnum compload0dlt; + Gnum compsize0; + Gnum commloadintn; + Gnum commloadextn; + Gnum commgainextn; + Gnum rootnum; /* Index of potential next root */ + + const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const Gnum * restrict const veextax = grafptr->veextax; + + if (grafptr->compload0 != grafptr->s.velosum) /* If not all vertices already in part 0 */ + bgraphZero (grafptr); /* Move all graph vertices to part 0 */ + + if (memAllocGroup ((void **) (void *) + &queudat.queutab, (size_t) (grafptr->s.vertnbr * sizeof (Gnum)), + &vexxtax, (size_t) (grafptr->s.vertnbr * sizeof (BgraphBipartGpVertex)), NULL) == NULL) { + errorPrint ("bgraphBipartGp: out of memory"); + return (1); + } + + memSet (vexxtax, 0, grafptr->s.vertnbr * sizeof (BgraphBipartGpVertex)); /* Initialize pass numbers */ + vexxtax -= grafptr->s.baseval; + + compsize0 = grafptr->s.vertnbr; /* All vertices in part zero */ + compload0dlt = grafptr->s.velosum - grafptr->compload0avg; + commloadintn = 0; + commloadextn = grafptr->commloadextn0; + commgainextn = grafptr->commgainextn0; + for (rootnum = grafptr->s.baseval; /* Loop on connected components */ + (rootnum < grafptr->s.vertnnd) && (compload0dlt > 0); rootnum ++) { + Gnum passnum; /* Pass number */ + Gnum diamnum; /* Number of current diameter vertex */ + Gnum diamval; /* Current diameter value */ + Gnum diamdeg; /* Degree of current diameter vertex */ + int diamflag; /* Flag set if improvement in diameter between passes */ + + while (vexxtax[rootnum].passnum != 0) /* Find first unallocated vertex */ + rootnum ++; + + for (diamnum = rootnum, diamval = diamdeg = 0, diamflag = 1, passnum = 1; /* Start from root */ + (passnum < paraptr->passnbr) && (diamflag -- != 0); passnum ++) { /* Loop if improvements */ + bgraphBipartGpQueueFlush (&queudat); /* Flush vertex queue */ + bgraphBipartGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ + vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ + vexxtax[diamnum].distval = 0; + + do { /* Loop on vertices in queue */ + Gnum vertnum; + Gnum distval; + Gnum edgenum; + + vertnum = bgraphBipartGpQueueGet (&queudat); /* Get vertex from queue */ + distval = vexxtax[vertnum].distval; /* Get vertex distance */ + + if ((distval > diamval) || /* If vertex increases diameter */ + ((distval == diamval) && /* Or is at diameter distance */ + ((vendtax[vertnum] - verttax[vertnum]) < diamdeg))) { /* With smaller degree */ + diamnum = vertnum; /* Set it as new diameter vertex */ + diamval = distval; + diamdeg = vendtax[vertnum] - verttax[vertnum]; + diamflag = 1; + } + + distval ++; /* Set neighbor distance */ + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* End vertex number */ + + vertend = edgetax[edgenum]; + if (vexxtax[vertend].passnum < passnum) { /* If vertex not yet queued */ + bgraphBipartGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ + vexxtax[vertend].passnum = passnum; + vexxtax[vertend].distval = distval; + } + } + } while (! bgraphBipartGpQueueEmpty (&queudat)); /* As long as queue is not empty */ + } + + bgraphBipartGpQueueFlush (&queudat); /* Flush vertex queue */ + bgraphBipartGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ + vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ + vexxtax[diamnum].distval = 0; + + do { /* Loop on vertices in queue */ + Gnum vertnum; + Gnum veloval; + Gnum veexval; + Gnum distval; + Gnum edgenum; + + vertnum = bgraphBipartGpQueueGet (&queudat); /* Get vertex from queue */ + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + veexval = (veextax != NULL) ? veextax[vertnum] : 0; + grafptr->parttax[vertnum] = 1; /* Move selected vertex to part 1 */ + compsize0 --; + compload0dlt -= veloval; + commloadextn += veexval; + commgainextn -= veexval * 2; + + distval = vexxtax[vertnum].distval + 1; + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* End vertex number */ + + vertend = edgetax[edgenum]; + if (vexxtax[vertend].passnum < passnum) { /* If vertex not yet queued */ + bgraphBipartGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ + vexxtax[vertend].passnum = passnum; + vexxtax[vertend].distval = distval; + } + } + } while ((compload0dlt > 0) && (! bgraphBipartGpQueueEmpty (&queudat))); /* As long as balance not achieved and queue is not empty */ + + if (! bgraphBipartGpQueueEmpty (&queudat)) { /* If frontier non empty */ + Gnum edloval; + Gnum fronnbr; + + fronnbr = 0; /* No frontier yet */ + edloval = 1; /* Assume no edge loads */ + do { + Gnum vertnum; + Gnum edgenum; + + vertnum = bgraphBipartGpQueueGet (&queudat); /* Get vertex from queue */ + grafptr->frontab[fronnbr ++] = vertnum; +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (grafptr->parttax[vertnum] != 0) { + errorPrint ("bgraphBipartGp: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* End vertex number */ + + vertend = edgetax[edgenum]; + if (grafptr->parttax[vertend] == 1) { /* If vertex belongs to other part */ + if (edlotax != NULL) + edloval = edlotax[edgenum]; + commloadintn += edloval; + if (vexxtax[vertend].distval != ~0) { /* If neighbor vertex not already put in frontier */ + grafptr->frontab[fronnbr ++] = vertend; /* Record it in frontier */ + vexxtax[vertend].distval = ~0; /* Set it as recorded */ + } + } + } + } while (! bgraphBipartGpQueueEmpty (&queudat)); + grafptr->fronnbr = fronnbr; + break; /* No need to process rest of graph */ + } /* Else grafptr->fronnbr = 0 anyway */ + } + + grafptr->compload0 = grafptr->compload0avg + compload0dlt; + grafptr->compload0dlt = compload0dlt; + grafptr->compsize0 = compsize0; + grafptr->commload = commloadintn * grafptr->domndist + commloadextn; + grafptr->commgainextn = commgainextn; + grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; + + memFree (queudat.queutab); /* Free group leader */ + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (grafptr) != 0) { + errorPrint ("bgraphBipartGp: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_gp.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_gp.h new file mode 100644 index 00000000..9018e639 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_gp.h @@ -0,0 +1,99 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_gp.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the Gibbs, Poole, and Stockmeyer **/ +/** bipartitioning algorithm. **/ +/** **/ +/** DATES : # Version 2.0 : from : 06 jun 1994 **/ +/** to 28 oct 1994 **/ +/** # Version 3.2 : from : 21 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 01 nov 2003 **/ +/** to 20 aug 2004 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct BgraphBipartGpParam_ { + INT passnbr; /*+ Number of passes to do +*/ +} BgraphBipartGpParam; + +/*+ Complementary vertex structure. +*/ + +typedef struct BgraphBipartGpVertex_ { + Gnum passnum; /*+ Number of pass when vertex selected +*/ + Gnum distval; /*+ Current distance from diameter vertex +*/ +} BgraphBipartGpVertex; + +/*+ Neighbor queue. +*/ + +typedef struct BgraphBipartGpQueue_ { + Gnum headnum; /*+ Head of distance queue +*/ + Gnum tailnum; /*+ Tail of distance queue +*/ + Gnum * queutab; /*+ Array of queue elements +*/ +} BgraphBipartGpQueue; + +/* +** The function prototypes. +*/ + +#ifndef BGRAPH_BIPART_GP +#define static +#endif + +int bgraphBipartGp (Bgraph * restrict const, const BgraphBipartGpParam * const); + +#undef static + +/* +** The macro definitions. +*/ + +#define bgraphBipartGpQueueFlush(queue) ((queue)->headnum = (queue)->tailnum = 0) +#define bgraphBipartGpQueueEmpty(queue) ((queue)->headnum <= (queue)->tailnum) +#define bgraphBipartGpQueuePut(queue,vnum) ((queue)->queutab[(queue)->headnum ++] = (vnum)) +#define bgraphBipartGpQueueGet(queue) ((queue)->queutab[(queue)->tailnum ++]) diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_ml.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_ml.c new file mode 100644 index 00000000..3d8034a9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_ml.c @@ -0,0 +1,352 @@ +/* Copyright 2004,2007-2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_ml.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Luca SCARANO (v3.1) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module bipartitions an active **/ +/** graph using a multi-level scheme. **/ +/** **/ +/** DATES : # Version 3.1 : from : 24 oct 1995 **/ +/** to 19 sep 1996 **/ +/** # Version 3.2 : from : 20 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 12 mar 1999 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 01 jun 2001 **/ +/** # Version 4.0 : from : 12 dec 2003 **/ +/** to 20 mar 2005 **/ +/** # Version 5.1 : from : 28 sep 2008 **/ +/** to 27 mar 2011 **/ +/** # Version 6.0 : from : 09 mar 2011 **/ +/** to 08 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_BIPART_ML + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "graph_coarsen.h" +#include "bgraph.h" +#include "bgraph_bipart_ml.h" +#include "bgraph_bipart_st.h" + +/*********************************************/ +/* */ +/* The coarsening and uncoarsening routines. */ +/* */ +/*********************************************/ + +/* This routine builds a coarser graph from the +** graph that is given on input. The coarser +** graphs differ at this stage from classical +** active graphs as their internal gains are not +** yet computed. +** It returns: +** - 0 : if the coarse graph has been built. +** - 1 : if threshold reached or on error. +*/ + +static +int +bgraphBipartMlCoarsen ( +const Bgraph * const finegrafptr, /*+ Finer graph +*/ +Bgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ +GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ +const BgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum comploadtmp; /* Increase of imbalance range for coarse graph */ + + if (graphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, + paraptr->coarnbr, paraptr->coarrat, NULL, NULL, 0, NULL) != 0) + return (1); /* Return if coarsening failed */ + + if (finegrafptr->veextax != NULL) { /* Merge external gains for coarsened vertices */ + GraphCoarsenMulti * restrict coarmulttax; + Gnum * restrict coarveextax; + Gnum coarvertnum; + + const Gnum * restrict const fineveextax = finegrafptr->veextax; + + if ((coarveextax = (Gnum *) memAlloc (coargrafptr->s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("bgraphBipartMlCoarsen: out of memory"); + graphExit (&coargrafptr->s); /* Only free Graph since veextab not allocated */ + return (1); + } + coarveextax -= coargrafptr->s.baseval; + coarmulttax = *coarmultptr; + coargrafptr->s.flagval |= BGRAPHFREEVEEX; + coargrafptr->veextax = coarveextax; + + for (coarvertnum = coargrafptr->s.baseval; coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { + Gnum finevertnum0; /* First multinode vertex */ + Gnum finevertnum1; /* Second multinode vertex */ + + finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; + finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; + coarveextax[coarvertnum] = (finevertnum0 != finevertnum1) + ? fineveextax[finevertnum0] + fineveextax[finevertnum1] + : fineveextax[finevertnum0]; + } + } + else /* If fine graph does not have external gains */ + coargrafptr->veextax = NULL; /* Coarse graph does not have external gains */ + + coargrafptr->s.flagval |= BGRAPHFREEPART; /* Only part array will have to be freed, as frontier is shared */ + coargrafptr->parttax = NULL; /* Do not allocate partition data yet */ + coargrafptr->frontab = finegrafptr->frontab; /* Use frontier array of finer graph as coarse frontier array */ + + comploadtmp = (finegrafptr->levlnum + 1) + + (Gnum) (((double) MIN ((finegrafptr->compload0max - finegrafptr->compload0avg), + (finegrafptr->compload0avg - finegrafptr->compload0min))) * 0.05); + coargrafptr->compload0min = finegrafptr->compload0min - comploadtmp; /* Only set constant partition parameters as others will be set on uncoarsening */ + coargrafptr->compload0max = finegrafptr->compload0max + comploadtmp; + coargrafptr->compload0avg = finegrafptr->compload0avg; + coargrafptr->commloadextn0 = finegrafptr->commloadextn0; + coargrafptr->commgainextn0 = finegrafptr->commgainextn0; + coargrafptr->domndist = finegrafptr->domndist; + coargrafptr->domnwght[0] = finegrafptr->domnwght[0]; + coargrafptr->domnwght[1] = finegrafptr->domnwght[1]; + coargrafptr->vfixload[0] = finegrafptr->vfixload[0]; + coargrafptr->vfixload[1] = finegrafptr->vfixload[1]; + coargrafptr->levlnum = finegrafptr->levlnum + 1; + + return (0); +} + +/* This routine propagates the bipartition of the +** coarser graph back to the finer graph, according +** to the multinode table of collapsed vertices. +** After the bipartition is propagated, it finishes +** to compute the parameters of the finer graph that +** were not computed at the coarsening stage. +** It returns: +** - 0 : if coarse graph data has been propagated to fine graph. +** - !0 : on error. +*/ + +static +int +bgraphBipartMlUncoarsen ( +Bgraph * restrict const finegrafptr, /*+ Finer graph +*/ +const Bgraph * const coargrafptr, /*+ Coarser graph +*/ +const GraphCoarsenMulti * const coarmulttax) /*+ Pointer to multinode array +*/ +{ + GraphPart * restrict fineparttax; + Gnum finefronnbr; + Gnum finecompsize1; + const GraphPart * restrict coarparttax; + Gnum coarvertnum; + Gnum coarfronnum; + Gnum * restrict coarfrontab; + + const Gnum * restrict const fineverttax = finegrafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const finevendtax = finegrafptr->s.vendtax; + const Gnum * restrict const fineedgetax = finegrafptr->s.edgetax; + + if (finegrafptr->parttax == NULL) { /* If partition array not yet allocated */ + if ((finegrafptr->parttax = (GraphPart *) memAlloc (finegrafptr->s.vertnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("bgraphBipartMlUncoarsen: out of memory"); + return (1); /* Allocated data will be freed along with graph structure */ + } + finegrafptr->parttax -= finegrafptr->s.baseval; + } + + if (coargrafptr == NULL) { /* If no coarse graph provided */ + bgraphZero (finegrafptr); /* Assign all vertices to part 0 */ + return (0); + } + + coarparttax = coargrafptr->parttax; + coarfrontab = coargrafptr->frontab; /* TRICK: also equal to finefrontab */ + fineparttax = finegrafptr->parttax; + finecompsize1 = coargrafptr->s.vertnbr - coargrafptr->compsize0; /* Pre-allocate sizes */ + + for (coarvertnum = coargrafptr->s.baseval; coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { + Gnum finevertnum0; /* First multinode vertex */ + Gnum finevertnum1; /* Second multinode vertex */ + GraphPart partval; + + finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; + finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; + partval = coarparttax[coarvertnum]; + + fineparttax[finevertnum0] = partval; + if (finevertnum0 != finevertnum1) { + fineparttax[finevertnum1] = partval; + finecompsize1 += partval; /* Account for extra vertices created in part 1 */ + } + } + + finegrafptr->compload0 = coargrafptr->compload0; + finegrafptr->compload0dlt = coargrafptr->compload0dlt; + finegrafptr->compsize0 = finegrafptr->s.vertnbr - finecompsize1; + finegrafptr->commload = coargrafptr->commload; + finegrafptr->commgainextn = coargrafptr->commgainextn; + finegrafptr->bbalval = coargrafptr->bbalval; + + for (coarfronnum = 0, finefronnbr = coargrafptr->fronnbr; /* Re-cycle frontier array from coarse to fine graph */ + coarfronnum < coargrafptr->fronnbr; coarfronnum ++) { + Gnum coarvertnum; + Gnum finevertnum0; /* First multinode vertex */ + Gnum finevertnum1; /* Second multinode vertex */ + + coarvertnum = coarfrontab[coarfronnum]; + finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; + finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; + + if (finevertnum0 != finevertnum1) { /* If multinode si made of two distinct vertices */ + GraphPart coarpartval; + Gnum fineedgenum; + + coarpartval = coarparttax[coarvertnum]; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + coarfrontab[coarfronnum] = ~0; +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + for (fineedgenum = fineverttax[finevertnum0]; + fineedgenum < finevendtax[finevertnum0]; fineedgenum ++) { + if (fineparttax[fineedgetax[fineedgenum]] != coarpartval) { /* If first vertex belongs to frontier */ + coarfrontab[coarfronnum] = finevertnum0; /* Record it in lieu of the coarse frontier vertex */ + break; + } + } + if (fineedgenum >= finegrafptr->s.vendtax[finevertnum0]) { /* If first vertex not in frontier */ + coarfrontab[coarfronnum] = finevertnum1; /* Then second vertex must be in frontier */ + continue; /* Skip to next multinode */ + } + + for (fineedgenum = fineverttax[finevertnum1]; /* Check if second vertex belong to frontier too */ + fineedgenum < finevendtax[finevertnum1]; fineedgenum ++) { + if (fineparttax[fineedgetax[fineedgenum]] != coarpartval) { /* If second vertex belongs to frontier */ + coarfrontab[finefronnbr ++] = finevertnum1; /* Record it at the end of the recycled frontier array */ + break; + } + } + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (coarfrontab[coarfronnum] == ~0) { + errorPrint ("bgraphBipartMlUncoarsen: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + } + else /* If coarse vertex is single node */ + coarfrontab[coarfronnum] = finevertnum0; /* Then it belongs to the frontier */ + } + finegrafptr->fronnbr = finefronnbr; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (finegrafptr) != 0) { + errorPrint ("bgraphBipartMlUncoarsen: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + return (0); +} + +/* This routine recursively performs the +** bipartitioning recursion. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +static +int +bgraphBipartMl2 ( +Bgraph * restrict const grafptr, /*+ Active graph +*/ +const BgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ +{ + Bgraph coargrafdat; + GraphCoarsenMulti * coarmultptr; + int o; + + if (bgraphBipartMlCoarsen (grafptr, &coargrafdat, &coarmultptr, paraptr) == 0) { + if (((o = bgraphBipartMl2 (&coargrafdat, paraptr)) == 0) && + ((o = bgraphBipartMlUncoarsen (grafptr, &coargrafdat, coarmultptr)) == 0) && + ((o = bgraphBipartSt (grafptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ + errorPrint ("bgraphBipartMl2: cannot apply ascending strategy"); + bgraphExit (&coargrafdat); + } + else { + if (((o = bgraphBipartMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ + ((o = bgraphBipartSt (grafptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ + errorPrint ("bgraphBipartMl2: cannot apply low strategy"); + } + + return (o); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the multi-level bipartitioning. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bgraphBipartMl ( +Bgraph * restrict const grafptr, /*+ Active graph +*/ +const BgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum levlnum; /* Save value for graph level */ + int o; + + levlnum = grafptr->levlnum; /* Save graph level */ + grafptr->levlnum = 0; /* Initialize coarsening level */ + o = bgraphBipartMl2 (grafptr, paraptr); /* Perform multi-level bipartitioning */ + grafptr->levlnum = levlnum; /* Restore graph level */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_ml.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_ml.h new file mode 100644 index 00000000..2be54652 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_ml.h @@ -0,0 +1,85 @@ +/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_ml.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Luca SCARANO (v3.1) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the multi-level graph bipartitio- **/ +/** ning routines. **/ +/** **/ +/** DATES : # Version 3.1 : from : 24 oct 1995 **/ +/** to 03 jul 1996 **/ +/** # Version 3.2 : from : 20 sep 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 12 dec 2003 **/ +/** to 20 mar 2005 **/ +/** # Version 5.1 : from : 13 jul 2010 **/ +/** to 13 jul 2010 **/ +/** # Version 6.0 : from : 16 apr 2011 **/ +/** to 03 sep 2011 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct BgraphBipartMlParam_ { + INT coarnbr; /*+ Minimum number of vertices +*/ + double coarrat; /*+ Coarsening ratio +*/ + Strat * stratlow; /*+ Strategy at lowest level +*/ + Strat * stratasc; /*+ Strategy at ascending levels +*/ +} BgraphBipartMlParam; + +/* +** The function prototypes. +*/ + +#ifndef BGRAPH_BIPART_ML +#define static +#endif + +static int bgraphBipartMlCoarsen (const Bgraph * const, Bgraph * restrict const, GraphCoarsenMulti * restrict * const, const BgraphBipartMlParam * const); +static int bgraphBipartMlUncoarsen (Bgraph * restrict const, const Bgraph * restrict const, const GraphCoarsenMulti * const); + +int bgraphBipartMl (Bgraph * restrict const, const BgraphBipartMlParam * const); +static int bgraphBipartMl2 (Bgraph * restrict const, const BgraphBipartMlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_st.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_st.c new file mode 100644 index 00000000..cda9fd57 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_st.c @@ -0,0 +1,371 @@ +/* Copyright 2004,2007,2009-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_st.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the strategy and **/ +/** method tables for graph bipartitioning **/ +/** methods. **/ +/** **/ +/** DATES : # Version 3.2 : from : 08 oct 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 12 mar 1999 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 01 jun 2001 **/ +/** # Version 4.0 : from : 12 jan 2004 **/ +/** to 20 aug 2004 **/ +/** # Version 5.0 : from : 27 nov 2006 **/ +/** to 29 may 2007 **/ +/** # Version 5.1 : from : 26 oct 2009 **/ +/** to 15 apr 2011 **/ +/** # Version 6.0 : from : 23 fev 2011 **/ +/** to 19 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_BIPART_ST + +#include "module.h" +#include "common.h" +#include "fibo.h" +#include "gain.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "graph_coarsen.h" +#include "bgraph.h" +#include "bgraph_bipart_bd.h" +#include "bgraph_bipart_df.h" +#include "bgraph_bipart_ex.h" +#include "bgraph_bipart_fm.h" +#include "bgraph_bipart_gg.h" +#include "bgraph_bipart_gp.h" +#include "bgraph_bipart_ml.h" +#include "bgraph_bipart_zr.h" +#include "bgraph_bipart_st.h" + +/* +** The static and global variables. +*/ + +static Bgraph bgraphdummy; /*+ Dummy active graph for offset computations +*/ + +static union { + BgraphBipartBdParam param; + StratNodeMethodData padding; +} bgraphbipartstdefaultbd = { { 3, &stratdummy } }; + +static union { + BgraphBipartDfParam param; + StratNodeMethodData padding; +} bgraphbipartstdefaultdf = { { 40, BGRAPHBIPARTDFTYPEBAL } }; + +static union { /* Default parameters for bipartitioning methods */ + BgraphBipartFmParam param; /* Parameter zone */ + StratNodeMethodData padding; /* To avoid reading out of structure */ +} bgraphbipartstdefaultfm = { { 80, ~0, 0.01L, BGRAPHBIPARTFMTYPEBOUNDARY } }; + +static union { + BgraphBipartGgParam param; + StratNodeMethodData padding; +} bgraphbipartstdefaultgg = { { 5 } }; + +static union { + BgraphBipartGpParam param; + StratNodeMethodData padding; +} bgraphbipartstdefaultgp = { { 5 } }; + +static union { + BgraphBipartMlParam param; + StratNodeMethodData padding; +} bgraphbipartstdefaultml = { { 100, 0.8L, &stratdummy, &stratdummy } }; + +static StratMethodTab bgraphbipartstmethtab[] = { /* Bipartitioning methods array */ + { BGRAPHBIPARTSTMETHBD, "b", bgraphBipartBd, &bgraphbipartstdefaultbd }, + { BGRAPHBIPARTSTMETHDF, "d", bgraphBipartDf, &bgraphbipartstdefaultdf }, + { BGRAPHBIPARTSTMETHEX, "x", bgraphBipartEx, NULL }, + { BGRAPHBIPARTSTMETHFM, "f", bgraphBipartFm, &bgraphbipartstdefaultfm }, + { BGRAPHBIPARTSTMETHGG, "h", bgraphBipartGg, &bgraphbipartstdefaultgg }, + { BGRAPHBIPARTSTMETHGP, "g", bgraphBipartGp, &bgraphbipartstdefaultgp }, + { BGRAPHBIPARTSTMETHML, "m", bgraphBipartMl, &bgraphbipartstdefaultml }, + { BGRAPHBIPARTSTMETHZR, "z", bgraphBipartZr, NULL }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab bgraphbipartstparatab[] = { /* Method parameter list */ + { BGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "bnd", + (byte *) &bgraphbipartstdefaultbd.param, + (byte *) &bgraphbipartstdefaultbd.param.stratbnd, + (void *) &bgraphbipartststratab }, + { BGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "org", + (byte *) &bgraphbipartstdefaultbd.param, + (byte *) &bgraphbipartstdefaultbd.param.stratorg, + (void *) &bgraphbipartststratab }, + { BGRAPHBIPARTSTMETHBD, STRATPARAMINT, "width", + (byte *) &bgraphbipartstdefaultbd.param, + (byte *) &bgraphbipartstdefaultbd.param.distmax, + NULL }, + { BGRAPHBIPARTSTMETHDF, STRATPARAMINT, "pass", + (byte *) &bgraphbipartstdefaultdf.param, + (byte *) &bgraphbipartstdefaultdf.param.passnbr, + NULL }, + { BGRAPHBIPARTSTMETHDF, STRATPARAMCASE, "type", + (byte *) &bgraphbipartstdefaultdf.param, + (byte *) &bgraphbipartstdefaultdf.param.typeval, + (void *) "bk" }, + { BGRAPHBIPARTSTMETHFM, STRATPARAMINT, "move", + (byte *) &bgraphbipartstdefaultfm.param, + (byte *) &bgraphbipartstdefaultfm.param.movenbr, + NULL }, + { BGRAPHBIPARTSTMETHFM, STRATPARAMINT, "pass", + (byte *) &bgraphbipartstdefaultfm.param, + (byte *) &bgraphbipartstdefaultfm.param.passnbr, + NULL }, + { BGRAPHBIPARTSTMETHFM, STRATPARAMDOUBLE, "bal", + (byte *) &bgraphbipartstdefaultfm.param, + (byte *) &bgraphbipartstdefaultfm.param.deltval, + NULL }, + { BGRAPHBIPARTSTMETHFM, STRATPARAMCASE, "type", + (byte *) &bgraphbipartstdefaultfm.param, + (byte *) &bgraphbipartstdefaultfm.param.typeval, + (void *) "ab" }, + { BGRAPHBIPARTSTMETHGG, STRATPARAMINT, "pass", + (byte *) &bgraphbipartstdefaultgg.param, + (byte *) &bgraphbipartstdefaultgg.param.passnbr, + NULL }, + { BGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "asc", + (byte *) &bgraphbipartstdefaultml.param, + (byte *) &bgraphbipartstdefaultml.param.stratasc, + (void *) &bgraphbipartststratab }, + { BGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "low", + (byte *) &bgraphbipartstdefaultml.param, + (byte *) &bgraphbipartstdefaultml.param.stratlow, + (void *) &bgraphbipartststratab }, + { BGRAPHBIPARTSTMETHML, STRATPARAMINT, "vert", + (byte *) &bgraphbipartstdefaultml.param, + (byte *) &bgraphbipartstdefaultml.param.coarnbr, + NULL }, + { BGRAPHBIPARTSTMETHML, STRATPARAMDOUBLE, "rat", + (byte *) &bgraphbipartstdefaultml.param, + (byte *) &bgraphbipartstdefaultml.param.coarrat, + NULL }, + { BGRAPHBIPARTSTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab bgraphbipartstcondtab[] = { /* Active graph condition parameter table */ + { STRATNODECOND, STRATPARAMDOUBLE, "bal", + (byte *) &bgraphdummy, + (byte *) &bgraphdummy.bbalval, + NULL }, + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &bgraphdummy, + (byte *) &bgraphdummy.s.edgenbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &bgraphdummy, + (byte *) &bgraphdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "lmin0", + (byte *) &bgraphdummy, + (byte *) &bgraphdummy.compload0min, + NULL }, + { STRATNODECOND, STRATPARAMINT, "lmax0", + (byte *) &bgraphdummy, + (byte *) &bgraphdummy.compload0max, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &bgraphdummy, + (byte *) &bgraphdummy.s.velosum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load0", + (byte *) &bgraphdummy, + (byte *) &bgraphdummy.compload0, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vert", + (byte *) &bgraphdummy, + (byte *) &bgraphdummy.s.vertnbr, + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab bgraphbipartststratab = { /* Strategy tables for graph bipartitioning methods */ + bgraphbipartstmethtab, + bgraphbipartstparatab, + bgraphbipartstcondtab }; + +/***********************************************/ +/* */ +/* This is the generic bipartitioning routine. */ +/* */ +/***********************************************/ + +/* This routine performs the bipartitioning of +** the given active graph according to the +** given strategy. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bgraphBipartSt ( +Bgraph * restrict const grafptr, /*+ Active graph to bipartition +*/ +const Strat * restrict const strat) /*+ Bipartitioning strategy +*/ +{ + StratTest val; /* Result of condition evaluation */ + BgraphStore savetab[2]; /* Results of the two strategies */ + int o; + int o2; + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (sizeof (Gnum) != sizeof (INT)) { + errorPrint ("bgraphBipartSt: invalid type specification for parser variables"); + return (1); + } + if ((sizeof (BgraphBipartFmParam) > sizeof (StratNodeMethodData)) || + (sizeof (BgraphBipartGgParam) > sizeof (StratNodeMethodData)) || + (sizeof (BgraphBipartMlParam) > sizeof (StratNodeMethodData))) { + errorPrint ("bgraphBipartSt: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ +#ifdef SCOTCH_DEBUG_BGRAPH1 + if (strat->tabl != &bgraphbipartststratab) { + errorPrint ("bgraphBipartSt: invalid parameter (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH1 */ + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + o = bgraphBipartSt (grafptr, strat->data.concat.strat[0]); /* Apply the first strategy */ + if (o == 0) /* If it worked all right */ + o |= bgraphBipartSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ + break; + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((val.typetest != STRATTESTVAL) || + (val.typenode != STRATPARAMLOG)) { + errorPrint ("bgraphBipartSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = bgraphBipartSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = bgraphBipartSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + break; + case STRATNODESELECT : + if (((bgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ + ((bgraphStoreInit (grafptr, &savetab[1])) != 0)) { + errorPrint ("bgraphBipartSt: out of memory"); + bgraphStoreExit (&savetab[0]); + return (1); + } + + bgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */ + o = bgraphBipartSt (grafptr, strat->data.select.strat[0]); /* Apply first strategy */ + bgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ + bgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ + o2 = bgraphBipartSt (grafptr, strat->data.select.strat[1]); /* Apply second strategy */ + + if ((o == 0) || (o2 == 0)) { /* If at least one method did bipartition */ + Gnum compload0; + int b0; + int b1; + + compload0 = grafptr->compload0avg + savetab[0].compload0dlt; + b0 = ((compload0 < grafptr->compload0min) || + (compload0 > grafptr->compload0max)) ? 1 : o; + compload0 = grafptr->compload0avg + savetab[1].compload0dlt; + b1 = ((compload0 < grafptr->compload0min) || + (compload0 > grafptr->compload0max)) ? 1 : o2; + + do { /* Do we want to restore partition 0 ? */ + if (b0 > b1) + break; + if (b0 == b1) { /* If both are valid or invalid */ + if (b0 == 0) { /* If both are valid */ + if ( (savetab[0].commload > grafptr->commload) || /* Compare on cut */ + ((savetab[0].commload == grafptr->commload) && + (abs (savetab[0].compload0dlt) > abs (grafptr->compload0dlt)))) + break; + } + else { /* If both are invalid */ + if ( (abs (savetab[0].compload0dlt) > abs (grafptr->compload0dlt)) || /* Compare on imbalance */ + ((abs (savetab[0].compload0dlt) == abs (grafptr->compload0dlt)) && + (savetab[0].commload > grafptr->commload))) + break; + } + } + + bgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ + } while (0); + } + if (o2 < o) /* o = min(o,o2): if one biparts, then bipart */ + o = o2; /* Else if one stops, then stop, else error */ + + bgraphStoreExit (&savetab[0]); /* Free both save areas */ + bgraphStoreExit (&savetab[1]); + break; +#ifdef SCOTCH_DEBUG_BGRAPH2 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_BGRAPH2 */ + default : +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_BGRAPH2 + default : + errorPrint ("bgraphBipartSt: invalid parameter (2)"); + return (1); +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_st.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_st.h new file mode 100644 index 00000000..0ec8970c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_st.h @@ -0,0 +1,86 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_st.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the strategy and method **/ +/** tables and the generic entry point for **/ +/** the graph bipartitioning methods. **/ +/** **/ +/** DATES : # Version 3.2 : from : 08 oct 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 4.0 : from : 15 jan 2002 **/ +/** to 15 jan 2002 **/ +/** # Version 5.0 : from : 27 nov 2006 **/ +/** to 13 jan 2007 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/** Method types. **/ + +typedef enum BgraphBipartStMethodType_ { + BGRAPHBIPARTSTMETHBD = 0, /*+ Band +*/ + BGRAPHBIPARTSTMETHDF, /*+ Diffusion +*/ + BGRAPHBIPARTSTMETHEX, /*+ Exactifying +*/ + BGRAPHBIPARTSTMETHFM, /*+ Fiduccia-Mattheyses +*/ + BGRAPHBIPARTSTMETHGG, /*+ Greedy Graph Growing +*/ + BGRAPHBIPARTSTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ + BGRAPHBIPARTSTMETHML, /*+ Multi-level (strategy) +*/ + BGRAPHBIPARTSTMETHZR, /*+ Move all to part zero +*/ + BGRAPHBIPARTSTMETHNBR /*+ Number of methods +*/ +} BgraphBipartStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab bgraphbipartststratab; + +/* +** The function prototypes. +*/ + +#ifndef BGRAPH_BIPART_ST +#define static +#endif + +int bgraphBipartSt (Bgraph * restrict const, const Strat * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_zr.c b/scotch_6.0.3/src/libscotch/bgraph_bipart_zr.c new file mode 100644 index 00000000..10b64ee9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_zr.c @@ -0,0 +1,94 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_zr.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module moves all of the vertices **/ +/** to the first subdomain of the **/ +/** bipartition. **/ +/** **/ +/** DATES : # Version 3.2 : from : 23 aug 1996 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 01 jun 2001 **/ +/** # Version 4.0 : from : 01 nov 2003 **/ +/** to 29 may 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_BIPART_ZR + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_zr.h" + +/********************************/ +/* */ +/* Zero bipartitioning routine. */ +/* */ +/********************************/ + +/* This routine moves all the vertices +** of the given graph to the first part. +** It returns: +** - 0 : if bipartitioning could be computed. +** - 1 : on error. +*/ + +int +bgraphBipartZr ( +Bgraph * restrict const grafptr) /*+ Active graph +*/ +{ + if (grafptr->compload0 != grafptr->s.velosum) /* If not all vertices already in part zero */ + bgraphZero (grafptr); + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (grafptr) != 0) { + errorPrint ("bgraphBipartZr: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_BGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_bipart_zr.h b/scotch_6.0.3/src/libscotch/bgraph_bipart_zr.h new file mode 100644 index 00000000..acc12a30 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_bipart_zr.h @@ -0,0 +1,62 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_bipart_zr.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a static mapper. **/ +/** These lines are the data declarations **/ +/** for the move-all-to-first-subdomain **/ +/** bipartitioning module. **/ +/** **/ +/** DATES : # Version 3.2 : from : 23 aug 1996 **/ +/** to 19 oct 1996 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 01 nov 2003 **/ +/** to 01 nov 2003 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef BGRAPH_BIPART_ZR +#define static +#endif + +int bgraphBipartZr (Bgraph * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/bgraph_check.c b/scotch_6.0.3/src/libscotch/bgraph_check.c new file mode 100644 index 00000000..bfd165b6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_check.c @@ -0,0 +1,227 @@ +/* Copyright 2004,2007,2009,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the bipartition **/ +/** graph consistency checking routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 08 jan 2004 **/ +/** to 07 dec 2005 **/ +/** # Version 5.1 : from : 04 oct 2009 **/ +/** to 04 oct 2009 **/ +/** # Version 6.0 : from : 06 oct 2013 **/ +/** to 25 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" + +/*************************/ +/* */ +/* These routines handle */ +/* bipartition graphs. */ +/* */ +/*************************/ + +/* This routine checks the consistency +** of the given bipartition graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +bgraphCheck ( +const Bgraph * restrict const grafptr) +{ + int * restrict flagtax; /* Frontier flag array */ + Gnum vertnum; /* Number of current vertex */ + Gnum fronnum; /* Number of frontier vertex */ + Gnum compload[2]; + Gnum compsize[2]; + Gnum commloadintn; + Gnum commloadextn; + Gnum commgainextn; + Gnum edloval; + int o; + + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const GraphPart * restrict const parttax = grafptr->parttax; + const Gnum * restrict const frontab = grafptr->frontab; + + if (grafptr->compload0avg != (Gnum) (((double) (grafptr->s.velosum + grafptr->vfixload[0] + grafptr->vfixload[1]) * (double) grafptr->domnwght[0]) / + (double) (grafptr->domnwght[0] + grafptr->domnwght[1])) - grafptr->vfixload[0]) { + errorPrint ("bgraphCheck: invalid average load"); + return (1); + } + + if (grafptr->compload0 != (grafptr->compload0avg + grafptr->compload0dlt)) { + errorPrint ("bgraphCheck: invalid load balance"); + return (1); + } + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + if ((parttax[vertnum] | 1) != 1) { /* If part is neither 0 nor 1 */ + errorPrint ("bgraphCheck: invalid part array"); + return (1); + } + } + + if ((grafptr->fronnbr < 0) || + (grafptr->fronnbr > grafptr->s.vertnbr)) { + errorPrint ("bgraphCheck: invalid number of frontier vertices"); + return (1); + } + + if ((flagtax = memAlloc (grafptr->s.vertnbr * sizeof (int))) == NULL) { + errorPrint ("bgraphCheck: out of memory"); + return (1); + } + memSet (flagtax, ~0, grafptr->s.vertnbr * sizeof (int)); + flagtax -= grafptr->s.baseval; + + o = 1; /* Assume failure when checking */ + for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { + Gnum vertnum; + Gnum edgenum; + GraphPart partval; + GraphPart flagval; + + vertnum = frontab[fronnum]; + if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->s.vertnnd)) { + errorPrint ("bgraphCheck: invalid vertex index in frontier array"); + goto fail; + } + if (flagtax[vertnum] != ~0) { + errorPrint ("bgraphCheck: duplicate vertex in frontier array"); + goto fail; + } + flagtax[vertnum] = 0; + partval = parttax[vertnum]; + + for (edgenum = verttax[vertnum], flagval = 0; + edgenum < vendtax[vertnum]; edgenum ++) + flagval |= parttax[edgetax[edgenum]] ^ partval; /* Flag set if neighbor part differs from vertex part */ + + if (flagval == 0) { + errorPrint ("bgraphCheck: invalid vertex in frontier array"); + goto fail; + } + } + + compload[0] = + compload[1] = 0; + compsize[0] = + compsize[1] = 0; + commloadintn = 0; + commloadextn = grafptr->commloadextn0; + commgainextn = 0; + edloval = 1; /* Assume edges are not weighted */ + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum partval; /* Part of current vertex */ + Gnum edgenum; /* Number of current edge */ + Gnum commcut[2]; + + partval = (Gnum) parttax[vertnum]; + if (grafptr->veextax != NULL) { + Gnum veexval; + + veexval = grafptr->veextax[vertnum]; + commloadextn += veexval * partval; + commgainextn += veexval * (1 - 2 * partval); + } + + compload[partval] += (velotax == NULL) ? 1 : velotax[vertnum]; + compsize[partval] ++; + + commcut[partval] = 1; /* Create loop to account for own vertex part */ + commcut[1 - partval] = 0; + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + int partend; + int partdlt; + + if (edlotax != NULL) + edloval = edlotax[edgenum]; + partend = parttax[edgetax[edgenum]]; + partdlt = partval ^ partend; + commcut[partend] ++; + commloadintn += partdlt * edloval * partend; /* Only count loads once, when (partend == 1) */ + } + + if ((commcut[0] != 0) && (commcut[1] != 0) && /* If vertex should be in frontier array */ + (flagtax[vertnum] != 0)) { + errorPrint ("bgraphCheck: vertex should be in frontier array"); + goto fail; + } + } + if (compsize[0] != grafptr->compsize0) { + errorPrint ("bgraphCheck: invalid part size"); + goto fail; + } + if (compload[0] != grafptr->compload0) { + errorPrint ("bgraphCheck: invalid part load"); + goto fail; + } + if ((commloadintn * grafptr->domndist + commloadextn) != grafptr->commload) { + errorPrint ("bgraphCheck: invalid communication loads"); + goto fail; + } + if (commgainextn != grafptr->commgainextn) { + errorPrint ("bgraphCheck: invalid communication gains"); + goto fail; + } + + o = 0; /* Everything turned well */ + +fail : + memFree (flagtax + grafptr->s.baseval); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/bgraph_store.c b/scotch_6.0.3/src/libscotch/bgraph_store.c new file mode 100644 index 00000000..d97c4a49 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/bgraph_store.c @@ -0,0 +1,171 @@ +/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : bgraph_store.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the save data **/ +/** structure handling routines for bipar- **/ +/** tition graphs. **/ +/** **/ +/** DATES : # Version 3.3 : from : 17 oct 1998 **/ +/** to 17 oct 1998 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 16 jun 2004 **/ +/** # Version 5.1 : from : 22 feb 2011 **/ +/** to 22 feb 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define BGRAPH_STORE + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" + +/**********************************/ +/* */ +/* Store graph handling routines. */ +/* */ +/**********************************/ + +/* This routine builds a save structure +** for the given active graph. +** It returns: +** - 0 : if allocation succeeded. +** - !0 : on error. +*/ + +int +bgraphStoreInit ( +const Bgraph * const grafptr, +BgraphStore * const storptr) +{ + Gnum savsize; + + savsize = (grafptr->s.vertnnd - grafptr->s.baseval) * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ + + if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ + errorPrint ("bgraphStoreInit: out of memory"); + return (1); + } + + return (0); +} + +/* This routine frees a save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +bgraphStoreExit ( +BgraphStore * const storptr) +{ + memFree (storptr->datatab); +#ifdef SCOTCH_DEBUG_BGRAPH2 + storptr->datatab = NULL; +#endif /* SCOTCH_DEBUG_BGRAPH2 */ +} + +/* This routine saves partition data from the +** given active graph to the given save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +bgraphStoreSave ( +const Bgraph * const grafptr, +BgraphStore * const storptr) +{ + Gnum vertnbr; /* Number of vertices in graph */ + byte * parttab; /* Pointer to part data save area */ + byte * frontab; /* Pointer to frontier data save area */ + + storptr->fronnbr = grafptr->fronnbr; /* Save partition parameters */ + storptr->compload0dlt = grafptr->compload0dlt; + storptr->compsize0 = grafptr->compsize0; + storptr->commload = grafptr->commload; + storptr->commgainextn = grafptr->commgainextn; + + frontab = storptr->datatab; /* Compute data offsets within save structure */ + parttab = frontab + grafptr->fronnbr * sizeof (Gnum); + + vertnbr = grafptr->s.vertnnd - grafptr->s.baseval; + memCpy (frontab, grafptr->frontab, grafptr->fronnbr * sizeof (Gnum)); + memCpy (parttab, grafptr->parttax + grafptr->s.baseval, vertnbr * sizeof (GraphPart)); +} + +/* This routine updates partition data of the +** given active graph, using the given save graph. +** It returns: +** - VOID : in all cases. +*/ + +void +bgraphStoreUpdt ( +Bgraph * const grafptr, +const BgraphStore * const storptr) +{ + Gnum vertnbr; /* Number of vertices in graph */ + byte * frontab; /* Pointer to frontier data save area */ + byte * parttab; /* Pointer to part data save area */ + + grafptr->fronnbr = storptr->fronnbr; /* Load partition parameters */ + grafptr->compload0 = storptr->compload0dlt + grafptr->compload0avg; + grafptr->compload0dlt = storptr->compload0dlt; + grafptr->compsize0 = storptr->compsize0; + grafptr->commload = storptr->commload; + grafptr->commgainextn = storptr->commgainextn; + grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; + + frontab = storptr->datatab; /* Compute data offsets within save structure */ + parttab = frontab + grafptr->fronnbr * sizeof (Gnum); + + vertnbr = grafptr->s.vertnnd - grafptr->s.baseval; + memCpy (grafptr->frontab, frontab, grafptr->fronnbr * sizeof (Gnum)); + memCpy (grafptr->parttax + grafptr->s.baseval, parttab, vertnbr * sizeof (GraphPart)); + +#ifdef SCOTCH_DEBUG_BGRAPH2 + if (bgraphCheck (grafptr) != 0) + errorPrint ("bgraphStoreUpdt: inconsistent graph data"); +#endif /* SCOTCH_DEBUG_BGRAPH2 */ +} diff --git a/scotch_6.0.3/src/libscotch/comm.c b/scotch_6.0.3/src/libscotch/comm.c new file mode 100644 index 00000000..2e47a89c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/comm.c @@ -0,0 +1,225 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : comm.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the large size **/ +/** communication handling routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 30 jul 2010 **/ +/** to : 30 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMM + +#include "module.h" +#include "common.h" +#include "comm.h" + +/************************************/ +/* */ +/* These routines handle large size */ +/* communications */ +/* */ +/************************************/ + +/* +** +*/ + +int +commAllgatherv ( +void * const senddattab, +const Gnum sendcntnbr, +MPI_Datatype sendtypval, +void * const recvdattab, +const Gnum * const recvcnttab, +const Gnum * const recvdsptab, +MPI_Datatype recvtypval, +MPI_Comm comm) +{ + int * restrict ircvcnttab; + int * restrict ircvdsptab; + int procglbnbr; + int procnum; + int o; + + MPI_Comm_size (comm, &procglbnbr); + if (memAllocGroup ((void **) (void *) + &ircvcnttab, (size_t) (procglbnbr * sizeof (int)), + &ircvdsptab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("commAllgatherv: out of memory"); + return (MPI_ERR_OTHER); + } + + for (procnum = 0; procnum < procglbnbr; procnum ++) { + ircvcnttab[procnum] = (int) recvcnttab[procnum]; + ircvdsptab[procnum] = (int) recvdsptab[procnum]; + if (((Gnum) ircvcnttab[procnum] != recvcnttab[procnum]) || + ((Gnum) ircvdsptab[procnum] != recvdsptab[procnum])) { + errorPrint ("commAllgatherv: communication indices out of range"); + memFree (ircvcnttab); + return (MPI_ERR_ARG); + } + } + + o = MPI_Allgatherv (senddattab, sendcntnbr, sendtypval, + recvdattab, ircvcnttab, ircvdsptab, recvtypval, comm); + + memFree (ircvcnttab); + + return (o); +} + +/* +** +*/ + +int +commGatherv ( +void * const senddattab, +const Gnum sendcntnbr, +MPI_Datatype sendtypval, +void * const recvdattab, +const Gnum * const recvcnttab, +const Gnum * const recvdsptab, +MPI_Datatype recvtypval, +const int rootnum, +MPI_Comm comm) +{ + int * restrict ircvcnttab; + int * restrict ircvdsptab; + int proclocnum; + int o; + + MPI_Comm_rank (comm, &proclocnum); + + ircvcnttab = NULL; + + if (rootnum == proclocnum) { + int procglbnbr; + int procnum; + + MPI_Comm_size (comm, &procglbnbr); + if (memAllocGroup ((void **) (void *) + &ircvcnttab, (size_t) (procglbnbr * sizeof (int)), + &ircvdsptab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("commGatherv: out of memory"); + return (MPI_ERR_OTHER); + } + + for (procnum = 0; procnum < procglbnbr; procnum ++) { + ircvcnttab[procnum] = (int) recvcnttab[procnum]; + ircvdsptab[procnum] = (int) recvdsptab[procnum]; + if (((Gnum) ircvcnttab[procnum] != recvcnttab[procnum]) || + ((Gnum) ircvdsptab[procnum] != recvdsptab[procnum])) { + errorPrint ("commGatherv: communication indices out of range"); + memFree (ircvcnttab); + return (MPI_ERR_ARG); + } + } + } + + o = MPI_Gatherv (senddattab, sendcntnbr, sendtypval, + recvdattab, ircvcnttab, ircvdsptab, recvtypval, rootnum, comm); + + if (ircvcnttab != NULL) + memFree (ircvcnttab); + + return (o); +} + +/* +** +*/ + +int +commScatterv ( +void * const senddattab, +const Gnum * const sendcnttab, +const Gnum * const senddsptab, +MPI_Datatype sendtypval, +void * const recvdattab, +const Gnum recvcntnbr, +MPI_Datatype recvtypval, +const int rootnum, +MPI_Comm comm) +{ + int * restrict isndcnttab; + int * restrict isnddsptab; + int proclocnum; + int o; + + MPI_Comm_rank (comm, &proclocnum); + + isndcnttab = NULL; + + if (rootnum == proclocnum) { + int procglbnbr; + int procnum; + + MPI_Comm_size (comm, &procglbnbr); + if (memAllocGroup ((void **) (void *) + &isndcnttab, (size_t) (procglbnbr * sizeof (int)), + &isnddsptab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("commScatterv: out of memory"); + return (MPI_ERR_OTHER); + } + + for (procnum = 0; procnum < procglbnbr; procnum ++) { + isndcnttab[procnum] = (int) sendcnttab[procnum]; + isnddsptab[procnum] = (int) senddsptab[procnum]; + if (((Gnum) isndcnttab[procnum] != sendcnttab[procnum]) || + ((Gnum) isnddsptab[procnum] != senddsptab[procnum])) { + errorPrint ("commScatterv: communication indices out of range"); + memFree (isndcnttab); + return (MPI_ERR_ARG); + } + } + } + + o = MPI_Scatterv (senddattab, isndcnttab, isnddsptab, sendtypval, + recvdattab, (int) recvcntnbr, recvtypval, rootnum, comm); + + if (isndcnttab != NULL) + memFree (isndcnttab); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/comm.h b/scotch_6.0.3/src/libscotch/comm.h new file mode 100644 index 00000000..326d8937 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/comm.h @@ -0,0 +1,83 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : comm.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for communication functions. **/ +/** **/ +/** DATES : # Version 5.1 : from : 30 jul 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +#define COMM_H + +/* +** The type and structure definitions. +*/ + +#ifndef GNUMMAX /* If dgraph.h not included */ +typedef INT Gnum; /* Vertex and edge numbers */ +typedef UINT Gunum; /* Unsigned type of same width */ +#define GNUMMAX (INTVALMAX) /* Maximum signed Gnum value */ +#define GNUMSTRING INTSTRING /* String to printf a Gnum */ +#endif /* GNUMMAX */ + +/* +** The function prototypes. +*/ + +#ifndef COMM +#define static +#endif + +int commAllgatherv (void * const, const Gnum, MPI_Datatype, void * const, const Gnum * const, const Gnum * const, MPI_Datatype, MPI_Comm); +int commGatherv (void * const, const Gnum, MPI_Datatype, void * const, const Gnum * const, const Gnum * const, MPI_Datatype, const int, MPI_Comm); +int commScatterv (void * const, const Gnum * const, const Gnum * const, MPI_Datatype, void * const, const Gnum, MPI_Datatype, const int, MPI_Comm); + +#undef static + +/* +** The macro definitions. +*/ + +#ifndef COMM +#ifndef INTSIZE64 +#define commAllgatherv MPI_Allgatherv +#define commGatherv MPI_Gatherv +#define commScatterv MPI_Scatterv +#endif /* INTSIZE64 */ +#endif /* COMM */ diff --git a/scotch_6.0.3/src/libscotch/common.c b/scotch_6.0.3/src/libscotch/common.c new file mode 100644 index 00000000..d726bcf3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common.c @@ -0,0 +1,140 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** David GOUDIN **/ +/** Pascal HENON **/ +/** Pierre RAMET **/ +/** Yves SECRETAN (v5.1) **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are common routines used **/ +/** by all modules. **/ +/** **/ +/** DATES : # Version 0.0 : from : 08 may 1998 **/ +/** to 14 sep 1998 **/ +/** # Version 2.0 : from : 27 sep 2004 **/ +/** to 27 sep 2004 **/ +/** # Version 5.1 : from : 27 jun 2010 **/ +/** to 23 nov 2010 **/ +/** # Version 6.0 : from : 21 sep 2013 **/ +/** to 21 sep 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include "common.h" + +/*******************/ +/* */ +/* Timing routine. */ +/* */ +/*******************/ + +double +clockGet (void) +{ +#ifdef MPI_INT + return (MPI_Wtime ()); +#else /* MPI_INT */ +#if defined COMMON_WINDOWS + double res = 0.0; + LARGE_INTEGER fq; + if (QueryPerformanceFrequency (&fq) == 0) { + FILETIME ft; + ULARGE_INTEGER t; + + GetSystemTimeAsFileTime (&ft); + t.LowPart = ft.dwLowDateTime; + t.HighPart = ft.dwHighDateTime; + res = (double) t.QuadPart / 10000000.0; + } + else { + LARGE_INTEGER pc; + + QueryPerformanceCounter (&pc); + res = (double) pc.QuadPart / (double) fq.QuadPart; + } + return (res); +#elif defined COMMON_TIMING_OLD /* Old Unix timing routine */ + struct rusage data; + + getrusage (RUSAGE_SELF, &data); + + return (((double) data.ru_utime.tv_sec + (double) data.ru_stime.tv_sec) + + ((double) data.ru_utime.tv_usec + (double) data.ru_stime.tv_usec) * 1.0e-6L); +#else /* COMMON_TIMING_OLD */ +#if defined (_POSIX_TIMERS) && (_POSIX_TIMERS >= 200112L) + struct timespec tp; + + clock_gettime (CLOCK_REALTIME, &tp); /* Elapsed time */ + + return ((double) tp.tv_sec + (double) tp.tv_nsec * 1.0e-9L); +#else /* defined (_POSIX_TIMERS) && (_POSIX_TIMERS >= 200112L) */ + struct timeval tv; + + gettimeofday (&tv, NULL); + + return ((double) tv.tv_sec + (double) tv.tv_usec * 1.0e-6L); +#endif /* defined (_POSIX_TIMERS) && (_POSIX_TIMERS >= 200112L) */ +#endif /* COMMON_TIMING_OLD */ +#endif /* MPI_INT */ +} + +/***************************/ +/* */ +/* Usage printing routine. */ +/* */ +/***************************/ + +void +usagePrint ( +FILE * const stream, +const char ** const data) +{ + const char ** cptr; + + fprintf (stream, "Usage is:\n"); + for (cptr = data; *cptr != NULL; cptr ++) + fprintf (stream, " %s\n", *cptr); +} diff --git a/scotch_6.0.3/src/libscotch/common.h b/scotch_6.0.3/src/libscotch/common.h new file mode 100644 index 00000000..8ab5bc89 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common.h @@ -0,0 +1,446 @@ +/* Copyright 2004,2007-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common.h **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** David GOUDIN **/ +/** Pascal HENON **/ +/** Pierre RAMET **/ +/** Cedric CHEVALIER (v5.0) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are the common data **/ +/** declarations for all modules. **/ +/** **/ +/** DATES : # Version 0.0 : from : 08 may 1998 **/ +/** to : 08 jan 2001 **/ +/** # Version 1.0 : from : 06 jun 2002 **/ +/** to : 06 jun 2002 **/ +/** # Version 2.0 : from : 13 jun 2005 **/ +/** to : 01 jul 2008 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to : 23 nov 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 28 mar 2014 **/ +/** **/ +/************************************************************/ + +#define COMMON_H + +/* +** The includes. +*/ + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 +#endif /* _XOPEN_SOURCE */ +#ifndef __USE_XOPEN2K +#define __USE_XOPEN2K /* For POSIX pthread_barrier_t */ +#endif /* __USE_XOPEN2K */ + +#include +#include /* Fow Windows _pipe () call */ +#include +#include +#include +#include +#include +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) +#include +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ +#ifdef HAVE_MALLOC_H +#include /* Deprecated, but required on some old systems */ +#endif /* HAVE_MALLOC_H */ +#include +#include +#include /* For the effective calls to clock () */ +#include +#include +#include +#if ((defined COMMON_TIMING_OLD) || (defined HAVE_SYS_TIME_H)) +#include +#endif /* ((defined COMMON_TIMING_OLD) || (defined HAVE_SYS_TIME_H)) */ +#if ((defined COMMON_TIMING_OLD) || (defined HAVE_SYS_RESOURCE_H)) +#include +#endif /* ((defined COMMON_TIMING_OLD) || (defined HAVE_SYS_RESOURCE_H)) */ +#if ((defined COMMON_WINDOWS) || (defined HAVE_WINDOWS_H)) +#include +#endif /* ((defined COMMON_WINDOWS) || (defined HAVE_WINDOWS_H)) */ +#if ((! defined COMMON_WINDOWS) && (! defined HAVE_NOT_UNISTD_H)) +#include +#endif /* ((! defined COMMON_WINDOWS) && (! defined HAVE_NOT_UNISTD_H)) */ + +#ifdef SCOTCH_PTSCOTCH +#include +#endif /* SCOTCH_PTSCOTCH */ + +#if ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) +#include +#endif /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ + +/* +** Working definitions. +*/ + +#ifdef COMMON_MEMORY_TRACE +#define memAlloc(size) memAllocRecord ((size) | 8) +#define memRealloc(ptr,size) memReallocRecord ((ptr), ((size) | 8)) +#define memFree(ptr) (memFreeRecord ((void *) (ptr)), 0) +#else /* COMMON_MEMORY_TRACE */ +#define memAlloc(size) malloc ((size) | 8) /* For platforms which return NULL for malloc(0) */ +#define memRealloc(ptr,size) realloc ((ptr),((size) | 8)) +#define memFree(ptr) (free ((char *) (ptr)), 0) +#endif /* COMMON_MEMORY_TRACE */ + +#define memSet(ptr,val,siz) memset ((void *) (ptr), (val), (siz)) +#define memCpy(dst,src,siz) memcpy ((void *) (dst), (void *) (src), (siz)) +#define memMov(dst,src,siz) memmove ((void *) (dst), (void *) (src), (siz)) + +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) < (y)) ? (y) : (x)) +#define ABS(x) MAX ((x), -(x)) +#define SIGN(x) (((x) < 0) ? -1 : 1) + +/* +** Handling of generic types. +*/ + +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_UINT_T)) +#define UINT32 uint32_t +#else /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_UINT_T)) */ +#define UINT32 u_int32_t +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_UINT_T)) */ + +#ifndef INT /* If type not externally overriden */ +#ifdef INTSIZE32 +#define INT int32_t +#define UINT UINT32 +#define COMM_INT MPI_INTEGER4 +#define INTSTRING "%d" +#else /* INTSIZE32 */ +#ifdef INTSIZE64 +#define INT int64_t +#if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_UINT_T)) +#define UINT uint64_t +#else /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_UINT_T)) */ +#define UINT u_int64_t +#endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_UINT_T)) */ +#define COMM_INT MPI_LONG_LONG +#define INTSTRING "%lld" +#else /* INTSIZE64 */ +#ifdef LONG /* Better not use it */ +#define INT long /* Long integer type */ +#define UINT unsigned long +#define COMM_INT MPI_LONG +#define INTSTRING "%ld" +#else /* LONG */ +#define INT int /* Default integer type */ +#define UINT unsigned int +#define COMM_INT MPI_INT /* Generic MPI integer type */ +#define INTSTRING "%d" +#endif /* LONG */ +#endif /* INTSIZE64 */ +#endif /* INTSIZE32 */ +#endif /* INT */ + +#ifndef IDX /* If type not externally overriden */ +#ifdef IDXSIZE32 +#define IDX int32_t +#else /* IDXSIZE32 */ +#ifdef IDXSIZE64 +#define IDX int64_t +#else /* IDXSIZE64 */ +#define IDX INT +#endif /* IDXSIZE64 */ +#endif /* IDXSIZE32 */ +#endif /* IDX */ + +#ifndef INTSIZEBITS +#define INTSIZEBITS (sizeof (INT) << 3) +#endif /* INTSIZEBITS */ + +#define INTVALMAX ((INT) (((UINT) 1 << (INTSIZEBITS - 1)) - 1)) + +#define byte unsigned char /* Byte type */ +#ifndef BYTE +#define BYTE byte +#endif /* BYTE */ +#ifndef COMM_BYTE +#define COMM_BYTE MPI_BYTE +#endif /* COMM_BYTE */ +#define COMM_PART COMM_BYTE + +/* +** Handling of pseudo-random numbers. +*/ + +/* The pseudo-random state structure. It is + based on a Mersenne twister generator, also + referred to as MT19937. */ + +typedef struct IntRandState_ { + UINT32 randtab[624]; /* State vector */ + int randnum; /* Index value */ +} IntRandState; + +/* +** Handling of flag arrays. +*/ + +#define flagSize(n) (((n) + (sizeof (int) << 3) - 1) / (sizeof (int) << 3)) +#define flagVal(a,n) (((a)[(n) / (sizeof (int) << 3)] >> ((n) & ((sizeof (int) << 3) - 1))) & 1) +#define flagSet(a,n) (a)[(n) / (sizeof (int) << 3)] |= (1 << ((n) & ((sizeof (int) << 3) - 1))) + +/* +** Handling of timers. +*/ + +/** The clock type. **/ + +typedef struct Clock_ { + double time[2]; /*+ The start and accumulated times +*/ +} Clock; + +/* +** Handling of Windows constructs. +*/ + +#if defined COMMON_WINDOWS +#define pipe(fd) _pipe (fd, 32768, O_BINARY) +#endif /* COMMON_WINDOWS */ + +/* +** Handling of threads. +*/ + +/** The thread creation flags **/ + +#define THREADNONE 0x0000 /* Thread capabilities */ + +#define THREADHASBARRIER 0x0001 + +#define THREADCANBARRIER THREADHASBARRIER +#define THREADCANSCAN THREADHASBARRIER +#define THREADCANREDUCE THREADHASBARRIER + +/** The thread barrier structure and routines **/ + +#ifdef COMMON_PTHREAD_BARRIER + +#ifndef PTHREAD_BARRIER_SERIAL_THREAD +#define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif /* PTHREAD_BARRIER_SERIAL_THREAD */ + +typedef struct ThreadBarrier_ { + int thrdnbr; /*+ Number of threads to wait for +*/ + volatile int thrdcur; /*+ Number of threads currently blocked +*/ + volatile int instnum; /*+ Number of barrier instance +*/ + pthread_mutex_t mutedat; + pthread_cond_t conddat; +} ThreadBarrier; + +int threadBarrierDestroy (ThreadBarrier *); +int threadBarrierInit (ThreadBarrier *, void *, int); /* Thread attribute not used */ +int threadBarrierWait (ThreadBarrier *); + +#else /* COMMON_PTHREAD_BARRIER */ + +#define ThreadBarrier pthread_barrier_t + +#define threadBarrierDestroy pthread_barrier_destroy +#define threadBarrierInit pthread_barrier_init +#define threadBarrierWait pthread_barrier_wait + +#endif /* COMMON_PTHREAD_BARRIER */ + +#define threadBarrier(t) threadBarrierWait (&(((ThreadGroupHeader *) (((ThreadHeader *) (void *) (t))->grouptr))->barrdat)) + +/** The thread service routines auxiliary function types **/ + +typedef int (* ThreadLaunchJoinFunc) (void * const, void * const); +typedef int (* ThreadLaunchStartFunc) (void * const); +typedef void (* ThreadReduceFunc) (void * const, void * const, void * const); +typedef void (* ThreadScanFunc) (void * const, void * const, void * const, const int); + +/** The thread group header block. **/ + +typedef struct ThreadGroupHeader_ { +#if ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) + int flagval; /*+ Thread block flags +*/ + size_t datasiz; /*+ Size of data array cell +*/ + int thrdnbr; /*+ Number of threads +*/ + ThreadLaunchStartFunc stafptr; /*+ Pointer to start routine +*/ + ThreadLaunchJoinFunc joifptr; /*+ Pointer to join routine +*/ + ThreadBarrier barrdat; /*+ Barrier data structure +*/ +#endif /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ +} ThreadGroupHeader; + +/** The thread header block. **/ + +typedef struct ThreadHeader_ { + void * grouptr; /*+ Pointer to thread group +*/ +#if ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) + pthread_t thidval; /*+ Thread ID +*/ + int thrdnum; /*+ Thread instance number +*/ +#endif /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ +} ThreadHeader; + +/** The number of threads **/ + +#ifdef SCOTCH_PTHREAD + +#ifndef SCOTCH_PTHREAD_NUMBER +#define SCOTCH_PTHREAD_NUMBER 1 +#endif /* SCOTCH_PTHREAD_NUMBER */ + +#else /* SCOTCH_PTHREAD */ + +#ifdef SCOTCH_PTHREAD_NUMBER +#undef SCOTCH_PTHREAD_NUMBER +#endif /* SCOTCH_PTHREAD_NUMBER */ +#define SCOTCH_PTHREAD_NUMBER 1 + +#endif /* SCOTCH_PTHREAD */ + +/* +** Handling of files. +*/ + +/** The file structure. **/ + +typedef struct File_ { + char * name; /*+ File name +*/ + FILE * pntr; /*+ File pointer +*/ + char * mode; /*+ Opening mode +*/ +} File; + +/* +** Function prototypes. +*/ + +void * memAllocGroup (void **, ...); +void * memReallocGroup (void *, ...); +void * memOffset (void *, ...); +#ifdef COMMON_MEMORY_TRACE +void * memAllocRecord (size_t); +void * memReallocRecord (void * const, size_t); +void memFreeRecord (void * const); +IDX memCur (); /* What is internally an intptr_t has to be turned into an interface type */ +IDX memMax (); +#endif /* COMMON_MEMORY_TRACE */ + +void usagePrint (FILE * const, const char (* [])); + +int fileBlockOpen (File * const, const int); +int fileBlockOpenDist (File * const, const int, const int, const int, const int); +void fileBlockClose (File * const, const int); +FILE * fileCompress (FILE * const, const int); +int fileCompressType (const char * const); +FILE * fileUncompress (FILE * const, const int); +int fileUncompressType (const char * const); +int fileNameDistExpand (char ** const, const int, const int, const int); + +void errorProg (const char * const); +void errorPrint (const char * const, ...); +void errorPrintW (const char * const, ...); + +int intLoad (FILE * const, INT * const); +int intSave (FILE * const, const INT); +void intAscn (INT * const, const INT, const INT); +void intPerm (INT * const, const INT); +void intRandInit (void); +void intRandReset (void); +void intRandSeed (INT); +#ifndef COMMON_RANDOM_SYSTEM +INT intRandVal (INT); +#endif /* COMMON_RANDOM_SYSTEM */ +void intSort1asc1 (void * const, const INT); +void intSort2asc1 (void * const, const INT); +void intSort2asc2 (void * const, const INT); +void intSort3asc1 (void * const, const INT); +void intSort3asc2 (void * const, const INT); +INT intSearchDicho (const INT * const, const INT, const INT, const INT); +INT intGcd (INT, INT); + +void clockInit (Clock * const); +void clockStart (Clock * const); +void clockStop (Clock * const); +double clockVal (Clock * const); +double clockGet (void); + +void stringSubst (char * const, const char * const, const char * const); + +#ifdef COMMON_PTHREAD +int threadLaunch (void * const, void * const, const size_t, int (*) (void *), int (*) (void *, void *), const int, const int); +void threadReduce (void * const, void * const, ThreadReduceFunc const, const int); +void threadScan (void * const, void * const, ThreadScanFunc const); +#endif /* COMMON_PTHREAD */ + +/* +** Macro definitions. +*/ + +#define clockInit(clk) ((clk)->time[0] = (clk)->time[1] = 0) +#define clockStart(clk) ((clk)->time[0] = clockGet ()) +#define clockStop(clk) ((clk)->time[1] += (clockGet () - (clk)->time[0])) +#define clockVal(clk) ((clk)->time[1]) + +#ifdef COMMON_RANDOM_SYSTEM +#ifdef COMMON_RANDOM_RAND +#define intRandVal(ival) ((INT) (((UINT) rand ()) % ((UINT) (ival)))) +#else /* COMMON_RANDOM_RAND */ +#define intRandVal(ival) ((INT) (((UINT) random ()) % ((UINT) (ival)))) +#endif /* COMMON_RANDOM_RAND */ +#endif /* COMMON_RANDOM_SYSTEM */ + +#define DATASIZE(n,p,i) ((INT) (((n) + ((p) - 1 - (i))) / (p))) +#define DATASCAN(n,p,i) ((i) * ((INT) (n) / (INT) (p)) + (((i) > ((n) % (p))) ? ((n) % (p)) : (i))) + +#define FORTRAN(nu,nl,pl,pc) FORTRAN2(REPLACE(nu),REPLACE(nl),pl,pc) +#define FORTRAN2(nu,nl,pl,pc) \ +void nu pl; \ +void nl pl \ +{ nu pc; } \ +void GLUE(nl,_) pl \ +{ nu pc; } \ +void GLUE(nl,__) pl \ +{ nu pc; } \ +void nu pl + +#define REPLACE(s) s +#define GLUE(p,s) p##s + +#define STRINGIFY2(n) #n +#define STRINGIFY(n) STRINGIFY2(n) diff --git a/scotch_6.0.3/src/libscotch/common_error.c b/scotch_6.0.3/src/libscotch/common_error.c new file mode 100644 index 00000000..55ace749 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_error.c @@ -0,0 +1,123 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_error.c **/ +/** **/ +/** AUTHORS : David GOUDIN **/ +/** Pascal HENON **/ +/** Francois PELLEGRINI **/ +/** Pierre RAMET **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** This module handles errors. **/ +/** **/ +/** DATES : # Version 0.0 : from : 08 may 1998 **/ +/** to 02 oct 1998 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON_ERROR + +#include "common.h" + +/********************************/ +/* */ +/* The error handling routines. */ +/* */ +/********************************/ + +static char errorProgName[32] = ""; + +/* This routine sets the program name for +** error reporting. +** It returns: +** - VOID : in all cases. +*/ + +void +errorProg ( +const char * const progstr) /*+ Program name +*/ +{ + strncpy (errorProgName, progstr, 29); + errorProgName[29] = '\0'; + strcat (errorProgName, ": "); + +} + +/* This routine prints an error message with +** a variable number of arguments, as printf () +** does, and exits. +** It returns: +** - EXIT : in all cases. +*/ + +void +errorPrint ( +const char * const errstr, /*+ printf-like variable argument list */ +...) +{ + va_list errlist; /* Argument list of the call */ + + fprintf (stderr, "%sERROR: ", errorProgName); + va_start (errlist, errstr); + vfprintf (stderr, errstr, errlist); /* Print arguments */ + va_end (errlist); + fprintf (stderr, "\n"); + fflush (stderr); /* In case it has been set to buffered mode */ +} + +/* This routine prints a warning message with +** a variable number of arguments, as printf () +** does. +** It returns: +** - VOID : in all cases. +*/ + +void +errorPrintW ( +const char * const errstr, /*+ printf-like variable argument list */ +...) +{ + va_list errlist; /* Argument list of the call */ + + fprintf (stderr, "%sWARNING: ", errorProgName); + va_start (errlist, errstr); + vfprintf (stderr, errstr, errlist); /* Print arguments */ + va_end (errlist); + fprintf (stderr, "\n"); + fflush (stderr); /* In case it has been set to buffered mode */ +} diff --git a/scotch_6.0.3/src/libscotch/common_file.c b/scotch_6.0.3/src/libscotch/common_file.c new file mode 100644 index 00000000..6a8b2610 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_file.c @@ -0,0 +1,305 @@ +/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_file.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles files and file **/ +/** names. **/ +/** **/ +/** DATES : # Version 5.0 : from : 21 may 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 27 jun 2010 **/ +/** to 27 jun 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON_FILE + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include "common.h" +#include "common_file.h" + +/*********************************/ +/* */ +/* Basic routines for filenames. */ +/* */ +/*********************************/ + +/* This routine expands distributed filenames +** according to process numbers and the root +** process number. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +fileNameDistExpand ( +char ** const nameptr, /*+ Pointer to name string pointer +*/ +const int procnbr, /*+ Number of processes +*/ +const int procnum, /*+ Number of current process +*/ +const int protnum) /*+ Root process number +*/ +{ + int namemax; + int namenum; + char * naexptr; + int naexmax; + int naexnum; + int flagval; /* Flag set if expansion took place */ + + namemax = strlen (*nameptr); + naexmax = namemax + FILENAMEDISTEXPANDNBR * 2; + + if ((naexptr = memAlloc ((naexmax + 1) * sizeof (char))) == NULL) /* "+ 1" for terminating character */ + return (1); + +#ifdef COMMON_DEBUG + sprintf (naexptr, FILENAMEDISTEXPANDSTR, procnbr); /* TRICK: Test if FILENAMEDISTEXPANDNBR is a size large enough */ + if (atoi (naexptr) != procnbr) { + errorPrint ("fileNameDistExpand: undersized integer string size"); + return (1); + } +#endif /* COMMON_DEBUG */ + + for (namenum = naexnum = flagval = 0; namenum < namemax; ) { + char charval; + int dataval = 0; + int datasiz; + + charval = (*nameptr)[namenum ++]; /* Get current characted */ + datasiz = 1; /* Assume individual expanded character */ + if (charval == '%') { + char chnxval; /* Value of next char */ + + switch (chnxval = (*nameptr)[namenum ++]) { + case 'p' : /* "%p" translates into number of processes */ + flagval = 1; + datasiz = FILENAMEDISTEXPANDNBR; + dataval = procnbr; + break; + case 'r' : /* "%r" translates into process rank */ + flagval = 1; + datasiz = FILENAMEDISTEXPANDNBR; + dataval = procnum; + break; + case '-' : /* "%-" translates into nothing but indicates distributed file */ + datasiz = 0; + flagval = 1; + break; + case '%' : /* "%%" translates into '%' */ + break; + default : + charval = chnxval; /* Unrecognized character */ + } + } + if (datasiz > 0) { + if ((naexnum + datasiz) > naexmax) { + char * nanwptr; + + naexmax += datasiz + FILENAMEDISTEXPANDNBR; + if ((nanwptr = memRealloc (naexptr, (naexmax + 1) * sizeof (char))) == NULL) { /* "+ 1" for terminating character */ + memFree (naexptr); + return (1); + } + naexptr = nanwptr; + } + if (datasiz == 1) + naexptr[naexnum ++] = charval; + else { + sprintf (&naexptr[naexnum], FILENAMEDISTEXPANDSTR, dataval); /* TRICK: Change format string if FILENAMEDISTEXPANDNBR changes */ + naexptr[naexnum + FILENAMEDISTEXPANDNBR] = ' '; + naexnum = strchr (&naexptr[naexnum], ' ') - naexptr; + } + } + } + naexptr[naexnum] = '\0'; /* Set terminating character as there is always room for it */ + + if ((flagval != 0) || (procnum == protnum)) /* If file name is a distributed one or we are the root process */ + *nameptr = naexptr; /* Replace new string by old one */ + else { + memFree (naexptr); /* No need for the expanded string */ + *nameptr = NULL; + } + + return (0); +} + +/* This routine opens a block of file +** descriptor structures. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +fileBlockOpen ( +File * const filetab, +const int filenbr) +{ + int i, j; + + for (i = 0; i < filenbr; i ++) { /* For all file names */ + if (filetab[i].pntr == NULL) /* If unwanted stream, do nothing */ + continue; + + for (j = 0; j < i; j ++) { + if ((filetab[i].mode[0] == filetab[j].mode[0]) && /* If very same name with same opening mode */ + (filetab[j].name != NULL) && + (strcmp (filetab[i].name, filetab[j].name) == 0)) { + filetab[i].pntr = filetab[j].pntr; /* Share pointer to already processed stream */ + filetab[i].name = NULL; /* Do not close this stream multiple times */ + break; + } + } + if (j == i) { /* If original stream */ + int compval; /* Compression type */ + FILE * compptr; /* Processed ((un)compressed) stream */ + + if (filetab[i].name[0] != '-') { /* If not standard stream, open it */ + if ((filetab[i].pntr = fopen (filetab[i].name, filetab[i].mode)) == NULL) { /* Open the file */ + errorPrint ("fileBlockOpen: cannot open file (%d)", i); + return (1); + } + } + compval = (filetab[i].mode[0] == 'r') ? fileUncompressType (filetab[i].name) : fileCompressType (filetab[i].name); + if (compval < 0) { + errorPrint ("fileBlockOpen: (un)compression type not implemented"); + return (1); + } + compptr = (filetab[i].mode[0] == 'r') ? fileUncompress (filetab[i].pntr, compval) : fileCompress (filetab[i].pntr, compval); + if (compptr == NULL) { + errorPrint ("fileBlockOpen: cannot create (un)compression subprocess"); + return (1); + } + filetab[i].pntr = compptr; /* Use processed stream instead of original stream */ + } + } + + return (0); +} + +/* This routine opens a block of eventually +** distributed file descriptor structures. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +fileBlockOpenDist ( +File * const filetab, +const int filenbr, +const int procglbnbr, +const int proclocnum, +const int protglbnum) +{ + int i, j; + + for (i = 0; i < filenbr; i ++) { /* For all file names */ + if (fileNameDistExpand (&filetab[i].name, procglbnbr, proclocnum, protglbnum) != 0) { /* If cannot allocate new name */ + errorPrint ("fileBlockOpenDist: cannot create file name (%d)", i); + return (1); + } + if (filetab[i].name == NULL) /* If inexisting stream because not root process and centralized stream */ + filetab[i].pntr = NULL; + if (filetab[i].pntr == NULL) /* If unwanted stream, do nothing */ + continue; + + for (j = 0; j < i; j ++) { + if ((filetab[i].mode[0] == filetab[j].mode[0]) && /* If very same name with same opening mode */ + (filetab[j].name != NULL) && + (strcmp (filetab[i].name, filetab[j].name) == 0)) { + filetab[i].pntr = filetab[j].pntr; /* Share pointer to already processed stream */ + filetab[i].name = NULL; /* Do not close this stream multiple times */ + break; + } + } + if (j == i) { /* If original stream */ + int compval; /* Compression type */ + FILE * compptr; /* Processed ((un)compressed) stream */ + + if (filetab[i].name[0] != '-') { /* If not standard stream, open it */ + if ((filetab[i].pntr = fopen (filetab[i].name, filetab[i].mode)) == NULL) { /* Open the file */ + errorPrint ("fileBlockOpenDist: cannot open file (%d)", i); + return (1); + } + } + compval = (filetab[i].mode[0] == 'r') ? fileUncompressType (filetab[i].name) : fileCompressType (filetab[i].name); + if (compval < 0) { + errorPrint ("fileBlockOpenDist: (un)compression type not implemented"); + return (1); + } + compptr = (filetab[i].mode[0] == 'r') ? fileUncompress (filetab[i].pntr, compval) : fileCompress (filetab[i].pntr, compval); + if (compptr == NULL) { + errorPrint ("fileBlockOpenDist: cannot create (un)compression subprocess"); + return (1); + } + filetab[i].pntr = compptr; /* Use processed stream instead of original stream */ + } + } + + return (0); +} + +/* This routine opens a block of file +** descriptor structures. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +void +fileBlockClose ( +File * const filetab, +const int filenbr) +{ + int i; + + for (i = 0; i < filenbr; i ++) { /* For all file names */ + if (filetab[i].pntr == NULL) /* If unwanted stream, do nothing */ + continue; + + if ((filetab[i].name != NULL) && /* If existing stream */ + (filetab[i].name[0] != '-')) { + fclose (filetab[i].pntr); /* Close the stream */ + } + } +} diff --git a/scotch_6.0.3/src/libscotch/common_file.h b/scotch_6.0.3/src/libscotch/common_file.h new file mode 100644 index 00000000..ca716eee --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_file.h @@ -0,0 +1,56 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_file.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the file and file name handling **/ +/** routines. **/ +/** **/ +/** DATES : # Version P0.5 : from : 21 may 2007 **/ +/** to 21 may 2007 **/ +/** **/ +/************************************************************/ + +#define COMMON_FILE_H + +/* +** The type and structure definitions. +*/ + +/* Expansion string size and associated format string. */ + +#define FILENAMEDISTEXPANDNBR 10 /* TRICK: Change this value in ssprintf() format strings too */ +#define FILENAMEDISTEXPANDSTR "%-10d" /* TRICK: Change this value if FILENAMEDISTEXPANDNBR changes */ diff --git a/scotch_6.0.3/src/libscotch/common_file_compress.c b/scotch_6.0.3/src/libscotch/common_file_compress.c new file mode 100644 index 00000000..c4dd2ba9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_file_compress.c @@ -0,0 +1,306 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_file_compress.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles compressed streams **/ +/** for compression. **/ +/** **/ +/** DATES : # Version 5.0 : from : 13 mar 2008 **/ +/** to : 15 may 2008 **/ +/** # Version 5.1 : from : 27 jun 2010 **/ +/** to 27 jun 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON_FILE +#define COMMON_FILE_COMPRESS + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include "common.h" +#include "common_file.h" +#include "common_file_compress.h" +#ifdef COMMON_FILE_COMPRESS_BZ2 +#include "bzlib.h" +#endif /* COMMON_FILE_COMPRESS_BZ2 */ +#ifdef COMMON_FILE_COMPRESS_GZ +#include "zlib.h" +#endif /* COMMON_FILE_COMPRESS_GZ */ + +/* +** The static definitions. +*/ + +static FileCompressTab filetab[] = { +#ifdef COMMON_FILE_COMPRESS_BZ2 + { ".bz2", FILECOMPRESSTYPEBZ2, }, +#else /* COMMON_FILE_COMPRESS_BZ2 */ + { ".bz2", FILECOMPRESSTYPENOTIMPL }, +#endif /* COMMON_FILE_COMPRESS_BZ */ +#ifdef COMMON_FILE_COMPRESS_GZ + { ".gz", FILECOMPRESSTYPEGZ, }, +#else /* COMMON_FILE_COMPRESS_GZ */ + { ".gz", FILECOMPRESSTYPENOTIMPL }, +#endif /* COMMON_FILE_COMPRESS_GZ */ +/* #ifdef COMMON_FILE_COMPRESS_LZMA */ /* TODO: Current lzmadec library does not offer compression to date */ +/* { ".lzma", FILECOMPRESSTYPELZMA }, */ +/* #else COMMON_FILE_COMPRESS_LZMA */ + { ".lzma", FILECOMPRESSTYPENOTIMPL }, +/* #endif /\* COMMON_FILE_COMPRESS_LZMA *\/ */ + { NULL, FILECOMPRESSTYPENOTIMPL } }; + +/*********************************/ +/* */ +/* Basic routines for filenames. */ +/* */ +/*********************************/ + +/* This routine searches the given file name +** for relevant extensions and returns the +** corresponding code if it is the case. +** It returns: +** - FILECOMPRESSTYPENONE : no recognized file extension. +** - FILECOMPRESSTYPENOTIMPL : compression algorithm not implemented. +** - FILECOMPRESSTYPExxxx : implemented compression algorithm. +*/ + +int +fileCompressType ( +const char * const nameptr) /*+ Name string +*/ +{ + int namelen; + int i; + + namelen = strlen (nameptr); + for (i = 0; filetab[i].name != NULL; i ++) { + int extnlen; /* Name of extension string */ + + extnlen = strlen (filetab[i].name); + if ((namelen >= extnlen) && (strncmp (filetab[i].name, nameptr + (namelen - extnlen), extnlen) == 0)) + return (filetab[i].type); + } + + return (FILECOMPRESSTYPENONE); +} + +/* This routine creates a thread to compress the +** given stream according to the given compression +** algorithm. +** If threads are available, compression will be +** performed by an auxiliary thread. Else, a child process +** will be fork()'ed, and after completion this process +** will remain a zombie until the main process terminates. +** It returns: +** - !NULL : stream holding compressed data. +** - NULL : on error. +*/ + +static +void * /* (void *) to comply to the Posix pthread API */ +fileCompress2 ( +FileCompressData * const dataptr) +{ + switch (dataptr->typeval) { +#ifdef COMMON_FILE_COMPRESS_BZ2 + case FILECOMPRESSTYPEBZ2 : + fileCompressBz2 (dataptr); + break; +#endif /* COMMON_FILE_COMPRESS_BZ2 */ +#ifdef COMMON_FILE_COMPRESS_GZ + case FILECOMPRESSTYPEGZ : + fileCompressGz (dataptr); + break; +#endif /* COMMON_FILE_COMPRESS_GZ */ +/* #ifdef COMMON_FILE_COMPRESS_LZMA /\* TODO: Current lzmadec library does not offer compression to date *\/ */ +/* case FILECOMPRESSTYPELZMA : */ +/* fileCompressLzma (dataptr); */ +/* break; */ +/* #endif /\* COMMON_FILE_COMPRESS_LZMA *\/ */ + default : + errorPrint ("fileCompress2: method not implemented"); + } + + close (dataptr->innerfd); /* Close writer's end */ + memFree (dataptr); /* Free buffers */ + + return ((void *) 0); /* Don't care anyway */ +} + +FILE * +fileCompress ( +FILE * const stream, /*+ Uncompressed stream +*/ +const int typeval) /*+ (Un)compression algorithm +*/ +{ + int filetab[2]; + FILE * writptr; + FileCompressData * dataptr; +#ifdef COMMON_PTHREAD + pthread_t thrdval; +#endif /* COMMON_PTHREAD */ + + if (typeval <= FILECOMPRESSTYPENONE) /* If uncompressed stream, return original stream pointer */ + return (stream); + + if (pipe (filetab) != 0) { + errorPrint ("fileCompress: cannot create pipe"); + return (NULL); + } + + if ((writptr = fdopen (filetab[1], "w")) == NULL) { + errorPrint ("fileCompress: cannot create stream"); + close (filetab[0]); + close (filetab[1]); + return (NULL); + } + + if ((dataptr = memAlloc (sizeof (FileCompressData) + FILECOMPRESSDATASIZE)) == NULL) { + errorPrint ("fileCompress: out of memory"); + close (filetab[0]); + fclose (writptr); + return (NULL); + } + + dataptr->typeval = typeval; /* Fill structure to be passed to compression thread/process */ + dataptr->innerfd = filetab[0]; + dataptr->outerstream = stream; /* Stream to write to */ + +#ifdef COMMON_PTHREAD + if (pthread_create (&thrdval, NULL, (void * (*) (void *)) fileCompress2, (void *) dataptr) != 0) { /* If could not create thread */ + errorPrint ("fileCompress: cannot create thread"); + memFree (dataptr); + close (filetab[0]); + fclose (writptr); + return (NULL); + } +#else /* COMMON_PTHREAD */ + switch (fork ()) { + case -1 : /* Error */ + errorPrint ("fileCompress: cannot create child process"); + memFree (dataptr); + close (filetab[0]); + fclose (writptr); + return (NULL); + case 0 : /* We are the son process */ + fclose (writptr); /* Close writer pipe stream */ + fileCompress2 (dataptr); /* Perform compression */ + exit (0); /* Exit gracefully */ + default : /* We are the father process */ + close (filetab[0]); /* Close the reader pipe end */ + } +#endif /* COMMON_PTHREAD */ + + return (writptr); +} + +/* This routine compresses a stream compressed in the +** gzip format. +** It returns: +** - void : in all cases. Compression stops immediately +** in case of error. +*/ + +#ifdef COMMON_FILE_COMPRESS_BZ2 +static +void +fileCompressBz2 ( +FileCompressData * const dataptr) +{ + BZFILE * bzfile; + int bzsize; + int bzerror; + + if ((bzfile = BZ2_bzWriteOpen (&bzerror, dataptr->outerstream, 9, 0, 0)) == NULL) { + errorPrint ("fileCompressBz2: cannot start compression"); + BZ2_bzWriteClose (&bzerror, bzfile, 1, NULL, NULL); + return; + } + + while ((bzsize = read (dataptr->innerfd, &dataptr->datatab, FILECOMPRESSDATASIZE)) > 0) { /* Read from pipe */ + BZ2_bzWrite (&bzerror, bzfile, &dataptr->datatab, bzsize); + if (bzerror != BZ_OK) { + errorPrint ("fileCompressBz2: cannot write"); + break; + } + } + if (bzsize < 0) { + errorPrint ("fileCompressBz2: cannot read"); + bzerror = BZ_STREAM_END; /* Will set abandon flag to 1 in BZ2_bzWriteClose */ + } + + BZ2_bzWriteClose (&bzerror, bzfile, (bzerror != BZ_OK) ? 1 : 0, NULL, NULL); + fclose (dataptr->outerstream); /* Do as zlib does */ +} +#endif /* COMMON_FILE_COMPRESS_BZ2 */ + +/* This routine compresses a stream compressed in the +** gzip format. +** It returns: +** - void : in all cases. Compression stops immediately +** in case of error. +*/ + +#ifdef COMMON_FILE_COMPRESS_GZ +static +void +fileCompressGz ( +FileCompressData * const dataptr) +{ + gzFile gzfile; + int gzsize; + + if ((gzfile = gzdopen (fileno (dataptr->outerstream), "wb")) == NULL) { + errorPrint ("fileCompressGz: cannot start compression"); + return; + } + gzsetparams (gzfile, 9, Z_DEFAULT_STRATEGY); /* Maximum compression */ + + while ((gzsize = read (dataptr->innerfd, &dataptr->datatab, FILECOMPRESSDATASIZE)) > 0) { /* Read from pipe */ + if (gzwrite (gzfile, &dataptr->datatab, gzsize) != gzsize) { + errorPrint ("fileCompressGz: cannot write"); + break; + } + } + if (gzsize < 0) + errorPrint ("fileCompressGz: cannot read"); + + gzclose (gzfile); +} +#endif /* COMMON_FILE_COMPRESS_GZ */ diff --git a/scotch_6.0.3/src/libscotch/common_file_compress.h b/scotch_6.0.3/src/libscotch/common_file_compress.h new file mode 100644 index 00000000..162f241d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_file_compress.h @@ -0,0 +1,109 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_file_compress.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the file (de)compression routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 12 mar 2008 **/ +/** to 17 mar 2008 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/* Buffer size. */ + +#define FILECOMPRESSDATASIZE (128 * 1024) /* Size of (un)compressing buffers */ + +/* Available types of (un)compression. */ + +typedef enum FileCompressType_ { + FILECOMPRESSTYPENOTIMPL = -1, /* Error code */ + FILECOMPRESSTYPENONE, /* No compression */ + FILECOMPRESSTYPEBZ2, + FILECOMPRESSTYPEGZ, + FILECOMPRESSTYPELZMA +} FileCompressType; + +/* (Un)compression type slot. */ + +typedef struct FileCompressTab_ { + char * name; /* File extension name */ + FileCompressType type; /* (Un)compression type */ +} FileCompressTab; + +/* +** The type and structure definitions. +*/ + +typedef struct FileCompressData_ { + int typeval; /*+ Type of (un)compression +*/ + int innerfd; /*+ Inner file handle (pipe end) +*/ + FILE * outerstream; /*+ Outer stream +*/ + double datatab; /*+ Start of data buffer +*/ +} FileCompressData; + +/* +** The function prototypes. +*/ + +#ifdef COMMON_FILE_COMPRESS_BZ2 +#ifdef COMMON_FILE_COMPRESS +static void fileCompressBz2 (FileCompressData * const dataptr); +#endif /* COMMON_FILE_COMPRESS */ +#ifdef COMMON_FILE_UNCOMPRESS +static void fileUncompressBz2 (FileCompressData * const dataptr); +#endif /* COMMON_FILE_UNCOMPRESS */ +#endif /* COMMON_FILE_COMPRESS_Bz2 */ +#ifdef COMMON_FILE_COMPRESS_GZ +#ifdef COMMON_FILE_COMPRESS +static void fileCompressGz (FileCompressData * const dataptr); +#endif /* COMMON_FILE_COMPRESS */ +#ifdef COMMON_FILE_UNCOMPRESS +static void fileUncompressGz (FileCompressData * const dataptr); +#endif /* COMMON_FILE_UNCOMPRESS */ +#endif /* COMMON_FILE_COMPRESS_GZ */ +#ifdef COMMON_FILE_COMPRESS_LZMA +/* #ifdef COMMON_FILE_COMPRESS */ +/* static void fileCompressLzma (FileCompressData * const dataptr); */ +/* #endif /\* COMMON_FILE_COMPRESS *\/ */ +#ifdef COMMON_FILE_UNCOMPRESS +static void fileUncompressLzma (FileCompressData * const dataptr); +#endif /* COMMON_FILE_UNCOMPRESS */ +#endif /* COMMON_FILE_COMPRESS_LZMA */ diff --git a/scotch_6.0.3/src/libscotch/common_file_uncompress.c b/scotch_6.0.3/src/libscotch/common_file_uncompress.c new file mode 100644 index 00000000..8e621eb7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_file_uncompress.c @@ -0,0 +1,362 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_file_uncompress.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles compressed streams **/ +/** for uncompression. **/ +/** **/ +/** DATES : # Version 5.0 : from : 11 mar 2008 **/ +/** to : 15 may 2008 **/ +/** # Version 5.1 : from : 27 jun 2010 **/ +/** to 27 jun 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON_FILE +#define COMMON_FILE_UNCOMPRESS + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include "common.h" +#include "common_file.h" +#include "common_file_compress.h" +#ifdef COMMON_FILE_COMPRESS_BZ2 +#include "bzlib.h" +#endif /* COMMON_FILE_COMPRESS_BZ2 */ +#ifdef COMMON_FILE_COMPRESS_GZ +#include "zlib.h" +#endif /* COMMON_FILE_COMPRESS_GZ */ +#ifdef COMMON_FILE_COMPRESS_LZMA +#include "lzmadec.h" /* TODO: Temporary interface */ +#endif /* COMMON_FILE_COMPRESS_LZMA */ + +/* +** The static definitions. +*/ + +static FileCompressTab filetab[] = { +#ifdef COMMON_FILE_COMPRESS_BZ2 + { ".bz2", FILECOMPRESSTYPEBZ2, }, +#else /* COMMON_FILE_COMPRESS_BZ2 */ + { ".bz2", FILECOMPRESSTYPENOTIMPL }, +#endif /* COMMON_FILE_COMPRESS_BZ */ +#ifdef COMMON_FILE_COMPRESS_GZ + { ".gz", FILECOMPRESSTYPEGZ, }, +#else /* COMMON_FILE_COMPRESS_GZ */ + { ".gz", FILECOMPRESSTYPENOTIMPL }, +#endif /* COMMON_FILE_COMPRESS_GZ */ +#ifdef COMMON_FILE_COMPRESS_LZMA + { ".lzma", FILECOMPRESSTYPELZMA }, +#else /* COMMON_FILE_COMPRESS_LZMA */ + { ".lzma", FILECOMPRESSTYPENOTIMPL }, +#endif /* COMMON_FILE_COMPRESS_LZMA */ + { NULL, FILECOMPRESSTYPENOTIMPL } }; + +/*********************************/ +/* */ +/* Basic routines for filenames. */ +/* */ +/*********************************/ + +/* This routine searches the given file name +** for relevant extensions and returns the +** corresponding code if it is the case. +** It returns: +** - FILECOMPRESSTYPENONE : no recognized file extension. +** - FILECOMPRESSTYPENOTIMPL : compression algorithm not implemented. +** - FILECOMPRESSTYPExxxx : implemented compression algorithm. +*/ + +int +fileUncompressType ( +const char * const nameptr) /*+ Name string +*/ +{ + int namelen; + int i; + + namelen = strlen (nameptr); + for (i = 0; filetab[i].name != NULL; i ++) { + int extnlen; /* Name of extension string */ + + extnlen = strlen (filetab[i].name); + if ((namelen >= extnlen) && (strncmp (filetab[i].name, nameptr + (namelen - extnlen), extnlen) == 0)) + return (filetab[i].type); + } + + return (FILECOMPRESSTYPENONE); +} + +/* This routine creates a thread to uncompress the +** given stream according to the given (un)compression +** algorithm. +** If threads are available, uncompression will be +** performed by an auxiliary thread. Else, a child process +** will be fork()'ed, and after completion this process +** will remain a zombie until the main process terminates. +** It returns: +** - !NULL : stream holding uncompressed data. +** - NULL : on error. +*/ + +static +void * /* (void *) to comply to the Posix pthread API */ +fileUncompress2 ( +FileCompressData * const dataptr) +{ + switch (dataptr->typeval) { +#ifdef COMMON_FILE_COMPRESS_BZ2 + case FILECOMPRESSTYPEBZ2 : + fileUncompressBz2 (dataptr); + break; +#endif /* COMMON_FILE_COMPRESS_BZ2 */ +#ifdef COMMON_FILE_COMPRESS_GZ + case FILECOMPRESSTYPEGZ : + fileUncompressGz (dataptr); + break; +#endif /* COMMON_FILE_COMPRESS_GZ */ +#ifdef COMMON_FILE_COMPRESS_LZMA + case FILECOMPRESSTYPELZMA : + fileUncompressLzma (dataptr); + break; +#endif /* COMMON_FILE_COMPRESS_LZMA */ + default : + errorPrint ("fileUncompress2: method not implemented"); + } + + close (dataptr->innerfd); /* Close writer's end */ + memFree (dataptr); /* Free buffers */ + + return ((void *) 0); /* Don't care anyway */ +} + +FILE * +fileUncompress ( +FILE * const stream, /*+ Compressed stream +*/ +const int typeval) /*+ (Un)compression algorithm +*/ +{ + int filetab[2]; + FILE * readptr; + FileCompressData * dataptr; +#ifdef COMMON_PTHREAD + pthread_t thrdval; +#endif /* COMMON_PTHREAD */ + + if (typeval <= FILECOMPRESSTYPENONE) /* If uncompressed stream, return original stream pointer */ + return (stream); + + if (pipe (filetab) != 0) { + errorPrint ("fileUncompress: cannot create pipe"); + return (NULL); + } + + if ((readptr = fdopen (filetab[0], "r")) == NULL) { + errorPrint ("fileUncompress: cannot create stream"); + close (filetab[0]); + close (filetab[1]); + return (NULL); + } + + if ((dataptr = memAlloc (sizeof (FileCompressData) + FILECOMPRESSDATASIZE)) == NULL) { + errorPrint ("fileUncompress: out of memory"); + fclose (readptr); + close (filetab[1]); + return (NULL); + } + + dataptr->typeval = typeval; /* Fill structure to be passed to uncompression thread/process */ + dataptr->innerfd = filetab[1]; + dataptr->outerstream = stream; + +#ifdef COMMON_PTHREAD + if (pthread_create (&thrdval, NULL, (void * (*) (void *)) fileUncompress2, (void *) dataptr) != 0) { /* If could not create thread */ + errorPrint ("fileUncompress: cannot create thread"); + memFree (dataptr); + fclose (readptr); + close (filetab[1]); + return (NULL); + } + pthread_detach (thrdval); /* Detach thread so that it will end up gracefully by itself */ +#else /* COMMON_PTHREAD */ + switch (fork ()) { + case -1 : /* Error */ + errorPrint ("fileUncompress: cannot create child process"); + memFree (dataptr); + fclose (readptr); + close (filetab[1]); + return (NULL); + case 0 : /* We are the son process */ + fclose (readptr); /* Close reader pipe stream */ + fileUncompress2 (dataptr); /* Perform uncompression */ + exit (0); /* Exit gracefully */ + default : /* We are the father process */ + close (filetab[1]); /* Close the writer pipe end */ + } +#endif /* COMMON_PTHREAD */ + + return (readptr); +} + +/* This routine uncompresses a stream compressed in the +** bzip2 format. +** It returns: +** - void : in all cases. Uncompression stops immediately +** in case of error. +*/ + +#ifdef COMMON_FILE_COMPRESS_BZ2 +static +void +fileUncompressBz2 ( +FileCompressData * const dataptr) +{ + BZFILE * bzfile; + int bzsize; + int bzerror; + + if (FILECOMPRESSDATASIZE < (BZ_MAX_UNUSED)) { + errorPrint ("fileUncompressBz2: cannot start decompression (1)"); + return; + } + if ((bzfile = BZ2_bzReadOpen (&bzerror, dataptr->outerstream, 0, 0, NULL, 0)) == NULL) { + errorPrint ("fileUncompressBz2: cannot start decompression (2)"); + BZ2_bzReadClose (&bzerror, bzfile); + return; + } + + while ((bzsize = BZ2_bzRead (&bzerror, bzfile, &dataptr->datatab, FILECOMPRESSDATASIZE), bzerror) >= BZ_OK) { /* If BZ_OK or BZ_STREAM_END */ + if (write (dataptr->innerfd, &dataptr->datatab, bzsize) != bzsize) { + errorPrint ("fileUncompressBz2: cannot write"); + bzerror = BZ_STREAM_END; /* Avoid other error message */ + break; + } + if (bzerror == BZ_STREAM_END) { /* If end of compressed stream */ + void * bzunusptr; + int bzunusnbr; + + BZ2_bzReadGetUnused (&bzerror, bzfile, &bzunusptr, &bzunusnbr); /* Get remaining chars in stream */ + if ((bzunusnbr == 0) && (feof (dataptr->outerstream) != 0)) { /* If end of uncompressed stream too */ + bzerror = BZ_STREAM_END; + break; + } + memMov (&dataptr->datatab, bzunusptr, bzunusnbr); + BZ2_bzReadClose (&bzerror, bzfile); + if ((bzfile = BZ2_bzReadOpen (&bzerror, dataptr->outerstream, 0, 0, &dataptr->datatab, bzunusnbr)) == NULL) { + errorPrint ("fileUncompressBz2: cannot start decompression (3)"); + bzerror = BZ_STREAM_END; + break; + } + } + } + if (bzerror != BZ_STREAM_END) + errorPrint ("fileUncompressBz2: cannot read"); + + BZ2_bzReadClose (&bzerror, bzfile); + fclose (dataptr->outerstream); /* Do as zlib does */ +} +#endif /* COMMON_FILE_COMPRESS_BZ2 */ + +/* This routine uncompresses a stream compressed in the +** gzip format. +** It returns: +** - void : in all cases. Uncompression stops immediately +** in case of error. +*/ + +#ifdef COMMON_FILE_COMPRESS_GZ +static +void +fileUncompressGz ( +FileCompressData * const dataptr) +{ + gzFile gzfile; + int gzsize; + + if ((gzfile = gzdopen (fileno (dataptr->outerstream), "rb")) == NULL) { + errorPrint ("fileUncompressGz: cannot start decompression"); + return; + } + + while ((gzsize = gzread (gzfile, &dataptr->datatab, FILECOMPRESSDATASIZE)) > 0) { + if (write (dataptr->innerfd, &dataptr->datatab, gzsize) != gzsize) { + errorPrint ("fileUncompressGz: cannot write"); + break; + } + } + if (gzsize < 0) + errorPrint ("fileUncompressGz: cannot read"); + + gzclose (gzfile); +} +#endif /* COMMON_FILE_COMPRESS_GZ */ + +/* This routine uncompresses a stream compressed in the +** lzma format. +** It returns: +** - void : in all cases. Uncompression stops immediately +** in case of error. +*/ + +#ifdef COMMON_FILE_COMPRESS_LZMA +static +void +fileUncompressLzma ( +FileCompressData * const dataptr) +{ + lzmadec_FILE * lzmafile; + ssize_t lzmasize; + + if ((lzmafile = lzmadec_dopen (fileno (dataptr->outerstream))) == NULL) { + errorPrint ("fileUncompressLzma: cannot start decompression"); + return; + } + + while ((lzmasize = lzmadec_read (lzmafile, (void *) &dataptr->datatab, FILECOMPRESSDATASIZE)) > 0) { + if (write (dataptr->innerfd, &dataptr->datatab, lzmasize) != lzmasize) { + errorPrint ("fileUncompressLzma: cannot write"); + break; + } + } + if (lzmasize < 0) + errorPrint ("fileUncompressLzma: cannot read"); + + lzmadec_close (lzmafile); +} +#endif /* COMMON_FILE_COMPRESS_LZMA */ diff --git a/scotch_6.0.3/src/libscotch/common_integer.c b/scotch_6.0.3/src/libscotch/common_integer.c new file mode 100644 index 00000000..28dd8fe5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_integer.c @@ -0,0 +1,489 @@ +/* Copyright 2004,2007-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_integer.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the generic integer **/ +/** type. **/ +/** **/ +/** DATES : # Version 0.0 : from : 07 sep 1998 **/ +/** to 22 sep 1998 **/ +/** # Version 0.1 : from : 07 jan 2002 **/ +/** to 17 jan 2003 **/ +/** # Version 1.0 : from : 23 aug 2005 **/ +/** to : 19 dec 2006 **/ +/** # Version 2.0 : from : 26 feb 2008 **/ +/** to : 26 feb 2008 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to : 16 jul 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON_INTEGER + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include "common.h" + +/********************************/ +/* */ +/* Basic routines for fast I/O. */ +/* */ +/********************************/ + +/* Fast read for INT values. +** It returns: +** - 1 : on success. +** - 0 : on error. +*/ + +int +intLoad ( +FILE * const stream, /*+ Stream to read from +*/ +INT * const valptr) /*+ Area where to put value +*/ +{ + int sign; /* Sign flag */ + int car; /* Character read */ + INT val; /* Value */ + + sign = 0; /* Assume positive constant */ + for ( ; ; ) { /* Consume whitespaces and sign */ + car = getc (stream); + if (isspace (car)) + continue; + if ((car >= '0') && (car <= '9')) + break; + if (car == '-') { + sign = 1; + car = getc (stream); + break; + } + if (car == '+') { + car = getc (stream); + break; + } + return (0); + } + if ((car < '0') || (car > '9')) /* If first char is non numeric */ + return (0); /* Then it is an error */ + val = car - '0'; /* Get first digit */ + for ( ; ; ) { + car = getc (stream); + if ((car < '0') || (car > '9')) { + ungetc (car, stream); + break; + } + val = val * 10 + (car - '0'); /* Accumulate digits */ + } + *valptr = (sign != 0) ? (- val) : val; /* Set result */ + + return (1); +} + +/* Write routine for INT values. +** It returns: +** - 1 : on success. +** - 0 : on error. +*/ + +int +intSave ( +FILE * const stream, /*+ Stream to write to +*/ +const INT val) /*+ Value to write +*/ +{ + return ((fprintf (stream, INTSTRING, (INT) val) == EOF) ? 0 : 1); +} + +/**********************************/ +/* */ +/* Permutation building routines. */ +/* */ +/**********************************/ + +/* This routine fills an array with +** consecutive INT values, in +** ascending order. +** It returns: +** - VOID : in all cases. +*/ + +void +intAscn ( +INT * const permtab, /*+ Permutation array to build +*/ +const INT permnbr, /*+ Number of entries in array +*/ +const INT baseval) /*+ Base value +*/ +{ + INT * permtax; + INT permnum; + INT permnnd; + + for (permnum = baseval, permnnd = baseval + permnbr, permtax = permtab - baseval; + permnum < permnnd; permnum ++) + permtax[permnum] = permnum; +} + +/* This routine computes a random permutation +** of an array of INT values. +** It returns: +** - VOID : in all cases. +*/ + +void +intPerm ( +INT * const permtab, /*+ Permutation array to build +*/ +const INT permnbr) /*+ Number of entries in array +*/ +{ + INT * permptr; + INT permrmn; + + for (permptr = permtab, permrmn = permnbr; /* Perform random permutation */ + permrmn > 0; permptr ++, permrmn --) { + INT permnum; + INT permtmp; + + permnum = intRandVal (permrmn); /* Select index to swap */ + permtmp = permptr[0]; /* Swap it with current index */ + permptr[0] = permptr[permnum]; + permptr[permnum] = permtmp; + } +} + +/*************************************/ +/* */ +/* Pseudo-random generator routines. */ +/* */ +/*************************************/ + +static volatile int intrandflag = 0; /*+ Flag set if generator already initialized +*/ +static UINT32 intrandseed = 1; /*+ Random seed +*/ +static IntRandState intrandstat; /*+ Random state value +*/ + +/* This routine initializes the pseudo-random +** generator if necessary. In order for multi-sequential +** programs to have exactly the same behavior on any +** process, the random seed does not depend on process +** rank. This routine is not really thread-safe, so it +** should not be called concurrently when it has never +** been initialized before. +** It returns: +** - VOID : in all cases. +*/ + +#ifndef COMMON_RANDOM_SYSTEM +static +void +intRandInit2 ( +IntRandState * restrict randptr, +int randval) +{ + UINT32 randtmp; + UINT32 i; + + randtmp = (UINT32) randval; + randptr->randtab[0] = randtmp; + for (i = 1; i < 623; i ++) { + randtmp = 0x6c078965 * randtmp ^ (randtmp >> 30) + i; + randptr->randtab[i] = randtmp; + } +} +#endif /* COMMON_RANDOM_SYSTEM */ + +void +intRandInit (void) +{ + if (intrandflag == 0) { /* Non thread-safe check */ + intrandflag = 1; /* Generator has been initialized */ + +#if ! ((defined COMMON_DEBUG) || (defined COMMON_RANDOM_FIXED_SEED) || (defined SCOTCH_DETERMINISTIC)) + intrandseed = time (NULL); /* Set random seed if needed */ +#endif /* ((defined COMMON_DEBUG) || (defined COMMON_RANDOM_FIXED_SEED)) */ + +#ifdef COMMON_RANDOM_SYSTEM +#ifdef COMMON_RANDOM_RAND + srand (intrandseed); +#else /* COMMON_RANDOM_RAND */ + srandom (intrandseed); +#endif /* COMMON_RANDOM_RAND */ +#else /* COMMON_RANDOM_SYSTEM */ + intRandInit2 (&intrandstat, intrandseed); /* Initialize state vector from random seed */ +#endif /* COMMON_RANDOM_SYSTEM */ + } +} + +/* This routine reinitializes the pseudo-random +** generator to its initial value. This routine +** is not thread-safe. +** It returns: +** - VOID : in all cases. +*/ + +void +intRandReset (void) +{ + if (intrandflag != 0) { /* Keep seed computed during first initialization */ +#ifdef COMMON_RANDOM_SYSTEM +#ifdef COMMON_RANDOM_RAND + srand (intrandseed); +#else /* COMMON_RANDOM_RAND */ + srandom (intrandseed); +#endif /* COMMON_RANDOM_RAND */ +#else /* COMMON_RANDOM_SYSTEM */ + intRandInit2 (&intrandstat, intrandseed); +#endif /* COMMON_RANDOM_SYSTEM */ + } + else + intRandInit (); +} + +/* This routine initializes the seed used by Scotch +** with the provided value. Hence, all subsequent +** calls to intRandInit() will start from this seed. +** It returns: +** - VOID : in all cases. +*/ + +void +intRandSeed ( +INT seedval) +{ + intrandseed = (UINT32) seedval; + intrandflag = 1; /* Generator has been initialized */ + +#ifdef COMMON_RANDOM_SYSTEM +#ifdef COMMON_RANDOM_RAND + srand (intrandseed); +#else /* COMMON_RANDOM_RAND */ + srandom (intrandseed); +#endif /* COMMON_RANDOM_RAND */ +#else /* COMMON_RANDOM_SYSTEM */ + intRandInit2 (&intrandstat, intrandseed); /* Initialize state vector from random seed */ +#endif /* COMMON_RANDOM_SYSTEM */ +} + +/* This routine computes a new pseudo-random +** 32bit value from the state that is passed +** to it. +** It returns: +** - x : pseudo-random value. +*/ + +#ifndef COMMON_RANDOM_SYSTEM +static +UINT32 +intRandVal2 ( +IntRandState * restrict randptr) +{ + int randnum; + UINT32 randval; + +#ifdef COMMON_DEBUG + if (intrandflag == 0) { + errorPrint ("intRandVal2: random generator not initialized"); + return (~0); + } +#endif /* COMMON_DEBUG */ + + randnum = randptr->randnum; + if (randnum == 0) { + int i; + + for (i = 0; i < 624; i ++) { + UINT32 randtmp; + + randtmp = (randptr->randtab[i] & 0x80000000) + (randptr->randtab[(i + 1) % 624] & 0x7FFFFFFF); + randtmp = randptr->randtab[(i + 397) % 624] ^ (randtmp >> 1); + if ((randtmp & 1) != 0) + randtmp ^= 0x9908B0DF; + + randptr->randtab[i] = randtmp; + } + } + + randval = randptr->randtab[randnum]; + randval ^= (randval >> 11); + randval ^= (randval >> 7) & 0x9D2C5680; + randval ^= (randval >> 15) & 0xEFC60000; + randval ^= (randval >> 18); + randptr->randnum = (randnum + 1) % 624; + + return (randval); +} +#endif /* COMMON_RANDOM_SYSTEM */ + +/* This routine returns a pseudo-random integer +** value in the range [0..randmax[. This routine +** is not thread-safe as it uses a global state +** variable. +** It returns: +** - x : pseudo-random value. +*/ + +#ifndef COMMON_RANDOM_SYSTEM +INT +intRandVal ( +INT randmax) +{ + return (((UINT) intRandVal2 (&intrandstat)) % randmax); +} +#endif /* COMMON_RANDOM_SYSTEM */ + +/*********************/ +/* */ +/* Sorting routines. */ +/* */ +/*********************/ + +/* This routine sorts an array of +** INT values in ascending order +** by their first value, used as key. +** It returns: +** - VOID : in all cases. +*/ + +#define INTSORTNAME intSort1asc1 +#define INTSORTSIZE (sizeof (INT)) +#define INTSORTSWAP(p,q) do { INT t; t = *((INT *) (p)); *((INT *) (p)) = *((INT *) (q)); *((INT *) (q)) = t; } while (0) +#define INTSORTCMP(p,q) (*((INT *) (p)) < *((INT *) (q))) +#include "common_sort.c" +#undef INTSORTNAME +#undef INTSORTSIZE +#undef INTSORTSWAP +#undef INTSORTCMP + +/* This routine sorts an array of pairs of +** INT values in ascending order by their +** first value, used as key. +** It returns: +** - VOID : in all cases. +*/ + +#define INTSORTNAME intSort2asc1 +#define INTSORTSIZE (2 * sizeof (INT)) +#define INTSORTSWAP(p,q) do { INT t, u; t = *((INT *) (p)); u = *((INT *) (p) + 1); *((INT *) (p)) = *((INT *) (q)); *((INT *) (p) + 1) = *((INT *) (q) + 1); *((INT *) (q)) = t; *((INT *) (q) + 1) = u; } while (0) +#define INTSORTCMP(p,q) (*((INT *) (p)) < *((INT *) (q))) +#include "common_sort.c" +#undef INTSORTNAME +#undef INTSORTSIZE +#undef INTSORTSWAP +#undef INTSORTCMP + +/* This routine sorts an array of pairs of +** INT values in ascending order by both +** of their values, used as primary and +** secondary keys. +** It returns: +** - VOID : in all cases. +*/ + +#define INTSORTNAME intSort2asc2 +#define INTSORTSIZE (2 * sizeof (INT)) +#define INTSORTSWAP(p,q) do { INT t, u; t = *((INT *) (p)); u = *((INT *) (p) + 1); *((INT *) (p)) = *((INT *) (q)); *((INT *) (p) + 1) = *((INT *) (q) + 1); *((INT *) (q)) = t; *((INT *) (q) + 1) = u; } while (0) +#define INTSORTCMP(p,q) ((*((INT *) (p)) < *((INT *) (q))) || ((*((INT *) (p)) == *((INT *) (q))) && (*((INT *) (p) + 1) < *((INT *) (q) + 1)))) +#include "common_sort.c" +#undef INTSORTNAME +#undef INTSORTSIZE +#undef INTSORTSWAP +#undef INTSORTCMP + +/* This routine sorts an array of 3-uples of +** INT values in ascending order by their +** first value, used as key. +** It returns: +** - VOID : in all cases. +*/ + +#define INTSORTNAME intSort3asc1 +#define INTSORTSIZE (3 * sizeof (INT)) +#define INTSORTSWAP(p,q) do { INT t, u, v; t = *((INT *) (p)); u = *((INT *) (p) + 1); v = *((INT *) (p) + 2); *((INT *) (p)) = *((INT *) (q)); *((INT *) (p) + 1) = *((INT *) (q) + 1); *((INT *) (p) + 2) = *((INT *) (q) + 2); *((INT *) (q)) = t; *((INT *) (q) + 1) = u; *((INT *) (q) + 2) = v; } while (0) +#define INTSORTCMP(p,q) (*((INT *) (p)) < *((INT *) (q))) +#include "common_sort.c" +#undef INTSORTNAME +#undef INTSORTSIZE +#undef INTSORTSWAP +#undef INTSORTCMP + +/* This routine sorts an array of 3-uples of +** INT values in ascending order by their +** first and second values, used as primary +** and secondary keys. +** It returns: +** - VOID : in all cases. +*/ + +#define INTSORTNAME intSort3asc2 +#define INTSORTSIZE (3 * sizeof (INT)) +#define INTSORTSWAP(p,q) do { INT t, u, v; t = *((INT *) (p)); u = *((INT *) (p) + 1); v = *((INT *) (p) + 2); *((INT *) (p)) = *((INT *) (q)); *((INT *) (p) + 1) = *((INT *) (q) + 1); *((INT *) (p) + 2) = *((INT *) (q) + 2); *((INT *) (q)) = t; *((INT *) (q) + 1) = u; *((INT *) (q) + 2) = v; } while (0) +#define INTSORTCMP(p,q) ((*((INT *) (p)) < *((INT *) (q))) || ((*((INT *) (p)) == *((INT *) (q))) && (*((INT *) (p) + 1) < *((INT *) (q) + 1)))) +#include "common_sort.c" +#undef INTSORTNAME +#undef INTSORTSIZE +#undef INTSORTSWAP +#undef INTSORTCMP + +/* This routine computes the greatest common +** divisor of two non-negative integers u and v. +** It returns: +** - x : the GCD of u and v. +*/ + +INT +intGcd ( +INT u, +INT v) +{ + INT t; + + if (v < u) { /* u should always be the biggest */ + t = u; + u = v; + v = t; + } + + while (v != 0) { + t = v; + v = u % v; + u = t; + } + + return (u); +} diff --git a/scotch_6.0.3/src/libscotch/common_memory.c b/scotch_6.0.3/src/libscotch/common_memory.c new file mode 100644 index 00000000..309badb6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_memory.c @@ -0,0 +1,587 @@ +/* Copyright 2004,2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_memory.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** This module handles errors. **/ +/** **/ +/** DATES : # Version 0.0 : from : 07 sep 2001 **/ +/** to 07 sep 2001 **/ +/** # Version 0.1 : from : 14 apr 2001 **/ +/** to 24 mar 2003 **/ +/** # Version 2.0 : from : 01 jul 2008 **/ +/** to : 01 jul 2008 **/ +/** # Version 5.1 : from : 22 nov 2008 **/ +/** to : 27 jun 2010 **/ +/** # Version 6.0 : from : 11 jun 2012 **/ +/** to : 10 oct 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON_MEMORY + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include "common.h" + +#define COMMON_MEMORY_SZSP (MAX ((sizeof (size_t)), (sizeof (double)))) /* Space for size, properly aligned */ + +#ifdef COMMON_MEMORY_CHECK + +#ifndef COMMON_MEMORY_TRACE +#define COMMON_MEMORY_TRACE +#endif /* COMMON_MEMORY_TRACE */ + +#define MEMORY_CHECK_BLOCKS 10000 +#define MEMORY_CHECK_BORDER 16384 /* Huge sentinel block */ + +#define COMMON_MEMORY_SKEW MEMORY_CHECK_BORDER +#define COMMON_MEMORY_OVHD (MEMORY_CHECK_BORDER * 2) + +static int memorycheckenabled = COMMON_MEMORY_CHECK; /* Set to 1 by default */ +static char memorycheckmagktab[16] = { 0123, 0156, 0371, 0012, 0345, 0272, 0301, 0234, + 0167, 0010, 0127, 0254, 0321, 0012, 0276, 0143 }; +static void * memorycheckbloktab[MEMORY_CHECK_BLOCKS] = { NULL }; /* Pre-allocated static array, less easily wrecked by out-of-bound heap memory writes */ +static int memorycheckbloknbr = 0; +static void * memorycheckwtchval = NULL; /* Block address to watch */ + +#endif /* COMMON_MEMORY_CHECK */ + +/*********************************/ +/* */ +/* The memory checking routines. */ +/* */ +/*********************************/ + +#ifdef COMMON_MEMORY_CHECK + +static +void +memCheckBlock ( +void * blokptr) +{ + char * zoneptr; + char * zoneend; + int zoneidx; + size_t bloksiz; + + bloksiz = *((size_t *) blokptr); + + for (zoneptr = (char *) blokptr + COMMON_MEMORY_SZSP, /* Check "before" sentinel */ + zoneend = (char *) blokptr + MEMORY_CHECK_BORDER, zoneidx = 0; + zoneptr < zoneend; ) { + if (*zoneptr ++ != memorycheckmagktab[zoneidx ++ % 16]) { + errorPrintW ("memoryCheck: error before block at %p, real size %ld", + (char *) blokptr + MEMORY_CHECK_BORDER, + (long) bloksiz); + break; + } + } + + for (zoneptr = (char *) blokptr + MEMORY_CHECK_BORDER + bloksiz, /* Check "after" sentinel */ + zoneend = (char *) zoneptr + MEMORY_CHECK_BORDER, zoneidx = 0; + zoneptr < zoneend; ) { + if (*zoneptr ++ != memorycheckmagktab[zoneidx ++ % 16]) { + errorPrintW ("memoryCheck: error after block at %p, real size %ld", + (char *) blokptr + MEMORY_CHECK_BORDER, + (long) bloksiz); + break; + } + } +} + +int +memCheck () +{ + int bloknum; + + for (bloknum = 0; bloknum < memorycheckbloknbr; bloknum ++) + memCheckBlock (memorycheckbloktab[bloknum]); +} + +int +memCheckToggle () +{ + return (memorycheckenabled = (memorycheckenabled != 0) ? 0 : 1); +} + +int +memCheckExists ( +void * blokptr) +{ + void * bloktmp; + int bloknum; + + bloktmp = (void *) ((char *) blokptr - MEMORY_CHECK_BORDER); + + for (bloknum = 0; bloknum < memorycheckbloknbr; bloknum ++) { + if (memorycheckbloktab[bloknum] == bloktmp) + return (1); + } + + return (0); +} + +size_t +memCheckSize ( +void * blokptr) +{ + void * bloktmp; + int bloknum; + + bloktmp = (void *) ((char *) blokptr - MEMORY_CHECK_BORDER); + + for (bloknum = 0; bloknum < memorycheckbloknbr; bloknum ++) { + if (memorycheckbloktab[bloknum] == bloktmp) + return (*((size_t *) bloktmp)); + } + + return (-1); +} + +void +memCheckWatch ( +void * blokptr) +{ + memorycheckwtchval = blokptr; /* Record user location */ +} + +static +void +memCheckEnlist ( +void * blokptr, +size_t bloksiz) +{ + char * zoneptr; + char * zoneend; + int zoneidx; + + if (memorycheckbloknbr >= MEMORY_CHECK_BLOCKS) { + errorPrintW ("memoryEnlist: too many blocks"); + return; + } + + if (memorycheckenabled != 0) + memCheck (); + + memorycheckbloktab[memorycheckbloknbr ++] = blokptr; /* Insert block into checked block array */ + + for (zoneptr = (char *) blokptr + COMMON_MEMORY_SZSP, /* Set "before" sentinel */ + zoneend = (char *) blokptr + MEMORY_CHECK_BORDER, zoneidx = 0; + zoneptr < zoneend; ) + *zoneptr ++ = memorycheckmagktab[zoneidx ++ % 16]; + + if (memorycheckwtchval == (void *) zoneend) /* Test user location */ + errorPrintW ("memoryEnlist: watched block address %p enlisted", zoneend); + + for (zoneptr = (char *) blokptr + MEMORY_CHECK_BORDER + bloksiz, /* Set "after" sentinel */ + zoneend = (char *) zoneptr + MEMORY_CHECK_BORDER, zoneidx = 0; + zoneptr < zoneend; ) + *zoneptr ++ = memorycheckmagktab[zoneidx ++ % 16]; +} + +static +void +memCheckDelist ( +void * blokptr) +{ + int bloknum; + + if (memorycheckenabled != 0) + memCheck (); + + for (bloknum = 0; bloknum < memorycheckbloknbr; bloknum ++) { + if (memorycheckbloktab[bloknum] == blokptr) + break; + } + if (bloknum == memorycheckbloknbr) { + errorPrintW ("memoryDelist: block not found"); + return; + } + + if (memorycheckwtchval == (void *) ((char *) blokptr + MEMORY_CHECK_BORDER)) + errorPrintW ("memoryDelist: watched block address %p unlisted", blokptr); + + memorycheckbloktab[bloknum] = memorycheckbloktab[-- memorycheckbloknbr]; /* Remove block from checked block array */ +} + +#endif /* COMMON_MEMORY_CHECK */ + +/*********************************/ +/* */ +/* The memory handling routines. */ +/* */ +/*********************************/ + +/* This routine keeps track of the amount of +** allocated memory, and keeps track of the +** maximum allowed. +*/ + +#ifdef COMMON_MEMORY_TRACE + +#ifndef COMMON_MEMORY_SKEW +#define COMMON_MEMORY_SKEW COMMON_MEMORY_SZSP /* Increase block size just to store size */ +#define COMMON_MEMORY_OVHD COMMON_MEMORY_SKEW +#endif /* COMMON_MEMORY_SKEW */ + +static intptr_t memorysiz = 0; /*+ Number of allocated bytes +*/ +static intptr_t memorymax = 0; /*+ Maximum amount of allocated data +*/ + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) +static int muteflag = 1; /*+ Flag for mutex initialization +*/ +static pthread_mutex_t mutelocdat; /*+ Local mutex for updates +*/ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + +/* This routine allocates and records +** a memory block. +** It returns: +** - NULL : if block could not be allocated. +** - !NULL : location of the allocated block. +*/ + +void * +memAllocRecord ( +size_t newsiz) +{ + byte * newptr; + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + if (muteflag != 0) { /* Unsafe code with respect to race conditions but should work as first allocs are sequential */ + muteflag = 0; + pthread_mutex_init (&mutelocdat, NULL); /* Initialize local mutex */ + } + pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + + if ((newptr = malloc (newsiz + COMMON_MEMORY_OVHD)) != NULL) { /* Non-zero size will guarantee non-NULL pointers */ + memorysiz += (intptr_t) newsiz; + if (memorymax < memorysiz) + memorymax = memorysiz; + +#ifdef COMMON_MEMORY_CHECK + memCheckEnlist (newptr, newsiz); +#endif /* COMMON_MEMORY_CHECK */ + + *((size_t *) newptr) = newsiz; /* Record size for freeing */ + newptr += COMMON_MEMORY_SKEW; /* Skew pointer while enforcing alignment */ + } + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + + return ((void *) newptr); /* Return skewed pointer or NULL */ +} + +/* This routine reallocates and records +** a memory block. +** It returns: +** - NULL : if block could not be reallocated. +** - !NULL : location of the reallocated block. +*/ + +void * +memReallocRecord ( +void * oldptr, +size_t newsiz) +{ + byte * tmpptr; + byte * newptr; + size_t oldsiz; + + tmpptr = ((byte *) oldptr) - COMMON_MEMORY_SKEW; + oldsiz = *((size_t *) tmpptr); + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + +#ifdef COMMON_MEMORY_CHECK + memCheckDelist (tmpptr); +#endif /* COMMON_MEMORY_CHECK */ + + if ((newptr = realloc (tmpptr, newsiz + COMMON_MEMORY_OVHD)) != NULL) { + memorysiz -= (intptr_t) oldsiz; /* Subtract then add unsigned values to avoid handling signs */ + memorysiz += (intptr_t) newsiz; + if (memorymax < memorysiz) + memorymax = memorysiz; + +#ifdef COMMON_MEMORY_CHECK + memCheckEnlist (newptr, newsiz); +#endif /* COMMON_MEMORY_CHECK */ + + *((size_t *) newptr) = newsiz; /* Record size for freeing */ + newptr += COMMON_MEMORY_SKEW; /* Skew pointer while enforcing alignment */ + } + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + + return ((void *) newptr); /* Return skewed pointer or NULL */ +} + +/* This routine frees a recorded +** memory block. +** It returns: +** - void : in all cases. +*/ + +void +memFreeRecord ( +void * oldptr) +{ + byte * tmpptr; + size_t oldsiz; + + tmpptr = ((byte *) oldptr) - COMMON_MEMORY_SKEW; + oldsiz = *((size_t *) tmpptr); + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + +#ifdef COMMON_MEMORY_CHECK + memCheckDelist (tmpptr); +#endif /* COMMON_MEMORY_CHECK */ + + free (tmpptr); + memorysiz -= oldsiz; + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ +} + +/* This routine returns the memory +** footprint of Scotch at the date +** of the call. +** It returns: +** - x : current memory footprint. +*/ + +IDX +memCur () +{ + intptr_t memotmp; + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + + memotmp = memorysiz; + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + + return ((IDX) memotmp); +} + +/* This routine returns the maximum memory +** footprint of Scotch at the date of the +** call. +** It returns: +** - x : current maximum memory footprint. +*/ + +IDX +memMax () +{ + intptr_t memotmp; + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + + memotmp = memorymax; + +#if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) + pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ +#endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ + + return ((IDX) memotmp); +} + +#else /* COMMON_MEMORY_TRACE */ + +/* Dummy routines if not compiled with flag +** COMMON_MEMORY_TRACE set. +*/ + +IDX +memCur () +{ + return ((IDX) -1); +} + +IDX +memMax () +{ + return ((IDX) -1); +} + +#endif /* COMMON_MEMORY_TRACE */ + +/* This routine allocates a set of arrays in +** a single memAlloc()'ed array, the address +** of which is placed in the first argument. +** Arrays to be allocated are described as +** a duplet of ..., &ptr, size, ..., +** terminated by a NULL pointer. +** It returns: +** - !NULL : pointer to block, all arrays allocated. +** - NULL : no array allocated. +*/ + +void * +memAllocGroup ( +void ** memptr, /*+ Pointer to first argument to allocate +*/ +...) +{ + va_list memlist; /* Argument list of the call */ + byte ** memloc; /* Pointer to pointer of current argument */ + size_t memoff; /* Offset value of argument */ + byte * blkptr; /* Pointer to memory chunk */ + + memoff = 0; + memloc = (byte **) memptr; /* Point to first memory argument */ + va_start (memlist, memptr); /* Start argument parsing */ + while (memloc != NULL) { /* As long as not NULL pointer */ + memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); + memoff += va_arg (memlist, size_t); + memloc = va_arg (memlist, byte **); + } + + if ((blkptr = (byte *) memAlloc (memoff)) == NULL) { /* If cannot allocate */ + *memptr = NULL; /* Set first pointer to NULL */ + return (NULL); + } + + memoff = 0; + memloc = (byte **) memptr; /* Point to first memory argument */ + va_start (memlist, memptr); /* Restart argument parsing */ + while (memloc != NULL) { /* As long as not NULL pointer */ + memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); /* Pad */ + *memloc = blkptr + memoff; /* Set argument address */ + memoff += va_arg (memlist, size_t); /* Accumulate padded sizes */ + memloc = va_arg (memlist, void *); /* Get next argument pointer */ + } + + return ((void *) blkptr); +} + +/* This routine reallocates a set of arrays in +** a single memRealloc()'ed array passed as +** first argument, and the address of which +** is placed in the second argument. +** Arrays to be allocated are described as +** a duplet of ..., &ptr, size, ..., +** terminated by a NULL pointer. +** It returns: +** - !NULL : pointer to block, all arrays allocated. +** - NULL : no array allocated. +*/ + +void * +memReallocGroup ( +void * oldptr, /*+ Pointer to block to reallocate +*/ +...) +{ + va_list memlist; /* Argument list of the call */ + byte ** memloc; /* Pointer to pointer of current argument */ + size_t memoff; /* Offset value of argument */ + byte * blkptr; /* Pointer to memory chunk */ + + memoff = 0; + va_start (memlist, oldptr); /* Start argument parsing */ + + while ((memloc = va_arg (memlist, byte **)) != NULL) { /* As long as not NULL pointer */ + memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); /* Pad */ + memoff += va_arg (memlist, size_t); /* Accumulate padded sizes */ + } + + if ((blkptr = (byte *) memRealloc (oldptr, memoff)) == NULL) /* If cannot allocate block */ + return (NULL); + + memoff = 0; + va_start (memlist, oldptr); /* Restart argument parsing */ + while ((memloc = va_arg (memlist, byte **)) != NULL) { /* As long as not NULL pointer */ + memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); /* Pad */ + *memloc = blkptr + memoff; /* Set argument address */ + memoff += va_arg (memlist, size_t); /* Accumulate padded sizes */ + } + + return ((void *) blkptr); +} + +/* This routine computes the offsets of arrays +** of given sizes and types with respect to a +** given base address passed as first argument. +** Arrays the offsets of which are to be computed +** are described as a duplet of ..., &ptr, size, ..., +** terminated by a NULL pointer. +** It returns: +** - !NULL : in all cases, pointer to the end of +** the memory area. +*/ + +void * +memOffset ( +void * memptr, /*+ Pointer to base address of memory area +*/ +...) +{ + va_list memlist; /* Argument list of the call */ + byte ** memloc; /* Pointer to pointer of current argument */ + size_t memoff; /* Offset value of argument */ + + memoff = 0; + va_start (memlist, memptr); /* Start argument parsing */ + + while ((memloc = va_arg (memlist, byte **)) != NULL) { /* As long as not NULL pointer */ + memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); + *memloc = (byte *) memptr + memoff; /* Set argument address */ + memoff += va_arg (memlist, size_t); /* Accumulate padded sizes */ + } + + return ((void *) ((byte *) memptr + memoff)); +} diff --git a/scotch_6.0.3/src/libscotch/common_sort.c b/scotch_6.0.3/src/libscotch/common_sort.c new file mode 100644 index 00000000..6639d1fd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_sort.c @@ -0,0 +1,255 @@ +/* This file is part of the Scotch distribution. It does +** not have the standard Scotch header with the INRIA & co. +** copyright notice because it is a very slight adaptation +** of the qsort routine of glibc 2.4, taylored to match +** Scotch needs. As Scotch is distributed according to the +** CeCILL-C license, which is LGPL-compatible, no further +** notices are required. Hence, this "common_sort.c" file +** is distributed according the terms of the LGPL, see +** copyright notice just below. +*/ + +/* Copyright (C) 1991,1992,1996,1997,1999,2004 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. */ + +/* If you consider tuning this algorithm, you should consult first: + Engineering a sort function; Jon Bentley and M. Douglas McIlroy; + Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */ + +#ifndef MAX_THRESH + +#define MAX_THRESH 6 + +#define max_thresh (MAX_THRESH * INTSORTSIZE) /* Variable turned into constant */ + +/* Stack node declarations used to store unfulfilled partition obligations. */ +typedef struct + { + char *lo; + char *hi; + } stack_node; + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ +/* The stack needs log (total_elements) entries (we could even subtract + log(MAX_THRESH)). Since total_elements has type size_t, we get as + upper bound for log (total_elements): + bits per byte (CHAR_BIT) * sizeof(size_t). */ +#define STACK_SIZE (CHAR_BIT * sizeof (INT)) +#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top)) +#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi))) +#define STACK_NOT_EMPTY (stack < top) + +#endif /* MAX_THRESH */ + +/* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of SIZE_MAX is allocated on the + stack. Assuming a 32-bit (64 bit) integer for size_t, this needs + only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). + Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segments. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (total_elems) + stack size is needed (actually O(1) in this case)! */ + +/* To be defined : +** INTSORTQUAL : whether the function is "static" or not +** INTSORTNAME : Name of function +** INTSORTSIZE : Size of elements to sort +** INTSORTSWAP : Swapping macro +** INTSORTCMP : Comparison function +*/ + +#ifdef INTSORTQUAL +INTSORTQUAL +#endif /* INTSORTQUAL */ +void +INTSORTNAME ( +void * const pbase, /*+ Array to sort +*/ +const INT total_elems) /*+ Number of entries to sort +*/ +{ + register char *base_ptr = (char *) pbase; + + if (total_elems == 0) + /* Avoid lossage with unsigned arithmetic below. */ + return; + + if (total_elems > MAX_THRESH) + { + char *lo = base_ptr; + char *hi = &lo[INTSORTSIZE * (total_elems - 1)]; + stack_node stack[STACK_SIZE]; + stack_node *top = stack; + + PUSH (NULL, NULL); + + while (STACK_NOT_EMPTY) + { + char *left_ptr; + char *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. */ + + char *mid = lo + INTSORTSIZE * ((hi - lo) / INTSORTSIZE >> 1); + + if (INTSORTCMP ((void *) mid, (void *) lo)) + INTSORTSWAP (mid, lo); + if (INTSORTCMP ((void *) hi, (void *) mid)) + INTSORTSWAP (mid, hi); + else + goto jump_over; + if (INTSORTCMP ((void *) mid, (void *) lo)) + INTSORTSWAP (mid, lo); + jump_over:; + + left_ptr = lo + INTSORTSIZE; + right_ptr = hi - INTSORTSIZE; + + /* 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 (INTSORTCMP ((void *) left_ptr, (void *) mid)) + left_ptr += INTSORTSIZE; + + while (INTSORTCMP ((void *) mid, (void *) right_ptr)) + right_ptr -= INTSORTSIZE; + + if (left_ptr < right_ptr) + { + INTSORTSWAP (left_ptr, right_ptr); + if (mid == left_ptr) + mid = right_ptr; + else if (mid == right_ptr) + mid = left_ptr; + left_ptr += INTSORTSIZE; + right_ptr -= INTSORTSIZE; + } + else if (left_ptr == right_ptr) + { + left_ptr += INTSORTSIZE; + right_ptr -= INTSORTSIZE; + 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 ((size_t) (right_ptr - lo) <= max_thresh) + { + if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore both small partitions. */ + POP (lo, hi); + else + /* Ignore small left partition. */ + lo = left_ptr; + } + else if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore small right partition. */ + hi = right_ptr; + else if ((right_ptr - lo) > (hi - left_ptr)) + { + /* Push larger left partition indices. */ + PUSH (lo, right_ptr); + lo = left_ptr; + } + else + { + /* Push larger right partition indices. */ + PUSH (left_ptr, hi); + hi = right_ptr; + } + } + } + + /* Once the BASE_PTR 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_PTR 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!). */ + +#define min(x, y) ((x) < (y) ? (x) : (y)) + + { + char *const end_ptr = &base_ptr[INTSORTSIZE * (total_elems - 1)]; + char *tmp_ptr = base_ptr; + char *thresh = min(end_ptr, base_ptr + max_thresh); + register char *run_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 + INTSORTSIZE; run_ptr <= thresh; run_ptr += INTSORTSIZE) + if (INTSORTCMP ((void *) run_ptr, (void *) tmp_ptr)) + tmp_ptr = run_ptr; + + if (tmp_ptr != base_ptr) + INTSORTSWAP (tmp_ptr, base_ptr); + + /* Insertion sort, running from left-hand-side up to right-hand-side. */ + + run_ptr = base_ptr + INTSORTSIZE; + while ((run_ptr += INTSORTSIZE) <= end_ptr) + { + tmp_ptr = run_ptr - INTSORTSIZE; + while (INTSORTCMP ((void *) run_ptr, (void *) tmp_ptr)) + tmp_ptr -= INTSORTSIZE; + + tmp_ptr += INTSORTSIZE; + if (tmp_ptr != run_ptr) + { + char *trav; + + trav = run_ptr + INTSORTSIZE; + while (--trav >= run_ptr) + { + char c = *trav; + char *hi, *lo; + + for (hi = lo = trav; (lo -= INTSORTSIZE) >= tmp_ptr; hi = lo) + *hi = *lo; + *hi = c; + } + } + } + } +} diff --git a/scotch_6.0.3/src/libscotch/common_string.c b/scotch_6.0.3/src/libscotch/common_string.c new file mode 100644 index 00000000..f1e02e6f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_string.c @@ -0,0 +1,109 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_string.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel direct block solver. **/ +/** These lines are common routines used **/ +/** by all modules. **/ +/** **/ +/** DATES : # Version 5.1 : from : 23 jul 2010 **/ +/** to 23 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include +#include "common.h" + +/********************************/ +/* */ +/* String substitution routine. */ +/* */ +/********************************/ + +static +void +stringSubst2 ( +char * const bsrcptr, +char * const bdstptr, +const char * const pattstr, +const char * const replstr, +const int pattsiz, +const int replsiz) +{ + char * pattptr; + int pattidx; + + pattptr = strstr (bsrcptr, pattstr); /* Search for the pattern in the remaining source string */ + pattidx = (pattptr == NULL) ? (strlen (bsrcptr) + 1): (pattptr - bsrcptr); /* Get length of unchanged part */ + + if (replsiz < pattsiz) /* If replacement is smaller, pre-move unchanged part */ + memMov (bdstptr, bsrcptr, pattidx * sizeof (char)); + + if (pattptr != NULL) /* If remaining part of string has to be processed */ + stringSubst2 (pattptr + pattsiz, bdstptr + pattidx + replsiz, pattstr, replstr, pattsiz, replsiz); + + if (replsiz > pattsiz) /* If replacement is longer, post-move unchanged part */ + memMov (bdstptr, bsrcptr, pattidx * sizeof (char)); + + if (pattptr != NULL) /* If there is something to replace */ + memCpy (bdstptr + pattidx, replstr, replsiz * sizeof (char)); /* Write replacement string */ + + return; +} + +void +stringSubst ( +char * const buffptr, /* String to search into */ +const char * const pattstr, /* Pattern to search for */ +const char * const replstr) /* Replacement string */ +{ + int pattsiz; + int replsiz; + + pattsiz = strlen (pattstr); + replsiz = strlen (replstr); + + stringSubst2 (buffptr, buffptr, pattstr, replstr, pattsiz, replsiz); +} diff --git a/scotch_6.0.3/src/libscotch/common_stub.c b/scotch_6.0.3/src/libscotch/common_stub.c new file mode 100644 index 00000000..35e7e057 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_stub.c @@ -0,0 +1,79 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_stub.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are common stub routines **/ +/** for several systems, used by all **/ +/** modules. **/ +/** **/ +/** DATES : # Version 5.0 : from : 11 may 2008 **/ +/** to 11 may 2008 **/ +/** # Version 5.1 : from : 27 jun 2010 **/ +/** to 01 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define COMMON + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include "common.h" + +/* +** The static and global variables. +*/ + +int commonStubDummy; /* Dummy variable so that the object file will never be empty */ + +/******************/ +/* */ +/* Stub routines. */ +/* */ +/******************/ + +#ifdef COMMON_STUB_FORK +int +fork () +{ + errorPrint ("fork() not implemented on this system"); + return (-1); +} +#endif /* COMMON_STUB_FORK */ diff --git a/scotch_6.0.3/src/libscotch/common_thread.c b/scotch_6.0.3/src/libscotch/common_thread.c new file mode 100644 index 00000000..23738921 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/common_thread.c @@ -0,0 +1,418 @@ +/* Copyright 2012-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : common_thread.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module provides routines to ease **/ +/** the use of Posix threads. **/ +/** **/ +/** DATES : # Version 6.0 : from : 04 jul 2012 **/ +/** to 14 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#ifdef SCOTCH_PTHREAD_AFFINITY_LINUX +#define _GNU_SOURCE +#include +#endif /* SCOTCH_PTHREAD_AFFINITY_LINUX */ + +#define COMMON_THREAD + +#ifndef COMMON_NOMODULE +#include "module.h" +#endif /* COMMON_NOMODULE */ +#include "common.h" + +/*****************************/ +/* */ +/* Thread handling routines. */ +/* */ +/*****************************/ + +#ifdef SCOTCH_PTHREAD + +/* These routines implement the classical barrier +** operations for systems that do not provide them. +*/ + +#ifdef COMMON_PTHREAD_BARRIER + +int +threadBarrierInit ( +ThreadBarrier * barrptr, +void * attrptr, /* Not used */ +int thrdnbr) +{ + barrptr->thrdnbr = thrdnbr; + barrptr->thrdcur = 0; + barrptr->instnum = 0; + pthread_mutex_init (&barrptr->mutedat, NULL); + pthread_cond_init (&barrptr->conddat, NULL); + + return (0); +} + +/* +** +*/ + +int +threadBarrierDestroy ( +ThreadBarrier * barrptr) +{ + pthread_cond_destroy (&barrptr->conddat); + pthread_mutex_destroy (&barrptr->mutedat); + + return (0); +} + +/* +** +*/ + +int +threadBarrierWait ( +ThreadBarrier * barrptr) +{ + int instnum; + int thrdcur; + int o; + + pthread_mutex_lock (&barrptr->mutedat); + + thrdcur = barrptr->thrdcur + 1; + instnum = barrptr->instnum; + + o = 0; /* Assume thread will not be the last one */ + + if (thrdcur == barrptr->thrdnbr) { + barrptr->thrdcur = 0; + barrptr->instnum = instnum + 1; + pthread_cond_broadcast (&barrptr->conddat); + o = PTHREAD_BARRIER_SERIAL_THREAD; /* Last thread returns special value */ + } + else { + barrptr->thrdcur = thrdcur; + do + pthread_cond_wait (&barrptr->conddat, &barrptr->mutedat); + while (barrptr->instnum == instnum); + } + + pthread_mutex_unlock (&barrptr->mutedat); + + return (o); +} + +#endif /* COMMON_PTHREAD_BARRIER */ + +/* This routine performs a synchronous +** reduction operation on the given block +** of threads. The routine is called only +** if the two threads in the reduction binary +** tree exist. +** A final, global barrier may be necessary for +** all threads to benefit from the result of the +** reduction operation. +** It returns: +** - void : in all cases. +*/ + +void +threadReduce ( +void * const dataptr, /* Per-thread data block */ +void * const contptr, /* Pointer to thread contents */ +ThreadReduceFunc const redfptr, /* Pointer to reduction routine */ +int rootnum) /* Root of reduction */ +{ + ThreadHeader * restrict const thrdptr = (ThreadHeader *) dataptr; + ThreadGroupHeader * restrict const grouptr = thrdptr->grouptr; + const size_t datasiz = grouptr->datasiz; + const int thrdnbr = grouptr->thrdnbr; + const int thrdnum = thrdptr->thrdnum; + int thrdnsk; /* Rank of thread in skewed reduction tree */ + int thrdmsk; + + thrdnsk = (thrdnum + thrdnbr - rootnum) % thrdnbr; + for (thrdmsk = 1; thrdmsk < thrdnbr; thrdmsk <<= 1) { + int thrdesk; /* Skewed rank of end thread */ + + threadBarrierWait (&grouptr->barrdat); + + thrdesk = thrdnsk ^ thrdmsk; /* Get skewed rank of end thread */ + + if (thrdesk < thrdnbr) { /* If end thread exists */ + if (thrdesk > thrdnsk) { /* If we are on the receiving side */ + int thrdend; + int thrddlt; + + thrdend = (thrdesk + rootnum) % thrdnbr; + thrddlt = thrdend - thrdnum; + redfptr (dataptr, contptr, (void *) ((byte *) contptr + thrddlt * datasiz)); /* Call reduction routine */ + } + else /* We are on the sending side */ + thrdnsk += thrdnbr; /* Make sure we will no longer work */ + } + } +} + +/* This routine performs a synchronous +** scan operation on the given block of +** threads. It requires a dummy area for +** storing every other result, hence the +** phase number that is passed to the +** auxiliary routine. +** It returns: +** - void : in all cases. +*/ + +void +threadScan ( +void * const dataptr, /* Per-thread data block */ +void * const contptr, /* Pointer to thread contents */ +ThreadScanFunc const scafptr) /* Scan function */ +{ + ThreadHeader * restrict const thrdptr = (ThreadHeader *) dataptr; + ThreadGroupHeader * restrict const grouptr = thrdptr->grouptr; + const size_t datasiz = grouptr->datasiz; + const int thrdnbr = grouptr->thrdnbr; + const int thrdnum = thrdptr->thrdnum; + int thrdmsk; + int i; + + for (thrdmsk = 1, i = 0; thrdmsk < thrdnbr; thrdmsk <<= 1, i ^= 1) ; /* Determine number of steps to go */ + if (i != 0) /* If number of steps is odd */ + scafptr (dataptr, contptr, NULL, 0); /* Pre-copy to swap area so that it will end at the right place */ + + for (thrdmsk = 1; thrdmsk < thrdnbr; thrdmsk <<= 1, i ^= 1) { + int thrdend; + + threadBarrierWait (&grouptr->barrdat); /* Barrier on all threads, even those which do not participate */ + + thrdend = thrdnum - thrdmsk; /* Get rank of end thread */ + scafptr (dataptr, contptr, (thrdend >= 0) ? (void *) ((byte *) contptr - thrdmsk * datasiz) : NULL, i); /* If end thread exists, perform scan, else just copy */ + } +} + +/* This routine actually launches the +** initial thread routine, and performs +** the necessary joins. It is its task +** to set its affinity mask, as in some +** thread implementations threads can +** only set affinity for themselves. +*/ + +static +void * +threadLaunch2 ( +void * dataptr) /* Per-thread data block */ +{ + ThreadHeader * restrict const thrdptr = (ThreadHeader *) dataptr; + ThreadGroupHeader * restrict const grouptr = thrdptr->grouptr; + const size_t datasiz = grouptr->datasiz; + const int thrdnbr = grouptr->thrdnbr; + const int thrdnum = thrdptr->thrdnum; + int thrdmsk; + int o; +#ifdef SCOTCH_PTHREAD_AFFINITY_LINUX + cpu_set_t cpuset; +#endif /* SCOTCH_PTHREAD_AFFINITY_LINUX */ + +#ifdef SCOTCH_PTHREAD_AFFINITY_LINUX + CPU_ZERO (&cpuset); + CPU_SET (thrdnum, &cpuset); /* Thread sets its own affinity */ + pthread_setaffinity_np (thrdptr->thidval, sizeof (cpu_set_t), &cpuset); +#endif /* SCOTCH_PTHREAD_AFFINITY_LINUX */ + + o = grouptr->stafptr (dataptr); /* Call start routine */ + + for (thrdmsk = 1; thrdmsk < thrdnbr; thrdmsk <<= 1) { + volatile ThreadHeader * restrict thrdtmp; /* Pointer to thread header of other thread */ + int thrdend; + + thrdend = thrdnum ^ thrdmsk; /* Get rank of end thread */ + if (thrdend >= thrdnbr) /* If end thread does not exist */ + continue; + + thrdtmp = (ThreadHeader *) ((byte *) dataptr + grouptr->datasiz * (thrdend - thrdnum)); + while (thrdtmp->thrdnum == -1) ; /* Spin-lock until end thread created */ + + if (thrdnum > thrdend) { /* If we are on the sending side */ + if (thrdtmp->thrdnum < 0) { /* If end thread could not be created */ + pthread_detach (thrdptr->thidval); /* Detach since nobody will join for us */ + o = 1; /* Set (useless) error return value */ + } + + pthread_exit ((void *) (intptr_t) o); /* Exit anyway */ + } + else { + if (thrdtmp->thrdnum < 0) /* If end thread could not be created */ + o = 1; /* Set error return value */ + else { + void * o2; + + pthread_join (thrdtmp->thidval, &o2); /* Get return value from end thread */ + o |= (int) (intptr_t) o2; /* Amalgamate return status */ + + if ((grouptr->joifptr != NULL) && /* If we have something to do */ + (o == 0)) /* And if no error in both threads */ + o |= grouptr->joifptr (dataptr, (void *) ((byte *) dataptr + thrdmsk * datasiz)); /* Call join routine */ + } + } + } + + return ((void *) (intptr_t) o); /* Thread of rank 0 returns global status */ +} + +/* This routine launches the given +** number of threads that will run the +** given start routine, and will end up +** calling the given join routine in a +** binary tree fashion. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +threadLaunch ( +void * const gdatptr, /* Pointer to thread group data block */ +void * const tdattab, /* Array of thread data */ +const size_t datasiz, /* Size of individual data array cell */ +ThreadLaunchStartFunc stafptr, /* Pointer to start routine */ +ThreadLaunchJoinFunc joifptr, /* Pointer to join routine */ +const int thrdnbr, /* Number of threads to run (including current) */ +const int flagval) /* Flag for thread operation data structures */ +{ + ThreadGroupHeader * const grouptr = (ThreadGroupHeader *) gdatptr; + ThreadHeader * thrdptr; + int thrdnum; + byte * dataptr; + void * o; + + grouptr->flagval = flagval; + grouptr->datasiz = datasiz; + grouptr->thrdnbr = thrdnbr; + grouptr->stafptr = stafptr; + grouptr->joifptr = joifptr; + + if ((flagval & THREADHASBARRIER) != 0) { + if (threadBarrierInit (&grouptr->barrdat, NULL, thrdnbr) != 0) { + errorPrint ("threadLaunch: cannot initialize barrier (1)"); + return (1); + } + } + + for (thrdnum = 0, dataptr = (byte *) tdattab; /* Prepare threads for launching */ + thrdnum < thrdnbr; thrdnum ++, dataptr += datasiz) { + ThreadHeader * thrdptr; + + thrdptr = (ThreadHeader *) dataptr; + thrdptr->thrdnum = -1; /* Set threads as not yet launched */ + } + + __sync_synchronize (); /* Full memory barrier */ + + for (thrdnum = 1, dataptr = (byte *) tdattab + datasiz; /* Launch threads from 1 to (thrdnbr - 1) */ + thrdnum < thrdnbr; thrdnum ++, dataptr += datasiz) { + ThreadHeader * thrdptr; + + thrdptr = (ThreadHeader *) dataptr; + thrdptr->grouptr = gdatptr; + thrdptr->thrdnum = thrdnum; + + if (pthread_create (&thrdptr->thidval, NULL, threadLaunch2, (void *) dataptr) != 0) { + errorPrint ("threadLaunch: cannot launch thread (%d)", thrdnum); + return (1); + } + } + + thrdptr = (ThreadHeader *) tdattab; /* Run thread 0 */ + thrdptr->grouptr = gdatptr; + thrdptr->thidval = pthread_self (); + thrdptr->thrdnum = 0; + + o = threadLaunch2 (tdattab); + + if ((flagval & THREADHASBARRIER) != 0) /* Free allocated resources */ + threadBarrierDestroy (&grouptr->barrdat); + + return ((int) (intptr_t) o); +} + +#else /* SCOTCH_PTHREAD */ + +/**********************************/ +/* */ +/* Thread handling routine stubs. */ +/* */ +/**********************************/ + +void +threadReduce ( +void * const dataptr, /* Per-thread data block */ +void * const contptr, /* Pointer to thread contents */ +ThreadReduceFunc const redfptr, /* Pointer to reduction routine */ +int rootnum) /* Root of reduction */ +{ + errorPrint ("threadReduce: Scotch not compiled with SCOTCH_PTHREAD"); +} + +void +threadScan ( +void * const dataptr, /* Per-thread data block */ +void * const contptr, /* Pointer to thread contents */ +ThreadScanFunc const scafptr) /* Scan function */ +{ + errorPrint ("threadScan: Scotch not compiled with SCOTCH_PTHREAD"); +} + +int +threadLaunch ( +void * const gdatptr, /* Pointer to thread group data block */ +void * const tdattab, /* Array of thread data */ +const size_t datasiz, /* Size of individual data array cell */ +ThreadLaunchStartFunc stafptr, /* Pointer to start routine */ +ThreadLaunchJoinFunc joifptr, /* Pointer to join routine */ +const int thrdnbr, /* Number of threads to run (including current) */ +const int flagval) /* Flag for thread operation data structures */ +{ + errorPrint ("threadLaunch: Scotch not compiled with SCOTCH_PTHREAD"); +} + +#endif /* SCOTCH_PTHREAD */ diff --git a/scotch_6.0.3/src/libscotch/dgraph.c b/scotch_6.0.3/src/libscotch/dgraph.c new file mode 100644 index 00000000..90568a5c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph.c @@ -0,0 +1,204 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Francois CHATENET (P0.0) **/ +/** Sebastien FOUCAULT (P0.0) **/ +/** Nicolas GICQUEL (P0.1) **/ +/** Jerome LACOSTE (P0.1) **/ +/** Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : This module contains the distributed **/ +/** graph data structure handling **/ +/** routines. **/ +/** **/ +/** DATES : # Version P0.0 : from : 01 apr 1997 **/ +/** to 01 apr 1997 **/ +/** # Version P0.1 : from : 12 apr 1998 **/ +/** to 20 jun 1998 **/ +/** # Version 5.0 : from : 16 feb 2005 **/ +/** to : 17 jul 2008 **/ +/** # Version 5.1 : from : 21 jun 2008 **/ +/** to : 30 jul 2010 **/ +/** # Version 6.0 : from : 12 sep 2012 **/ +/** to : 12 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" + +/*************************************/ +/* */ +/* These routines handle distributed */ +/* source graphs. */ +/* */ +/*************************************/ + +/* This routine initializes a distributed graph +** structure. In order to avoid collective +** communication whenever possible, the allocation +** of send and receive index arrays is not performed +** in the routine itself, but rather delegated to +** subsequent routines such as dgraphBuild. +** However, these arrays will not be freed by +** dgraphFree, but by dgraphExit. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphInit ( +Dgraph * restrict const grafptr, /* Distributed graph structure */ +MPI_Comm proccomm) /* Communicator to be used for all communications */ +{ + memSet (grafptr, 0, sizeof (Dgraph)); /* Clear public and private graph fields */ + + grafptr->proccomm = proccomm; /* Set private fields */ + MPI_Comm_size (proccomm, &grafptr->procglbnbr); /* Get communicator data */ + MPI_Comm_rank (proccomm, &grafptr->proclocnum); + + return (0); +} + +/* This routine frees the public and private data +** of the given distributed graph, but not its +** communicator. +** Private data could have been kept and freed only +** in dgraphExit(). Yet, freeing it along with the +** graph public data is a way to avoid memory +** fragmentation. Moreover, it allows to use compact +** private data if some graphs are known not to have +** holes. +** It is not a collective routine, as no communication +** is needed to perform the freeing of memory structures. +** It returns: +** - VOID : in all cases. +*/ + +static +void +dgraphFree2 ( +Dgraph * restrict const grafptr) +{ + if ((grafptr->flagval & DGRAPHFREETABS) != 0) { /* If local arrays must be freed */ + if (grafptr->vertloctax != NULL) + memFree (grafptr->vertloctax + grafptr->baseval); + if ((grafptr->flagval & DGRAPHVERTGROUP) == 0) { /* If vertex arrays not grouped */ + if (grafptr->vendloctax != (grafptr->vertloctax + 1)) + memFree (grafptr->vendloctax + grafptr->baseval); + if (grafptr->veloloctax != NULL) + memFree (grafptr->veloloctax + grafptr->baseval); + if (grafptr->vnumloctax != NULL) + memFree (grafptr->vnumloctax + grafptr->baseval); + if (grafptr->vlblloctax != NULL) + memFree (grafptr->vlblloctax + grafptr->baseval); + } + if (grafptr->edgeloctax != NULL) + memFree (grafptr->edgeloctax + grafptr->baseval); + if ((grafptr->flagval & DGRAPHEDGEGROUP) == 0) { /* If edge arrays not grouped */ + if (grafptr->edloloctax != NULL) + memFree (grafptr->edloloctax + grafptr->baseval); + } + } + if ((grafptr->flagval & DGRAPHFREEPSID) != 0) { /* If process send arrays must be freed */ + if (grafptr->procsidtab != NULL) + memFree (grafptr->procsidtab); + } + if ((grafptr->flagval & DGRAPHFREEEDGEGST) != 0) { /* If ghost array must be freed */ + if (grafptr->edgegsttax != NULL) + memFree (grafptr->edgegsttax + grafptr->baseval); + } + if ((grafptr->flagval & DGRAPHFREEPRIV) != 0) /* If private data has to be freed */ + if (grafptr->procdsptab != NULL) + memFree (grafptr->procdsptab); /* Free group leader of graph private data */ +} + +void +dgraphFree ( +Dgraph * restrict const grafptr) +{ + DgraphFlag flagval; + MPI_Comm proccomm; /* Data for temporarily saving private data */ + int procglbnbr; + int proclocnum; + + dgraphFree2 (grafptr); /* Free all user fields */ + + flagval = grafptr->flagval & DGRAPHFREECOMM; + proccomm = grafptr->proccomm; /* Save private fields only */ + procglbnbr = grafptr->procglbnbr; + proclocnum = grafptr->proclocnum; + + memSet (grafptr, 0, sizeof (Dgraph)); /* Reset graph structure */ + + grafptr->flagval = flagval; /* Restore private fields */ + grafptr->proccomm = proccomm; + grafptr->procglbnbr = procglbnbr; + grafptr->proclocnum = proclocnum; + + return; +} + +/* This routine destroys a distributed graph structure. +** It is not a collective routine, as no communication +** is needed to perform the freeing of memory structures. +** Private data are always destroyed. If this is not +** wanted, use dgraphFree() instead. +** It returns: +** - VOID : in all cases. +*/ + +void +dgraphExit ( +Dgraph * restrict const grafptr) +{ + if ((grafptr->flagval & DGRAPHFREECOMM) != 0) /* If communicator has to be freed */ + MPI_Comm_free (&grafptr->proccomm); /* Free it */ + + dgraphFree2 (grafptr); + +#ifdef SCOTCH_DEBUG_DGRAPH1 + memSet (grafptr, 0, sizeof (Dgraph)); +#endif /* SCOTCH_DEBUG_DGRAPH1 */ +} diff --git a/scotch_6.0.3/src/libscotch/dgraph.h b/scotch_6.0.3/src/libscotch/dgraph.h new file mode 100644 index 00000000..bbe3be90 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph.h @@ -0,0 +1,233 @@ +/* Copyright 2007-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Francois CHATENET (P0.0) **/ +/** Sebastien FOUCAULT (P0.0) **/ +/** Nicolas GICQUEL (P0.1) **/ +/** Jerome LACOSTE (P0.1) **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed source graph **/ +/** structure. **/ +/** **/ +/** DATES : # Version P0.0 : from : 01 apr 1997 **/ +/** to : 20 jun 1997 **/ +/** # Version P0.1 : from : 07 apr 1998 **/ +/** to : 20 jun 1998 **/ +/** # Version P0.2 : from : 11 may 1999 **/ +/** to : 02 feb 2000 **/ +/** # Version P0.3 : from : 16 jun 2005 **/ +/** to : 16 jun 2005 **/ +/** # Version 5.0 : from : 22 jul 2005 **/ +/** to : 03 aug 2007 **/ +/** # Version 5.1 : from : 11 nov 2007 **/ +/** to : 20 feb 2011 **/ +/** # Version 6.0 : from : 30 aug 2012 **/ +/** to : 26 sep 2012 **/ +/** **/ +/************************************************************/ + +#define DGRAPH_H + +#define PTSCOTCH_FOLD_DUP /* Activate folding on coarsening */ + +#ifndef SCOTCH_COMM_PTOP_RAT +#define SCOTCH_COMM_PTOP_RAT 0.25 /* Percentage under which point-to-point is allowed */ +#endif /* SCOTCH_COMM_PTOP_RAT */ + +/* +** The defines. +*/ + +/* Graph flags. */ + +#define DGRAPHNONE 0x0000 /* No options set */ + +#define DGRAPHFREEPRIV 0x0001 /* Set if private arrays freed on exit */ +#define DGRAPHFREECOMM 0x0002 /* MPI communicator has to be freed */ +#define DGRAPHFREETABS 0x0004 /* Set if local arrays freed on exit */ +#define DGRAPHFREEPSID 0x0008 /* Set if procsidtab freed on exit */ +#define DGRAPHFREEEDGEGST 0x0010 /* Set if edgegsttab freed on exit */ +#define DGRAPHHASEDGEGST 0x0020 /* Edge ghost array computed */ +#define DGRAPHVERTGROUP 0x0040 /* All vertex arrays grouped */ +#define DGRAPHEDGEGROUP 0x0080 /* All edge arrays grouped */ +#define DGRAPHFREEALL (DGRAPHFREEPRIV | DGRAPHFREECOMM | DGRAPHFREETABS | DGRAPHFREEPSID | DGRAPHFREEEDGEGST) +#define DGRAPHCOMMPTOP 0x0100 /* Use point-to-point collective communication */ + +#define DGRAPHBITSUSED 0x01FF /* Significant bits for plain distributed graph routines */ +#define DGRAPHBITSNOTUSED 0x0200 /* Value above which bits not used by plain distributed graph routines */ + +/* Used in algorithms */ + +#define COARPERTPRIME 31 /* Prime number */ +#define COARHASHPRIME 179 /* Prime number */ + +/* +** The type and structure definitions. +*/ + +/* The graph basic types, which must be signed. */ + +#ifndef GNUMMAX /* If graph.h not included */ +typedef INT Gnum; /* Vertex or edge number */ +#define GNUMMAX (INTVALMAX) /* Maximum Gnum value */ +#define GNUMSTRING INTSTRING /* String to printf a Gnum */ +#endif /* GNUMMAX */ + +#define GNUM_MPI COMM_INT /* MPI type for Gnum is MPI type for INT */ + +#define GRAPHPART_MPI COMM_BYTE /* Raw byte type for graph parts */ + +/* Tags used for point-to-point communications. */ + +typedef enum DgraphTag_ { + TAGPROCVRTTAB = 0, /*+ procvrttab message +*/ + TAGVERTLOCTAB, /*+ vertloctab message +*/ + TAGVENDLOCTAB, /*+ vendloctab message +*/ + TAGVELOLOCTAB, /*+ veloloctab message +*/ + TAGVNUMLOCTAB, /*+ vnumloctab message +*/ + TAGVLBLLOCTAB, /*+ vlblloctab message +*/ + TAGEDGELOCTAB, /*+ edgeloctab message +*/ + TAGEDLOLOCTAB, /*+ edloloctab message +*/ + TAGDATALOCTAB, /*+ Generic data message +*/ + TAGOK, /*+ Positive answer +*/ + TAGBAD, /*+ Negative answer +*/ + TAGHALO = 100, /*+ Tag class for halo +*/ + TAGCOARSEN = 200, /*+ Tag class for coarsening +*/ + TAGMATCH = 300, /*+ Tag class for matching +*/ + TAGFOLD = 400, /*+ Tag class for folding +*/ + TAGBAND = 500 /*+ Tag class for band graph +*/ +} DgraphTag; + +/*+ The graph flag type. +*/ + +typedef int DgraphFlag; /*+ Graph property flags +*/ + +/*+ The vertex part type, in compressed form. From graph.h +*/ + +#ifndef GRAPH_H +typedef byte GraphPart; +#endif /* GRAPH_H */ + +/* The distributed graph structure. */ + +typedef struct Dgraph_ { + DgraphFlag flagval; /*+ Graph properties +*/ + Gnum baseval; /*+ Base index for edge/vertex arrays +*/ + Gnum vertglbnbr; /*+ Global number of vertices +*/ + Gnum vertglbmax; /*+ Maximum number of local vertices over all processes +*/ + Gnum vertgstnbr; /*+ Number of local + ghost vertices +*/ + Gnum vertgstnnd; /*+ vertgstnbr + baseval +*/ + Gnum vertlocnbr; /*+ Local number of vertices +*/ + Gnum vertlocnnd; /*+ Local number of vertices + baseval +*/ + Gnum * vertloctax; /*+ Local vertex beginning index array [based] +*/ + Gnum * vendloctax; /*+ Local vertex end index array [based] +*/ + Gnum * veloloctax; /*+ Local vertex load array if present +*/ + Gnum velolocsum; /*+ Local sum of all vertex loads +*/ + Gnum veloglbsum; /*+ Global sum of all vertex loads +*/ + Gnum * vnumloctax; /*+ Arrays of global vertex numbers in original graph +*/ + Gnum * vlblloctax; /*+ Arrays of vertex labels (when read from file) +*/ + Gnum edgeglbnbr; /*+ Global number of arcs +*/ + Gnum edgeglbmax; /*+ Maximum number of local edges over all processes +*/ + Gnum edgelocnbr; /*+ Number of local edges +*/ + Gnum edgelocsiz; /*+ Size of local edge array (= edgelocnbr when compact) +*/ + Gnum edgeglbsmx; /*+ Maximum size of local edge arrays over all processes +*/ + Gnum * edgegsttax; /*+ Edge array holding local indices of neighbors [based] +*/ + Gnum * edgeloctax; /*+ Edge array holding global neighbor numbers [based] +*/ + Gnum * edloloctax; /*+ Edge load array +*/ + Gnum degrglbmax; /*+ Maximum degree over all processes +*/ + MPI_Comm proccomm; /*+ Graph communicator +*/ + int prockeyval; /*+ Communicator key value: folded communicators are distinct +*/ + int procglbnbr; /*+ Number of processes sharing graph data +*/ + int proclocnum; /*+ Number of this process +*/ + Gnum * procvrttab; /*+ Global array of vertex number ranges [+1,based] +*/ + Gnum * proccnttab; /*+ Count array for local number of vertices +*/ + Gnum * procdsptab; /*+ Displacement array with respect to proccnttab [+1,based] +*/ + int procngbnbr; /*+ Number of neighboring processes +*/ + int procngbmax; /*+ Maximum number of neighboring processes +*/ + int * procngbtab; /*+ Array of neighbor process numbers [sorted] +*/ + int * procrcvtab; /*+ Number of vertices to receive in ghost vertex sub-arrays +*/ + int procsndnbr; /*+ Overall size of local send array +*/ + int * procsndtab; /*+ Number of vertices to send in ghost vertex sub-arrays +*/ + int * procsidtab; /*+ Array of indices to build communication vectors (send) +*/ + int procsidnbr; /*+ Size of the send index array +*/ +} Dgraph; + +/* +** The function prototypes. +*/ + +int dgraphInit (Dgraph * const, MPI_Comm); +void dgraphExit (Dgraph * const); +void dgraphFree (Dgraph * const); +int dgraphLoad (Dgraph * const, FILE * const, const Gnum, const DgraphFlag); +int dgraphSave (Dgraph * const, FILE * const); +int dgraphBuild (Dgraph * const, const Gnum, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, Gnum * const, Gnum * const, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const); +int dgraphBuild2 (Dgraph * const, const Gnum, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, const Gnum, Gnum * const, Gnum * const, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, const Gnum); +int dgraphBuild3 (Dgraph * const, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, const Gnum, Gnum * const, Gnum * const, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, const Gnum); +int dgraphBuild4 (Dgraph * const); +int dgraphBuildHcub (Dgraph * const, const Gnum, const Gnum, const Gnum); +int dgraphBuildGrid3D (Dgraph * const, const Gnum, const Gnum, const Gnum, const Gnum, const Gnum, const int); +int dgraphCheck (const Dgraph * const); +int dgraphView (const Dgraph * const, FILE * const); +int dgraphGhst2 (Dgraph * const, const int); +int dgraphBand (Dgraph * restrict const, const Gnum, Gnum * restrict const, const GraphPart * restrict const, const Gnum, const Gnum, Gnum, Dgraph * restrict const, Gnum * restrict * const, GraphPart * restrict * const, Gnum * const, Gnum * const, Gnum * const); + +int dgraphFold (const Dgraph * restrict const, const int, Dgraph * restrict const, const void * restrict const, void ** restrict const, MPI_Datatype); +int dgraphFold2 (const Dgraph * restrict const, const int, Dgraph * restrict const, MPI_Comm, const void * restrict const, void ** restrict const, MPI_Datatype); +int dgraphFoldDup (const Dgraph * restrict const, Dgraph * restrict const, void * restrict const, void ** restrict const, MPI_Datatype); +int dgraphInduce2 (Dgraph * restrict const, Gnum (*) (Dgraph * restrict const, Dgraph * restrict const, const void * restrict const, Gnum * restrict const), const void * const, const Gnum, Gnum *, Dgraph * restrict const); + +int dgraphInduceList (Dgraph * const, const Gnum, const Gnum * const, Dgraph * const); +int dgraphInducePart (Dgraph * const, const GraphPart * restrict const, const Gnum, const GraphPart, Dgraph * const); +#ifdef GRAPH_H +int dgraphGather (const Dgraph * restrict const, Graph * restrict); +int dgraphGather2 (const Dgraph * restrict const, Graph * restrict, const int, const Gnum); +int dgraphGatherAll (const Dgraph * restrict const, Graph * restrict); +int dgraphGatherAll2 (const Dgraph * restrict const, Graph * restrict, const Gnum, const int); +int dgraphScatter (Dgraph * const, const Graph * const); +#endif /* GRAPH_H */ + +int dgraphHaloSync (Dgraph * const, void * const, MPI_Datatype); + +/* +** The macro definitions. +*/ + +#define dgraphGhst(grafptr) dgraphGhst2 (grafptr, 0) /* Build ghost edge array in addition to local edge array */ +#define dgraphGhstReplace(grafptr) dgraphGhst2 (grafptr, 1) /* Replace local edge array by ghost edge array */ +#define dgraphHasGhst(grafptr) (((grafptr)->flagval & DGRAPHHASEDGEGST) != 0) /* If graph has a ghost edge array */ diff --git a/scotch_6.0.3/src/libscotch/dgraph_allreduce.c b/scotch_6.0.3/src/libscotch/dgraph_allreduce.c new file mode 100644 index 00000000..fd2d7ae7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_allreduce.c @@ -0,0 +1,91 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_allreduce.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the distributed source **/ +/** graph building routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 28 aug 2006 **/ +/** to : 28 aug 2006 **/ +/** **/ +/************************************************************/ + +#define DGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" + +/* This routine creates an allreduce operator from +** the function pointer that is passed to it, and +** use it to perform an allreduce operation on the +** given data. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphAllreduceMaxSum2 ( +Gnum * reduloctab, /* Pointer to array of local Gnum data */ +Gnum * reduglbtab, /* Pointer to array of reduced Gnum data */ +int redumaxsumnbr, /* Number of max + sum Gnum operations */ +MPI_User_function * redufuncptr, /* Pointer to operator function */ +MPI_Comm proccomm) /* Communicator to be used for reduction */ +{ + MPI_Datatype redutypedat; /* Data type for finding best separator */ + MPI_Op reduoperdat; /* Handle of MPI operator for finding best separator */ + + if ((MPI_Type_contiguous (redumaxsumnbr, GNUM_MPI, &redutypedat) != MPI_SUCCESS) || + (MPI_Type_commit (&redutypedat) != MPI_SUCCESS) || + (MPI_Op_create (redufuncptr, 1, &reduoperdat) != MPI_SUCCESS)) { + errorPrint ("dgraphAllreduceMaxSum: communication error (1)"); + return (1); + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 1, redutypedat, reduoperdat, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphAllreduceMaxSum: communication error (2)"); + return (1); + } + + if ((MPI_Op_free (&reduoperdat) != MPI_SUCCESS) || + (MPI_Type_free (&redutypedat) != MPI_SUCCESS)) { + errorPrint ("dgraphAllreduceMaxSum: communication error (3)"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_allreduce.h b/scotch_6.0.3/src/libscotch/dgraph_allreduce.h new file mode 100644 index 00000000..3424e5bb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_allreduce.h @@ -0,0 +1,77 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/**********************************************************/ +/* */ +/* NAME : dgraph_allreduce.h */ +/* */ +/* AUTHOR : Francois PELLEGRINI */ +/* */ +/* FUNCTION : These lines are the data declarations */ +/* for the communication routines */ +/* */ +/* # Version 5.0 : from : 28 aug 2006 */ +/* to 29 aug 2006 */ +/* */ +/**********************************************************/ + +/* +** The defines. +*/ + +/*+ Combined maximum-sum reduction operator +*/ + +#define DGRAPHALLREDUCEMAXSUMOP(m,s) \ +static \ +void \ +dgraphAllreduceMaxSumOp##m##_##s ( \ +const Gnum * const in, /* First operand */ \ +Gnum * const inout, /* Second and output operand */ \ +const int * const len, /* Number of instances ; should be 1, not used */ \ +const MPI_Datatype * const typedat) /* MPI datatype ; not used */ \ +{ \ + int i; \ + \ + for (i = 0; i < (m); i ++) /* Perform maximum on first part of data array */ \ + if (in[i] > inout[i]) \ + inout[i] = in[i]; \ + \ + for ( ; i < ((m) + (s)); i ++) /* Perform sum on second part of data array */ \ + inout[i] += in[i]; \ +} + +#define dgraphAllreduceMaxSum(rlt,rgt,m,s,comm) dgraphAllreduceMaxSum2 ((rlt), (rgt), (m) + (s), (MPI_User_function *) (dgraphAllreduceMaxSumOp##m##_##s), (comm)) + +/* +** The function prototypes. +*/ + +int dgraphAllreduceMaxSum2 (Gnum *, Gnum *, int, MPI_User_function *, MPI_Comm); diff --git a/scotch_6.0.3/src/libscotch/dgraph_band.c b/scotch_6.0.3/src/libscotch/dgraph_band.c new file mode 100644 index 00000000..999c20d7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_band.c @@ -0,0 +1,482 @@ +/* Copyright 2007-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_band.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a distributed band **/ +/** graph from the given frontier array. **/ +/** **/ +/** DATES : # Version 5.1 : from : 11 nov 2007 **/ +/** to : 20 feb 2011 **/ +/** # Version 6.0 : from : 03 apr 2012 **/ +/** to : 26 sep 2012 **/ +/** **/ +/** NOTES : # This code derives from the code of **/ +/** vdgraph_separate_bd.c in version 5.0. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_BAND + +#include "module.h" +#include "common.h" +#include "dgraph.h" + +/**********************************/ +/* */ +/* Distance computation routines. */ +/* */ +/**********************************/ + +#define DGRAPHBANDGROWNAME dgraphBand +#define DGRAPHBANDGROWEDGE(n) bandedgelocnbr += vendloctax[n] - vertloctax[n] +#define DGRAPHBANDGROWENQ1 for (queulocnum = 0; queulocnum < queulocnbr; queulocnum ++) { \ + Gnum vertlocnum; \ + \ + vertlocnum = queuloctab[queulocnum]; \ + vnumgsttax[vertlocnum] = bandvertlocnnd ++; \ + DGRAPHBANDGROWEDGE (vertlocnum); \ + } +#define DGRAPHBANDGROWENQ2 bandvertlocnnd ++ +#define DGRAPHBANDGROWENQ3 /* Nothing more to send */ +#define DGRAPHBANDGROWENQ4 bandvertlocnnd ++ +#define DGRAPHBANDGROWSMUL(n) (n) +#include "dgraph_band_grow.h" +#include "dgraph_band_grow.c" +#undef DGRAPHBANDGROWNAME +#undef DGRAPHBANDGROWEDGE +#undef DGRAPHBANDGROWENQU +#undef DGRAPHBANDGROWSMUL + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes a distributed index array +** of given width around the current separator. +** It returns: +** - 0 : if the index array could be computed. +** - !0 : on error. +*/ + +int +dgraphBand ( +Dgraph * restrict const grafptr, /*+ Distributed graph +*/ +const Gnum fronlocnbr, /*+ Number of frontier vertices +*/ +Gnum * restrict const fronloctab, /*+ Array of frontier vertices, re-used as queue array +*/ +const GraphPart * restrict const partgsttax, /*+ Part array for original graph ({0,1} or {0,1,2}) +*/ +const Gnum complocload0, /*+ Load in part 0 or {0,2} +*/ +const Gnum complocload1, /*+ Load in part 1 +*/ +Gnum distmax, /*+ Maximum distance from separator vertices +*/ +Dgraph * restrict const bandgrafptr, /*+ Pointer to band graph structure to fill +*/ +Gnum * restrict * const bandfronlocptr, /*+ Pointer to bandfronloctab +*/ +GraphPart * restrict * const bandpartgstptr, /*+ Pointer to bandpartgsttax +*/ +Gnum * const bandvertlvlptr, /*+ Pointer to based start index of last level +*/ +Gnum * const bandvertlocptr1, /*+ Pointer to number of band vertices in part 1 +*/ +Gnum * const bandvertlocancptr) /*+ Pointer to flag set if anchor vertices overloaded +*/ +{ + Gnum bandvertlocnnd; /* End of local band vertex array, (without anchor vertices) */ + Gnum bandvertlocnbr; /* Number of local band vertices (including anchor vertices) */ + Gnum bandvertlocnbr1; /* Number of band graph vertices in part 1 except anchor 1 */ + Gnum bandvertlvlnum; /* Index of first band vertex belonging to last level */ + Gnum * restrict bandvertloctax; + Gnum bandvertlocadj; /* Ajust value for local-to-global band vertex indices */ + Gnum bandvertlocancadj; /* Flag set when anchor(s) represent unexistent vertices */ + Gnum bandvertlocnum; + Gnum bandvelolocsum; + Gnum bandvelolocsum1; + Gnum * restrict bandedgeloctax; + Gnum bandedgelocnum; + Gnum bandedgeloctmp; + Gnum bandedgelocnbr; /* Number of local edges in band graph */ + Gnum * restrict bandedloloctax; + Gnum bandedlolocnbr; /* Size of local band edge load array */ + Gnum * restrict bandfronloctab; + GraphPart * restrict bandpartgsttax; + Gnum bandvnumgstsiz; + Gnum * restrict bandvnumgsttax; /* Indices of selected band vertices in band graph */ + Gnum banddegrlocmax; + Gnum degrval; + Gnum veloval; + const Gnum * restrict edgegsttax; + Gnum fronlocnum; + int cheklocval; + int chekglbval; + int procngbnum; + + if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("dgraphBand: cannot compute ghost edge array"); + return (1); + } + + cheklocval = 0; + bandvnumgstsiz = MAX ((grafptr->vertgstnbr * sizeof (Gnum)), (grafptr->procglbnbr * sizeof (int))); /* TRICK: re-use array for further error collective communications */ + if ((bandvnumgsttax = memAlloc (bandvnumgstsiz)) == NULL) { + errorPrint ("dgraphBand: out of memory (1)"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_DGRAPH1 /* This communication cannot be covered by a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphBand: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (chekglbval != 0) + return (1); + + memSet (bandvnumgsttax, ~0, grafptr->vertgstnbr * sizeof (Gnum)); /* Reset part array */ + bandvnumgsttax -= grafptr->baseval; + + if ((((grafptr->flagval & DGRAPHCOMMPTOP) != 0) ? dgraphBandPtop : dgraphBandColl) + (grafptr, fronlocnbr, fronloctab, distmax, bandvnumgsttax, &bandvertlvlnum, &bandvertlocnbr, &bandedgelocnbr) != 0) + return (1); + + if (bandvertlvlptr != NULL) + *bandvertlvlptr = bandvertlvlnum; + + bandedgelocnbr += 2 * ((bandvertlocnbr + grafptr->baseval - bandvertlvlnum) + (grafptr->procglbnbr - 1)); /* Add edges to and from anchors */ + bandvertlocnbr += 2; /* Add anchor vertices */ + bandedlolocnbr = (grafptr->edloloctax != NULL) ? bandedgelocnbr : 0; + + dgraphInit (bandgrafptr, grafptr->proccomm); + bandgrafptr->flagval = (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* Arrays created by the routine itself */ + bandgrafptr->baseval = grafptr->baseval; + + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ + &bandgrafptr->procdsptab, (size_t) ((grafptr->procglbnbr + 1) * sizeof (Gnum)), + &bandgrafptr->proccnttab, (size_t) (grafptr->procglbnbr * sizeof (Gnum)), + &bandgrafptr->procngbtab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &bandgrafptr->procrcvtab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &bandgrafptr->procsndtab, (size_t) (grafptr->procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("dgraphBand: out of memory (2)"); + cheklocval = 1; + } + else if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ + &bandgrafptr->vertloctax, (size_t) ((bandvertlocnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ + &bandgrafptr->vnumloctax, (size_t) (bandvertlocnbr * sizeof (Gnum)), + &bandgrafptr->veloloctax, (size_t) (bandvertlocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphBand: out of memory (3)"); + cheklocval = 1; + } + else if (bandgrafptr->vertloctax -= bandgrafptr->baseval, + bandgrafptr->veloloctax -= bandgrafptr->baseval, + bandgrafptr->vnumloctax -= bandgrafptr->baseval, + (memAllocGroup ((void **) (void *) + &bandedgeloctax, (size_t) (bandedgelocnbr * sizeof (Gnum)), + &bandedloloctax, (size_t) (bandedlolocnbr * sizeof (Gnum)), NULL) == NULL)) { + errorPrint ("dgraphBand: out of memory (4)"); + cheklocval = 1; + } + else { + bandedgeloctax -= bandgrafptr->baseval; + bandedloloctax = (grafptr->edloloctax != NULL) ? (bandedloloctax - bandgrafptr->baseval) : NULL; + + if ((bandfronloctab = memAlloc (bandvertlocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphBand: out of memory (5)"); + cheklocval = 1; + } + else if ((bandpartgsttax = memAlloc ((bandvertlocnbr + bandedgelocnbr) * sizeof (GraphPart))) == NULL) { /* Upper bound on number of ghost vertices */ + errorPrint ("dgraphBand: out of memory (6)"); + cheklocval = 1; + } + else + bandpartgsttax -= bandgrafptr->baseval; + } + + if (cheklocval != 0) { /* In case of memory error */ + bandgrafptr->procdsptab[0] = -1; + if (MPI_Allgather (&bandgrafptr->procdsptab[0], 1, GNUM_MPI, /* Send received data to dummy array */ + bandvnumgsttax + bandgrafptr->baseval, 1, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphBand: communication error (2)"); + return (1); + } + if (bandfronloctab != NULL) + memFree (bandfronloctab); + dgraphFree (bandgrafptr); + memFree (bandvnumgsttax + bandgrafptr->baseval); + return (1); + } + else { + bandgrafptr->procdsptab[0] = bandvertlocnbr; + if (MPI_Allgather (&bandgrafptr->procdsptab[0], 1, GNUM_MPI, + &bandgrafptr->procdsptab[1], 1, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphBand: communication error (3)"); + return (1); + } + } + bandgrafptr->procdsptab[0] = bandgrafptr->baseval; /* Build vertex-to-process array */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + memSet (bandgrafptr->vnumloctax + bandgrafptr->baseval, ~0, (bandvertlocnbr * sizeof (Gnum))); +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + for (procngbnum = 1; procngbnum <= grafptr->procglbnbr; procngbnum ++) { /* Process potential error flags from other processes */ + if (bandgrafptr->procdsptab[procngbnum] < 0) { /* If error notified by another process */ + if (bandpartgsttax != NULL) + memFree (bandpartgsttax + bandgrafptr->baseval); + if (bandfronloctab != NULL) + memFree (bandfronloctab); + dgraphFree (bandgrafptr); + memFree (bandvnumgsttax + bandgrafptr->baseval); + return (1); + } + bandgrafptr->procdsptab[procngbnum] += bandgrafptr->procdsptab[procngbnum - 1]; + bandgrafptr->proccnttab[procngbnum - 1] = bandgrafptr->procdsptab[procngbnum] - bandgrafptr->procdsptab[procngbnum - 1]; + } + + for (fronlocnum = 0, bandvertlocnum = bandgrafptr->baseval, bandvertlocadj = bandgrafptr->procdsptab[grafptr->proclocnum] - bandgrafptr->baseval; + fronlocnum < fronlocnbr; fronlocnum ++, bandvertlocnum ++) { /* Turn all graph frontier vertices into band frontier vertices */ + Gnum vertlocnum; + + bandfronloctab[fronlocnum] = bandvertlocnum; /* All frontier vertices are first vertices of band graph */ + vertlocnum = fronloctab[fronlocnum]; + bandgrafptr->vnumloctax[bandvertlocnum] = vertlocnum; + bandvnumgsttax[vertlocnum] += bandvertlocadj; /* Turn local indices in band graph into global indices */ + } + for (bandvertlocnnd = bandvertlocnbr + bandgrafptr->baseval - 2; /* Pick selected band vertices from rest of frontier array without anchors */ + bandvertlocnum < bandvertlocnnd; fronlocnum ++, bandvertlocnum ++) { + Gnum vertlocnum; + + vertlocnum = fronloctab[fronlocnum]; + bandgrafptr->vnumloctax[bandvertlocnum] = vertlocnum; + bandvnumgsttax[vertlocnum] += bandvertlocadj; /* Turn local indices in band graph into global indices */ + } + bandgrafptr->vnumloctax[bandvertlocnnd] = /* Prevent Valgrind from yelling when centralizing band graphs */ + bandgrafptr->vnumloctax[bandvertlocnnd + 1] = -1; + + if (dgraphHaloSync (grafptr, (byte *) (bandvnumgsttax + bandgrafptr->baseval), GNUM_MPI) != 0) { /* Share global indexing of halo vertices */ + errorPrint ("dgraphBand: cannot perform halo exchange"); + return (1); + } + + edgegsttax = grafptr->edgegsttax; + + veloval = 1; + bandvertloctax = bandgrafptr->vertloctax; + bandvertlocnbr1 = 0; + bandvelolocsum = 0; + bandvelolocsum1 = 0; + banddegrlocmax = 0; + for (bandvertlocnum = bandedgelocnum = bandgrafptr->baseval; /* Build global vertex array of band graph */ + bandvertlocnum < bandvertlvlnum; bandvertlocnum ++) { /* For all vertices that do not belong to the last level */ + Gnum vertlocnum; + Gnum edgelocnum; + Gnum degrval; + GraphPart partval; + Gnum partval1; + + vertlocnum = bandgrafptr->vnumloctax[bandvertlocnum]; + partval = partgsttax[vertlocnum]; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (partval > 2) { + errorPrint ("dgraphBand: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + partval1 = partval & 1; + bandvertlocnbr1 += partval1; /* Count vertices in part 1 */ + bandpartgsttax[bandvertlocnum] = partval; + bandvertloctax[bandvertlocnum] = bandedgelocnum; + if (grafptr->veloloctax != NULL) { + veloval = grafptr->veloloctax[vertlocnum]; + bandvelolocsum += veloval; + bandvelolocsum1 += veloval & (- partval1); /* Sum vertex load if (partval == 1) */ + } + bandgrafptr->veloloctax[bandvertlocnum] = veloval; + + degrval = grafptr->vendloctax[vertlocnum] - grafptr->vertloctax[vertlocnum]; + if (banddegrlocmax < degrval) + banddegrlocmax = degrval; + + for (edgelocnum = grafptr->vertloctax[vertlocnum]; /* For all original edges */ + edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (bandvnumgsttax[edgegsttax[edgelocnum]] == ~0) { /* All ends should belong to the band graph too */ + errorPrint ("dgraphBand: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + bandedgeloctax[bandedgelocnum ++] = bandvnumgsttax[edgegsttax[edgelocnum]]; + } + } + for ( ; bandvertlocnum < bandvertlocnnd; bandvertlocnum ++) { /* For all vertices that belong to the last level except anchors */ + Gnum vertlocnum; + Gnum edgelocnum; + Gnum degrval; + GraphPart partval; + Gnum partval1; + + vertlocnum = bandgrafptr->vnumloctax[bandvertlocnum]; + partval = partgsttax[vertlocnum]; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (partval > 2) { + errorPrint ("dgraphBand: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + partval1 = partval & 1; + bandvertlocnbr1 += partval1; /* Count vertices in part 1 */ + bandpartgsttax[bandvertlocnum] = partval; + bandvertloctax[bandvertlocnum] = bandedgelocnum; + if (grafptr->veloloctax != NULL) { + veloval = grafptr->veloloctax[vertlocnum]; + bandvelolocsum += veloval; + bandvelolocsum1 += veloval & (- partval1); /* Sum vertex load if (partval == 1) */ + } + bandgrafptr->veloloctax[bandvertlocnum] = veloval; + + for (edgelocnum = grafptr->vertloctax[vertlocnum]; /* For all original edges */ + edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { + Gnum bandvertlocend; + + bandvertlocend = bandvnumgsttax[edgegsttax[edgelocnum]]; + if (bandvertlocend != ~0) { /* If end vertex belongs to band graph */ + if (bandedloloctax != NULL) /* If graph has edge weights, copy load */ + bandedloloctax[bandedgelocnum] = grafptr->edloloctax[edgelocnum]; + bandedgeloctax[bandedgelocnum ++] = bandvertlocend; + } + } + if (bandedloloctax != NULL) /* If graph has edge weights */ + bandedloloctax[bandedgelocnum] = 1; /* Edge to anchor has load 1 */ + bandedgeloctax[bandedgelocnum ++] = bandvertlocnnd + bandvertlocadj + partval1; /* Add edge to anchor of proper part */ + + degrval = bandedgelocnum - bandvertloctax[bandvertlocnum]; + if (banddegrlocmax < degrval) + banddegrlocmax = degrval; + } + + memFree (bandvnumgsttax + bandgrafptr->baseval); /* Free useless space */ + + bandpartgsttax[bandvertlocnnd] = 0; /* Set parts of anchor vertices */ + bandpartgsttax[bandvertlocnnd + 1] = 1; + bandvertloctax[bandvertlocnum] = bandedgelocnum; /* Process anchor vertex in part 0 */ + for (procngbnum = 0; procngbnum < grafptr->proclocnum; procngbnum ++) /* Build clique with anchors of part 0 */ + bandedgeloctax[bandedgelocnum ++] = bandgrafptr->procdsptab[procngbnum + 1] - 2; + for (procngbnum ++; procngbnum < grafptr->procglbnbr; procngbnum ++) /* Build clique with anchors of part 0 */ + bandedgeloctax[bandedgelocnum ++] = bandgrafptr->procdsptab[procngbnum + 1] - 2; + bandedgeloctmp = bandedgelocnum + (bandvertlocnnd - bandvertlvlnum); + for (procngbnum = 0; procngbnum < grafptr->proclocnum; procngbnum ++) /* Build clique with anchors of part 1 */ + bandedgeloctax[bandedgeloctmp ++] = bandgrafptr->procdsptab[procngbnum + 1] - 1; + for (procngbnum ++; procngbnum < grafptr->procglbnbr; procngbnum ++) /* Build clique with anchors of part 1 */ + bandedgeloctax[bandedgeloctmp ++] = bandgrafptr->procdsptab[procngbnum + 1] - 1; + bandvertloctax[bandvertlocnnd + 2] = bandedgeloctmp; + bandedgelocnbr = bandedgeloctmp - bandgrafptr->baseval; /* Set real number of edges */ + for (bandvertlocnum = bandvertlvlnum, bandedgeloctmp = bandedgelocnum + (bandvertlocnnd - bandvertlvlnum); /* Link vertices of last level to anchors */ + bandvertlocnum < bandvertlocnnd; bandvertlocnum ++) { + if (bandpartgsttax[bandvertlocnum] == 0) + bandedgeloctax[bandedgelocnum ++] = bandvertlocnum + bandvertlocadj; + else + bandedgeloctax[-- bandedgeloctmp] = bandvertlocnum + bandvertlocadj; + } + bandvertloctax[bandvertlocnnd + 1] = bandedgeloctmp; + degrval = bandvertloctax[bandvertlocnnd + 1] - bandvertloctax[bandvertlocnnd]; + if (banddegrlocmax < degrval) + banddegrlocmax = degrval; + degrval = bandvertloctax[bandvertlocnnd + 2] - bandvertloctax[bandvertlocnnd + 1]; + if (banddegrlocmax < degrval) + banddegrlocmax = degrval; + + if (bandedloloctax != NULL) { /* If graph has edge weights */ + Gnum edgelocnum; + Gnum edgelocnnd; + + for (bandvertlocnum = bandgrafptr->baseval; /* For all vertices that do not belong to the last level */ + bandvertlocnum < bandvertlvlnum; bandvertlocnum ++) { + Gnum vertlocnum; + Gnum bandedgelocnum; + + vertlocnum = bandgrafptr->vnumloctax[bandvertlocnum]; + bandedgelocnum = bandvertloctax[bandvertlocnum]; + memCpy (bandedloloctax + bandedgelocnum, /* Copy edge load array */ + &grafptr->edloloctax[grafptr->vertloctax[vertlocnum]], + (bandvertloctax[bandvertlocnum + 1] - bandedgelocnum) * sizeof (Gnum)); + } /* Vertices of last level have been processed before */ + for (edgelocnum = bandvertloctax[bandvertlocnnd], /* Loads of anchor edges are all 1's too */ + edgelocnnd = bandvertloctax[bandvertlocnnd + 2]; + edgelocnum < edgelocnnd; edgelocnum ++) + bandedloloctax[edgelocnum] = 1; + } + + if (grafptr->veloloctax == NULL) { /* If original graph is not weighted */ + bandgrafptr->veloloctax[bandvertlocnnd] = complocload0 + bandvertlocnbr1 - bandvertlocnbr + 2; /* Plus 2 for anchors */ + bandgrafptr->veloloctax[bandvertlocnnd + 1] = complocload1 - bandvertlocnbr1; + } + else { + bandgrafptr->veloloctax[bandvertlocnnd] = complocload0 + bandvelolocsum1 - bandvelolocsum; + bandgrafptr->veloloctax[bandvertlocnnd + 1] = complocload1 - bandvelolocsum1; + } + bandvertlocancadj = 0; + if ((bandgrafptr->veloloctax[bandvertlocnnd] == 0) || /* If at least one anchor is empty */ + (bandgrafptr->veloloctax[bandvertlocnnd + 1] == 0)) { + bandvertlocancadj = 1; + bandgrafptr->veloloctax[bandvertlocnnd] ++; /* Increase weight of both anchors to keep balance */ + bandgrafptr->veloloctax[bandvertlocnnd + 1] ++; + } + + bandgrafptr->procvrttab = bandgrafptr->procdsptab; /* Graph does not have holes */ + bandgrafptr->vertlocnbr = bandvertlocnbr; + bandgrafptr->vertlocnnd = bandvertlocnbr + bandgrafptr->baseval; + bandgrafptr->vendloctax = bandvertloctax + 1; /* Band graph is compact */ + bandgrafptr->velolocsum = grafptr->velolocsum + 2 * bandvertlocancadj; + bandgrafptr->edgeloctax = bandedgeloctax; + bandgrafptr->edloloctax = bandedloloctax; + bandgrafptr->edgelocnbr = bandedgelocnbr; + bandgrafptr->edgelocsiz = bandedgelocnbr; + bandgrafptr->degrglbmax = banddegrlocmax; /* Local maximum degree will be turned into global maximum degree */ + if (dgraphBuild4 (bandgrafptr) != 0) { + errorPrint ("dgraphBand: cannot build band graph"); + return (1); + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphCheck (bandgrafptr) != 0) { + errorPrint ("dgraphBand: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + *bandfronlocptr = bandfronloctab; + *bandpartgstptr = bandpartgsttax; + *bandvertlocptr1 = bandvertlocnbr1; + *bandvertlocancptr = bandvertlocancadj; + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_band_grow.c b/scotch_6.0.3/src/libscotch/dgraph_band_grow.c new file mode 100644 index 00000000..6a140443 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_band_grow.c @@ -0,0 +1,591 @@ +/* Copyright 2007-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_band_grow.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module flags vertices according **/ +/** to a breadth-first search traversal of **/ +/** the distributed graph. It is used both **/ +/** by dgraphBand() and dgraphGrow(). **/ +/** **/ +/** DATES : # Version 5.1 : from : 11 nov 2007 **/ +/** to : 20 feb 2011 **/ +/** # Version 6.0 : from : 03 apr 2012 **/ +/** to : 26 sep 2012 **/ +/** **/ +/** NOTES : # This code derives from the code of **/ +/** vdgraph_separate_bd.c in version **/ +/** 5.0. It was first moved to **/ +/** dgraph_band.c, then to here to be **/ +/** mutualized between dgraphBand and **/ +/** dgraphGrow. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPHBANDGROWNSTR STRINGIFY (DGRAPHBANDGROWNAME) + +/**********************************/ +/* */ +/* Distance computation routines. */ +/* */ +/**********************************/ + +/* This routine computes a distributed index array +** of given width around the current separator, +** using collective communication. +** It returns: +** - 0 : if the index array could be computed. +** - !0 : on error. +*/ + +int +DGRAPHBANDGROWNAMECOLL ( +Dgraph * restrict const grafptr, /*+ Distributed graph +*/ +const Gnum queulocnbr, /*+ Number of frontier vertices, start size for vertex queue +*/ +Gnum * restrict const queuloctab, /*+ Array of frontier vertices, re-used as queue array +*/ +const Gnum distmax, /*+ Maximum distance from separator vertices +*/ +Gnum * restrict const vnumgsttax, /*+ Flag or index array to fill +*/ +Gnum * restrict const bandvertlvlptr, /*+ Pointer to based start index of last level +*/ +Gnum * restrict const bandvertlocptr, /*+ Pointer to bandvertlocnnd +*/ +Gnum * restrict const bandedgelocptr) /*+ Pointer to bandedgelocnbr +*/ +{ + Gnum queulocnum; + Gnum vertlocnnd; + Gnum vnumgstsiz; /* Size of vnumgsttax; TRICK: re-use */ + Gnum vrcvdatsiz; /* Sizes of data send and receive arrays */ + Gnum vsnddatsiz; + Gnum * vrcvdattab; /* Data arrays [norestrict:async] */ + Gnum * restrict vsnddattab; + Gnum * restrict procvgbtab; /* Array of neighbor bounds [+1] */ + int procngbnbr; + int procngbnum; + int * restrict vrcvcnttab; + int * restrict vsndcnttab; + int * restrict vrcvdsptab; + int * restrict vsnddsptab; + int * restrict nsndidxtab; + int vrcvdspnum; + int vsnddspnum; + Gnum queuheadidx; /* Index of head of queue */ + Gnum queutailidx; /* Index of tail of queue */ + Gnum bandvertlvlnum; + Gnum bandvertlocnnd; + Gnum bandedgelocnbr; + Gnum distval; +#ifdef SCOTCH_DEBUG_DGRAPH1 + Gnum reduloctab[3]; + Gnum reduglbtab[3]; +#else /* SCOTCH_DEBUG_DGRAPH1 */ + Gnum reduglbtab[1]; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + const Gnum * restrict const edgegsttax = grafptr->edgegsttax; + const Gnum * restrict const edgeloctax = grafptr->edgeloctax; + + procngbnbr = grafptr->procngbnbr; + + reduglbtab[0] = 0; /* Assume everything is all right */ + + vrcvdatsiz = DGRAPHBANDGROWSMUL (grafptr->procsndnbr); /* Senders and receivers inverted because we send local, not halo vertices */ + vsnddatsiz = DGRAPHBANDGROWSMUL (grafptr->vertgstnbr - grafptr->vertlocnbr); + if (memAllocGroup ((void **) (void *) + &procvgbtab, (size_t) ((procngbnbr + 1) * sizeof (Gnum)), + &nsndidxtab, (size_t) (procngbnbr * sizeof (int)), + &vrcvcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &vsndcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), /* TRICK: vsndcnttab, vrcvdsptab, vrcvdattab, vrcvdattab joined */ + &vrcvdsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &vsnddsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &vrcvdattab, (size_t) (vrcvdatsiz * sizeof (Gnum)), + &vsnddattab, (size_t) (vsnddatsiz * sizeof (Gnum)), NULL) == NULL) { + errorPrint (DGRAPHBANDGROWNSTR "Coll: out of memory (1)"); + reduglbtab[0] = 1; + } +#ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication not needed and not absorbable by the algorithm */ + reduloctab[0] = reduglbtab[0]; + reduloctab[1] = distmax; + reduloctab[2] = - distmax; + if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint (DGRAPHBANDGROWNSTR "Coll: communication error (1)"); + return (1); + } + if (reduglbtab[1] != - reduglbtab[2]) { + errorPrint (DGRAPHBANDGROWNSTR "Coll: invalid parameters"); + reduglbtab[0] = 1; + } +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (reduglbtab[0] != 0) { + if (vnumgsttax != NULL) { + if (procvgbtab != NULL) + memFree (procvgbtab); /* Free group leader */ + memFree (vnumgsttax); + } + return (1); + } + + memSet (vsndcnttab, 0, (((int *) vrcvdattab) - vsndcnttab) * sizeof (int)); /* TRICK: vsndcnttab, vrcvdsptab, vrcvdattab, vrcvdattab joined */ + + for (procngbnum = 0, vrcvdspnum = vsnddspnum = 0; /* Build communication index arrays */ + procngbnum < procngbnbr; procngbnum ++) { + int procglbnum; + + procglbnum = grafptr->procngbtab[procngbnum]; + procvgbtab[procngbnum] = grafptr->procvrttab[procglbnum]; + vrcvdsptab[procglbnum] = vrcvdspnum; + vsnddsptab[procglbnum] = vsnddspnum; + vrcvdspnum += DGRAPHBANDGROWSMUL (grafptr->procsndtab[procglbnum]); /* Senders and receivers are reversed */ + vsnddspnum += DGRAPHBANDGROWSMUL (grafptr->procrcvtab[procglbnum]); + } + procvgbtab[procngbnum] = grafptr->procvrttab[grafptr->procglbnbr]; + + bandvertlvlnum = /* Start index of last level is start index */ + bandvertlocnnd = grafptr->baseval; /* Reset number of band vertices, plus base */ + bandedgelocnbr = 0; /* No edges accounted for yet */ + + DGRAPHBANDGROWENQ1; /* Record queued vertices in index array and account for their edges */ + + vertlocnnd = grafptr->vertlocnnd; + + queuheadidx = 0; /* No queued vertex read yet */ + queutailidx = queulocnbr; /* All frontier vertices are already in queue */ + for (distval = 0; ++ distval <= distmax; ) { + Gnum queunextidx; /* Tail index for enqueuing vertices of next band */ + int procngbnum; + + bandvertlvlnum = bandvertlocnnd; /* Save start index of current level, based */ + *bandvertlvlptr = bandvertlvlnum; + + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) /* Build communication index arrays */ + nsndidxtab[procngbnum] = vsnddsptab[grafptr->procngbtab[procngbnum]]; + + for (queunextidx = queutailidx; queuheadidx < queutailidx; ) { /* For all vertices in queue */ + Gnum vertlocnum; + Gnum edgelocnum; + + vertlocnum = queuloctab[queuheadidx ++]; /* Dequeue vertex */ + for (edgelocnum = vertloctax[vertlocnum]; edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { + Gnum vertlocend; + + vertlocend = edgegsttax[edgelocnum]; + if (vnumgsttax[vertlocend] != ~0) /* If end vertex has already been processed */ + continue; /* Skip to next vertex */ + + if (vertlocend < vertlocnnd) { /* If end vertex is local */ + vnumgsttax[vertlocend] = DGRAPHBANDGROWENQ2; /* Label vertex as enqueued */ + queuloctab[queunextidx ++] = vertlocend; /* Enqueue vertex for next pass */ + DGRAPHBANDGROWEDGE (vertlocend); /* Account for its edges */ + } + else { /* End vertex is a ghost */ + Gnum vertglbend; + int procngbnum; + int procngbmax; + int nsndidxnum; + + vnumgsttax[vertlocend] = 0; /* Label ghost vertex as enqueued */ + vertglbend = edgeloctax[edgelocnum]; /* Get global number of end vertex */ + + procngbnum = 0; + procngbmax = procngbnbr; + while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (procvgbtab[procngbmed] > vertglbend) + procngbmax = procngbmed; + else + procngbnum = procngbmed; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((grafptr->procvrttab[grafptr->procngbtab[procngbnum]] > vertglbend) || + (grafptr->procvrttab[grafptr->procngbtab[procngbnum] + 1] <= vertglbend) || + (nsndidxtab[procngbnum] >= (vsnddsptab[grafptr->procngbtab[procngbnum]] + grafptr->procrcvtab[grafptr->procngbtab[procngbnum]]))) { + errorPrint (DGRAPHBANDGROWNSTR "Coll: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + nsndidxnum = nsndidxtab[procngbnum]; + vsnddattab[nsndidxnum ++] = vertglbend - procvgbtab[procngbnum] + grafptr->baseval; /* Buffer local value on neighbor processor */ + DGRAPHBANDGROWENQ3; /* Send additional data if needed */ + nsndidxtab[procngbnum] = nsndidxnum; + } + } + } + + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { + int procglbnum; + + procglbnum = grafptr->procngbtab[procngbnum]; + vsndcnttab[procglbnum] = nsndidxtab[procngbnum] - vsnddsptab[procglbnum]; + } + + if (MPI_Alltoall (vsndcnttab, 1, MPI_INT, vrcvcnttab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint (DGRAPHBANDGROWNSTR "Coll: communication error (2)"); + return (1); + } + if (MPI_Alltoallv (vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, + vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint (DGRAPHBANDGROWNSTR "Coll: communication error (3)"); + return (1); + } + + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { /* For all receive buffers */ + Gnum * restrict vrcvdatptr; + int vertrcvnum; + int procglbnum; + int statsiz; + + procglbnum = grafptr->procngbtab[procngbnum]; + vrcvdatptr = vrcvdattab + vrcvdsptab[procglbnum]; + statsiz = vrcvcnttab[procglbnum]; + for (vertrcvnum = 0; vertrcvnum < statsiz; vertrcvnum += DGRAPHBANDGROWSMUL (1)) { + Gnum vertlocend; + + vertlocend = vrcvdatptr[vertrcvnum]; /* Get local vertex from message */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocend < grafptr->baseval) || (vertlocend >= vertlocnnd)) { + errorPrint (DGRAPHBANDGROWNSTR "Coll: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (vnumgsttax[vertlocend] != ~0) /* If end vertex has already been processed */ + continue; /* Skip to next vertex */ + + vnumgsttax[vertlocend] = DGRAPHBANDGROWENQ4; /* Label vertex as enqueued */ + queuloctab[queunextidx ++] = vertlocend; /* Enqueue vertex for next pass */ + DGRAPHBANDGROWEDGE (vertlocend); /* Account for its edges */ + } + } + + queutailidx = queunextidx; /* Prepare queue for next sweep */ + } + + memFree (procvgbtab); /* Free group leader */ + + *bandvertlocptr = bandvertlocnnd - grafptr->baseval; + *bandedgelocptr = bandedgelocnbr; + + return (0); +} + +/* This routine computes a distributed index array +** of given width around the current separator, +** using point-to-point communication. +** It returns: +** - 0 : if the index array could be computed. +** - !0 : on error. +*/ + +int +DGRAPHBANDGROWNAMEPTOP ( +Dgraph * restrict const grafptr, /*+ Distributed graph +*/ +const Gnum queulocnbr, /*+ Number of frontier vertices, start size for vertex queue +*/ +Gnum * restrict const queuloctab, /*+ Array of frontier vertices, re-used as queue array +*/ +const Gnum distmax, /*+ Maximum distance from separator vertices +*/ +Gnum * restrict const vnumgsttax, /*+ Flag or index array to fill +*/ +Gnum * restrict const bandvertlvlptr, /*+ Pointer to based start index of last level +*/ +Gnum * restrict const bandvertlocptr, /*+ Pointer to bandvertlocnnd +*/ +Gnum * restrict const bandedgelocptr) /*+ Pointer to bandedgelocnbr +*/ +{ + Gnum queulocnum; + Gnum vertlocnnd; + Gnum vnumgstsiz; /* Size of vnumgsttax; TRICK: re-use */ + Gnum vrcvdatsiz; /* Sizes of data send and receive arrays */ + Gnum vsnddatsiz; + Gnum * vrcvdattab; /* Data arrays [norestrict:async] */ + Gnum * vsnddattab; + Gnum * restrict procvgbtab; /* Array of neighbor bounds [+1] */ + int procngbnbr; + int procngbnum; + int procngbnxt; + Gnum * restrict nrcvdsptab; + Gnum * restrict nsnddsptab; + Gnum nrcvdspnum; + Gnum nsnddspnum; + Gnum * restrict nsndidxtab; + Gnum queuheadidx; /* Index of head of queue */ + Gnum queutailidx; /* Index of tail of queue */ + MPI_Request * nrcvreqtab; /* Array of receive requests */ + MPI_Request * nsndreqtab; /* Array of receive requests */ + Gnum bandvertlvlnum; + Gnum bandvertlocnnd; + Gnum bandedgelocnbr; + Gnum distval; +#ifdef SCOTCH_DEBUG_DGRAPH1 + Gnum reduloctab[3]; + Gnum reduglbtab[3]; +#else /* SCOTCH_DEBUG_DGRAPH1 */ + Gnum reduglbtab[1]; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + const Gnum * restrict const edgegsttax = grafptr->edgegsttax; + const Gnum * restrict const edgeloctax = grafptr->edgeloctax; + + procngbnbr = grafptr->procngbnbr; + + reduglbtab[0] = 0; /* Assume everything is all right */ + + vrcvdatsiz = DGRAPHBANDGROWSMUL (grafptr->procsndnbr); /* Senders and receivers inverted because we send local, not halo vertices */ + vsnddatsiz = DGRAPHBANDGROWSMUL (grafptr->vertgstnbr - grafptr->vertlocnbr); + if (memAllocGroup ((void **) (void *) + &procvgbtab, (size_t) ((procngbnbr + 1) * sizeof (Gnum)), + &nrcvdsptab, (size_t) ((procngbnbr + 1) * sizeof (Gnum)), /* +1 to check against end of array */ + &nsnddsptab, (size_t) ((procngbnbr + 1) * sizeof (Gnum)), /* +1 to check against end of array */ + &nsndidxtab, (size_t) (procngbnbr * sizeof (Gnum)), /* Here Gnum's since point-to-point */ + &nrcvreqtab, (size_t) (procngbnbr * sizeof (MPI_Request)), + &nsndreqtab, (size_t) (procngbnbr * sizeof (MPI_Request)), + &vrcvdattab, (size_t) (vrcvdatsiz * sizeof (Gnum)), + &vsnddattab, (size_t) (vsnddatsiz * sizeof (Gnum)), NULL) == NULL) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: out of memory (1)"); + reduglbtab[0] = 1; + } +#ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication not needed and not absorbable by the algorithm */ + reduloctab[0] = reduglbtab[0]; + reduloctab[1] = distmax; + reduloctab[2] = - distmax; + if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: communication error (1)"); + return (1); + } + if (reduglbtab[1] != - reduglbtab[2]) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: invalid parameters"); + reduglbtab[0] = 1; + } +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (reduglbtab[0] != 0) { + if (vnumgsttax != NULL) { + if (procvgbtab != NULL) + memFree (procvgbtab); /* Free group leader */ + memFree (vnumgsttax); + } + return (1); + } + + for (procngbnum = 0, nrcvdspnum = nsnddspnum = procngbnxt = 0; /* Build communication index arrays */ + procngbnum < procngbnbr; procngbnum ++) { + int procglbnum; + + procglbnum = grafptr->procngbtab[procngbnum]; + if ((procngbnxt == 0) && (procglbnum > grafptr->proclocnum)) /* Find index of first neighbor of higher rank */ + procngbnxt = procngbnum; + procvgbtab[procngbnum] = grafptr->procvrttab[procglbnum]; + nrcvdsptab[procngbnum] = nrcvdspnum; /* Arrays are indexed per neighbor since we are doing point-to-point communication */ + nsnddsptab[procngbnum] = nsnddspnum; + nrcvdspnum += DGRAPHBANDGROWSMUL (grafptr->procsndtab[procglbnum]); /* Senders and receivers are reversed */ + nsnddspnum += DGRAPHBANDGROWSMUL (grafptr->procrcvtab[procglbnum]); + } + procvgbtab[procngbnum] = grafptr->procvrttab[grafptr->procglbnbr]; + nrcvdsptab[procngbnum] = nrcvdspnum; /* Mark end of communication index arrays */ + nsnddsptab[procngbnum] = nsnddspnum; + + procngbnum = procngbnxt; /* Create receive requests in descending order */ + if (procngbnbr != 0) { + do { + procngbnum = (procngbnum + (procngbnbr - 1)) % procngbnbr; /* Pre-decrement neighbor rank */ + if (MPI_Recv_init (vrcvdattab + nrcvdsptab[procngbnum], (int) (nrcvdsptab[procngbnum + 1] - nrcvdsptab[procngbnum]), GNUM_MPI, + grafptr->procngbtab[procngbnum], TAGBAND, + grafptr->proccomm, nrcvreqtab + procngbnum) != MPI_SUCCESS) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: communication error (2)"); + return (1); + } + } while (procngbnum != procngbnxt); + } + + bandvertlvlnum = /* Start index of last level is start index */ + bandvertlocnnd = grafptr->baseval; /* Reset number of band vertices, plus base */ + bandedgelocnbr = 0; /* No edges accounted for yet */ + + DGRAPHBANDGROWENQ1; /* Record queued vertices in index array and account for their edges */ + + vertlocnnd = grafptr->vertlocnnd; + + queuheadidx = 0; /* No queued vertex read yet */ + queutailidx = queulocnbr; /* All frontier vertices are already in queue */ + for (distval = 0; ++ distval <= distmax; ) { + Gnum queunextidx; /* Tail index for enqueuing vertices of next band */ + int vrcvreqnbr; + + if (MPI_Startall (procngbnbr, nrcvreqtab) != MPI_SUCCESS) { /* Start all receive operations from neighbors */ + errorPrint (DGRAPHBANDGROWNSTR "Ptop: communication error (3)"); + return (1); + } + + bandvertlvlnum = bandvertlocnnd; /* Save start index of current level, based */ + *bandvertlvlptr = bandvertlvlnum; + + memCpy (nsndidxtab, nsnddsptab, procngbnbr * sizeof (Gnum)); /* Reset send buffer indices */ + + for (queunextidx = queutailidx; queuheadidx < queutailidx; ) { /* For all vertices in queue */ + Gnum vertlocnum; + Gnum edgelocnum; + + vertlocnum = queuloctab[queuheadidx ++]; /* Dequeue vertex */ + for (edgelocnum = vertloctax[vertlocnum]; edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { + Gnum vertlocend; + + vertlocend = edgegsttax[edgelocnum]; + if (vnumgsttax[vertlocend] != ~0) /* If end vertex has already been processed */ + continue; /* Skip to next vertex */ + + if (vertlocend < vertlocnnd) { /* If end vertex is local */ + vnumgsttax[vertlocend] = DGRAPHBANDGROWENQ2; /* Label vertex as enqueued */ + queuloctab[queunextidx ++] = vertlocend; /* Enqueue vertex for next pass */ + DGRAPHBANDGROWEDGE (vertlocend); /* Account for its edges */ + } + else { /* End vertex is a ghost */ + Gnum vertglbend; + int procngbnum; + int procngbmax; + int nsndidxnum; + + vnumgsttax[vertlocend] = 0; /* Label ghost vertex as enqueued */ + vertglbend = edgeloctax[edgelocnum]; /* Get global number of end vertex */ + + procngbnum = 0; + procngbmax = procngbnbr; + while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (procvgbtab[procngbmed] > vertglbend) + procngbmax = procngbmed; + else + procngbnum = procngbmed; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((grafptr->procvrttab[grafptr->procngbtab[procngbnum]] > vertglbend) || + (grafptr->procvrttab[grafptr->procngbtab[procngbnum] + 1] <= vertglbend) || + (nsndidxtab[procngbnum] >= nsnddsptab[procngbnum + 1])) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + nsndidxnum = nsndidxtab[procngbnum]; + vsnddattab[nsndidxnum ++] = vertglbend - procvgbtab[procngbnum] + grafptr->baseval; /* Buffer local value on neighbor processor */ + DGRAPHBANDGROWENQ3; /* Send additional data if needed */ + nsndidxtab[procngbnum] = nsndidxnum; + } + } + } + + procngbnum = procngbnxt; /* Send all buffers to neighbors */ + if (procngbnbr != 0) { + do { + int procglbnum; + + procglbnum = grafptr->procngbtab[procngbnum]; + + if (MPI_Isend (vsnddattab + nsnddsptab[procngbnum], nsndidxtab[procngbnum] - nsnddsptab[procngbnum], + GNUM_MPI, grafptr->procngbtab[procngbnum], TAGBAND, grafptr->proccomm, + nsndreqtab + procngbnum) != MPI_SUCCESS) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: communication error (4)"); + return (1); + } + procngbnum = (procngbnum + 1) % procngbnbr; /* Post-increment neighbor rank */ + } while (procngbnum != procngbnxt); + } + + for (vrcvreqnbr = procngbnbr; vrcvreqnbr > 0; vrcvreqnbr --) { /* For all pending receive requests */ + Gnum * restrict vrcvdatptr; + int vertrcvnum; + MPI_Status statdat; + int statsiz; + int o; + +#ifdef SCOTCH_DETERMINISTIC + procngbnum = vrcvreqnbr - 1; + o = MPI_Wait (&nrcvreqtab[procngbnum], &statdat); +#else /* SCOTCH_DETERMINISTIC */ + o = MPI_Waitany (procngbnbr, nrcvreqtab, &procngbnum, &statdat); +#endif /* SCOTCH_DETERMINISTIC */ + if ((o != MPI_SUCCESS) || + (MPI_Get_count (&statdat, GNUM_MPI, &statsiz) != MPI_SUCCESS)) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: communication error (5)"); + return (1); + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (statdat.MPI_SOURCE != grafptr->procngbtab[procngbnum]) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + vrcvdatptr = vrcvdattab + nrcvdsptab[procngbnum]; + for (vertrcvnum = 0; vertrcvnum < statsiz; vertrcvnum += DGRAPHBANDGROWSMUL (1)) { + Gnum vertlocend; + + vertlocend = vrcvdatptr[vertrcvnum]; /* Get local vertex from message */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocend < grafptr->baseval) || (vertlocend >= vertlocnnd)) { + errorPrint (DGRAPHBANDGROWNSTR "dgraphBandPtop: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (vnumgsttax[vertlocend] != ~0) /* If end vertex has already been processed */ + continue; /* Skip to next vertex */ + + vnumgsttax[vertlocend] = DGRAPHBANDGROWENQ4; /* Label vertex as enqueued */ + queuloctab[queunextidx ++] = vertlocend; /* Enqueue vertex for next pass */ + DGRAPHBANDGROWEDGE (vertlocend); /* Account for its edges */ + } + } + + queutailidx = queunextidx; /* Prepare queue for next sweep */ + + if (MPI_Waitall (procngbnbr, nsndreqtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait until all send operations completed */ + errorPrint (DGRAPHBANDGROWNSTR "Ptop: communication error (6)"); + return (1); + } + } + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { /* Free persistent receive requests */ + if (MPI_Request_free (nrcvreqtab + procngbnum) != MPI_SUCCESS) { + errorPrint (DGRAPHBANDGROWNSTR "Ptop: communication error (7)"); + return (1); + } + } + + memFree (procvgbtab); /* Free group leader */ + + *bandvertlocptr = bandvertlocnnd - grafptr->baseval; + *bandedgelocptr = bandedgelocnbr; + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_band_grow.h b/scotch_6.0.3/src/libscotch/dgraph_band_grow.h new file mode 100644 index 00000000..09c64f3d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_band_grow.h @@ -0,0 +1,62 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_band_grow.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file provides the prototypes of **/ +/** the generic band graph growing **/ +/** routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 26 sep 2012 **/ +/** to : 26 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#define DGRAPHBANDGROWNAMECOLL DGRAPHBANDGROWNAMECOLL2 (REPLACE (DGRAPHBANDGROWNAME)) +#define DGRAPHBANDGROWNAMECOLL2(s) GLUE (s,Coll) + +#define DGRAPHBANDGROWNAMEPTOP DGRAPHBANDGROWNAMEPTOP2 (REPLACE (DGRAPHBANDGROWNAME)) +#define DGRAPHBANDGROWNAMEPTOP2(s) GLUE (s,Ptop) + +/* +** The function prototypes. +*/ + +int DGRAPHBANDGROWNAMECOLL (Dgraph * restrict const, const Gnum, Gnum * restrict const, const Gnum, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); +int DGRAPHBANDGROWNAMEPTOP (Dgraph * restrict const, const Gnum, Gnum * restrict const, const Gnum, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); diff --git a/scotch_6.0.3/src/libscotch/dgraph_build.c b/scotch_6.0.3/src/libscotch/dgraph_build.c new file mode 100644 index 00000000..dd5dbfdb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_build.c @@ -0,0 +1,521 @@ +/* Copyright 2007,2010,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_build.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Francois CHATENET (P0.0) **/ +/** Sebastien FOUCAULT (P0.0) **/ +/** Nicolas GICQUEL (P0.1) **/ +/** Jerome LACOSTE (P0.1) **/ +/** Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : These lines are the distributed source **/ +/** graph building routines. **/ +/** **/ +/** DATES : # Version P0.1 : from : 01 apr 1997 **/ +/** to : 20 jun 1997 **/ +/** # Version P0.2 : from : 02 feb 2000 **/ +/** to : 02 feb 2000 **/ +/** # Version 5.0 : from : 22 jul 2005 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 30 jul 2010 **/ +/** to : 03 nov 2010 **/ +/** # Version 6.0 : from : 23 dec 2013 **/ +/** to : 05 jun 2014 **/ +/** **/ +/************************************************************/ + +#define DGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_allreduce.h" +#include "dgraph_build.h" + +/* This routine builds a distributed graph from +** the local arrays that are passed to it. If +** a vertex label array is given, it is assumed +** that edge ends are given with respect to these +** labels, and thus they are updated so as to be +** given with respect to the implicit (based) +** global numbering. +** As for all routines that build graphs, the private +** fields of the Dgraph structure have to be initialized +** if they are not already. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphBuild ( +Dgraph * restrict const grafptr, /* Graph */ +const Gnum baseval, /* Base for indexing */ +const Gnum vertlocnbr, /* Number of local vertices */ +const Gnum vertlocmax, /* Maximum number of local vertices */ +Gnum * const vertloctax, /* Local vertex begin array */ +Gnum * const vendloctax, /* Local vertex end array */ +Gnum * const veloloctax, /* Local vertex load array (if any) */ +Gnum * const vnumloctax, /* Local vertex number array (if any) */ +Gnum * const vlblloctax, /* Local vertex label array (if any) */ +const Gnum edgelocnbr, /* Number of local edges */ +const Gnum edgelocsiz, /* Size of local edge array */ +Gnum * const edgeloctax, /* Local edge array */ +Gnum * const edgegsttax, /* Ghost edge array (if any); not const */ +Gnum * const edloloctax) /* Local edge load array (if any) */ +{ + Gnum vertlocnum; + Gnum vertlocnnd; + Gnum velolocsum; + Gnum degrlocmax; /* Local maximum degree */ + + for (vertlocnum = baseval, vertlocnnd = vertlocnbr + baseval, degrlocmax = 0; + vertlocnum < vertlocnnd; vertlocnum ++) { + Gnum degrval; + + degrval = vendloctax[vertlocnum] - vertloctax[vertlocnum]; + if (degrlocmax < degrval) + degrlocmax = degrval; + } + + if (veloloctax == NULL) /* Get local vertex load sum */ + velolocsum = vertlocnbr; + else { + Gnum vertlocnum; + + for (vertlocnum = baseval, velolocsum = 0; + vertlocnum < vertlocnnd; vertlocnum ++) + velolocsum += veloloctax[vertlocnum]; + } + + return (dgraphBuild2 (grafptr, baseval, + vertlocnbr, vertlocmax, vertloctax, vendloctax, veloloctax, velolocsum, vnumloctax, vlblloctax, + edgelocnbr, edgelocsiz, edgeloctax, edgegsttax, edloloctax, degrlocmax)); +} + +/* This routine builds a distributed graph from +** the local arrays that are passed to it. If +** a vertex label array is given, it is assumed +** that edge ends are given with respect to these +** labels, and thus they are updated so as to be +** given with respect to the implicit (based) +** global numbering. +** As for all routines that build graphs, the private +** fields of the Dgraph structure have to be initialized +** if they are not already. +** These graphs do not have holes, since procvrttab +** points to procdsptab. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphBuild2 ( +Dgraph * restrict const grafptr, /* Graph */ +const Gnum baseval, /* Base for indexing */ +const Gnum vertlocnbr, /* Number of local vertices */ +const Gnum vertlocmax, /* Maximum number of local vertices */ +Gnum * const vertloctax, /* Local vertex begin array */ +Gnum * const vendloctax, /* Local vertex end array */ +Gnum * const veloloctax, /* Local vertex load array (if any) */ +const Gnum velolocsum, /* Local sum of vertex loads */ +Gnum * const vnumloctax, /* Local vertex number array (if any) */ +Gnum * const vlblloctax, /* Local vertex label array (if any) */ +const Gnum edgelocnbr, /* Number of local edges */ +const Gnum edgelocsiz, /* Size of local edge array */ +Gnum * const edgeloctax, /* Local edge array */ +Gnum * const edgegsttax, /* Ghost edge array (if any); not const */ +Gnum * const edloloctax, /* Local edge load array (if any) */ +const Gnum degrlocmax) +{ + Gnum procnum; + int reduloctab[2]; + int cheklocval; /* Local consistency flag */ + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocmax < vertlocnbr) || + (edgelocsiz < edgelocnbr)) { + errorPrint ("dgraphBuild2: invalid parameters"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + cheklocval = 0; + if (grafptr->procdsptab == NULL) { /* If private data not yet allocated */ + int procglbnbr; + + procglbnbr = grafptr->procglbnbr; + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ + &grafptr->procdsptab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), + &grafptr->procvrttab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), + &grafptr->proccnttab, (size_t) (procglbnbr * sizeof (Gnum)), + &grafptr->procngbtab, (size_t) (procglbnbr * sizeof (int)), + &grafptr->procrcvtab, (size_t) (procglbnbr * sizeof (int)), + &grafptr->procsndtab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { + int * dummtab; + + errorPrint ("dgraphBuild2: out of memory"); + if ((dummtab = memAlloc ((procglbnbr * 2) * sizeof (int))) != NULL) { + reduloctab[0] = + reduloctab[1] = -1; + if (MPI_Allgather (reduloctab, 2, MPI_INT, /* Use dummy receive array (if can be allocated too) */ + dummtab, 2, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) + errorPrint ("dgraphBuild2: communication error (1)"); + + memFree (dummtab); + } + return (1); + } + } + + reduloctab[0] = (int) vertlocnbr; + reduloctab[1] = (int) vertlocmax; + if (MPI_Allgather (reduloctab, 2, MPI_INT, /* Use procngbtab and procrcvtab as a joint allreduce receive array */ + grafptr->procngbtab, 2, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphBuild2: communication error (2)"); + return (1); + } + + grafptr->procdsptab[0] = /* Build vertex-to-process array */ + grafptr->procvrttab[0] = baseval; + for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { + if (grafptr->procngbtab[procnum] < 0) { /* If error notified by another process during memory allocation */ + memFree (grafptr->procdsptab); + grafptr->procdsptab = NULL; /* Free memory that has just been allocated */ + return (1); + } + + grafptr->procdsptab[procnum + 1] = grafptr->procdsptab[procnum] + (Gnum) grafptr->procngbtab[2 * procnum]; + grafptr->procvrttab[procnum + 1] = grafptr->procvrttab[procnum] + (Gnum) grafptr->procngbtab[2 * procnum + 1]; + grafptr->proccnttab[procnum] = grafptr->procdsptab[procnum + 1] - grafptr->procdsptab[procnum]; + } + + grafptr->flagval |= DGRAPHFREEPRIV; + return (dgraphBuild3 (grafptr, baseval, + vertlocnbr, vertloctax, vendloctax, veloloctax, velolocsum, vnumloctax, vlblloctax, + edgelocnbr, edgelocsiz, edgeloctax, edgegsttax, edloloctax, degrlocmax)); +} + +/* This routine builds a distributed graph from +** the local arrays that are passed to it. If +** a vertex label array is given, it is assumed +** that edge ends are given with respect to these +** labels, and thus they are updated so as to be +** given with respect to the implicit (based) +** global numbering. +** This alternate interface assumes that the private +** fields of the Dgraph structure have already been +** initialized. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +DGRAPHALLREDUCEMAXSUMOP (17, 3) + +int +dgraphBuild3 ( +Dgraph * restrict const grafptr, /* Graph */ +const Gnum baseval, /* Base for indexing */ +const Gnum vertlocnbr, /* Number of local vertices */ +Gnum * const vertloctax, /* Local vertex begin array */ +Gnum * const vendloctax, /* Local vertex end array */ +Gnum * const veloloctax, /* Local vertex load array (if any) */ +const Gnum velolocsum, /* Local sum of vertex loads */ +Gnum * const vnumloctax, /* Local vertex number array (if any) */ +Gnum * const vlblloctax, /* Local vertex label array (if any) */ +const Gnum edgelocnbr, /* Number of local edges */ +const Gnum edgelocsiz, /* Minimum useful size of local edge array */ +Gnum * const edgeloctax, /* Local edge array */ +Gnum * const edgegsttax, /* Ghost edge array (if any); not const */ +Gnum * const edloloctax, /* Local edge load array (if any) */ +const Gnum degrlocmax) +{ + int procglbnbr; /* Number of processes sharing graph data */ + int procrcvnum; /* Number of process from which to receive */ + int procsndnum; /* Number of process to which to send */ + int procngbnbr; /* Number of neighbors processed */ + int procngbnum; /* Number of current neighbor process */ + int procngbsel; /* Value of the currently used neighbor buffers */ + Gnum vertngbmin; /* Smallest vertex number of neighbor process */ + Gnum vertlocnum; + Gnum edgelocnum; + const Gnum * vlbllocptr; /* Pointer to current vertex label */ + DgraphLablSortVert * vesongbptr; /* Pointer to current sort cell */ + DgraphLablSortVert * vesongbtnd; /* Pointer to end of current sort array */ + DgraphLablSortVert * vesongbtab[2]; /* Neighbor vertex sorting array [norestrict:async] */ + int vesongbnbr[2]; /* Sizes of both vertex sort arrays */ + DgraphLablSortEdge * edsoloctab; /* Local edge sorting array */ + DgraphLablSortEdge * edsoloctnd; /* Pointer to end of edge sort array */ + DgraphLablSortEdge * edsolocptr; /* Pointer to current sort edge */ + MPI_Request requloctab[2]; /* Arrays for pipelined communication */ + MPI_Status statloctab[2]; + int cheklocval; /* Local consistency flag */ + int chekglbval; /* Global consistency flag */ + Gnum reduloctab[20]; /* Arrays for reductions */ + Gnum reduglbtab[20]; + + reduloctab[0] = baseval; /* Check argument consistency */ + reduloctab[1] = - baseval; + reduloctab[2] = (veloloctax != NULL) ? 1 : 0; + reduloctab[3] = - reduloctab[2]; + reduloctab[4] = (vnumloctax != NULL) ? 1 : 0; + reduloctab[5] = - reduloctab[4]; + reduloctab[6] = (vlblloctax != NULL) ? 1 : 0; + reduloctab[7] = - reduloctab[6]; + reduloctab[8] = (edloloctax != NULL) ? 1 : 0; + reduloctab[9] = - reduloctab[8]; + reduloctab[10] = (edgegsttax != NULL) ? 1 : 0; + reduloctab[11] = - reduloctab[10]; + reduloctab[12] = vertlocnbr; /* Get maximum number of local vertices */ + reduloctab[13] = edgelocnbr; + reduloctab[14] = edgelocsiz; + reduloctab[15] = degrlocmax; + reduloctab[16] = (grafptr->procdsptab == NULL) ? 1 : 0; /* Error if private data not yet allocated */ + + reduloctab[17] = vertlocnbr; /* Sum local sizes */ + reduloctab[18] = velolocsum; + reduloctab[19] = edgelocnbr; + + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 17, 3, grafptr->proccomm) != 0) { + errorPrint ("dgraphBuild3: cannot compute reductions"); + return (1); + } + if (reduglbtab[16] != 0) { + errorPrint ("dgraphBuild3: no private data"); + return (1); + } + if ((reduglbtab[1] != - reduglbtab[0]) || + (reduglbtab[3] != - reduglbtab[2]) || + (reduglbtab[5] != - reduglbtab[4]) || + (reduglbtab[7] != - reduglbtab[6]) || + (reduglbtab[9] != - reduglbtab[8]) || + (reduglbtab[11] != - reduglbtab[10])) { + errorPrint ("dgraphBuild3: inconsistent parameters"); + return (1); + } + + grafptr->vertglbmax = reduglbtab[12]; /* Set maximum number of local vertices */ + grafptr->edgeglbmax = reduglbtab[13]; /* Set maximum number of local edges */ + grafptr->edgeglbsmx = reduglbtab[14]; /* Set maximum size of local edge arrays */ + grafptr->degrglbmax = reduglbtab[15]; /* Set maximum degree */ + + grafptr->baseval = baseval; + grafptr->vertglbnbr = reduglbtab[17]; /* Set global and local data */ + grafptr->vertlocnbr = vertlocnbr; + grafptr->vertlocnnd = vertlocnbr + baseval; + grafptr->velolocsum = velolocsum; + grafptr->veloglbsum = reduglbtab[18]; + grafptr->vertloctax = vertloctax; + grafptr->vendloctax = vendloctax; + grafptr->veloloctax = veloloctax; + grafptr->vnumloctax = vnumloctax; + grafptr->vlblloctax = vlblloctax; + grafptr->edgeglbnbr = reduglbtab[19]; + grafptr->edgelocnbr = edgelocnbr; + grafptr->edgelocsiz = edgelocsiz; + grafptr->edgegsttax = edgegsttax; + grafptr->edgeloctax = edgeloctax; + grafptr->edloloctax = edloloctax; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((grafptr->procdsptab[grafptr->procglbnbr] - baseval) < grafptr->vertglbnbr) { + errorPrint ("dgraphBuild3: invalid process vertex array"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (vlblloctax != NULL) { /* If vertex labels given */ + procglbnbr = grafptr->procglbnbr; + + if (memAllocGroup ((void **) (void *) + &vesongbtab[0], (size_t) (grafptr->vertglbmax * sizeof (DgraphLablSortVert)), + &vesongbtab[1], (size_t) (grafptr->vertglbmax * sizeof (DgraphLablSortVert)), + &edsoloctab, (size_t) (grafptr->edgeglbmax * sizeof (DgraphLablSortEdge)), + NULL) == NULL) { + errorPrint ("dgraphBuild3: out of memory"); + return (1); + } + + for (vertlocnum = 0, vesongbptr = vesongbtab[0], vlbllocptr = vlblloctax + baseval; + vertlocnum < vertlocnbr; + vertlocnum ++, vesongbptr ++, vlbllocptr ++) { + vesongbptr->vlblglbnum = *vlbllocptr; /* Build vertex sort array */ + vesongbptr->vertlocnum = vertlocnum; /* Local index is not based */ + } + intSort2asc1 (vesongbtab[0], vertlocnbr); + vesongbnbr[0] = vertlocnbr; /* Set array size */ + + cheklocval = 0; + + for (vesongbptr = vesongbtab[0] + 1, vesongbtnd = vesongbtab[0] + vertlocnbr; + vesongbptr < vesongbtnd; vesongbptr ++) { + if (vesongbptr[0].vlblglbnum == vesongbptr[-1].vlblglbnum) { + cheklocval = 1; + break; + } + } +#ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ + MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm); +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (chekglbval != 0) { + errorPrint ("dgraphBuild3: duplicate vertex label (1)"); + memFree (vesongbtab[0]); + return (1); + } + + for (edsolocptr = edsoloctab, edsoloctnd = edsoloctab + edgelocnbr, edgelocnum = baseval; + edsolocptr < edsoloctnd; edsolocptr ++, edgelocnum ++) { + edsolocptr->vlblglbnum = edgeloctax[edgelocnum]; + edsolocptr->edgelocnum = edgelocnum; + } + intSort2asc2 (edsoloctab, grafptr->edgelocnbr); + + procrcvnum = (grafptr->proclocnum + 1) % procglbnbr; /* Compute indices of neighbors */ + procsndnum = (grafptr->proclocnum - 1 + procglbnbr) % procglbnbr; + + for (procngbnbr = 0, procngbsel = 0; /* For all processes */ + procngbnbr < procglbnbr; + procngbnbr ++, procngbsel = 1 - procngbsel) { + procngbnum = (grafptr->proclocnum + procngbnbr) % procglbnbr; /* Get neighbor process */ + vertngbmin = grafptr->procvrttab[procngbnum]; /* Get neighbor vertex number range */ + + if (procngbnbr < (procglbnbr - 1)) { /* If not last iteration */ + MPI_Irecv (vesongbtab[1 - procngbsel], 2 * grafptr->vertglbmax, GNUM_MPI, procrcvnum, TAGVLBLLOCTAB, grafptr->proccomm, &requloctab[0]); + MPI_Isend (vesongbtab[procngbsel], 2 * vesongbnbr[procngbsel], GNUM_MPI, procsndnum, TAGVLBLLOCTAB, grafptr->proccomm, &requloctab[1]); + } + + if (vesongbnbr[procngbsel] > 0) { /* If neighbor vertex sort array not empty */ + for (edsolocptr = edsoloctab, /* Replace label by global vertex number */ + vesongbptr = vesongbtab[procngbsel], vesongbtnd = vesongbptr + vesongbnbr[procngbsel]; + edsolocptr < edsoloctnd; ) { + if (edsolocptr->vlblglbnum == vesongbptr->vlblglbnum) { + if (edsolocptr->edgelocnum == -1) /* If edge label already replaced */ + cheklocval = 1; /* Set error flag */ + else { + edgeloctax[edsolocptr->edgelocnum] = vertngbmin + vesongbptr->vertlocnum; + edsolocptr->edgelocnum = -1; /* Edge has been processed */ + } + edsolocptr ++; /* One more edge processed */ + continue; /* Go on as quickly as possible */ + } + if (edsolocptr->vlblglbnum < vesongbptr->vlblglbnum) { + edsolocptr ++; /* One more edge processed */ + continue; /* Go on as quickly as possible */ + } + while (edsolocptr->vlblglbnum > vesongbptr->vlblglbnum) { + if (++ vesongbptr >= vesongbtnd) { /* Break if all labels processed */ + edsolocptr = edsoloctnd; + break; + } + } + } + } + + if (procngbnbr < (procglbnbr - 1)) { /* If not last iteration */ + MPI_Waitall (2, requloctab, statloctab); /* Wait for communication completion */ + MPI_Get_count (&statloctab[0], GNUM_MPI, &vesongbnbr[1 - procngbsel]); + vesongbnbr[1 - procngbsel] /= 2; /* Count items, not fields */ + } + } + + memFree (vesongbtab[0]); + +#ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ + MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm); +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (chekglbval != 0) { + errorPrint ("dgraphBuild3: duplicate vertex label (2)"); + return (1); + } + } + + return (0); +} + +/* This subroutine computes the reduced values +** of all of the distributed graph fields. +** It does not deal with vertex labels, nor with +** the ghost edge array. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +DGRAPHALLREDUCEMAXSUMOP (4, 3) + +int +dgraphBuild4 ( +Dgraph * restrict const grafptr) /* Distributed graph */ +{ + Gnum reduloctab[7]; /* Arrays for reductions */ + Gnum reduglbtab[7]; + + reduloctab[0] = grafptr->vertlocnbr; /* Get maximum over all processes */ + reduloctab[1] = grafptr->edgelocnbr; + reduloctab[2] = grafptr->edgelocsiz; + reduloctab[3] = grafptr->degrglbmax; /* Here, degrglbmax may store only a local maximum degree before calling */ + + reduloctab[4] = grafptr->vertlocnbr; /* Sum local sizes */ + reduloctab[5] = grafptr->velolocsum; + reduloctab[6] = grafptr->edgelocnbr; + + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 4, 3, grafptr->proccomm) != 0) { + errorPrint ("dgraphBuild4: cannot compute reductions"); + return (1); + } + + grafptr->vertglbmax = reduglbtab[0]; /* Set maximum number of local vertices */ + grafptr->edgeglbmax = reduglbtab[1]; /* Set maximum number of local edges */ + grafptr->edgeglbsmx = reduglbtab[2]; /* Set maximum size of local edge arrays */ + grafptr->degrglbmax = reduglbtab[3]; /* Set maximum degree */ + + grafptr->vertglbnbr = reduglbtab[4]; + grafptr->veloglbsum = reduglbtab[5]; + grafptr->edgeglbnbr = reduglbtab[6]; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((grafptr->procdsptab[grafptr->procglbnbr] - grafptr->baseval) < grafptr->vertglbnbr) { + errorPrint ("dgraphBuild4: invalid process vertex array"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_build.h b/scotch_6.0.3/src/libscotch/dgraph_build.h new file mode 100644 index 00000000..a151afc1 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_build.h @@ -0,0 +1,71 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/**********************************************************/ +/* */ +/* NAME : dgraph_build.h */ +/* */ +/* AUTHOR : Francois PELLEGRINI */ +/* Francois CHATENET (P0.0) */ +/* Sebastien FOUCAULT (P0.0) */ +/* Nicolas GICQUEL (P0.1) */ +/* Jerome LACOSTE (P0.1) */ +/* */ +/* FUNCTION : Part of a parallel static mapper. */ +/* These lines are the data declarations */ +/* for the distributed source graph */ +/* building routines. */ +/* */ +/* # Version P0.1 : from : 01 apr 1997 */ +/* to 13 sep 2006 */ +/* # Version 5.0 : from : 22 dec 2006 */ +/* to 22 dec 2006 */ +/* */ +/**********************************************************/ + +/* +** The type and structure definitions. +*/ + +/* Sort structure for local vertices. First + element used for intSort2asc1. */ + +typedef struct DgraphLablSortVert_ { + Gnum vlblglbnum; /* Global vertex label: FIRST */ + Gnum vertlocnum; /* Index in local vertex array */ +} DgraphLablSortVert; + +/* Sort structure for local edges. */ + +typedef struct DgraphLablSortEdge_ { + Gnum vlblglbnum; /* Global vertex label */ + Gnum edgelocnum; /* Index of local edge */ +} DgraphLablSortEdge; diff --git a/scotch_6.0.3/src/libscotch/dgraph_build_grid3d.c b/scotch_6.0.3/src/libscotch/dgraph_build_grid3d.c new file mode 100644 index 00000000..e616fb5a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_build_grid3d.c @@ -0,0 +1,481 @@ +/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_build_grid3d.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (5.0) **/ +/** **/ +/** FUNCTION : These lines are the distributed source **/ +/** graph building routines for 3D grid **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 5.0 : from : 21 jul 2005 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 05 jun 2010 **/ +/** to : 06 jun 2010 **/ +/** **/ +/************************************************************/ + +#define DGRAPH_BUILD_GRID3D + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_build_grid3d.h" + +/**************************************/ +/* */ +/* Vertex neighbor handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +static +Gnum +dgraphBuildGrid3Dvertex26M ( +const DgraphBuildGrid3DData * restrict const dataptr, +const Gnum vertglbnum, +Gnum edgelocnum, +const Gnum posxval, +const Gnum posyval, +const Gnum poszval) +{ + Gnum ngbxmin; + Gnum ngbxmax; + Gnum ngbxval; + Gnum ngbymin; + Gnum ngbymax; + Gnum ngbyval; + Gnum ngbzmin; + Gnum ngbzmax; + Gnum ngbzval; + + ngbxmin = (posxval > 0) ? -1 : 0; + ngbymin = (posyval > 0) ? -1 : 0; + ngbzmin = (poszval > 0) ? -1 : 0; + ngbxmax = (posxval < (dataptr->dimxval - 1)) ? 1 : 0; + ngbymax = (posyval < (dataptr->dimyval - 1)) ? 1 : 0; + ngbzmax = (poszval < (dataptr->dimzval - 1)) ? 1 : 0; + + for (ngbzval = ngbzmin; ngbzval <= ngbzmax; ngbzval ++) { + for (ngbyval = ngbymin; ngbyval <= ngbymax; ngbyval ++) { + for (ngbxval = ngbxmin; ngbxval <= ngbxmax; ngbxval ++) { + if ((ngbxval | ngbyval | ngbzval) != 0) /* If not loop edge */ + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, + (posxval + dataptr->dimxval + ngbxval) % dataptr->dimxval, + (posyval + dataptr->dimyval + ngbyval) % dataptr->dimyval, + (poszval + dataptr->dimzval + ngbzval) % dataptr->dimzval); + } + } + } + + return (edgelocnum); +} + +/* +** +*/ + +static +Gnum +dgraphBuildGrid3Dvertex26T ( +const DgraphBuildGrid3DData * restrict const dataptr, +const Gnum vertglbnum, +Gnum edgelocnum, +const Gnum posxval, +const Gnum posyval, +const Gnum poszval) +{ + Gnum ngbxmin; + Gnum ngbxmax; + Gnum ngbxval; + Gnum ngbymin; + Gnum ngbymax; + Gnum ngbyval; + Gnum ngbzmin; + Gnum ngbzmax; + Gnum ngbzval; + + ngbxmin = dataptr->t26.ngbxmin; + ngbxmax = dataptr->t26.ngbxmax; + ngbymin = dataptr->t26.ngbymin; + ngbymax = dataptr->t26.ngbymax; + ngbzmin = dataptr->t26.ngbzmin; + ngbzmax = dataptr->t26.ngbzmax; + + for (ngbzval = ngbzmin; ngbzval <= ngbzmax; ngbzval ++) { + for (ngbyval = ngbymin; ngbyval <= ngbymax; ngbyval ++) { + for (ngbxval = ngbxmin; ngbxval <= ngbxmax; ngbxval ++) { + Gnum vertglbend; + + vertglbend = (((poszval + ngbzval) % dataptr->dimzval) * dataptr->dimyval + + ((posyval + ngbyval) % dataptr->dimyval)) * dataptr->dimxval + + ((posxval + ngbxval) % dataptr->dimxval) + dataptr->baseval; + if (vertglbend != vertglbnum) { /* If not loop edge */ + if (dataptr->edloloctax != NULL) + dataptr->edloloctax[edgelocnum] = ((vertglbend + vertglbnum) % 16) + 1; + dataptr->edgeloctax[edgelocnum ++] = vertglbend; + } + } + } + } + + return (edgelocnum); +} + +/* +** +*/ + +static +Gnum +dgraphBuildGrid3Dvertex6M ( +const DgraphBuildGrid3DData * restrict const dataptr, +const Gnum vertglbnum, +Gnum edgelocnum, +const Gnum posxval, +const Gnum posyval, +const Gnum poszval) +{ + Gnum ngbxval; + Gnum ngbyval; + Gnum ngbzval; + + ngbxval = posxval - 1; + if (ngbxval >= 0) + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, ngbxval, posyval, poszval); + ngbxval = posxval + 1; + if (ngbxval < dataptr->dimxval) + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, ngbxval, posyval, poszval); + + ngbyval = posyval - 1; + if (ngbyval >= 0) + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, ngbyval, poszval); + ngbyval = posyval + 1; + if (ngbyval < dataptr->dimyval) + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, ngbyval, poszval); + + ngbzval = poszval - 1; + if (ngbzval >= 0) + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, posyval, ngbzval); + ngbzval = poszval + 1; + if (ngbzval < dataptr->dimzval) + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, posyval, ngbzval); + + return (edgelocnum); +} + +/* +** +*/ + +static +Gnum +dgraphBuildGrid3Dvertex6T ( +const DgraphBuildGrid3DData * restrict const dataptr, +const Gnum vertglbnum, +Gnum edgelocnum, +const Gnum posxval, +const Gnum posyval, +const Gnum poszval) +{ + Gnum ngbxval; + Gnum ngbyval; + Gnum ngbzval; + + if (dataptr->dimxval > 1) { + ngbxval = (posxval + 1) % dataptr->dimxval; + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, ngbxval, posyval, poszval); + if (dataptr->dimxval > 2) { + ngbxval = (posxval + dataptr->dimxval - 1) % dataptr->dimxval; + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, ngbxval, posyval, poszval); + } + } + + if (dataptr->dimyval > 1) { + ngbyval = (posyval + 1) % dataptr->dimyval; + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, ngbyval, poszval); + if (dataptr->dimyval > 2) { + ngbyval = (posyval + dataptr->dimyval - 1) % dataptr->dimyval; + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, ngbyval, poszval); + } + } + + if (dataptr->dimzval > 1) { + ngbzval = (poszval + 1) % dataptr->dimzval; + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, posyval, ngbzval); + if (dataptr->dimzval > 2) { + ngbzval = (poszval + dataptr->dimzval - 1) % dataptr->dimzval; + DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, posyval, ngbzval); + } + } + + return (edgelocnum); +} + +/*******************************************/ +/* */ +/* The distributed graph building routine. */ +/* */ +/*******************************************/ + +/* This routine builds a distrbuted grid graph +** of the given dimensions. +** hashval is the increment between two vertex +** indices (1 for sliced meshes). +** flagval is a combilation of: +** - 1 : 26-neighbor mesh (default: 6-neighbor mesh). +** - 2 : torus (default: mesh) +** - 4 : weighted vertices (default: no weights). +** - 8 : weighted edges (default: no weights). +** It returns: +** - 0 : graph created. +** - !0 : on error. +*/ + +int +dgraphBuildGrid3D ( +Dgraph * restrict const grafptr, /* Graph */ +const Gnum baseval, /* Base value */ +const Gnum dimxval, /* First dimension */ +const Gnum dimyval, /* Second dimension */ +const Gnum dimzval, /* Third dimension */ +const Gnum incrval, /* Increment step */ +const int flagval) /* Grid type */ +{ + DgraphBuildGrid3DData datadat; /* Data structure for creating vertices */ + Gnum proclocadj; /* Number of processes with most vertices */ + Gnum vertglbmin; /* Minimum global index of local vertices */ + Gnum vertglbnbr; + Gnum vertlocnbr; + Gnum vertlocnnd; + Gnum vertlocnum; + Gnum * vertloctax; + Gnum velolocsiz; + Gnum velolocsum; + Gnum * veloloctax; + Gnum * vlblloctax; + Gnum vlbllocsiz; + Gnum edgelocsiz; + Gnum edgelocnum; + Gnum * edgeloctab; + Gnum edlolocsiz; + Gnum * edloloctab; + Gnum degrglbmax; + +#ifdef SCOTCH_DEBUG_DGRAPH1 + if ((dimxval < 1) || (dimyval < 1) || (dimzval < 1)) { /* At least one vertex */ + errorPrint ("dgraphBuildGrid3D: invalid parameters (1)"); + return (1); + } + if (incrval < 1) { + errorPrint ("dgraphBuildGrid3D: invalid parameters (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + + vertglbnbr = dimxval * dimyval * dimzval; + vertlocnbr = DATASIZE (vertglbnbr, grafptr->procglbnbr, grafptr->proclocnum); + + if ((flagval & 1) != 0) { /* If 26-neighbor mesh */ + degrglbmax = 26; + if ((flagval & 2) != 0) { /* If torus graph */ + datadat.t26.ngbxmin = (dimxval > 1) ? (dimxval - 1) : dimxval; /* Avoid loop edges */ + datadat.t26.ngbxmax = (dimxval > 2) ? (dimxval + 1) : dimxval; + datadat.t26.ngbymin = (dimyval > 1) ? (dimyval - 1) : dimyval; + datadat.t26.ngbymax = (dimyval > 2) ? (dimyval + 1) : dimyval; + datadat.t26.ngbzmin = (dimzval > 1) ? (dimzval - 1) : dimzval; + datadat.t26.ngbzmax = (dimzval > 2) ? (dimzval + 1) : dimzval; + + datadat.funcvrtptr = dgraphBuildGrid3Dvertex26T; + } + else + datadat.funcvrtptr = dgraphBuildGrid3Dvertex26M; + } + else { /* If 6-neighbor mesh */ + degrglbmax = 6; + datadat.funcvrtptr = ((flagval & 2) != 0) ? dgraphBuildGrid3Dvertex6T : dgraphBuildGrid3Dvertex6M; + } + edgelocsiz = vertlocnbr * degrglbmax; /* (Possibly upper bound on) number of edges */ + vlbllocsiz = (incrval != 1) ? vertlocnbr : 0; /* If no hashing, no need for vertex labels */ + velolocsiz = ((flagval & 4) != 0) ? vertlocnbr : 0; + edlolocsiz = ((flagval & 8) != 0) ? edgelocsiz : 0; + + if (memAllocGroup ((void **) (void *) + &vertloctax, (size_t) ((vertlocnbr + 1) * sizeof (Gnum)), /* +1 to indicate end of array */ + &veloloctax, (size_t) (velolocsiz * sizeof (Gnum)), + &vlblloctax, (size_t) (vlbllocsiz * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphBuildGrid3D: out of memory (1)"); + return (1); + } + if (memAllocGroup ((void **) (void *) + &edgeloctab, (size_t) (edgelocsiz * sizeof (Gnum)), + &edloloctab, (size_t) (edlolocsiz * sizeof (Gnum)), NULL) == NULL) { + memFree (vertloctax); + errorPrint ("dgraphBuildGrid3D: out of memory (2)"); + return (1); + } + + datadat.baseval = baseval; + datadat.dimxval = dimxval; + datadat.dimyval = dimyval; + datadat.dimzval = dimzval; + datadat.edgeloctax = edgeloctab - baseval; + datadat.edloloctax = ((flagval & 8) != 0) ? (edloloctab - baseval) : NULL; + vertloctax = vertloctax - baseval; + veloloctax = ((flagval & 4) != 0) ? (veloloctax - baseval) : NULL; + vlblloctax = (incrval != 1) ? (vlblloctax - baseval) : NULL; + + proclocadj = vertglbnbr % grafptr->procglbnbr; /* Number of processes with +1 number of vertices */ + vertglbmin = (vertglbnbr / grafptr->procglbnbr) * grafptr->proclocnum + MIN (grafptr->proclocnum, proclocadj); + + edgelocnum = + vertlocnum = baseval; + vertlocnnd = baseval + vertlocnbr; + velolocsum = (veloloctax == NULL) ? vertlocnbr : 0; + if (incrval != 1) { /* If strided or pseudo-randomly distributed mesh */ + Gnum vertglbidx; /* Un-based global index of current vertex */ + Gnum rondlocnbr; /* Number of already completed rounds of increments */ + Gnum a; + Gnum b; + + a = (vertglbnbr > incrval) ? vertglbnbr : incrval; /* Get biggest of the two */ + b = (vertglbnbr + incrval) - a; /* Get smallest of the two */ + do { + Gnum t; + + t = a % b; + if (t == 0) + break; + a = b; + b = t; + } while (b > 1); /* Compute GCD of vertglbnbr and incrval in b */ + + rondlocnbr = (vertglbmin * b) / vertglbnbr; + vertglbidx = (vertglbmin * incrval + rondlocnbr) % vertglbnbr; /* Compute skewed index, with rounds */ + + for ( ; vertlocnum < vertlocnnd; vertlocnum ++) { + Gnum vertglbnum; + Gnum positmp; + Gnum posxval; + Gnum posyval; + Gnum poszval; + + poszval = vertglbidx / (dimxval * dimyval); + positmp = vertglbidx % (dimxval * dimyval); + posyval = positmp / dimxval; + posxval = positmp % dimxval; + + vertglbnum = vertglbidx + baseval; + vertloctax[vertlocnum] = edgelocnum; + vlblloctax[vertlocnum] = vertglbnum; + if (veloloctax != NULL) { + velolocsum += + veloloctax[vertlocnum] = (vertglbnum % 16) + 1; + } + edgelocnum = datadat.funcvrtptr (&datadat, vertglbnum, edgelocnum, posxval, posyval, poszval); +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgelocnum > (edgelocsiz + baseval)) { + errorPrint ("dgraphBuildGrid3D: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + vertglbidx = (vertglbidx + incrval) % vertglbnbr; /* Add increment to global index */ + if (vertglbidx == rondlocnbr) { /* If we looped back to the current beginning */ + rondlocnbr ++; /* Start a new round of increments */ + vertglbidx = rondlocnbr; + } + } + } + else { /* Regularly sliced mesh */ + Gnum vertglbnum; /* Based global vertex number */ + Gnum positmp; + Gnum posxval; + Gnum posyval; + Gnum poszval; + + poszval = vertglbmin / (dimxval * dimyval); + positmp = vertglbmin % (dimxval * dimyval); + posyval = positmp / dimxval; + posxval = positmp % dimxval; + + for (vertglbnum = vertglbmin + baseval; vertlocnum < vertlocnnd; vertlocnum ++, vertglbnum ++) { + vertloctax[vertlocnum] = edgelocnum; + if (veloloctax != NULL) { + velolocsum += + veloloctax[vertlocnum] = (vertglbnum % 16) + 1; + } + + edgelocnum = datadat.funcvrtptr (&datadat, vertglbnum, edgelocnum, posxval, posyval, poszval); +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgelocnum > (edgelocsiz + baseval)) { + errorPrint ("dgraphBuildGrid3D: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (++ posxval >= dimxval) { + posxval = 0; + if (++ posyval >= dimyval) { + posyval = 0; + poszval ++; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((poszval >= dimzval) && + (vertglbnum < (vertglbnbr + baseval - 1))){ + errorPrint ("dgraphBuildGrid3D: internal error (X)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + } + } + } + } + vertloctax[vertlocnum] = edgelocnum; /* Mark end of local vertex array */ + + grafptr->flagval = (DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP); /* All arrays will be freed on exit */ + + if (dgraphBuild2 (grafptr, baseval, /* Build distributed graph */ + vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, veloloctax, velolocsum, NULL, vlblloctax, + edgelocnum - baseval, edgelocsiz, datadat.edgeloctax, NULL, datadat.edloloctax, degrglbmax) != 0) { + memFree (datadat.edgeloctax + baseval); /* Free memory group leaders */ + memFree (vertloctax + baseval); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_build_grid3d.h b/scotch_6.0.3/src/libscotch/dgraph_build_grid3d.h new file mode 100644 index 00000000..438bbdba --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_build_grid3d.h @@ -0,0 +1,101 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_build_grid3d.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data **/ +/** declarations for the distributed 3D **/ +/** grid graph building routine. **/ +/** **/ +/** DATES : # Version 5.1 : from : 06 jun 2010 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ The multinode table element, which contains + pairs of based indices of collapsed vertices. + Both values are equal for uncollapsed vertices. +*/ + +typedef struct DgraphBuildGrid3DData_ { + Gnum baseval; + Gnum dimxval; + Gnum dimyval; + Gnum dimzval; + Gnum * edgeloctax; + Gnum * edloloctax; + Gnum (* funcvrtptr) (const struct DgraphBuildGrid3DData_ * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); + struct { /* Pre-computed data for 26-neighbor torus */ + Gnum ngbxmin; + Gnum ngbxmax; + Gnum ngbymin; + Gnum ngbymax; + Gnum ngbzmin; + Gnum ngbzmax; + } t26; +} DgraphBuildGrid3DData; + +/* +** The function prototypes. +*/ + +#ifndef DGRAPH_BUILD_GRID3D +#define static +#endif + +static Gnum dgraphBuildGrid3Dvertex26M (const DgraphBuildGrid3DData * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); +static Gnum dgraphBuildGrid3Dvertex26T (const DgraphBuildGrid3DData * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); +static Gnum dgraphBuildGrid3Dvertex6M (const DgraphBuildGrid3DData * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); +static Gnum dgraphBuildGrid3Dvertex6T (const DgraphBuildGrid3DData * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); + +#undef static + +/* +** The macro definitions. +*/ + +#define DGRAPHBUILDGRID3DNGB(d,v,e,x,y,z) { \ + Gnum edgeloctmp; \ + Gnum vertglbend; \ + edgeloctmp = (e); \ + vertglbend = ((z) * (d)->dimyval + (y)) * (d)->dimxval + (x) + (d)->baseval; \ + (d)->edgeloctax[edgeloctmp] = vertglbend; \ + if ((d)->edloloctax != NULL) \ + (d)->edloloctax[edgeloctmp] = ((vertglbend + (v)) % 16) + 1; \ + } + diff --git a/scotch_6.0.3/src/libscotch/dgraph_build_hcub.c b/scotch_6.0.3/src/libscotch/dgraph_build_hcub.c new file mode 100644 index 00000000..35622ccb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_build_hcub.c @@ -0,0 +1,212 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_build_hcub.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : These lines are the distributed source **/ +/** graph building routines for hypercube **/ +/** graphs. **/ +/** **/ +/** DATES : # Version P0.1 : from : 19 may 1999 **/ +/** to : 19 may 1999 **/ +/** # Version P0.2 : from : 02 feb 2000 **/ +/** to : 02 feb 2000 **/ +/** # Version 5.0 : from : 20 jul 2005 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 12 nov 2008 **/ +/** to : 12 nov 2008 **/ +/** **/ +/************************************************************/ + +#define DGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" + +/*******************************************/ +/* */ +/* The distributed graph building routine. */ +/* */ +/*******************************************/ + +/* This routine builds a distributed hypercube of +** given dimension. +** Since this routine calls dgraphBuild, the private +** data of the Dgraph structure will be initialized +** by the latter, if needed. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphBuildHcub ( +Dgraph * restrict const grafptr, /* Graph */ +const Gnum hcubdim, /* Hypercube dimension */ +const Gnum baseval, /* Base value */ +const Gnum flagval) /* Flags */ +{ + Gnum procngbnum; + Gnum vertglbnbr; /* Total number of vertices */ + Gnum vertglbnum; /* Global number of current vertex */ + Gnum vertlocnbr; /* Number of local vertices */ + Gnum velolocnbr; /* Number of local vertex loads */ + Gnum vertlocnnd; + Gnum vertlocnum; + Gnum * restrict vertloctax; + Gnum * restrict veloloctax; +#ifdef SCOTCH_DEBUG_DGRAPH3 + Gnum * restrict vlblloctax; +#endif /* SCOTCH_DEBUG_DGRAPH3 */ + Gnum edgelocnbr; + Gnum * restrict edgeloctax; + Gnum edgelocnum; + Gnum edlolocnbr; + Gnum * restrict edloloctax; + int cheklocval; + Gnum reduloctab[7]; + Gnum reduglbtab[7]; + + vertglbnbr = 1 << hcubdim; + vertlocnbr = DATASIZE (vertglbnbr, grafptr->procglbnbr, grafptr->proclocnum); + velolocnbr = ((flagval & 1) != 0) ? vertlocnbr : 0; + edgelocnbr = vertlocnbr * hcubdim; /* Set local number of arcs */ + edlolocnbr = ((flagval & 2) != 0) ? edgelocnbr : 0; + + for (procngbnum = 0, vertglbnum = 0; /* Compute index of first local vertex */ + procngbnum < grafptr->proclocnum; procngbnum ++) + vertglbnum += DATASIZE (vertglbnbr, grafptr->procglbnbr, procngbnum); + + cheklocval = 0; + vertloctax = + edgeloctax = NULL; + if (memAllocGroup ((void **) (void *) + &vertloctax, (size_t) ((vertlocnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ +#ifdef SCOTCH_DEBUG_DGRAPH3 + &vlblloctax, (size_t) (vertlocnbr * sizeof (Gnum)), +#endif /* SCOTCH_DEBUG_DGRAPH3 */ + &veloloctax, (size_t) (vertlocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphBuildHcub: out of memory (1)"); + cheklocval = 1; + } + else if (memAllocGroup ((void **) (void *) + &edgeloctax, (size_t) (edgelocnbr * sizeof (Gnum)), + &edloloctax, (size_t) (edlolocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphBuildHcub: out of memory (2)"); + cheklocval = 1; + } + reduloctab[0] = hcubdim; + reduloctab[1] = - hcubdim; + reduloctab[2] = baseval; + reduloctab[3] = - baseval; + reduloctab[4] = flagval; + reduloctab[5] = - flagval; + reduloctab[6] = cheklocval; + + if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphBuildHcub: communication error"); + return (1); + } + if (reduglbtab[6] != 0) { + if (vertloctax != NULL) { + if (edgeloctax != NULL) + memFree (edgeloctax); + memFree (vertloctax); + } + return (1); + } + if ((reduglbtab[1] != - reduglbtab[0]) || + (reduglbtab[3] != - reduglbtab[2]) || + (reduglbtab[5] != - reduglbtab[4])) { + errorPrint ("dgraphBuildHcub: inconsistent parameters"); + return (1); + } + vertloctax -= baseval; + veloloctax = ((flagval & 1) != 0) ? (veloloctax - baseval) : NULL; + edgeloctax -= baseval; + edloloctax = ((flagval & 2) != 0) ? (edloloctax - baseval) : NULL; +#ifdef SCOTCH_DEBUG_DGRAPH3 + vlblloctax -= baseval; +#endif /* SCOTCH_DEBUG_DGRAPH3 */ + + for (vertlocnum = baseval, vertlocnnd = vertlocnbr + baseval, edgelocnum = baseval; + vertlocnum < vertlocnnd; vertlocnum ++, vertglbnum ++) { + Gnum vertngbbit; /* Bit that differs between neighbors */ + + if (veloloctax != NULL) + veloloctax[vertlocnum] = 1 + (vertglbnum & 3); /* Pseudo random weight (1 to 5) */ +#ifdef SCOTCH_DEBUG_DGRAPH3 + vlblloctax[vertlocnum] = ((vertglbnum * COARHASHPRIME) % vertglbnbr) + baseval; /* Hash vertices to spread labels */ +#endif /* SCOTCH_DEBUG_DGRAPH3 */ + vertloctax[vertlocnum] = edgelocnum; + + for (vertngbbit = 1; vertngbbit < vertglbnbr; vertngbbit <<= 1, edgelocnum ++) { +#ifdef SCOTCH_DEBUG_DGRAPH3 + edgeloctax[edgelocnum] = (((vertglbnum ^ vertngbbit) * COARHASHPRIME) % vertglbnbr) + baseval; +#else /* SCOTCH_DEBUG_DGRAPH3 */ + edgeloctax[edgelocnum] = (vertglbnum ^ vertngbbit) + baseval; +#endif /* SCOTCH_DEBUG_DGRAPH3 */ + if (edloloctax != NULL) + edloloctax[edgelocnum] = ((vertglbnum + edgeloctax[edgelocnum]) % 16) + 1; /* Pseudo random weight (1 to 16) */ + } + } + vertloctax[vertlocnum] = edgelocnum; /* Mark end of local vertex array */ + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgelocnum != edgelocnbr + baseval) { + errorPrint ("dgraphBuildHcub: internal error"); + memFree (vertloctax + baseval); /* Free memory group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (dgraphBuild2 (grafptr, baseval, /* Build the distributed graph */ +#ifdef SCOTCH_DEBUG_DGRAPH3 + vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, NULL, vertlocnbr, NULL, vlblloctax, +#else /* SCOTCH_DEBUG_DGRAPH3 */ + vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, NULL, vertlocnbr, NULL, NULL, +#endif /* SCOTCH_DEBUG_DGRAPH3 */ + edgelocnbr, edgelocnbr, edgeloctax, NULL, edloloctax, hcubdim) != 0) { + memFree (edgeloctax + baseval); /* Free memory group leaders */ + memFree (vertloctax + baseval); + return (1); + } + + grafptr->flagval |= DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* Arrays created by the routine itself */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_check.c b/scotch_6.0.3/src/libscotch/dgraph_check.c new file mode 100644 index 00000000..f5b34cea --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_check.c @@ -0,0 +1,500 @@ +/* Copyright 2007-2010,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_check.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Francois CHATENET (P0.0) **/ +/** Sebastien FOUCAULT (P0.0) **/ +/** Nicolas GICQUEL (P0.1) **/ +/** Jerome LACOSTE (P0.1) **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : Part of a parallel static mapper. **/ +/** This module contains the distributed **/ +/** graph consistency checking routine. **/ +/** **/ +/** # Version P0.0 : from : 01 apr 1997 **/ +/** to 20 jun 1997 **/ +/** # Version P0.1 : from : 14 apr 1998 **/ +/** to 20 jun 1998 **/ +/** # Version P0.2 : from : 11 may 1999 **/ +/** to 02 feb 2000 **/ +/** # Version 5.0 : from : 04 jul 2005 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 20 nov 2008 **/ +/** to : 30 jul 2010 **/ +/** # Version 6.0 : from : 29 sep 2012 **/ +/** to : 09 feb 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_CHECK + +#include "module.h" +#include "common.h" +#include "dgraph.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This function checks the consistency +** of the given distributed graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +dgraphCheck ( +const Dgraph * restrict const grafptr) +{ + MPI_Comm proccomm; /* Graph communicator */ + int procglbnbr; /* Number of processes sharing graph data */ + int proclocnum; /* Number of this process */ + int procrcvnum; /* Number of process from which to receive */ + int procsndnum; /* Number of process to which to send */ + int procngbsel; /* Value of the currently used neighbor buffers */ + int procngbnum; /* Number of current neighbor process */ + Gnum * procngbtab; /* Array of neighbor vertex ranges */ + int procnum; + Gnum vertlocnum; + Gnum vertngbmin; /* Smallest vertex number of neighbor process */ + Gnum vertngbmax; /* Largest vertex number of neighbor process */ + int vertngbnbr[2]; /* Size of the neighbor vertex arrays */ + Gnum * restrict vertngbtab[2]; /* Array of two neighbor vertex arrays */ + Gnum * restrict vertngbptr; /* Pointer to working neighbor vertex array */ + Gnum * restrict vendngbtab[2]; /* Array of two neighbor end vertex arrays */ + Gnum * restrict vendngbptr; /* Pointer to working neighbor end vertex array */ + Gnum edgelocnbr; /* Local number of edges */ + int edgengbnbr[2]; /* Size of the neighbor vertex arrays */ + Gnum * restrict edgengbtab[2]; /* Array of two neighbor edge arrays */ + Gnum * restrict edgengbptr; /* Pointer to working neighbor edge array */ + Gnum * restrict edlongbtab[2]; /* Array of two neighbor edge load arrays */ + Gnum * restrict edlongbptr; /* Pointer to working neighbor edge load array */ + Gnum edlolocsiz; /* Size of neighbor edge load array (if any) */ + int cheklocval; /* Local consistency flag */ + int chekglbval; /* Global consistency flag */ + Gnum reduloctab[20]; /* Arrays for reductions */ + Gnum reduglbtab[20]; + MPI_Request requloctab[8]; /* Arrays for pipelined communications */ + MPI_Status statloctab[8]; + + Gnum * restrict const vertloctax = grafptr->vertloctax; + Gnum * restrict const vendloctax = grafptr->vendloctax; + Gnum * restrict const veloloctax = grafptr->veloloctax; + Gnum * restrict const edgeloctax = grafptr->edgeloctax; + Gnum * restrict const edgegsttax = grafptr->edgegsttax; + Gnum * restrict const edloloctax = grafptr->edloloctax; + + proccomm = grafptr->proccomm; /* Simplify */ + + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize */ + errorPrint ("dgraphCheck: communication error (1)"); + return (1); + } + + cheklocval = /* Assume everything is all right */ + chekglbval = 0; + MPI_Comm_size (proccomm, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (proccomm, &proclocnum); + + if ((grafptr->procglbnbr != procglbnbr) || + (grafptr->proclocnum != proclocnum) || + ((grafptr->procdsptab == NULL) && (grafptr->vertlocnbr != 0))) { + errorPrint ("dgraphCheck: inconsistent communication data (1)"); + cheklocval = 1; + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCheck: communication error (2)"); + return (1); + } + if (chekglbval != 0) + return (1); + reduloctab[0] = (grafptr->procdsptab == NULL) ? 0 : 1; /* If private data not initialized */ + if (MPI_Allreduce (reduloctab, reduglbtab, 1, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCheck: communication error (3)"); + return (1); + } + if (reduglbtab[0] == 0) /* If distributed graph is empty */ + return (0); /* Do not go any further */ + if (reduglbtab[0] != procglbnbr) { /* If private data not consistently here */ + errorPrint ("dgraphCheck: inconsistent communication data (2)"); + return (1); + } + + for (procrcvnum = 0; procrcvnum < grafptr->procglbnbr; procrcvnum ++) { + if ((grafptr->proccnttab[procrcvnum] < 0) || + (grafptr->proccnttab[procrcvnum] != (grafptr->procdsptab[procrcvnum + 1] - grafptr->procdsptab[procrcvnum])) || + (grafptr->proccnttab[procrcvnum] > (grafptr->procvrttab[procrcvnum + 1] - grafptr->procvrttab[procrcvnum]))) { + errorPrint ("dgraphCheck: inconsistent communication data (3)"); + cheklocval = 1; + } + } + if (grafptr->proccnttab[proclocnum] != grafptr->vertlocnbr) { + errorPrint ("dgraphCheck: inconsistent communication data (4)"); + cheklocval = 1; + } + + procrcvnum = (proclocnum + 1) % procglbnbr; /* Compute indices of neighbors */ + procsndnum = (proclocnum - 1 + procglbnbr) % procglbnbr; + + if ((procngbtab = (Gnum *) memAlloc ((procglbnbr + 1) * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphCheck: out of memory (1)"); + cheklocval = 1; + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCheck: communication error (4)"); + return (1); + } + if (chekglbval != 0) { + if (procngbtab != NULL) + memFree (procngbtab); + return (1); + } + + MPI_Sendrecv (grafptr->procdsptab, procglbnbr + 1, GNUM_MPI, procsndnum, TAGPROCVRTTAB, /* Check vertex range array */ + procngbtab, procglbnbr + 1, GNUM_MPI, procrcvnum, TAGPROCVRTTAB, + proccomm, &statloctab[0]); + for (procngbnum = 0; procngbnum <= procglbnbr; procngbnum ++) { + if (grafptr->procdsptab[procngbnum] != procngbtab[procngbnum]) { + errorPrint ("dgraphCheck: inconsistent communication data (5)"); + cheklocval = 1; + break; + } + } + + MPI_Sendrecv (grafptr->procvrttab, procglbnbr + 1, GNUM_MPI, procsndnum, TAGPROCVRTTAB, /* Check vertex range array */ + procngbtab, procglbnbr + 1, GNUM_MPI, procrcvnum, TAGPROCVRTTAB, + proccomm, &statloctab[0]); + for (procngbnum = 0; procngbnum <= procglbnbr; procngbnum ++) { + if (grafptr->procvrttab[procngbnum] != procngbtab[procngbnum]) { + errorPrint ("dgraphCheck: inconsistent communication data (6)"); + cheklocval = 1; + break; + } + } + memFree (procngbtab); + + if ((grafptr->baseval < 0) || /* Elementary constraints on graph fields */ + (grafptr->baseval > 1) || /* Strong limitation on base value */ + (grafptr->vertlocnbr < 0) || + (grafptr->vertlocnnd != (grafptr->vertlocnbr + grafptr->baseval)) || + (((grafptr->flagval & DGRAPHHASEDGEGST) != 0) && + ((grafptr->vertgstnbr < grafptr->vertlocnbr) || + (grafptr->vertgstnnd != (grafptr->vertgstnbr + grafptr->baseval)))) || + (grafptr->edgelocnbr < 0) || + (grafptr->edgelocsiz < grafptr->edgelocnbr)) { + errorPrint ("dgraphCheck: inconsistent local graph data"); + cheklocval = 1; + } + + reduloctab[ 0] = grafptr->flagval; + reduloctab[ 1] = - grafptr->flagval; + reduloctab[ 2] = grafptr->baseval; + reduloctab[ 3] = - grafptr->baseval; + reduloctab[ 4] = grafptr->vertglbnbr; + reduloctab[ 5] = - grafptr->vertglbnbr; + reduloctab[ 6] = grafptr->vertglbmax; + reduloctab[ 7] = - grafptr->vertglbmax; + reduloctab[ 8] = grafptr->vertlocnbr; + reduloctab[ 9] = grafptr->edgeglbnbr; + reduloctab[10] = - grafptr->edgeglbnbr; + reduloctab[11] = grafptr->edgeglbmax; + reduloctab[12] = - grafptr->edgeglbmax; + reduloctab[13] = grafptr->edgelocnbr; + reduloctab[14] = grafptr->edgelocsiz; + reduloctab[15] = grafptr->edgeglbsmx; + reduloctab[16] = - grafptr->edgeglbsmx; + reduloctab[17] = grafptr->degrglbmax; + reduloctab[18] = - grafptr->degrglbmax; + reduloctab[19] = (Gnum) cheklocval; + if (MPI_Allreduce (reduloctab, reduglbtab, 20, GNUM_MPI, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCheck: communication error (5)"); + return (1); + } + if (reduglbtab[19] != 0) + return (1); + if ((reduglbtab[ 1] != - reduglbtab[ 0]) || /* Check if global graph data match */ + (reduglbtab[ 3] != - reduglbtab[ 2]) || + (reduglbtab[ 5] != - reduglbtab[ 4]) || + (reduglbtab[ 7] != - reduloctab[ 6]) || + (reduglbtab[ 8] != reduloctab[ 6]) || + (reduglbtab[10] != - reduglbtab[ 9]) || + (reduglbtab[12] != - reduglbtab[11]) || + (reduglbtab[13] != reduloctab[11]) || /* Recompute and test maximum number of local edges */ + (reduglbtab[14] != reduloctab[15]) || /* Recompute and test maximum size of local edge array */ + (reduglbtab[16] != - reduloctab[15]) || + (reduglbtab[18] != - reduloctab[17])) { + errorPrint ("dgraphCheck: inconsistent global graph data (1)"); + cheklocval = 1; + } + reduloctab[0] = (veloloctax != NULL) ? 1 : 0; /* Check consistency */ + reduloctab[1] = (edgegsttax != NULL) ? 1 : 0; + reduloctab[2] = (edloloctax != NULL) ? 1 : 0; + reduloctab[3] = (grafptr->vnumloctax != NULL) ? 1 : 0; + reduloctab[4] = grafptr->vertlocnbr; /* Recompute local sizes */ + reduloctab[5] = grafptr->edgelocnbr; + reduloctab[6] = (Gnum) cheklocval; + if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCheck: communication error (6)"); + return (1); + } + if (reduglbtab[6] != 0) + return (1); + if (((reduglbtab[0] != 0) && (reduglbtab[0] != procglbnbr)) || + ((reduglbtab[1] != 0) && (reduglbtab[1] != procglbnbr)) || + ((reduglbtab[2] != 0) && (reduglbtab[2] != procglbnbr)) || + ((reduglbtab[3] != 0) && (reduglbtab[3] != procglbnbr)) || + (reduglbtab[4] != grafptr->vertglbnbr) || + (reduglbtab[5] != grafptr->edgeglbnbr)) { + errorPrint ("dgraphCheck: inconsistent global graph data (2)"); + cheklocval = 1; + } + + for (vertlocnum = grafptr->baseval, edgelocnbr = 0; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + + if ((vendloctax[vertlocnum] < vertloctax[vertlocnum]) || + (vendloctax[vertlocnum] > (grafptr->edgelocsiz + grafptr->baseval))) { + errorPrint ("dgraphCheck: inconsistent local vertex arrays"); + edgelocnbr = grafptr->edgelocnbr; /* Avoid unwanted cascaded error messages */ + cheklocval = 1; + break; + } + edgelocnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + + if ((grafptr->flagval & DGRAPHHASEDGEGST) != 0) { /* If ghost edge array is valid */ + for (edgelocnum = vertloctax[vertlocnum]; edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { + if ((edgegsttax[edgelocnum] < grafptr->baseval) || + (edgegsttax[edgelocnum] >= grafptr->vertgstnnd)) { + errorPrint ("dgraphCheck: inconsistent ghost edge array"); + edgelocnbr = grafptr->edgelocnbr; /* Avoid unwanted cascaded error messages */ + vertlocnum = grafptr->vertlocnnd; /* Exit outer loop */ + cheklocval = 1; + break; + } + + if ((edloloctax != NULL) && + (edloloctax[edgelocnum] <= 0)) { + errorPrint ("dgraphCheck: invalid edge load"); + edgelocnbr = grafptr->edgelocnbr; /* Avoid unwanted cascaded error messages */ + vertlocnum = grafptr->vertlocnnd; /* Exit outer loop */ + cheklocval = 1; + break; + } + } + } + } + if (edgelocnbr != grafptr->edgelocnbr) { + errorPrint ("dgraphCheck: invalid local number of edges"); + cheklocval = 1; + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCheck: communication error (7)"); + return (1); + } + if (chekglbval != 0) + return (1); + + if (veloloctax != NULL) { /* Check vertex load consistency */ + Gnum velolocsum; + Gnum veloglbsum; + + for (vertlocnum = grafptr->baseval, velolocsum = 0; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { + Gnum veloval; + + veloval = veloloctax[vertlocnum]; + if ((veloval < 0) && (cheklocval == 0)) { + errorPrint ("dgraphCheck: invalid vertex load"); + cheklocval = 1; + } + + velolocsum += veloval; + } + + MPI_Allreduce (&velolocsum, &veloglbsum, 1, GNUM_MPI, MPI_SUM, proccomm); + + if (velolocsum != grafptr->velolocsum) { + errorPrint ("dgraphCheck: invalid local vertex load sum"); + cheklocval = 1; + } + if (veloglbsum != grafptr->veloglbsum) { + errorPrint ("dgraphCheck: invalid global vertex load sum"); + cheklocval = 1; + } + MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm); + if (chekglbval != 0) + return (1); + } + + edlolocsiz = (edloloctax != NULL) ? grafptr->edgeglbsmx : 0; + if (memAllocGroup ((void **) (void *) + &vertngbtab[0], (size_t) (grafptr->vertglbmax * sizeof (Gnum)), /* Send vertex and vertex end arrays, even when they are compact */ + &vertngbtab[1], (size_t) (grafptr->vertglbmax * sizeof (Gnum)), + &vendngbtab[0], (size_t) (grafptr->vertglbmax * sizeof (Gnum)), + &vendngbtab[1], (size_t) (grafptr->vertglbmax * sizeof (Gnum)), + &edgengbtab[0], (size_t) (grafptr->edgeglbsmx * sizeof (Gnum)), + &edgengbtab[1], (size_t) (grafptr->edgeglbsmx * sizeof (Gnum)), + &edlongbtab[0], (size_t) (edlolocsiz * sizeof (Gnum)), + &edlongbtab[1], (size_t) (edlolocsiz * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphCheck: out of memory (2)"); + cheklocval = 1; + } + edgengbtab[0] -= grafptr->baseval; /* Base edges arrays only */ + edgengbtab[1] -= grafptr->baseval; + if (edloloctax == NULL) { /* If graph edges are not weighted */ + edlongbtab[0] = /* Edge load arrays are fake */ + edlongbtab[1] = NULL; + } + else { + edlongbtab[0] -= grafptr->baseval; + edlongbtab[1] -= grafptr->baseval; + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCheck: communication error (8)"); + return (1); + } + if (chekglbval != 0) { + if (cheklocval == 0) + memFree (vertngbtab[0]); /* Free group leader */ + return (1); + } + + procngbsel = 0; /* Initial work array selector */ + vertngbptr = vertloctax + grafptr->baseval; /* Start working on self arrays */ + vendngbptr = vendloctax + grafptr->baseval; /* Un-base vertex arrays */ + edgengbptr = edgeloctax; /* Edge arrays are based */ + edlongbptr = edloloctax; + vertngbnbr[0] = grafptr->vertlocnbr; /* Set number of local vertices and edges to send */ + edgengbnbr[0] = grafptr->edgelocsiz; /* Send all of edge array is case graph is not compact */ + for (procnum = 0; procnum < procglbnbr; procnum ++) { /* For all processes including self */ + Gnum procngbnum; + Gnum vertlocnum; + Gnum vertglbnum; + + procngbnum = (proclocnum + procnum) % procglbnbr; /* Compute neighbor process number */ + vertngbmin = grafptr->procvrttab[procngbnum]; /* Get neighbor vertex number range */ + vertngbmax = grafptr->procvrttab[procngbnum + 1]; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertngbnbr[procngbsel] != grafptr->proccnttab[procngbnum]) || + (vertngbnbr[procngbsel] > (vertngbmax - vertngbmin))) { + errorPrint ("dgraphCheck: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (procnum < (procglbnbr - 1)) { /* For all rounds except the last one */ + MPI_Irecv (vertngbtab[1 - procngbsel], grafptr->vertglbmax, GNUM_MPI, procrcvnum, TAGVERTLOCTAB, proccomm, &requloctab[4]); + MPI_Irecv (vendngbtab[1 - procngbsel], grafptr->vertglbmax, GNUM_MPI, procrcvnum, TAGVENDLOCTAB, proccomm, &requloctab[5]); + MPI_Irecv (edgengbtab[1 - procngbsel] + grafptr->baseval, grafptr->edgeglbsmx, GNUM_MPI, procrcvnum, TAGEDGELOCTAB, proccomm, &requloctab[6]); + MPI_Isend (vertngbptr, vertngbnbr[procngbsel], GNUM_MPI, procsndnum, TAGVERTLOCTAB, proccomm, &requloctab[1]); + MPI_Isend (vendngbptr, vertngbnbr[procngbsel], GNUM_MPI, procsndnum, TAGVENDLOCTAB, proccomm, &requloctab[2]); + MPI_Isend (edgengbptr + grafptr->baseval, edgengbnbr[procngbsel], GNUM_MPI, procsndnum, TAGEDGELOCTAB, proccomm, &requloctab[3]); + if (edlongbptr != NULL) { + MPI_Irecv (edlongbtab[1 - procngbsel] + grafptr->baseval, grafptr->edgeglbsmx, GNUM_MPI, procrcvnum, TAGEDLOLOCTAB, proccomm, &requloctab[7]); + MPI_Isend (edlongbptr + grafptr->baseval, edgengbnbr[procngbsel], GNUM_MPI, procsndnum, TAGEDLOLOCTAB, proccomm, &requloctab[0]); + /* Complete communications before accessing arrays being sent */ + MPI_Waitall (8, &requloctab[0], &statloctab[0]); + } + else + MPI_Waitall (6, &requloctab[1], &statloctab[1]); + MPI_Get_count (&statloctab[4], GNUM_MPI, &vertngbnbr[1 - procngbsel]); + MPI_Get_count (&statloctab[6], GNUM_MPI, &edgengbnbr[1 - procngbsel]); + } + + for (vertlocnum = grafptr->baseval, vertglbnum = grafptr->procvrttab[proclocnum]; + vertlocnum < grafptr->vertlocnnd; vertlocnum ++, vertglbnum ++) { + Gnum edgelocnum; + + for (edgelocnum = vertloctax[vertlocnum]; + edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { + Gnum vertglbend; + + vertglbend = edgeloctax[edgelocnum]; + if ((vertglbend >= vertngbmin) && /* If end vertex belongs to current neighbor process */ + (vertglbend < vertngbmax)) { + Gnum edgengbnum; + Gnum edgengbnnd; + Gnum edgengbsum; + + for (edgengbnum = vertngbptr[vertglbend - vertngbmin], + edgengbnnd = vendngbptr[vertglbend - vertngbmin], edgengbsum = 0; + edgengbnum < edgengbnnd; edgengbnum ++) { + if (edgengbptr[edgengbnum] == vertglbnum) { /* If matching edge found */ + edgengbsum ++; /* Account for it */ + if ((edlongbptr != NULL) && /* If edge weights do not match */ + (edlongbptr[edgengbnum] != edloloctax[edgelocnum])) + cheklocval = 3; + } + } + if (edgengbsum < 1) /* If matching edge not found */ + cheklocval = 1; + else if (edgengbsum > 1) /* If duplicate edge */ + cheklocval = 2; + } + } + } + MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm); + + if (chekglbval != 0) { /* Error number ranges from 1 to 3 */ + if (chekglbval == 1) + errorPrint ("dgraphCheck: arc data do not match"); + else if (chekglbval == 2) + errorPrint ("dgraphCheck: duplicate arc"); + else + errorPrint ("dgraphCheck: arc load data do not match"); + memFree (vertngbtab[0]); /* Free group leader */ + return (1); + } + + procngbsel ^= 1; /* Swap work and receive buffers */ + vertngbptr = vertngbtab[procngbsel]; /* Point to future work buffers */ + vendngbptr = vendngbtab[procngbsel]; /* Vertex pointers are unbased */ + edgengbptr = edgengbtab[procngbsel]; /* Edge pointers are based */ + edlongbptr = edlongbtab[procngbsel]; + } + memFree (vertngbtab[0]); /* Free group leader */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_coarsen.c b/scotch_6.0.3/src/libscotch/dgraph_coarsen.c new file mode 100644 index 00000000..794ba48e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_coarsen.c @@ -0,0 +1,1070 @@ +/* Copyright 2007-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_coarsen.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : This file implements the coarsening **/ +/** phase of the multi-level method. **/ +/** The implementation uses several **/ +/** processes, which could have several **/ +/** threads each (3 at this time). **/ +/** **/ +/** DATES : # Version 5.0 : from : 27 jul 2005 **/ +/** to : 15 may 2008 **/ +/** # Version 5.1 : from : 23 jun 2008 **/ +/** to : 20 feb 2011 **/ +/** # Version 6.0 : from : 11 sep 2012 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +#define DGRAPH_COARSEN + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_allreduce.h" +#include "dgraph_coarsen.h" +#include "dgraph_match.h" + +/******************************/ +/* */ +/* Graph coarsening routines. */ +/* */ +/******************************/ + +static +int +dgraphCoarsenInit ( +DgraphCoarsenData * restrict const coarptr, /*+ Coarsening data structure +*/ +Dgraph * restrict const finegrafptr, /*+ Graph to coarsen +*/ +Dgraph * restrict const coargrafptr) /*+ Coarse graph to build +*/ +{ + int procglbnbr; + int procglbnum; + int procngbnbr; + int procngbnum; + int procngbnxt; + int vertrcvnbr; + int vertsndnbr; + Gnum vertlocnbr; + Gnum vertgstnbr; + int vdsprcvnum; + int vdspsndnum; + byte * bufftab; + size_t buffsiz; + + const int * restrict const fineprocngbtab = finegrafptr->procngbtab; + const int * restrict const fineprocrcvtab = finegrafptr->procrcvtab; + const int * restrict const fineprocsndtab = finegrafptr->procsndtab; + + vertlocnbr = finegrafptr->vertlocnbr; + vertgstnbr = finegrafptr->vertgstnbr; + procglbnbr = finegrafptr->procglbnbr; + procngbnbr = finegrafptr->procngbnbr; + vertrcvnbr = vertgstnbr - vertlocnbr; + vertsndnbr = finegrafptr->procsndnbr; + + coarptr->coarprvptr = NULL; /* Assume nothing to free on error */ + coarptr->multloctmp = NULL; + coarptr->nsndidxtab = NULL; + coarptr->nrcvidxtab = NULL; + + if ((coarptr->coarprvptr = memAllocGroup ((void **) (void *) /* Allocate distributed coarse graph private data */ + &coargrafptr->procdsptab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), + &coargrafptr->proccnttab, (size_t) (procglbnbr * sizeof (Gnum)), + &coargrafptr->procngbtab, (size_t) (procglbnbr * sizeof (int)), + &coargrafptr->procrcvtab, (size_t) (procglbnbr * sizeof (int)), + &coargrafptr->procsndtab, (size_t) (procglbnbr * sizeof (int)), NULL)) == NULL) { + errorPrint ("dgraphCoarsenInit: out of memory (1)"); + return (1); + } + coargrafptr->procvrttab = coargrafptr->procdsptab; /* Coarse graph has no holes */ + + if (coarptr->multloctab == NULL) { /* If no multinode array provided */ + if ((coarptr->multloctab = memAlloc (vertlocnbr * sizeof (DgraphCoarsenMulti))) == NULL) { + errorPrint ("dgraphCoarsenInit: out of memory (2)"); + dgraphCoarsenExit (coarptr); + return (1); + } + coarptr->multloctmp = coarptr->multloctab; /* Array will have to be freed on error */ + } + + if (memAllocGroup ((void **) (void *) /* Data used up to edge exchange phase at coarse graph build time */ + &coarptr->nrcvidxtab, (size_t) (procngbnbr * sizeof (int)), + &coarptr->vrcvdsptab, (size_t) ((procglbnbr + 1) * sizeof (int)), /* TRICK: "+1" for size count */ + &coarptr->coargsttax, (size_t) (vertgstnbr * sizeof (Gnum)), + &coarptr->procgsttax, (size_t) (vertrcvnbr * sizeof (int)), /* TRICK: Only purely ghost part of array will be used */ + &coarptr->vrcvdattab, (size_t) (vertrcvnbr * sizeof (DgraphCoarsenVert)), NULL) == NULL) { + errorPrint ("dgraphCoarsenInit: out of memory (3)"); + dgraphCoarsenExit (coarptr); + return (1); + } + + buffsiz = 2 * MAX ((procngbnbr * sizeof (MPI_Request)), (procglbnbr * sizeof (int))); + if (memAllocGroup ((void **) (void *) /* Data released after coarse vertex index exchange phase */ + &coarptr->nsndidxtab, (size_t) (procngbnbr * sizeof (int)), + &coarptr->vsnddsptab, (size_t) ((procglbnbr + 1) * sizeof (int)), /* TRICK: "+1" for size count check */ + &bufftab, (size_t) buffsiz, + &coarptr->dcntloctab, (size_t) (procglbnbr * sizeof (DgraphCoarsenCount)), + &coarptr->dcntglbtab, (size_t) (procglbnbr * sizeof (DgraphCoarsenCount)), + &coarptr->vsnddattab, (size_t) (vertsndnbr * sizeof (DgraphCoarsenVert)), NULL) == NULL) { + errorPrint ("dgraphCoarsenInit: out of memory (4)"); + dgraphCoarsenExit (coarptr); + return (1); + } + coarptr->nrcvreqtab = (MPI_Request *) (void *) bufftab; /* TRICK: point-to-point requests and collective arrays share same space */ + coarptr->nsndreqtab = coarptr->nrcvreqtab + procngbnbr; + coarptr->vrcvcnttab = (int *) (void *) bufftab; + coarptr->vsndcnttab = coarptr->vrcvcnttab + procglbnbr; + + for (procglbnum = 0, vdsprcvnum = vdspsndnum = 0; /* Build communication index arrays */ + procglbnum < procglbnbr; procglbnum ++) { + coarptr->vrcvdsptab[procglbnum] = vdsprcvnum; + coarptr->vsnddsptab[procglbnum] = vdspsndnum; + vdsprcvnum += fineprocrcvtab[procglbnum]; + vdspsndnum += fineprocsndtab[procglbnum]; + } + coarptr->vrcvdsptab[procglbnum] = vdsprcvnum; /* Mark end of communication index arrays */ + coarptr->vsnddsptab[procglbnum] = vdspsndnum; + + for (procngbnum = procngbnxt = 0; procngbnum < procngbnbr; procngbnum ++) { + if ((procngbnxt == 0) && (fineprocngbtab[procngbnum] > finegrafptr->proclocnum)) { /* Find index of first neighbor of higher rank */ + procngbnxt = procngbnum; + break; + } + } + coarptr->procngbnxt = procngbnxt; + + coarptr->coargsttax -= finegrafptr->baseval; + coarptr->finegrafptr = finegrafptr; + coarptr->coargrafptr = coargrafptr; + + memSet (coarptr->dcntloctab, 0, procglbnbr * sizeof (DgraphCoarsenCount)); + + memSet (coarptr->procgsttax, ~0, vertrcvnbr * sizeof (int)); /* Values have not yet been computed */ + coarptr->procgsttax -= vertlocnbr + finegrafptr->baseval; /* TRICK: base array such that only purely ghost part is used */ + + coarptr->edgekptnbr = 0; + + return (0); +} + +static +void +dgraphCoarsenExit ( +DgraphCoarsenData * restrict const coarptr) /*+ Coarsening data structure +*/ +{ + if (coarptr->nsndidxtab != NULL) /* Auxiliary array is released after first phase of coarse graph building */ + memFree (coarptr->nsndidxtab); + if (coarptr->nrcvidxtab != NULL) + memFree (coarptr->nrcvidxtab); + if (coarptr->multloctmp != NULL) /* If multinode array not provided nor passed back to calling routine */ + memFree (coarptr->multloctmp); + if (coarptr->coarprvptr != NULL) /* If ownership of coarse graph private data not yet transferred to it */ + memFree (coarptr->coarprvptr); +} + +static +int +dgraphCoarsenBuildColl ( +DgraphCoarsenData * restrict const coarptr) +{ + Gnum vertlocadj; + int procngbnbr; + int procngbnum; + + MPI_Comm proccomm = coarptr->finegrafptr->proccomm; + Dgraph * restrict const grafptr = coarptr->finegrafptr; + const int * restrict const procngbtab = grafptr->procngbtab; + Gnum * restrict const coargsttax = coarptr->coargsttax; + int * restrict const vsndcnttab = coarptr->vsndcnttab; + int * restrict const vrcvdsptab = coarptr->coargrafptr->procrcvtab; /* TRICK: use coarse graph procrcvtab and procsndtab */ + int * restrict const vsnddsptab = coarptr->coargrafptr->procsndtab; + int * restrict const nrcvidxtab = coarptr->nrcvidxtab; + int * restrict const nsndidxtab = coarptr->nsndidxtab; + + procngbnbr = grafptr->procngbnbr; + vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; + + memSet (vsndcnttab, 0, grafptr->procglbnbr * sizeof (int)); + memSet (vrcvdsptab, 0, grafptr->procglbnbr * sizeof (int)); + memSet (vsnddsptab, 0, grafptr->procglbnbr * sizeof (int)); + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { + int procglbnum; + + procglbnum = procngbtab[procngbnum]; + vsndcnttab[procglbnum] = 2 * (nsndidxtab[procngbnum] - coarptr->vsnddsptab[procglbnum]); + vrcvdsptab[procglbnum] = 2 * coarptr->vrcvdsptab[procglbnum]; + vsnddsptab[procglbnum] = 2 * coarptr->vsnddsptab[procglbnum]; + } + + if (MPI_Alltoall (vsndcnttab, 1, MPI_INT, coarptr->vrcvcnttab, 1, MPI_INT, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsenBuildColl: communication error (1)"); + return (1); + } + if (MPI_Alltoallv (coarptr->vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, + coarptr->vrcvdattab, coarptr->vrcvcnttab, vrcvdsptab, GNUM_MPI, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsenBuildColl: communication error (2)"); + return (1); + } + + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { /* For all received data chunks */ + int vrcvidxnnd; + int vrcvidxnum; + int procglbnum; + int statsiz; + + const DgraphCoarsenVert * restrict const vrcvdattab = coarptr->vrcvdattab; /* After data is received */ + + procglbnum = procngbtab[procngbnum]; + statsiz = coarptr->vrcvcnttab[procglbnum]; + for (vrcvidxnum = coarptr->vrcvdsptab[procglbnum], vrcvidxnnd = vrcvidxnum + (statsiz / 2); /* TRICK: each message item costs 2 Gnum's */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ + Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ + Gnum multglbnum; /* Global number of coarse vertex */ + + vertglbnum = vrcvdattab[vrcvidxnum].datatab[0]; + multglbnum = vrcvdattab[vrcvidxnum].datatab[1]; + vertlocnum = vertglbnum - vertlocadj; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocnum < grafptr->baseval) || /* If matching request is not directed towards our process */ + (vertlocnum >= grafptr->vertlocnnd)) { + errorPrint ("dgraphCoarsenBuildColl: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + coargsttax[vertlocnum] = multglbnum; + } + nrcvidxtab[procngbnum] = vrcvidxnnd; /* Keep receive end index for preparing edge arrays */ + } + + return (0); +} + +static +int +dgraphCoarsenBuildPtop ( +DgraphCoarsenData * restrict const coarptr) +{ + Gnum vertlocadj; + int procngbnbr; + int procngbnum; + int vrcvreqnbr; + + MPI_Comm proccomm = coarptr->finegrafptr->proccomm; + Dgraph * restrict const grafptr = coarptr->finegrafptr; + const int * restrict const procngbtab = grafptr->procngbtab; + Gnum * restrict const coargsttax = coarptr->coargsttax; + const int * restrict const vrcvdsptab = coarptr->vrcvdsptab; + const int * restrict const vsnddsptab = coarptr->vsnddsptab; + int * restrict const nrcvidxtab = coarptr->nrcvidxtab; + int * restrict const nsndidxtab = coarptr->nsndidxtab; + + procngbnbr = grafptr->procngbnbr; + vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; + + if (procngbnbr > 0) { /* No communication else */ + procngbnum = coarptr->procngbnxt; /* Post receives in descending order */ + do { + int procglbnum; + + procngbnum = (procngbnum + (procngbnbr - 1)) % procngbnbr; /* Pre-decrement neighbor rank */ + procglbnum = procngbtab[procngbnum]; + if (MPI_Irecv (coarptr->vrcvdattab + vrcvdsptab[procglbnum], 2 * (vrcvdsptab[procglbnum + 1] - vrcvdsptab[procglbnum]), GNUM_MPI, + procglbnum, TAGCOARSEN, proccomm, &coarptr->nrcvreqtab[procngbnum]) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsenBuildPtop: communication error (1)"); + return (1); + } + } while (procngbnum != coarptr->procngbnxt); + + procngbnum = coarptr->procngbnxt; /* Post sends in ascending order */ + do { + int procglbnum; + + procglbnum = procngbtab[procngbnum]; + if (MPI_Isend (coarptr->vsnddattab + vsnddsptab[procglbnum], 2 * (nsndidxtab[procngbnum] - vsnddsptab[procglbnum]), GNUM_MPI, + procglbnum, TAGCOARSEN, proccomm, &coarptr->nsndreqtab[procngbnum]) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsenBuildPtop: communication error (2)"); + return (1); + } + procngbnum = (procngbnum + 1) % procngbnbr; /* Post-increment neighbor rank */ + } while (procngbnum != coarptr->procngbnxt); + } + + for (vrcvreqnbr = procngbnbr; vrcvreqnbr > 0; vrcvreqnbr --) { /* For all pending receive requests */ + int vrcvidxnnd; + int vrcvidxnum; + int procngbnum; + MPI_Status statdat; + int statsiz; + int o; + +#ifdef SCOTCH_DETERMINISTIC + procngbnum = vrcvreqnbr - 1; + o = MPI_Wait (&coarptr->nrcvreqtab[procngbnum], &statdat); +#else /* SCOTCH_DETERMINISTIC */ + o = MPI_Waitany (procngbnbr, coarptr->nrcvreqtab, &procngbnum, &statdat); +#endif /* SCOTCH_DETERMINISTIC */ + if ((o != MPI_SUCCESS) || + (MPI_Get_count (&statdat, GNUM_MPI, &statsiz) != MPI_SUCCESS)) { + errorPrint ("dgraphCoarsenBuildPtop: communication error (3)"); + return (1); + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (statdat.MPI_SOURCE != procngbtab[procngbnum]) { + errorPrint ("dgraphCoarsenBuildPtop: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + { + const DgraphCoarsenVert * restrict const vrcvdattab = coarptr->vrcvdattab; /* After data is received */ + + for (vrcvidxnum = vrcvdsptab[procngbtab[procngbnum]], vrcvidxnnd = vrcvidxnum + (statsiz / 2); /* TRICK: each message item costs 2 Gnum's */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ + Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ + Gnum multglbnum; /* Global number of coarse vertex */ + + vertglbnum = vrcvdattab[vrcvidxnum].datatab[0]; + multglbnum = vrcvdattab[vrcvidxnum].datatab[1]; + vertlocnum = vertglbnum - vertlocadj; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocnum < grafptr->baseval) || /* If matching request is not directed towards our process */ + (vertlocnum >= grafptr->vertlocnnd)) { + errorPrint ("dgraphCoarsenBuildPtop: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + coargsttax[vertlocnum] = multglbnum; + } + nrcvidxtab[procngbnum] = vrcvidxnnd; /* Keep receive end index for preparing edge arrays */ + } + } + + if (MPI_Waitall (procngbnbr, coarptr->nsndreqtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for send requests to complete */ + errorPrint ("dgraphCoarsenBuildPtop: communication error (4)"); + return (1); + } + + return (0); +} + +/* This routine performs the coarsening of edges +** with respect to the coarmulttax array computed +** by dgraphMatch. All data must be available when +** running (all receptions done). This function is +** inspired by libscotch/src/graph_coarsen_edge.c. +*/ + +DGRAPHALLREDUCEMAXSUMOP (3, 1) + +static +int +dgraphCoarsenBuild ( +DgraphCoarsenData * restrict const coarptr) +{ + Gnum vertlocnum; + Gnum vertlocadj; + Gnum edgelocnbr; + Gnum edlolocval; + Gnum * restrict ercvdattab; + Gnum * restrict esnddattab; + int * restrict ercvcnttab; + int * restrict esndcnttab; + int * restrict ercvdsptab; + int * restrict esnddsptab; + int ercvdspval; + int esnddspval; + int ercvdatsiz; + int esnddatsiz; + DgraphCoarsenMulti * restrict multloctax; + Gnum multlocnum; + Gnum multlocadj; + int procngbnbr; + int procngbnum; + int procnum; + Gnum coarvertglbnum; + Gnum coarvertlocnum; + Gnum coarvertlocnnd; + Gnum * restrict coarvertloctax; + Gnum * restrict coarveloloctax; + Gnum coarvelolocsum; + Gnum coardegrlocmax; + Gnum coaredgelocnum; + Gnum * restrict coaredgeloctax; + Gnum * restrict coaredloloctax; + Gnum coarhashnbr; /* Size of hash table */ + Gnum coarhashmsk; /* Mask for access hash table */ + DgraphCoarsenHash * restrict coarhashtab; /* Table of edges to other multinodes */ + Gnum reduloctab[4]; + Gnum reduglbtab[4]; + int cheklocval; + int chekglbval; +#ifdef SCOTCH_DEBUG_DGRAPH2 + int * restrict ercvdbgtab; +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + MPI_Comm proccomm = coarptr->finegrafptr->proccomm; + Dgraph * restrict const grafptr = coarptr->finegrafptr; + Dgraph * restrict const coargrafptr = coarptr->coargrafptr; + Gnum * restrict const coargsttax = coarptr->coargsttax; + const int * restrict const procngbtab = grafptr->procngbtab; + const int * restrict const procgsttax = coarptr->procgsttax; + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + const Gnum * restrict const veloloctax = grafptr->veloloctax; + const Gnum * restrict const edgeloctax = grafptr->edgeloctax; + const Gnum * restrict const edgegsttax = grafptr->edgegsttax; + const Gnum * restrict const edloloctax = grafptr->edloloctax; + const DgraphCoarsenMulti * restrict const multloctab = coarptr->multloctab; + DgraphCoarsenVert * const vrcvdattab = coarptr->vrcvdattab; /* [norestrict:async] */ + DgraphCoarsenVert * restrict const vsnddattab = coarptr->vsnddattab; + int * restrict const nsndidxtab = coarptr->nsndidxtab; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + memSet (coargsttax + grafptr->baseval, ~0, grafptr->vertgstnbr * sizeof (Gnum)); +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + procngbnbr = grafptr->procngbnbr; + + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) /* Reset indices for sending messages */ + nsndidxtab[procngbnum] = coarptr->vsnddsptab[procngbtab[procngbnum]]; + + vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; + multlocadj = coarptr->coargrafptr->procdsptab[grafptr->proclocnum]; + for (multlocnum = 0; multlocnum < coarptr->multlocnbr; multlocnum ++) { + Gnum vertlocnum0; + Gnum vertlocnum1; + + vertlocnum0 = multloctab[multlocnum].vertglbnum[0] - vertlocadj; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocnum0 < grafptr->baseval) || + (vertlocnum0 >= grafptr->vertlocnnd)) { + errorPrint ("dgraphCoarsenBuild: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + coargsttax[vertlocnum0] = multlocnum + multlocadj; + + vertlocnum1 = multloctab[multlocnum].vertglbnum[1]; + if (vertlocnum1 >= 0) { /* If second vertex is local */ + vertlocnum1 -= vertlocadj; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocnum1 < grafptr->baseval) || + (vertlocnum1 >= grafptr->vertlocnnd)) { + errorPrint ("dgraphCoarsenBuild: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + coargsttax[vertlocnum1] = multlocnum + multlocadj; /* Don't care if single multinode */ + } + else { + Gnum edgelocnum; + Gnum vertglbnum1; + Gnum vertgstnum1; + int coarsndidx; + int procngbnum; + + edgelocnum = -2 - vertlocnum1; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((edgelocnum < grafptr->baseval) || + (edgelocnum >= (grafptr->edgelocsiz + grafptr->baseval))) { + errorPrint ("dgraphCoarsenBuild: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + vertglbnum1 = edgeloctax[edgelocnum]; + vertgstnum1 = edgegsttax[edgelocnum]; + + procngbnum = procgsttax[vertgstnum1]; /* Find neighbor owner process */ + if (procngbnum < 0) { /* If neighbor had not been computed */ + errorPrint ("dgraphCoarsenBuild: internal error (4)"); + return (1); + } + + coarsndidx = nsndidxtab[procngbnum] ++; /* Get position of message in send array */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (coarsndidx >= coarptr->vsnddsptab[procngbtab[procngbnum] + 1]) { + errorPrint ("dgraphCoarsenBuild: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + vsnddattab[coarsndidx].datatab[0] = vertglbnum1; + vsnddattab[coarsndidx].datatab[1] = multlocnum + multlocadj; /* Send multinode value */ + } + } + + if (coarptr->multloctmp != NULL) { /* If we allocated the multinode array */ + coarptr->multloctmp = + coarptr->multloctab = memRealloc (coarptr->multloctab, coarptr->multlocnbr * sizeof (DgraphCoarsenMulti)); /* In the mean time, resize multinode array */ + } + + if ((((grafptr->flagval & DGRAPHCOMMPTOP) != 0) ? dgraphCoarsenBuildPtop : dgraphCoarsenBuildColl) (coarptr) != 0) + return (1); + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsenBuild: communication error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + ercvcnttab = coarptr->coargrafptr->procrcvtab; /* TRICK: re-use some private coarse graph arrays after vertex exchange phase */ + ercvdsptab = coarptr->coargrafptr->procsndtab; + for (procnum = 0, ercvdspval = 0; procnum < grafptr->procglbnbr; procnum ++) { /* TRICK: dcntglbtab array no longer needed afterwards; can be freed */ + ercvdsptab[procnum] = ercvdspval; + ercvcnttab[procnum] = coarptr->dcntglbtab[procnum].vertsndnbr * ((veloloctax != NULL) ? 2 : 1) + + coarptr->dcntglbtab[procnum].edgesndnbr * ((edloloctax != NULL) ? 2 : 1); + ercvdspval += ercvcnttab[procnum]; + } + + memFree (coarptr->nsndidxtab); /* Free now useless work memory */ + coarptr->nsndidxtab = NULL; /* This block won't be reclaimed */ + +#ifdef SCOTCH_DEBUG_DGRAPH2 + for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { + if (coargsttax[vertlocnum] < 0) { + errorPrint ("dgraphCoarsenBuild: invalid matching"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (dgraphHaloSync (grafptr, coargsttax + grafptr->baseval, GNUM_MPI) != 0) { + errorPrint ("dgraphCoarsenBuild: cannot propagate multinode indices"); + return (1); + } + + edgelocnbr = coarptr->edgekptnbr + coarptr->edgercvnbr; /* Upper bound on number of edges */ + ercvdatsiz = coarptr->vertrcvnbr + coarptr->edgercvnbr; /* Basic size: degrees plus edge data */ + esnddatsiz = coarptr->vertsndnbr + coarptr->edgesndnbr; + if (grafptr->veloloctax != NULL) { /* Add vertex loads if necessary */ + ercvdatsiz += coarptr->vertrcvnbr; + esnddatsiz += coarptr->vertsndnbr; + } + if (grafptr->edloloctax != NULL) { /* Add edge loads if necessary */ + ercvdatsiz += coarptr->edgercvnbr; + esnddatsiz += coarptr->edgesndnbr; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (ercvdspval != ercvdatsiz) { + errorPrint ("dgraphCoarsenBuild: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + for (coarhashmsk = 31; coarhashmsk < grafptr->degrglbmax; coarhashmsk = coarhashmsk * 2 + 1) ; + coarhashmsk = coarhashmsk * 4 + 3; + coarhashnbr = coarhashmsk + 1; + + cheklocval = 0; + coargrafptr->flagval = DGRAPHFREETABS | DGRAPHFREEPRIV | DGRAPHVERTGROUP; /* Coarse graph is not yet based */ + coarptr->coarprvptr = NULL; /* Transfer ownership of private arrays to coarse graph */ + if (memAllocGroup ((void **) (void *) + &coargrafptr->vertloctax, (size_t) ((coarptr->multlocnbr + 1) * sizeof (Gnum)), + &coargrafptr->veloloctax, (size_t) ( coarptr->multlocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphCoarsenBuild: out of memory (1)"); + cheklocval = 1; + } + else if ((coargrafptr->edgeloctax = memAlloc (edgelocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphCoarsenBuild: out of memory (2)"); + cheklocval = 1; + } + else if ((coargrafptr->edloloctax = memAlloc (edgelocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphCoarsenBuild: out of memory (3)"); + cheklocval = 1; + } + else if ((coarptr->nsndidxtab = memAllocGroup ((void **) (void *) /* TRICK: allow data array to be released on error */ + &esndcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &esnddsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &esnddattab, (size_t) (esnddatsiz * sizeof (Gnum)), + &ercvdattab, (size_t) (ercvdatsiz * sizeof (Gnum)), +#ifdef SCOTCH_DEBUG_DGRAPH2 + &ercvdbgtab, (size_t) (grafptr->procglbnbr * sizeof (int)), +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + &coarhashtab, (size_t) (coarhashnbr * sizeof (DgraphCoarsenHash)), NULL)) == NULL) { + errorPrint ("dgraphCoarsenBuild: out of memory (4)"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be overlapped by a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsenBuild: communication error (2)"); + chekglbval = 1; + } +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (chekglbval != 0) { + dgraphFree (coargrafptr); + return (1); + } + + memSet (coarhashtab, ~0, coarhashnbr * sizeof (DgraphCoarsenHash)); + + coargrafptr->baseval = grafptr->baseval; + coargrafptr->vertlocnnd = coargrafptr->baseval + coargrafptr->vertlocnbr; + coargrafptr->vertloctax -= coargrafptr->baseval; + coargrafptr->vendloctax = coargrafptr->vertloctax + 1; /* Graph is compact */ + coargrafptr->veloloctax -= coargrafptr->baseval; + coargrafptr->edgeloctax -= coargrafptr->baseval; + coargrafptr->edloloctax -= coargrafptr->baseval; + + for (procngbnum = procnum = 0, esnddspval = 0; procngbnum < procngbnbr; procngbnum ++) { + int procglbnum; + int vrcvidxnnd; + int vrcvidxnum; + + procglbnum = procngbtab[procngbnum]; + while (procnum < procglbnum) { /* Fill empty slots */ + esnddsptab[procnum] = esnddspval; + esndcnttab[procnum] = 0; + procnum ++; + } + esnddsptab[procnum] = esnddspval; + + for (vrcvidxnum = coarptr->vrcvdsptab[procglbnum], vrcvidxnnd = coarptr->nrcvidxtab[procngbnum]; /* For all multinode requests received, in order */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum vertlocnum; + Gnum edgelocnum; + Gnum edgelocnnd; + + vertlocnum = vrcvdattab[vrcvidxnum].datatab[0] - vertlocadj; + edgelocnum = vertloctax[vertlocnum]; + edgelocnnd = vendloctax[vertlocnum]; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((esnddspval + ((veloloctax != NULL) ? 2 : 1) + ((edloloctax != NULL) ? 2 : 1) * (edgelocnnd - edgelocnum)) > esnddatsiz) { + errorPrint ("dgraphCoarsenBuild: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + esnddattab[esnddspval ++] = (edgelocnnd - edgelocnum); /* Write degree */ + if (veloloctax != NULL) + esnddattab[esnddspval ++] = veloloctax[vertlocnum]; + if (edloloctax != NULL) { + for ( ; edgelocnum < edgelocnnd; edgelocnum ++) { + esnddattab[esnddspval ++] = coargsttax[edgegsttax[edgelocnum]]; + esnddattab[esnddspval ++] = edloloctax[edgelocnum]; + } + } + else { + for ( ; edgelocnum < edgelocnnd; edgelocnum ++) + esnddattab[esnddspval ++] = coargsttax[edgegsttax[edgelocnum]]; + } + } + esndcnttab[procnum] = esnddspval - esnddsptab[procnum]; + procnum ++; + } + while (procnum < grafptr->procglbnbr) { /* Complete fill-in of empty slots */ + esnddsptab[procnum] = esnddspval; + esndcnttab[procnum] = 0; + procnum ++; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (esnddspval != esnddatsiz) { + errorPrint ("dgraphCoarsenBuild: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + while (procnum < grafptr->procglbnbr) { /* Complete edge data send displacement array */ + esnddsptab[procnum] = esnddspval; + esndcnttab[procnum] = 0; + procnum ++; + } + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Alltoall (esndcnttab, 1, MPI_INT, ercvdbgtab, 1, MPI_INT, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsenBuild: communication error (3)"); + return (1); + } + for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { + if (ercvdbgtab[procnum] != ercvcnttab[procnum]) { + errorPrint ("dgraphCoarsenBuild: internal error (9)"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (MPI_Alltoallv (esnddattab, esndcnttab, esnddsptab, GNUM_MPI, + ercvdattab, ercvcnttab, ercvdsptab, GNUM_MPI, proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsenBuild: communication error (4)"); + return (1); + } + + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) + ercvdsptab[procngbnum] = ercvdsptab[procngbtab[procngbnum]]; + + multloctax = coarptr->multloctab - grafptr->baseval; + + edlolocval = 1; + coarvelolocsum = 0; + coardegrlocmax = 0; + coarvertloctax = coargrafptr->vertloctax; + coarveloloctax = coargrafptr->veloloctax; + coaredgeloctax = coargrafptr->edgeloctax; + coaredloloctax = coargrafptr->edloloctax; + for (coarvertlocnum = coaredgelocnum = grafptr->baseval, coarvertglbnum = multlocadj, coarvertlocnnd = coarvertlocnum + coargrafptr->vertlocnbr; + coarvertlocnum < coarvertlocnnd; coarvertlocnum ++, coarvertglbnum ++) { + Gnum coarvelolocval; + Gnum vertlocnum; + int i; + + coarvertloctax[coarvertlocnum] = coaredgelocnum; + + i = 0; + coarvelolocval = 0; + vertlocnum = multloctax[coarvertlocnum].vertglbnum[0] - vertlocadj; + while (1) { /* Pseudo-infinite loop on both vertices of the multinode */ + Gnum vertglbnum; + Gnum edgelocnum; + Gnum edgelocnnd; + Gnum degrlocval; + int procngbnum; + int ercvidxnum; + + coarvelolocval += (veloloctax != NULL) ? veloloctax[vertlocnum] : 1; + for (edgelocnum = vertloctax[vertlocnum], edgelocnnd = vendloctax[vertlocnum]; /* Loop on edges of first (and sometimes second) local mate */ + edgelocnum < edgelocnnd; edgelocnum ++) { + Gnum coarvertglbend; + Gnum h; + + coarvertglbend = coargsttax[edgegsttax[edgelocnum]]; + if (coarvertglbend == coarvertglbnum) /* If end of collapsed edge */ + continue; + + if (edloloctax != NULL) + edlolocval = edloloctax[edgelocnum]; + for (h = (coarvertglbend * COARHASHPRIME) & coarhashmsk; ; h = (h + 1) & coarhashmsk) { + if (coarhashtab[h].vertorgnum != coarvertglbnum) { /* If old slot */ + coarhashtab[h].vertorgnum = coarvertglbnum; /* Mark it in reference array */ + coarhashtab[h].vertendnum = coarvertglbend; + coarhashtab[h].edgelocnum = coaredgelocnum; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (coaredgelocnum >= (edgelocnbr + coargrafptr->baseval)) { + errorPrint ("dgraphCoarsenBuild: internal error (10)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + coaredgeloctax[coaredgelocnum] = coarvertglbend; /* One more edge created */ + coaredloloctax[coaredgelocnum] = edlolocval; + coaredgelocnum ++; + break; /* Give up hashing */ + } + if (coarhashtab[h].vertendnum == coarvertglbend) { /* If coarse edge already exists */ + coaredloloctax[coarhashtab[h].edgelocnum] += edlolocval; + break; /* Give up hashing */ + } + } + } + + if (i ++ > 0) /* If second local vertex has been processed, exit */ + break; + + vertglbnum = multloctax[coarvertlocnum].vertglbnum[1]; + + if (vertglbnum >= 0) { /* If second multinode vertex is local */ + if ((vertglbnum - vertlocadj) == vertlocnum) /* If single multinode */ + break; + vertlocnum = (vertglbnum - vertlocadj); + continue; + } + + edgelocnum = -2 - vertglbnum; + multloctax[coarvertlocnum].vertglbnum[1] = edgeloctax[edgelocnum]; /* Set second vertex of multinode */ + procngbnum = procgsttax[edgegsttax[edgelocnum]]; + ercvidxnum = ercvdsptab[procngbnum]; + degrlocval = ercvdattab[ercvidxnum ++]; + coarvelolocval += (veloloctax != NULL) ? ercvdattab[ercvidxnum ++] : 1; + + while (degrlocval -- > 0) { + Gnum coarvertglbend; + Gnum h; + + coarvertglbend = ercvdattab[ercvidxnum ++]; + if (edloloctax != NULL) + edlolocval = ercvdattab[ercvidxnum ++]; + if (coarvertglbend == coarvertglbnum) /* If end of collapsed edge */ + continue; + + for (h = (coarvertglbend * COARHASHPRIME) & coarhashmsk; ; h = (h + 1) & coarhashmsk) { + if (coarhashtab[h].vertorgnum != coarvertglbnum) { /* If old slot */ + coarhashtab[h].vertorgnum = coarvertglbnum; /* Mark it in reference array */ + coarhashtab[h].vertendnum = coarvertglbend; + coarhashtab[h].edgelocnum = coaredgelocnum; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (coaredgelocnum >= (edgelocnbr + coargrafptr->baseval)) { + errorPrint ("dgraphCoarsenBuild: internal error (11)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + coaredgeloctax[coaredgelocnum] = coarvertglbend; /* One more edge created */ + coaredloloctax[coaredgelocnum] = edlolocval; + coaredgelocnum ++; + break; /* Give up hashing */ + } + if (coarhashtab[h].vertendnum == coarvertglbend) { /* If coarse edge already exists */ + coargrafptr->edloloctax[coarhashtab[h].edgelocnum] += edlolocval; + break; /* Give up hashing */ + } + } + } + + ercvdsptab[procngbnum] = ercvidxnum; /* Write back updated receive index */ + break; /* Exit loop after processing remote mate */ + } + coarvelolocsum += coarvelolocval; + coarveloloctax[coarvertlocnum] = coarvelolocval; + if (coardegrlocmax < (coaredgelocnum - coarvertloctax[coarvertlocnum])) + coardegrlocmax = (coaredgelocnum - coarvertloctax[coarvertlocnum]); + } + coarvertloctax[coarvertlocnum] = coaredgelocnum; /* Set end of compact edge array */ + coargrafptr->velolocsum = coarvelolocsum; + coargrafptr->veloglbsum = grafptr->veloglbsum; + coargrafptr->edgelocnbr = + coargrafptr->edgelocsiz = coaredgelocnum - coargrafptr->baseval; + + coargrafptr->edgeloctax = memRealloc (coaredgeloctax + coargrafptr->baseval, coargrafptr->edgelocnbr * sizeof (Gnum)); + coargrafptr->edgeloctax -= coargrafptr->baseval; + coargrafptr->edloloctax = memRealloc (coaredloloctax + coargrafptr->baseval, coargrafptr->edgelocnbr * sizeof (Gnum)); + coargrafptr->edloloctax -= coargrafptr->baseval; + + reduloctab[0] = coargrafptr->vertlocnbr; /* Get maximum over all processes */ + reduloctab[1] = coargrafptr->edgelocnbr; + reduloctab[2] = coardegrlocmax; /* Get local maximum degree */ + reduloctab[3] = coargrafptr->edgelocnbr; + + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 3, 1, proccomm) != 0) { + errorPrint ("dgraphCoarsenBuild: communication error (5)"); + return (1); + } + + coargrafptr->vertglbmax = reduglbtab[0]; + coargrafptr->edgeglbmax = reduglbtab[1]; + coargrafptr->degrglbmax = reduglbtab[2]; /* It is now a real global maximum degree */ + coargrafptr->edgeglbnbr = reduglbtab[3]; + coargrafptr->edgeglbsmx = coargrafptr->edgeglbmax; + + return (0); +} + +/***************************/ +/* */ +/* The coarsening routine. */ +/* */ +/***************************/ + +/* This routine coarsens the given fine distributed +** graph, as long as the coarsening ratio remains +** below some threshold value and the coarsened graph +** is not too small. +** If a multinode array is provided (*multlocptr != NULL), +** it must be of a size sufficient to hold multinode data +** in any configuration, including in the case of folding +** with duplication, where folded data is spread across +** floor(P/2) processes. +** It returns: +** - 0 : if the graph has been coarsened. +** - 1 : if the graph could not be coarsened. +** - 2 : on error. +*/ + +int +dgraphCoarsen ( +Dgraph * restrict const finegrafptr, /*+ Graph to coarsen +*/ +Dgraph * restrict const coargrafptr, /*+ Coarse graph to build +*/ +DgraphCoarsenMulti * restrict * const multlocptr, /*+ Pointer to un-based multinode array +*/ +const Gnum passnbr, /*+ Number of coarsening passes to go +*/ +const Gnum coarnbr, /*+ Minimum number of coarse vertices +*/ +const double coarrat, /*+ Maximum contraction ratio +*/ +const int flagval) /*+ Flag value +*/ +{ + DgraphMatchData matedat; /* Matching state data; includes coarsening handling data */ + Gnum vertrcvnbr; /* Overall number of vertices to be received from neighbors */ + Gnum edgercvnbr; /* Overall number of edges to be received from neighbors */ + Gnum vertsndnbr; /* Overall number of vertices to be sent to neighbors */ + Gnum edgesndnbr; /* Overall number of edges to be sent to neighbors */ + int cheklocval; + int chekglbval; + Gnum coarvertmax; + Gnum passnum; + int procnum; + int o; + +#ifdef SCOTCH_DEBUG_DGRAPH1 + if (coarrat < 0.5L) /* If impossible coarsening ratio wanted */ + return (1); /* We will never succeed */ +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + + coarvertmax = (Gnum) ((double) finegrafptr->vertglbnbr * coarrat); /* Maximum number of coarse vertices */ + if (coarvertmax < coarnbr) /* If there are too few vertices in graph */ + return (1); /* It is useless to go any further */ + + if (dgraphGhst (finegrafptr) != 0) { /* Compute ghost edge array of fine graph if not already present */ + errorPrint ("dgraphCoarsen: cannot compute ghost edge array"); + return (2); + } + + matedat.c.flagval = flagval; + matedat.c.multloctab = *multlocptr; /* Propagate the provided multinode array or NULL if it has to be allocated */ + cheklocval = dgraphCoarsenInit (&matedat.c, finegrafptr, coargrafptr); + cheklocval |= dgraphMatchInit (&matedat, 0.5F); + +#ifdef SCOTCH_DEBUG_DGRAPH1 /* This communication cannot be covered by a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, finegrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsen: communication error (1)"); + return (2); + } +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (chekglbval != 0) + return (2); + + for (passnum = 0; passnum < passnbr; passnum ++) { + ((passnum == 0) ? dgraphMatchHl : dgraphMatchHy) (&matedat); /* If first pass, process lightest vertices first */ + + if ((((finegrafptr->flagval & DGRAPHCOMMPTOP) != 0) ? dgraphMatchSyncPtop : dgraphMatchSyncColl) (&matedat) != 0) { + errorPrint ("dgraphCoarsen: cannot perform matching"); + dgraphMatchExit (&matedat); + dgraphCoarsenExit (&matedat.c); + return (2); + } + } + dgraphMatchLy (&matedat); /* All remaining vertices are matched locally */ + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphMatchCheck (&matedat) != 0) { + errorPrint ("dgraphCoarsen: invalid matching"); + dgraphMatchExit (&matedat); + dgraphCoarsenExit (&matedat.c); + return (2); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + dgraphMatchExit (&matedat); + + vertsndnbr = + edgesndnbr = 0; + for (procnum = 0; procnum < finegrafptr->procglbnbr; procnum ++) { + vertsndnbr += matedat.c.dcntloctab[procnum].vertsndnbr; + edgesndnbr += matedat.c.dcntloctab[procnum].edgesndnbr; + matedat.c.dcntloctab[procnum].vertlocnbr = matedat.c.multlocnbr; + } + matedat.c.vertsndnbr = vertsndnbr; + matedat.c.edgesndnbr = edgesndnbr; + + if (MPI_Alltoall (matedat.c.dcntloctab, 3, GNUM_MPI, matedat.c.dcntglbtab, 3, GNUM_MPI, finegrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphCoarsen: communication error (2)"); + return (2); + } + + vertrcvnbr = + edgercvnbr = 0; + coargrafptr->procdsptab[0] = finegrafptr->baseval; /* Build vertex-to-process array */ + for (procnum = 0; procnum < finegrafptr->procglbnbr; procnum ++) { + Gnum proccntval; + + vertrcvnbr += matedat.c.dcntglbtab[procnum].vertsndnbr; + edgercvnbr += matedat.c.dcntglbtab[procnum].edgesndnbr; + proccntval = matedat.c.dcntglbtab[procnum].vertlocnbr; + coargrafptr->proccnttab[procnum] = proccntval; + coargrafptr->procdsptab[procnum + 1] = coargrafptr->procdsptab[procnum] + proccntval; + } + coargrafptr->vertlocnbr = matedat.c.multlocnbr; + coargrafptr->vertglbnbr = coargrafptr->procdsptab[finegrafptr->procglbnbr] - finegrafptr->baseval; + matedat.c.vertrcvnbr = vertrcvnbr; + matedat.c.edgercvnbr = edgercvnbr; + + if (coargrafptr->vertglbnbr > coarvertmax) { /* If coarsening ratio not met */ + dgraphCoarsenExit (&matedat.c); + return (1); + } + + if (dgraphCoarsenBuild (&matedat.c) != 0) { /* Build coarse graph */ + dgraphCoarsenExit (&matedat.c); + return (2); + } + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphCheck (coargrafptr) != 0) { /* Check graph consistency */ + errorPrint ("dgraphCoarsen: inconsistent graph data"); + dgraphFree (coargrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + matedat.c.multloctmp = NULL; /* So that it will not be freed */ + dgraphCoarsenExit (&matedat.c); /* Free all other temporary arrays */ + + o = 0; /* Assume everything is now all right */ +#ifdef PTSCOTCH_FOLD_DUP + if (((flagval & DGRAPHCOARSENFOLDDUP) != 0) && /* If some form of folding is requested */ + (coargrafptr->procglbnbr >= 2)) { /* And if there is need to it */ + Dgraph coargrafdat; /* Coarse graph data before folding */ + DgraphCoarsenMulti * coarmultptr; /* Pointer to folded multinode array */ + MPI_Datatype coarmultype; + + MPI_Type_contiguous (2, GNUM_MPI, &coarmultype); /* Define type for MPI transfer */ + MPI_Type_commit (&coarmultype); /* Commit new type */ + + coargrafdat = *coargrafptr; /* Copy unfolded coarse graph data to save area */ + coarmultptr = NULL; /* Assume we will not get a multinode array */ + if ((flagval & DGRAPHCOARSENFOLDDUP) == DGRAPHCOARSENFOLD) { /* Do a simple folding */ + memSet (coargrafptr, 0, sizeof (Dgraph)); /* Also reset procglbnbr for unused processes */ + o = dgraphFold (&coargrafdat, 0, coargrafptr, (void *) matedat.c.multloctab, (void **) (void *) &coarmultptr, coarmultype); + } + else { /* Do a duplicant-folding */ + int loopval; + int dumyval; + + o = dgraphFoldDup (&coargrafdat, coargrafptr, (void *) matedat.c.multloctab, (void **) (void *) &coarmultptr, coarmultype); + loopval = intRandVal (finegrafptr->proclocnum + intRandVal (finegrafptr->proclocnum * 2 + 1) + 1); + while (loopval --) /* Desynchronize pseudo-random generator across processes */ + dumyval = intRandVal (2); + } + dgraphExit (&coargrafdat); /* Free unfolded graph */ + MPI_Type_free (&coarmultype); + if (*multlocptr == NULL) /* If unfolded multinode array was not user-provided, free it */ + memFree (matedat.c.multloctab); + *multlocptr = coarmultptr; /* Return folded multinode array or NULL */ + } + else /* No folding at all */ +#endif /* PTSCOTCH_FOLD_DUP */ + *multlocptr = matedat.c.multloctab; /* Return un-based pointer (maybe the same as initially user-provided) */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_coarsen.h b/scotch_6.0.3/src/libscotch/dgraph_coarsen.h new file mode 100644 index 00000000..54f63bbc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_coarsen.h @@ -0,0 +1,152 @@ +/* Copyright 2007-2009,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_coarsen.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : This file implements the distributed **/ +/** graph coarsening method. **/ +/** **/ +/** DATES : # Version 5.0 : from : 27 Jul 2005 **/ +/** to : 24 feb 2007 **/ +/** # Version 5.1 : from : 11 nov 2008 **/ +/** to : 26 may 2009 **/ +/** # Version 6.0 : from : 18 sep 2012 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Graph option flags. Their values must be equal + to those defined in library.h and library_f.h +*/ + +#define DGRAPHCOARSENNONE 0x0000 /* No options set */ +#define DGRAPHCOARSENFOLD 0x0100 /* Do folding without duplication */ +#define DGRAPHCOARSENFOLDDUP 0x0300 /* Do folding with duplication */ +#define DGRAPHCOARSENNOMERGE 0x4000 /* Do not merge isolated vertices */ + +/* +** The type and structure definitions. +*/ + +/*+ The multinode table element, which contains + pairs of based indices of collapsed vertices. + Both values are equal for uncollapsed vertices. +*/ + +typedef struct DgraphCoarsenMulti_ { + Gnum vertglbnum[2]; /*+ Global indices of the collapsed vertices of a multinode +*/ +} DgraphCoarsenMulti; + +/* This structure defines vertex data exchange + cell. It can have many uses depending on the + type of algorithm. */ + +typedef struct DgraphCoarsenVert_ { + Gnum datatab[2]; /*+ Two values +*/ +} DgraphCoarsenVert; + +/* This structure defines the inter-process vertex and + edge count structure. At matching time, it records + the amount of data to be sent to each neighbor process. */ + +typedef struct DgraphCoarsenCount_ { + Gnum vertsndnbr; + Gnum edgesndnbr; + Gnum vertlocnbr; +} DgraphCoarsenCount; + +/*+ A table made of such elements is used during + coarsening to build the edge array of the new + graph, after the labeling of the vertices. +*/ + +typedef struct DgraphCoarsenHash_ { + Gnum vertorgnum; /*+ Origin vertex (i.e. pass) number +*/ + Gnum vertendnum; /*+ Other end vertex number +*/ + Gnum edgelocnum; /*+ Number of corresponding edge +*/ +} DgraphCoarsenHash; + + +/*+ This structure gathers all data necessary + to the proper execution of the coarsening + and matching routines. +*/ + +typedef struct DgraphCoarsenData_ { + int flagval; /*+ Flag value +*/ + Dgraph * finegrafptr; /*+ Pointer to fine graph +*/ + Dgraph * coargrafptr; /*+ Pointer to coarse graph which is built +*/ + int * coarprvptr; /*+ Pointer to coarse private data to free in case of error +*/ + DgraphCoarsenVert * vrcvdattab; /*+ Area reserved for receiving vertex messages +*/ + DgraphCoarsenVert * vsnddattab; /*+ Area reserved for sending vertex messages +*/ + int * vrcvcnttab; /*+ Count data for vertex receive sub-arrays +*/ + int * vsndcnttab; /*+ Count data for vertex send sub-arrays +*/ + int * vrcvdsptab; /*+ Displacement for vertex receive sub-arrays [+1] +*/ + int * vsnddsptab; /*+ Displacement data for vertex send sub-arrays [+1] +*/ + int * nrcvidxtab; /*+ Count array for neighbor receive sub-arrays +*/ + int * nsndidxtab; /*+ Count array for neighbor send sub-arrays +*/ + MPI_Request * nrcvreqtab; /*+ Request array for receive requests +*/ + MPI_Request * nsndreqtab; /*+ TRICK: nsndreqtab = (nrcvreqtab + procngbnbr) +*/ + int * procgsttax; /*+ Array giving the neighbor process index of each ghost vertex +*/ + int procngbnxt; /*+ Index of first neighbor of higher rank than current process +*/ + DgraphCoarsenCount * dcntloctab; /*+ Count array for sending vertices and edges +*/ + DgraphCoarsenCount * dcntglbtab; /*+ Count array for receiving vertices and edges +*/ + Gnum * coargsttax; /*+ Fine-to-coarse vertex index array +*/ + DgraphCoarsenMulti * multloctmp; /*+ Pointer to multloctab structure to free (if any) +*/ + DgraphCoarsenMulti * multloctab; /*+ Structure which contains the result of the matching +*/ + Gnum multlocnbr; /*+ Index of next multinode to be created +*/ + Gnum vertrcvnbr; /*+ Number of fine vertices to be received +*/ + Gnum edgercvnbr; /*+ Number of fine edges to be received +*/ + Gnum edgekptnbr; /*+ Upper bound on number of edges kept from finer graph +*/ + Gnum vertsndnbr; /*+ Number of fine vertices to be sent +*/ + Gnum edgesndnbr; /*+ Number of fine edges to be sent +*/ +} DgraphCoarsenData; + +/* +** The function prototypes. +*/ + +#ifndef DGRAPH_COARSEN +#define static +#endif + +static int dgraphCoarsenInit (DgraphCoarsenData * restrict const, Dgraph * restrict const, Dgraph * restrict const); +static void dgraphCoarsenExit (DgraphCoarsenData * restrict const); +static int dgraphCoarsenBuild (DgraphCoarsenData * restrict const); + +int dgraphCoarsen (Dgraph * restrict const, Dgraph * restrict const, DgraphCoarsenMulti * restrict * const, const Gnum, const Gnum, const double, const int); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/dgraph_fold.c b/scotch_6.0.3/src/libscotch/dgraph_fold.c new file mode 100644 index 00000000..2a84e01d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_fold.c @@ -0,0 +1,758 @@ +/* Copyright 2007-2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_fold.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the distributed **/ +/** source graph folding function. **/ +/** **/ +/** DATES : # Version 5.0 : from : 10 aug 2006 **/ +/** to : 27 jun 2008 **/ +/** # Version 5.1 : from : 12 nov 2008 **/ +/** to : 04 jan 2011 **/ +/** # Version 6.0 : from : 28 sep 2014 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_fold.h" +#include "dgraph_fold_comm.h" + +/******************************/ +/* */ +/* This routine handles */ +/* distributed source graphs. */ +/* */ +/******************************/ + +/* This routine builds a folded graph by merging graph +** data to the processes of the first half or to the +** second half of the communicator. +** The key value of the folded communicator is not +** changed as it is not relevant. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphFold ( +const Dgraph * restrict const orggrafptr, +const int partval, /* 0 for first half, 1 for second half */ +Dgraph * restrict const fldgrafptr, +const void * restrict const orgdataptr, /* Un-based array of data which must be folded, e.g. coarmulttab */ +void ** restrict const flddataptr, /* Un-based array of data which must be folded, e.g. coarmulttab */ +MPI_Datatype datatype) +{ + int fldprocnbr; + int fldprocnum; /* Index of local process in folded communicator */ + int fldproccol; /* Color of receiver or not wanted in communicator */ + MPI_Comm fldproccomm; /* Communicator of folded part */ + int o; + + fldprocnbr = (orggrafptr->procglbnbr + 1) / 2; + fldprocnum = orggrafptr->proclocnum; + if (partval == 1) { + fldprocnum = fldprocnum - fldprocnbr; + fldprocnbr = orggrafptr->procglbnbr - fldprocnbr; + } + fldproccol = ((fldprocnum >= 0) && (fldprocnum < fldprocnbr)) ? 0 : MPI_UNDEFINED; + + if (MPI_Comm_split (orggrafptr->proccomm, fldproccol, fldprocnum, &fldproccomm) != MPI_SUCCESS) { + errorPrint ("dgraphFold: communication error"); + return (1); + } + + o = dgraphFold2 (orggrafptr, partval, fldgrafptr, fldproccomm, orgdataptr, flddataptr, datatype); + fldgrafptr->prockeyval = fldproccol; /* Key of folded communicator is always zero if no duplication occurs */ + + return (o); +} + +int +dgraphFold2 ( +const Dgraph * restrict const orggrafptr, +const int partval, /* 0 for first half, 1 for second half */ +Dgraph * restrict const fldgrafptr, +MPI_Comm fldproccomm, +const void * restrict const orgdataptr, /* Un-based array of data which must be kept, e.g. coarmulttab */ +void ** restrict const flddataptr, /* Un-based array of data which must be kept, e.g. coarmulttab */ +MPI_Datatype datatype) +{ + int fldcommtypval; /* Type of communication for this process */ + DgraphFoldCommData * restrict fldcommdattab; /* Array of two communication data */ + Gnum * restrict fldcommvrttab; /* Starting global send indices of communications */ + Gnum * restrict fldvertidxtab; /* Start indices of vertex arrays */ + Gnum * restrict fldedgeidxtab; /* Start indices of edge arrays */ + Gnum * restrict fldedgecnttab; /* Number of edges exchanged during each communication */ + Gnum * restrict fldedgecnptab; /* Temporary save for fldedgecnttab for MPI standard */ + Gnum fldvertlocnbr; /* Number of vertices in local folded part */ + Gnum fldedgelocsiz; /* (Upper bound of) number of edges in folded graph */ + Gnum fldedlolocsiz; /* (Upper bound of) number of edge loads in folded graph */ + int fldprocglbnbr; + int fldproclocnum; /* Index of local process in folded communicator */ + int fldvertadjnbr; + Gnum * restrict fldvertadjtab; /* Array of global start indices for adjustment slots */ + Gnum * restrict fldvertdlttab; /* Array of index adjustments for original global indices */ + int cheklocval; + int chekglbval; + int commmax; + int commnbr; + int requnbr; + MPI_Request * restrict requtab; + int infosiz; /* Size of one information */ + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (orggrafptr->vendloctax != (orggrafptr->vertloctax + 1)) { + errorPrint ("dgraphFold2: graph must be compact"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + fldprocglbnbr = (orggrafptr->procglbnbr + 1) / 2; + if (partval == 1) { + fldproclocnum = orggrafptr->proclocnum - fldprocglbnbr; + fldprocglbnbr = orggrafptr->procglbnbr - fldprocglbnbr; + } + else + fldproclocnum = orggrafptr->proclocnum; + + fldcommtypval = ((fldproclocnum >= 0) && (fldproclocnum < fldprocglbnbr)) ? DGRAPHFOLDCOMMRECV : DGRAPHFOLDCOMMSEND; + if (orgdataptr != NULL) + MPI_Type_size (datatype, &infosiz); + + cheklocval = 0; + fldcommdattab = NULL; + fldvertidxtab = NULL; + if (fldcommtypval == DGRAPHFOLDCOMMRECV) { /* If we are going to receive */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (fldgrafptr == NULL) { + errorPrint ("dgraphFold2: invalid parameters (1)"); + return (1); + } + if (fldproccomm == MPI_COMM_NULL) { + errorPrint ("dgraphFold2: invalid parameters (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + memSet (fldgrafptr, 0, sizeof (Dgraph)); /* Pre-initialize graph fields */ + + fldgrafptr->proccomm = fldproccomm; + fldgrafptr->procglbnbr = fldprocglbnbr; + fldgrafptr->proclocnum = fldproclocnum; + fldgrafptr->flagval = DGRAPHFREEALL | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* For premature freeing on error */ + + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ + &fldgrafptr->procdsptab, (size_t) ((fldprocglbnbr + 1) * sizeof (Gnum)), + &fldgrafptr->proccnttab, (size_t) (fldprocglbnbr * sizeof (Gnum)), + &fldgrafptr->procngbtab, (size_t) (fldprocglbnbr * sizeof (int)), + &fldgrafptr->procrcvtab, (size_t) (fldprocglbnbr * sizeof (int)), + &fldgrafptr->procsndtab, (size_t) (fldprocglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("dgraphFold2: out of memory (1)"); + cheklocval = 1; + } + else if (dgraphFoldComm (orggrafptr, partval, &commmax, &fldcommtypval, &fldcommdattab, &fldcommvrttab, /* Process can become a sender receiver */ + fldgrafptr->proccnttab, &fldvertadjnbr, &fldvertadjtab, &fldvertdlttab) != 0) { + errorPrint ("dgraphFold2: cannot compute folding communications (1)"); + cheklocval = 1; + } + else { + Gnum fldvelolocnbr; + + if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver */ + int i; + + for (i = 0, fldvertlocnbr = 0; (i < commmax) && (fldcommdattab[i].procnum != -1); i ++) + fldvertlocnbr += fldcommdattab[i].vertnbr; + commnbr = i; + + fldedgelocsiz = orggrafptr->edgeglbsmx * i; /* Upper bound on received edges */ + if ((orggrafptr->degrglbmax > 0) && (fldvertlocnbr < (fldedgelocsiz / orggrafptr->degrglbmax))) /* Choose best upper bound on number of edges (avoid multiply overflow) */ + fldedgelocsiz = fldvertlocnbr * orggrafptr->degrglbmax; + + fldedgelocsiz += orggrafptr->edgelocnbr; /* Add local edges and vertices */ + fldvertlocnbr += orggrafptr->vertlocnbr; + } + else { /* Process is a sender receiver */ + fldvertlocnbr = fldcommvrttab[0] - orggrafptr->procvrttab[orggrafptr->proclocnum]; /* Communications will remove vertices */ + fldedgelocsiz = orggrafptr->vertloctax[fldvertlocnbr + orggrafptr->baseval] - orggrafptr->baseval; /* Exact number of edges */ + + fldgrafptr->edgelocnbr = + fldgrafptr->edgelocsiz = fldedgelocsiz; + } + fldvelolocnbr = (orggrafptr->veloloctax != NULL) ? fldvertlocnbr : 0; + + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ + &fldgrafptr->vertloctax, (size_t) ((fldvertlocnbr + 1) * sizeof (Gnum)), + &fldgrafptr->vnumloctax, (size_t) ( fldvertlocnbr * sizeof (Gnum)), + &fldgrafptr->veloloctax, (size_t) ( fldvelolocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphFold2: out of memory (2)"); + cheklocval = 1; + } + else if (fldgrafptr->vertloctax -= orggrafptr->baseval, + fldgrafptr->vnumloctax -= orggrafptr->baseval, + fldgrafptr->vendloctax = fldgrafptr->vertloctax + 1, /* Folded graph is compact */ + fldgrafptr->veloloctax = ((orggrafptr->veloloctax != NULL) ? (fldgrafptr->veloloctax - orggrafptr->baseval) : NULL), + fldedlolocsiz = ((orggrafptr->edloloctax != NULL) ? fldedgelocsiz : 0), + (fldgrafptr->edgeloctax = memAlloc ((fldedgelocsiz + fldedlolocsiz) * sizeof (Gnum))) == NULL) { /* Allocate single array for both edge arrays */ + errorPrint ("dgraphFold2: out of memory (3)"); + cheklocval = 1; + } + else { + if (orgdataptr != NULL) { + if ((*flddataptr = (byte *) memAlloc (fldvertlocnbr * infosiz)) == NULL) { + errorPrint ("dgraphFold2: out of memory (4)"); + cheklocval = 1; + } + } + fldgrafptr->edgeloctax -= orggrafptr->baseval; /* Do not care about the validity of edloloctax at this stage */ + } + } + } + else { /* Process is a sender */ +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (fldproccomm != MPI_COMM_NULL) { + errorPrint ("dgraphFold2: invalid parameters (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + if (dgraphFoldComm (orggrafptr, partval, &commmax, &fldcommtypval, &fldcommdattab, &fldcommvrttab, NULL, NULL, NULL, NULL) != 0) { + errorPrint ("dgraphFold2: cannot compute folding communications (2)"); + cheklocval = 1; + } + } + + if ((cheklocval == 0) && + (memAllocGroup ((void **) (void *) /* Allocate folding data */ + &fldvertidxtab, (size_t) (commmax * sizeof (Gnum)), + &fldedgeidxtab, (size_t) (commmax * sizeof (Gnum)), + &fldedgecnttab, (size_t) (commmax * sizeof (Gnum)), + &fldedgecnptab, (size_t) (commmax * sizeof (Gnum)), + &requtab, (size_t) (commmax * DGRAPHFOLDTAGNBR * sizeof (MPI_Request)), NULL) == NULL)) { + errorPrint ("dgraphFold2: out of memory (5)"); + cheklocval = 1; + } + +#ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, orggrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (1)"); + chekglbval = 1; + } +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (chekglbval != 0) { + if ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) { + if (fldvertidxtab != NULL) + memFree (fldvertidxtab); /* Free group leader */ + if (fldcommdattab != NULL) + memFree (fldcommdattab); + dgraphExit (fldgrafptr); + } + return (1); + } + + requnbr = 0; /* Communications without further processing are placed at beginning of array */ + + if ((fldcommtypval & DGRAPHFOLDCOMMSEND) != 0) { /* If process is (also) a sender */ + Gnum vertsndbas; + Gnum vertsndnbr; + int i; + + vertsndnbr = ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) ? (fldcommvrttab[0] - orggrafptr->procvrttab[orggrafptr->proclocnum]) : 0; /* If process is also a receiver, start sending after kept vertices */ + + for (i = 0, vertsndbas = orggrafptr->baseval; /* For all send communications to perform */ + (i < commmax) && (fldcommdattab[i].procnum != -1) && (cheklocval == 0); i ++) { + vertsndbas += vertsndnbr; + vertsndnbr = fldcommdattab[i].vertnbr; + + fldvertidxtab[i] = vertsndbas; + fldedgeidxtab[i] = orggrafptr->vertloctax[vertsndbas]; + fldedgecnptab[i] = /* Save fldedgecnttab in temporary array to read it while MPI communication in progress */ + fldedgecnttab[i] = orggrafptr->vertloctax[vertsndbas + vertsndnbr] - orggrafptr->vertloctax[vertsndbas]; /* Graph is compact */ + if (MPI_Isend (&fldedgecnptab[i], 1, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVLBLLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (2)"); + cheklocval = 1; + } + } + commnbr = i; + + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Isend (orggrafptr->vertloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVERTLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (3)"); + cheklocval = 1; + } + } + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Isend (orggrafptr->edgeloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGEDGELOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (4)"); + cheklocval = 1; + } + } + if (orggrafptr->veloloctax != NULL) { + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Isend (orggrafptr->veloloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVELOLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (5)"); + cheklocval = 1; + } + } + } + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + int procsndnum; /* Rank of process to send to */ + + procsndnum = fldcommdattab[i].procnum; + if ((orggrafptr->edloloctax != NULL) && + (MPI_Isend (orggrafptr->edloloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, procsndnum, + TAGFOLD + TAGEDLOLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { + errorPrint ("dgraphFold2: communication error (6)"); + cheklocval = 1; + } + else if ((orggrafptr->vnumloctax != NULL) && + (MPI_Isend (orggrafptr->vnumloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, procsndnum, + TAGFOLD + TAGVNUMLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { + errorPrint ("dgraphFold2: communication error (7)"); + cheklocval = 1; + } + else if ((orgdataptr != NULL) && + (MPI_Isend ((byte *) orgdataptr + ((fldvertidxtab[i] - orggrafptr->baseval) * infosiz), fldcommdattab[i].vertnbr, datatype, procsndnum, + TAGFOLD + TAGDATALOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { + errorPrint ("dgraphFold2: communication error (8)"); + cheklocval = 1; + } + } + } /* Communications of sender-receivers will be completed in the receiving phase */ + + if ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) { /* If process is (also) a receiver */ + Gnum orgvertlocnbr; + Gnum orgvertlocnnd; + Gnum orgvertlocmin; + Gnum orgvertlocmax; + Gnum fldvertlocadj; + Gnum fldvelolocsum; + Gnum fldedgelocnum; + Gnum fldedgelocnnd; + int fldprocnum; + int procngbmin; + int procngbmax; + int i; + + const Gnum * restrict const orgedgeloctax = orggrafptr->edgeloctax; + Gnum * restrict const fldedgeloctax = fldgrafptr->edgeloctax; + + fldgrafptr->procvrttab = fldgrafptr->procdsptab; /* Graph does not have holes */ + fldgrafptr->procdsptab[0] = orggrafptr->baseval; /* Build private data of folded graph and array */ + for (fldprocnum = 0; fldprocnum < fldprocglbnbr; fldprocnum ++) /* New subdomain indices start from baseval */ + fldgrafptr->procdsptab[fldprocnum + 1] = fldgrafptr->procdsptab[fldprocnum] + fldgrafptr->proccnttab[fldprocnum]; + + if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver */ + Gnum fldedgelocbas; + Gnum fldvertrcvbas; + Gnum fldvertrcvnbr; + + for (i = 0, fldvertrcvbas = orggrafptr->vertlocnnd, fldvertrcvnbr = 0; /* For all receive communications to perform */ + (i < commnbr) && (cheklocval == 0); i ++) { + fldvertrcvbas += fldvertrcvnbr; + fldvertrcvnbr = fldcommdattab[i].vertnbr; + + fldvertidxtab[i] = fldvertrcvbas; + if (MPI_Irecv (&fldedgecnttab[i], 1, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVLBLLOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGENBR * commmax + i]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (9)"); + cheklocval = 1; + } + } + + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { /* Let these communications progress while we process the edge size messages */ + if (MPI_Irecv (fldgrafptr->vertloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVERTLOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGVERT * commmax + i]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (10)"); + cheklocval = 1; + } + } + + MPI_Waitall (commnbr, &requtab[DGRAPHFOLDTAGENBR * commmax], MPI_STATUSES_IGNORE); + + for (i = 0, fldedgelocbas = orggrafptr->vertloctax[orggrafptr->vertlocnnd]; (i < commnbr) && (cheklocval == 0); i ++) { + fldedgeidxtab[i] = fldedgelocbas; + fldedgelocbas += fldedgecnttab[i]; + + if (MPI_Irecv (fldgrafptr->edgeloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGEDGELOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGEDGE * commmax + i]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (11)"); + cheklocval = 1; + } + } + fldgrafptr->edgelocnbr = /* Get number of local edges */ + fldgrafptr->edgelocsiz = fldedgelocbas - orggrafptr->baseval; + + if (orggrafptr->veloloctax != NULL) { + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Irecv (fldgrafptr->veloloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVELOLOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGVELO * commmax + i]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (12)"); + cheklocval = 1; + } + } + } + if (orggrafptr->edloloctax != NULL) { + fldgrafptr->edloloctax = fldgrafptr->edgeloctax + fldgrafptr->edgelocnbr; /* Set start index of edge load array */ + + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Irecv (fldgrafptr->edloloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGEDLOLOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGEDLO * commmax + i]) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (13)"); + cheklocval = 1; + } + } + } + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + int procrcvnum; /* Rank of process to receive from */ + Gnum vertrcvnbr; + + procrcvnum = fldcommdattab[i].procnum; + vertrcvnbr = fldcommdattab[i].vertnbr; + if ((orggrafptr->vnumloctax != NULL) && + (MPI_Irecv (fldgrafptr->vnumloctax + fldvertidxtab[i], vertrcvnbr, GNUM_MPI, procrcvnum, + TAGFOLD + TAGVNUMLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { + errorPrint ("dgraphFold2: communication error (14)"); + cheklocval = 1; + } + else if ((orgdataptr != NULL) && + (MPI_Irecv ((byte *) (*flddataptr) + ((fldvertidxtab[i] - orggrafptr->baseval) * infosiz), vertrcvnbr, datatype, procrcvnum, + TAGFOLD + TAGDATALOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { + errorPrint ("dgraphFold2: communication error (15)"); + cheklocval = 1; + } + } + + orgvertlocnbr = orggrafptr->vertlocnbr; /* Process all local vertices */ + orgvertlocnnd = orggrafptr->vertlocnnd; + + if (orggrafptr->vnumloctax == NULL) { /* If original graph does not have vertex numbers, create remote parts of vertex number array */ + Gnum fldvertlocnum; + Gnum fldvertlocadj; + int i; + + Gnum * restrict const fldvnumloctax = fldgrafptr->vnumloctax; + + for (i = 0, fldvertlocnum = orgvertlocnnd; i < commnbr; i ++) { + Gnum fldvertlocnnd; + + for (fldvertlocnnd = fldvertlocnum + fldcommdattab[i].vertnbr, fldvertlocadj = fldcommvrttab[i]; + fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) + fldvnumloctax[fldvertlocnum] = fldvertlocadj ++; + } + } + + fldedgelocnnd = orggrafptr->vertloctax[orggrafptr->vertlocnnd]; + fldvelolocsum = orggrafptr->velolocsum; /* In case there are vertex loads, we keep all of existing load */ + } + else { /* Receiver process is also a sender */ + orgvertlocnbr = fldvertlocnbr; /* Process only remaining local vertices */ + orgvertlocnnd = fldvertlocnbr + orggrafptr->baseval; + + if (orggrafptr->veloloctax != NULL) { /* If original graph has vertex loads */ + Gnum fldvertlocnum; + + for (fldvertlocnum = orggrafptr->baseval, fldvelolocsum = 0; /* Accumulate load sum of remaining part */ + fldvertlocnum < orgvertlocnnd; fldvertlocnum ++) + fldvelolocsum += orggrafptr->veloloctax[fldvertlocnum]; + } + fldedgelocnnd = orggrafptr->vertloctax[orgvertlocnnd]; /* Reorder remaining local part of edge array */ + if (orggrafptr->edloloctax != NULL) + fldgrafptr->edloloctax = fldgrafptr->edgeloctax + fldgrafptr->edgelocnbr; /* Set start index of edge load array */ + + commnbr = 0; /* Turn sender-receiver into normal receiver without any communications to perform */ + } + + for (procngbmin = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ + procngbmax - procngbmin > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbmin) / 2; + if (fldvertadjtab[procngbmed] <= orggrafptr->procvrttab[orggrafptr->proclocnum]) + procngbmin = procngbmed; + else + procngbmax = procngbmed; + } + orgvertlocmin = fldvertadjtab[procngbmin]; + orgvertlocmax = fldvertadjtab[procngbmax]; + fldvertlocadj = fldvertdlttab[procngbmin]; + for (fldedgelocnum = orggrafptr->baseval; fldedgelocnum < fldedgelocnnd; fldedgelocnum ++) { + Gnum orgvertlocend; + + orgvertlocend = orgedgeloctax[fldedgelocnum]; + + if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ + (orgvertlocend < orgvertlocmax)) + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; + else { /* End vertex is not local */ + int procngbnum; + int procngbmax; + + for (procngbnum = 0, procngbmax = fldvertadjnbr; + procngbmax - procngbnum > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (fldvertadjtab[procngbmed] <= orgvertlocend) + procngbnum = procngbmed; + else + procngbmax = procngbmed; + } + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbnum]; + } + } + + if (orggrafptr->veloloctax != NULL) /* If original graph has vertex loads */ + memCpy (fldgrafptr->veloloctax + orggrafptr->baseval, /* Copy local part of vertex load array */ + orggrafptr->veloloctax + orggrafptr->baseval, orgvertlocnbr * sizeof (Gnum)); + + if (orggrafptr->edloloctax != NULL) /* If original graph has edge loads */ + memCpy (fldgrafptr->edloloctax + orggrafptr->baseval, /* Copy local part of edge load array */ + orggrafptr->edloloctax + orggrafptr->baseval, + (orggrafptr->vertloctax[orgvertlocnnd] - orggrafptr->baseval) * sizeof (Gnum)); + + if (orggrafptr->vnumloctax != NULL) /* If original graph has vertex numbers */ + memCpy (fldgrafptr->vnumloctax + orggrafptr->baseval, /* Copy local part of vertex number array */ + orggrafptr->vnumloctax + orggrafptr->baseval, orgvertlocnbr * sizeof (Gnum)); + else { /* Build local part of vertex number array */ + Gnum fldvertlocnum; + Gnum fldvertlocadj; + + for (fldvertlocnum = orggrafptr->baseval, fldvertlocadj = orggrafptr->procvrttab[orggrafptr->proclocnum]; + fldvertlocnum < orgvertlocnnd; fldvertlocnum ++) + fldgrafptr->vnumloctax[fldvertlocnum] = fldvertlocadj ++; + } + + memCpy (fldgrafptr->vertloctax + orggrafptr->baseval, /* Copy local part of vertex array, since it is compact */ + orggrafptr->vertloctax + orggrafptr->baseval, orgvertlocnbr * sizeof (Gnum)); /* Last value is not copied */ + fldgrafptr->vertloctax[fldvertlocnbr + orggrafptr->baseval] = fldgrafptr->edgelocnbr + orggrafptr->baseval; + + if (orgdataptr != NULL) /* If additional data present */ + memCpy ((byte *) (*flddataptr), (byte *) orgdataptr, orgvertlocnbr * infosiz); /* Copy local part */ + + for (i = 0; i < commnbr; i ++) { + int j; + + if (MPI_Waitany (commnbr, &requtab[DGRAPHFOLDTAGVERT * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (16)"); + cheklocval = 1; + } + else { /* Adjust first remote part of vertex array */ + Gnum fldvertlocnum; + Gnum fldvertlocnnd; + Gnum fldvertlocadj; + + Gnum * restrict const fldvertloctax = fldgrafptr->vertloctax; + + fldvertlocnum = fldvertidxtab[j]; + fldvertlocadj = fldedgeidxtab[j] - fldgrafptr->vertloctax[fldvertlocnum]; + + for (fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) + fldvertloctax[fldvertlocnum] += fldvertlocadj; + } + } + + for (i = 0; i < commnbr; i ++) { + MPI_Status statdat; + int j; + + if (MPI_Waitany (commnbr, &requtab[DGRAPHFOLDTAGEDGE * commmax], &j, &statdat) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (17)"); + cheklocval = 1; + } + else if (cheklocval == 0) { /* Adjust remote part(s) of edge array */ + Gnum orgvertlocmin; + Gnum orgvertlocmax; + Gnum fldvertlocadj; + int procngbnum; + int procngbmax; + + Gnum * restrict const fldedgeloctax = fldgrafptr->edgeloctax; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + int fldedgercvnbr; + + MPI_Get_count (&statdat, GNUM_MPI, &fldedgercvnbr); + if (fldedgercvnbr != fldedgecnttab[j]) { + errorPrint ("dgraphFold2: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + for (procngbnum = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ + procngbmax - procngbnum > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (fldvertadjtab[procngbmed] <= fldcommvrttab[j]) + procngbnum = procngbmed; + else + procngbmax = procngbmed; + } + orgvertlocmin = fldvertadjtab[procngbnum]; + orgvertlocmax = fldvertadjtab[procngbmax]; + fldvertlocadj = fldvertdlttab[procngbnum]; + for (fldedgelocnum = fldedgeidxtab[j], fldedgelocnnd = fldedgelocnum + fldedgecnttab[j]; + fldedgelocnum < fldedgelocnnd; fldedgelocnum ++) { /* Reorder end vertices */ + Gnum orgvertlocend; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (fldedgelocnum >= (fldgrafptr->edgelocnbr + orggrafptr->baseval)) { + errorPrint ("dgraphFold2: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + orgvertlocend = fldedgeloctax[fldedgelocnum]; + + if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ + (orgvertlocend < orgvertlocmax)) + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; + else { + int procngbnum; + int procngbmax; + + for (procngbnum = 0, procngbmax = fldvertadjnbr; + procngbmax - procngbnum > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (fldvertadjtab[procngbmed] <= orgvertlocend) + procngbnum = procngbmed; + else + procngbmax = procngbmed; + } + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbnum]; + } + } + } + } + + if (orggrafptr->veloloctax == NULL) /* If no vertex loads, reset graph vertex load to number of vertices */ + fldvelolocsum = fldvertlocnbr; + else { /* Graph has vertex loads and load of local part has already been computed */ + for (i = 0; i < commnbr; i ++) { + int j; + + if (MPI_Waitany (commnbr, &requtab[DGRAPHFOLDTAGVELO * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (18)"); + cheklocval = 1; + } + else if (cheklocval == 0) { /* Accumulate vertex loads for received vertex load array */ + Gnum fldvertlocnum; + Gnum fldvertlocnnd; + + for (fldvertlocnum = fldvertidxtab[j], fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; + fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) + fldvelolocsum += fldgrafptr->veloloctax[fldvertlocnum]; + } + } + } + + if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver, edge arrays may have been oversized */ + Gnum fldedgeloctmp; + + fldedgeloctmp = fldgrafptr->edgelocnbr; + if (orggrafptr->edloloctax != NULL) { + fldedgeloctmp *= 2; + if (MPI_Waitall (commnbr, &requtab[DGRAPHFOLDTAGEDLO * commmax], MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for edge load sub-arrays */ + errorPrint ("dgraphFold2: communication error (19)"); + cheklocval = 1; + } + } + + fldgrafptr->edgeloctax = memRealloc (fldgrafptr->edgeloctax + orggrafptr->baseval, fldedgeloctmp * sizeof (Gnum)); + fldgrafptr->edgeloctax -= orggrafptr->baseval; + if (orggrafptr->edloloctax != NULL) + fldgrafptr->edloloctax = fldgrafptr->edgeloctax + fldgrafptr->edgelocnbr; + } + + fldgrafptr->baseval = orggrafptr->baseval; + fldgrafptr->vertlocnbr = fldvertlocnbr; + fldgrafptr->vertlocnnd = fldvertlocnbr + orggrafptr->baseval; + fldgrafptr->velolocsum = fldvelolocsum; + fldgrafptr->degrglbmax = orggrafptr->degrglbmax; + if (dgraphBuild4 (fldgrafptr) != 0) { + errorPrint ("dgraphFold2: cannot build folded graph"); + dgraphExit (fldgrafptr); + return (1); + } + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphCheck (fldgrafptr) != 0) { /* Check graph consistency; vnumloctab is not checked so no need to wait for it */ + errorPrint ("dgraphFold2: internal error (3)"); + dgraphExit (fldgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + } + + memFree (fldcommdattab); /* Free group leader */ + + if (MPI_Waitall (requnbr, requtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for all graph data to arrive because graph could be freed afterwards */ + errorPrint ("dgraphFold2: communication error (20)"); + cheklocval = 1; + } + + memFree (fldvertidxtab); /* Free group leader including request array */ + +#ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, orggrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphFold2: communication error (21)"); + chekglbval = 1; + } +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + + return (chekglbval); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_fold.h b/scotch_6.0.3/src/libscotch/dgraph_fold.h new file mode 100644 index 00000000..721d4985 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_fold.h @@ -0,0 +1,67 @@ +/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_fold.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed source graph **/ +/** folding routines. **/ +/** **/ +/** # Version 5.0 : from : 06 sep 2006 **/ +/** to 06 sep 2006 **/ +/** # Version 5.1 : from : 31 dec 2008 **/ +/** to 01 jan 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/* Slot indices used for point-to-point folding + communications. First indices are used for + communications without further processing. + At the moment, there are two anonymous slots: + the first one for vnumloctab, and the second + one for vertinfotab. */ + +typedef enum DgraphFoldTag_ { + DGRAPHFOLDTAGENBR = 2, /*+ Edge size message +*/ + DGRAPHFOLDTAGVERT, /*+ vertloctab message +*/ + DGRAPHFOLDTAGVELO, /*+ veloloctab message +*/ + DGRAPHFOLDTAGEDGE, /*+ edgeloctab message +*/ + DGRAPHFOLDTAGEDLO, /*+ edgeloctab message +*/ + DGRAPHFOLDTAGNBR /*+ Number of tags +*/ +} DgraphFoldTag; diff --git a/scotch_6.0.3/src/libscotch/dgraph_fold_comm.c b/scotch_6.0.3/src/libscotch/dgraph_fold_comm.c new file mode 100644 index 00000000..c358a848 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_fold_comm.c @@ -0,0 +1,438 @@ +/* Copyright 2007,2009-2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_fold_comm.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes the communication **/ +/** pattern of the distributed graph **/ +/** folding process. **/ +/** **/ +/** DATES : # Version 5.0 : from : 23 may 2006 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 18 jan 2009 **/ +/** to : 10 sep 2011 **/ +/** **/ +/************************************************************/ + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_fold_comm.h" + +/* This routine computes an optimized communication +** scheme for folding the data of a distributed graph. +** It is currently based on a maximum fixed number of +** communications per process. If this maximum is reached, +** the algorithm will fail. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphFoldComm ( +const Dgraph * restrict const grafptr, +const int partval, /* 0 for first half, 1 for second half */ +int * restrict const commptr, /* Pointer to maximum number of communications per process */ +int * restrict const commtypval, /* Process will be sender or receiver */ +DgraphFoldCommData *restrict * restrict const commdatptr, /* Slots for communication */ +Gnum *restrict * restrict const commvrtptr, /* Slots of starting global vertex send indices */ +Gnum * restrict const proccnttab, /* Receive count array, for receivers */ +int * restrict const vertadjnbrptr, /* Number of adjustment ranges, for receivers */ +Gnum * restrict * restrict const vertadjptr, /* Pointer to global index adjustment array, for receivers */ +Gnum * restrict * restrict const vertdltptr) /* Pointer to global delta adjustment array, for receivers */ +{ + int commmax; /* Maximum number of communications per process */ + int procnum; + Gnum * restrict commvrttab; + DgraphFoldCommData * restrict commdattab; + DgraphFoldCommData * restrict procsrttab; /* Sort array */ + int procsndbas; + int procsndmnd; + int procsndidx; + int procrcvbas; + int procrcvnnd; + int procrcvidx; + int fldprocnbr; + Gnum * restrict vertadjtab; + Gnum * restrict vertdlttab; + int * restrict vertprmtab; /* Permutation array for adjustment range computations */ + int i; +#ifdef SCOTCH_DEBUG_DGRAPH2 + DgraphFoldCommData * restrict procchktab; + int chekloctab[2]; + int chekglbtab[2]; + + if (grafptr->procglbnbr < 2) { + errorPrint ("dgraphFoldComm: invalid parameters"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if ((procsrttab = memAlloc (grafptr->procglbnbr * sizeof (DgraphFoldCommData))) == NULL) { + errorPrint ("dgraphFoldComm: out of memory (1)"); + return (1); + } + + for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { + procsrttab[procnum].procnum = procnum; + procsrttab[procnum].vertnbr = grafptr->proccnttab[procnum]; + } + fldprocnbr = (grafptr->procglbnbr + 1) / 2; /* Get number of processes in part 0 (always more than in part 1) */ + + intSort2asc1 (procsrttab, fldprocnbr); /* Sort both parts of processor array */ + intSort2asc1 (procsrttab + fldprocnbr, grafptr->procglbnbr - fldprocnbr); + + if (partval == 0) { /* If part 0 will receive the data */ + procrcvbas = 0; /* Receive by ascending weight order in first part */ + procrcvnnd = fldprocnbr; + procsndbas = grafptr->procglbnbr; /* Send by descending weight order in other part */ + procsndmnd = fldprocnbr; + } + else { /* Part 1 will receive the data */ + procrcvbas = fldprocnbr; /* Receive by ascending weight order in first part */ + procrcvnnd = grafptr->procglbnbr; + procsndbas = fldprocnbr; /* Send by descending weight order in other part */ + procsndmnd = 0; + fldprocnbr = grafptr->procglbnbr - fldprocnbr; + } + *commtypval = ((grafptr->proclocnum >= procrcvbas) && (grafptr->proclocnum < procrcvnnd)) ? DGRAPHFOLDCOMMRECV : DGRAPHFOLDCOMMSEND; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((*commtypval == DGRAPHFOLDCOMMRECV) && + ((proccnttab == NULL) || (vertadjptr == NULL) || (vertdltptr == NULL))) { + errorPrint ("dgraphFoldComm: internal error (1)"); + memFree (procsrttab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + for (commmax = DGRAPHFOLDCOMMNBR, commdattab = NULL; ; commmax ++) { /* Start with small number of communications per process */ + int procrcvnum; + int procsndnum; + int procsndnxt; /* Index of next sender to process after current sender */ + Gnum vertglbsum; /* Global number of vertices already sent from all previous senders */ + Gnum vertglbavg; /* Global average value of sent vertices to reach during current round */ + Gnum vertsndrmn; /* Remaining number of vertices to send from current sending process */ + int flagrcvval; /* Number of messages already sent by receiver and sender */ + int flagsndval; + int commtmp; + + if (commdattab != NULL) + memFree (commdattab); + + commtmp = (proccnttab == NULL) ? 0 : commmax; + if (memAllocGroup ((void **) (void *) + &commdattab, (size_t) (commmax * sizeof (DgraphFoldCommData)), + &commvrttab, (size_t) (commmax * sizeof (Gnum)), + &vertadjtab, (size_t) (commtmp * grafptr->procglbnbr * sizeof (Gnum)), + &vertdlttab, (size_t) (commtmp * grafptr->procglbnbr * sizeof (Gnum)), +#ifdef SCOTCH_DEBUG_DGRAPH2 + &procchktab, (size_t) (commmax * grafptr->procglbnbr * sizeof (DgraphFoldCommData)), +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + &vertprmtab, (size_t) ((commmax + 1) * fldprocnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("dgraphFoldComm: out of memory (2)"); + memFree (procsrttab); + return (1); + } + + for (i = 0; i < commmax; i ++) { /* Assume we will perform no communication at all */ + commdattab[i].procnum = -1; + commdattab[i].vertnbr = 0; + } + if (proccnttab != NULL) { /* If we are a receiver process, start filling count and adjustment arrays */ + int procrcvtmp; + + memSet (vertprmtab, ~0, (commmax + 1) * fldprocnbr * sizeof (int)); /* Reset adjustment index arrays */ + memSet (vertadjtab, ~0, commmax * grafptr->procglbnbr * sizeof (Gnum)); + + for (procrcvtmp = procrcvbas; procrcvtmp < procrcvnnd; procrcvtmp ++) { /* Fill count and adjustment arrays for receiver processes slots */ + vertadjtab[procrcvtmp * commmax] = grafptr->procvrttab[procrcvtmp]; + vertdlttab[procrcvtmp * commmax] = + proccnttab[procrcvtmp - procrcvbas] = grafptr->proccnttab[procrcvtmp]; + vertprmtab[(procrcvtmp - procrcvbas) * (commmax + 1)] = procrcvtmp * commmax; + } + } + + for (procrcvidx = procrcvbas; procrcvidx < (procrcvnnd - 1); procrcvidx ++, procrcvnnd --) { /* Overloaded receiver vertices will re-send some of their load */ + Gnum vertsndnbr; /* Potential overload of receiver process */ + + procsndidx = procrcvnnd - 1; + vertsndnbr = procsrttab[procsndidx].vertnbr - DATASIZE (grafptr->vertglbnbr, fldprocnbr, procsndidx - procrcvbas); + if (vertsndnbr <= 0) /* If no further overload to improve, exit loop */ + break; + + procrcvnum = procsrttab[procrcvidx].procnum; + procsndnum = procsrttab[procsndidx].procnum; + + procsrttab[procrcvidx].vertnbr = - (procsrttab[procrcvidx].vertnbr + vertsndnbr); /* Flag as having had a communication */ + if (proccnttab != NULL) { /* If we are a receiver process, fill count and adjustment arrays */ + proccnttab[procrcvnum - procrcvbas] += vertsndnbr; + proccnttab[procsndnum - procrcvbas] -= vertsndnbr; /* Vertices are transferred between receiver processes */ + vertadjtab[procsndnum * commmax + 1] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndnbr; + vertdlttab[procsndnum * commmax + 1] = vertsndnbr; + vertdlttab[procsndnum * commmax] -= vertsndnbr; + vertprmtab[(procrcvnum - procrcvbas) * (commmax + 1) + 1] = procsndnum * commmax + 1; + + if (procsndnum == grafptr->proclocnum) { /* If we are the sender receiver process */ + *commtypval = DGRAPHFOLDCOMMSEND | DGRAPHFOLDCOMMRECV; /* Indicate it */ + commdattab[0].procnum = procrcvnum; /* Record communication */ + commdattab[0].vertnbr = vertsndnbr; + commvrttab[0] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndnbr; /* Set starting global index of vertices to be sent */ + } + else if (procrcvnum == grafptr->proclocnum) { /* If we are the receiver receiver process */ + commdattab[0].procnum = procsndnum; /* Record communication */ + commdattab[0].vertnbr = vertsndnbr; + commvrttab[0] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndnbr; /* Set starting global index of vertices to be sent */ + } + } + } + + while ((procsndmnd < procsndbas) && (procsrttab[procsndmnd].vertnbr == 0)) /* Do not account for empty sender processes */ + procsndmnd ++; + + if (procsndmnd >= procsndbas) /* If there are no more sender processes */ + break; /* We have completed communication computation */ + + procsndidx = procsndbas - 1; + procsndnxt = procsndidx - 1; + vertsndrmn = procsrttab[procsndidx].vertnbr; + flagsndval = 0; + procrcvidx = procrcvbas; + procrcvnum = procsrttab[procrcvidx].procnum; + flagrcvval = 0; + vertglbavg = DATASIZE (grafptr->vertglbnbr, fldprocnbr, 0); + vertglbsum = procsrttab[procrcvidx].vertnbr; /* Account for vertices already present in receiver process */ + if (vertglbsum < 0) { /* If first receiver has already received a communication */ + flagrcvval = 1; + vertglbsum = - vertglbsum; + procsrttab[procrcvidx].vertnbr = vertglbsum; /* Un-flag */ + } + + while (1) { + Gnum vertrcvrmn; /* Remaining number of vertices to receive */ + Gnum vertsndnbr; /* Number of vertices actually sent and received */ + Gnum vertsndnxt; /* Adjustment to add to vertex count of next sender */ + int mesgrcvrmn; /* Number of message slots to receive small messages */ + int flagsndnxt; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (flagrcvval + flagsndval >= (commmax * 2)) { + errorPrint ("dgraphFoldComm: internal error (2)"); + memFree (commdattab); /* Free group leader */ + memFree (procsrttab); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + vertrcvrmn = (vertglbavg > vertglbsum) ? (vertglbavg - vertglbsum) : 0; /* Remaining space on receiver */ + mesgrcvrmn = (vertsndrmn >= vertrcvrmn) ? (commmax - 1) : (commmax - 2); + if ((procsndidx > procsndmnd) && /* If there remains small messages to be considered */ + (((flagsndval == 0) && /* If sender has not sent anything yet or just started */ + (flagrcvval < mesgrcvrmn)) || /* And receiver has space for larger messages to come */ + ((flagrcvval == 0) && /* Or if receiver has not received anything yet */ + (flagsndval < (commmax - 2)))) && /* And sender has enough slots to send */ + (vertrcvrmn >= procsrttab[procsndmnd].vertnbr)) { /* And if receiver can hold small message entirely */ + procsndnxt = procsndidx; /* Current large message will be processed next time */ + procsndidx = procsndmnd; /* Process smallest message available to date */ + flagsndnxt = flagsndval; /* Record location of next message to send */ + flagsndval = 0; + vertsndnxt = procsrttab[procsndnxt].vertnbr - vertsndrmn; /* Record vertices already sent */ + vertsndnbr = /* All of its contents will be sent in one piece */ + vertsndrmn = procsrttab[procsndmnd].vertnbr; + procsndmnd ++; /* Small message has been processed */ + } + else { + flagsndnxt = 0; + vertsndnxt = 0; /* Next sender will not have been interrupted by a small message */ + vertsndnbr = ((flagsndval >= (commmax - 1)) || /* If last chance to send for this process */ + (((procrcvnnd - procrcvidx) * (commmax - 1) - flagrcvval) <= (procsndidx - procsndmnd))) /* Or if too few communications remain with sender receivers accounted for */ + ? vertsndrmn /* Send all of the vertices to be sent */ + : MIN (vertsndrmn, vertrcvrmn); /* Else just send what the receiver needs */ + } + procsndnum = procsrttab[procsndidx].procnum; + + if (vertsndnbr > 0) { /* If useful communication can take place */ + if (proccnttab != NULL) { /* If we are a receiver process, fill count and adjustment arrays */ + proccnttab[procrcvnum - procrcvbas] += vertsndnbr; + vertadjtab[procsndnum * commmax + flagsndval] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndrmn; + vertdlttab[procsndnum * commmax + flagsndval] = vertsndnbr; + vertprmtab[(procrcvnum - procrcvbas) * (commmax + 1) + 1 + flagrcvval] = procsndnum * commmax + flagsndval; + + if (procrcvnum == grafptr->proclocnum) { /* If we are the receiver process */ + commdattab[flagrcvval].procnum = procsndnum; /* Record communication */ + commdattab[flagrcvval].vertnbr = vertsndnbr; + commvrttab[flagrcvval] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndrmn; /* Set starting global index of vertices to be sent */ + } + } + else if (procsndnum == grafptr->proclocnum) { /* If we are the sending process */ + commdattab[flagsndval].procnum = procrcvnum; /* Record communication */ + commdattab[flagsndval].vertnbr = vertsndnbr; + commvrttab[flagsndval] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndrmn; /* Set starting global index of vertices to be sent */ + } + vertglbsum += vertsndnbr; /* Account for vertices sent and received */ + vertsndrmn -= vertsndnbr; + flagsndval ++; + flagrcvval ++; + } + if (vertsndrmn <= 0) { /* If sending process has sent everything */ + procsndidx = procsndnxt; /* Process next vertex to send */ + if (procsndidx < procsndmnd) /* If was last sending process, end loop */ + break; + procsndnxt = procsndidx - 1; /* Prepare next sender process */ + flagsndval = flagsndnxt; /* Skip to next sending process */ + vertsndrmn = procsrttab[procsndidx].vertnbr - vertsndnxt; + } + if ((flagrcvval >= commmax) || /* If receiver cannot receive more */ + ((vertglbsum >= vertglbavg) && /* Or has received what it needed and is not forced to accept more */ + (((procrcvnnd - procrcvidx) * (commmax - 1) - flagrcvval) > (procsndidx - procsndmnd)))) { + if (++ procrcvidx >= procrcvnnd) /* If was last receiver, exit loop and go finalizing communication arrays */ + break; + + procrcvnum = procsrttab[procrcvidx].procnum; /* Skip to next receiver process */ + vertglbavg += DATASIZE (grafptr->vertglbnbr, fldprocnbr, procrcvidx - procrcvbas); + if (procsrttab[procrcvidx].vertnbr >= 0) { /* If receiver did not receive from a sender receiver */ + flagrcvval = 0; + vertglbsum += procsrttab[procrcvidx].vertnbr; /* Account for vertices already present in receiver process */ + } + else { /* Receiver already received from a sender receiver */ + flagrcvval = 1; /* Already a communication performed */ + vertglbsum -= procsrttab[procrcvidx].vertnbr; /* Use negative value */ + } + } + } + + if ((procsndidx <= procsndmnd) && (vertsndrmn <= 0)) /* If no sender vertex which has something to send remains */ + break; /* Exit the loop on increasing number of communications */ + } + +#ifdef SCOTCH_DEBUG_DGRAPH2 + chekloctab[0] = - commmax; + chekloctab[1] = commmax; + if (MPI_Allreduce (chekloctab, chekglbtab, 2, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphFoldComm: communication error"); + memFree (commdattab); /* Free group leader */ + return (1); + } + if ((chekglbtab[0] != chekloctab[0]) || + (chekglbtab[1] != chekloctab[1])) { + errorPrint ("dgraphFoldComm: internal error (3)"); + memFree (commdattab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (proccnttab != NULL) { /* If we are a receiver process */ + int vertadjnbr; /* Number of adjustment slots */ + Gnum vertadjsum; /* Current new starting position of current slot */ + + for (procnum = 0, vertadjsum = grafptr->baseval; procnum < ((commmax + 1) * fldprocnbr); procnum ++) { + int vertprmnum; + Gnum vertadjtmp; + + vertprmnum = vertprmtab[procnum]; + if (vertprmnum == ~0) /* Skip empty slots */ + continue; + + vertadjtmp = vertdlttab[vertprmnum]; /* Accumulate new slot indices and compute adjustments */ + vertdlttab[vertprmnum] = vertadjsum - vertadjtab[vertprmnum]; + vertadjsum += vertadjtmp; + } + + for (procnum = vertadjnbr = 0; procnum < (commmax * grafptr->procglbnbr); procnum ++) { /* Compact vertex adjustment arrays */ + if (vertadjtab[procnum] != -1) { + vertadjtab[vertadjnbr] = vertadjtab[procnum]; + vertdlttab[vertadjnbr] = vertdlttab[procnum]; + vertadjnbr ++; + } + } + vertadjtab[vertadjnbr] = grafptr->procvrttab[grafptr->procglbnbr]; /* Set upper bound on global vertex indices */ + + *vertadjnbrptr = vertadjnbr; + *vertadjptr = vertadjtab; + *vertdltptr = vertdlttab; + } + *commdatptr = commdattab; /* Set group leader */ + *commvrtptr = commvrttab; + *commptr = commmax; + + memFree (procsrttab); + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (proccnttab == NULL) { /* If we are a sender process */ + Gnum vertsndnbr; /* Number of vertices actually sent */ + int i; + + for (i = 0, vertsndnbr = 0; (i < commmax) && (commdattab[i].procnum >= 0); i ++) + vertsndnbr += commdattab[i].vertnbr; + if (vertsndnbr != grafptr->vertlocnbr) { + errorPrint ("dgraphFoldComm: internal error (4)"); + memFree (commdattab); /* Free group leader */ + return (1); + } + } + if (MPI_Allgather (commdattab, 2 * commmax, GNUM_MPI, + procchktab, 2 * commmax, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphFoldComm: communication error"); + memFree (commdattab); /* Free group leader */ + return (1); + } + + for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { + int commnum; + + for (commnum = 0; (commnum < commmax) && (procchktab[commmax * procnum + commnum].procnum != -1); commnum ++) { + Gnum procend; + Gnum vertnbr; + int commend; + + procend = procchktab[commmax * procnum + commnum].procnum; + vertnbr = procchktab[commmax * procnum + commnum].vertnbr; + + for (commend = 0; commend < commmax; commend ++) { + if ((procchktab[commmax * procend + commend].procnum == procnum) && + (procchktab[commmax * procend + commend].vertnbr == vertnbr)) + break; + } + if (commend >= commmax) { + errorPrint ("dgraphFoldComm: internal error (5)"); + memFree (commdattab); /* Free group leader */ + return (1); + } + } + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_fold_comm.h b/scotch_6.0.3/src/libscotch/dgraph_fold_comm.h new file mode 100644 index 00000000..e75749e0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_fold_comm.h @@ -0,0 +1,82 @@ +/* Copyright 2007,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_fold_comm.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed source graph **/ +/** building routines. **/ +/** **/ +/** # Version 5.0 : from : 23 may 2006 **/ +/** to 19 aug 2006 **/ +/** # Version 5.1 : from : 30 jul 2010 **/ +/** to 03 jan 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Starting maximum number of communications per process +*/ + +#define DGRAPHFOLDCOMMNBR 4 /* Starting maximum number of communications per process */ + +/* +** The type and structure definitions. +*/ + +/*+ Process communication type. Receivers that have + more local vertices than needed can also be + senders, hence the " = 1" to allow for or-ing + both values. +*/ + +typedef enum DgraphFoldCommType_ { + DGRAPHFOLDCOMMRECV = 1, /*+ Process is a receiver +*/ + DGRAPHFOLDCOMMSEND /*+ Process is a sender +*/ +} DgraphFoldCommType; + +/* Sort structure for processors. */ + +typedef struct DgraphFoldCommData_ { + Gnum vertnbr; /* Number of vertices; TRICK: FIRST */ + Gnum procnum; /* Processor index (Gnum for sorting) */ +} DgraphFoldCommData; + +/* +** The function prototypes. +*/ + +int dgraphFoldComm (const Dgraph * restrict const, const int, int * restrict const, int * restrict const, DgraphFoldCommData * restrict * restrict const, Gnum * restrict * restrict const, Gnum * restrict const, int * restrict const, Gnum * restrict * restrict const, Gnum * restrict * restrict const); diff --git a/scotch_6.0.3/src/libscotch/dgraph_fold_dup.c b/scotch_6.0.3/src/libscotch/dgraph_fold_dup.c new file mode 100644 index 00000000..307bfffb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_fold_dup.c @@ -0,0 +1,173 @@ +/* Copyright 2007-2009 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_fold_dup.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module folds a distributed graph **/ +/** into two distinct copies, which may **/ +/** be different when the number of **/ +/** processes is odd. **/ +/** **/ +/** DATES : # Version 5.0 : from : 10 aug 2006 **/ +/** to : 20 jun 2007 **/ +/** # Version 5.1 : from : 14 nov 2008 **/ +/** to : 28 oct 2009 **/ +/** # Version 6.0 : from : 28 sep 2014 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +#define DGRAPH +#define DGRAPH_FOLD_DUP + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_fold_dup.h" + +/******************************/ +/* */ +/* This routine handles */ +/* distributed source graphs. */ +/* */ +/******************************/ + +/* This routine builds two folded graphs of +** a given graph on each of the two halves +** of the processes. The number of processes +** does not need to be even. There is a +** multi-threaded version, as well as a +** sequential one. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +#ifdef SCOTCH_PTHREAD +static +void * +dgraphFoldDup2 ( +void * const dataptr) /* Pointer to thread data */ +{ + DgraphFoldDupData * fldthrdptr; + + fldthrdptr = (DgraphFoldDupData *) dataptr; + + return ((void *) (intptr_t) dgraphFold2 (fldthrdptr->orggrafptr, fldthrdptr->partval, fldthrdptr->fldgrafptr, + fldthrdptr->fldproccomm, fldthrdptr->orgdataptr, + fldthrdptr->flddataptr, fldthrdptr->datatype)); +} +#endif /* SCOTCH_PTHREAD */ + +int +dgraphFoldDup ( +const Dgraph * restrict const orggrafptr, +Dgraph * restrict const fldgrafptr, +void * restrict const orgdataptr, /* Un-based array of data which must be folded, e.g. coarmulttab */ +void ** restrict const flddataptr, /* Un-based array of data which must be folded, e.g. coarmulttab */ +MPI_Datatype datatype) +{ + int fldprocnbr; + int fldprocnum; + int fldproccol; + MPI_Comm fldproccommtab[2]; +#ifdef SCOTCH_PTHREAD + Dgraph orggrafdat; + DgraphFoldDupData fldthrdtab[2]; + pthread_t thrdval; /* Data of second thread */ +#endif /* SCOTCH_PTHREAD */ + int o; + + fldprocnbr = (orggrafptr->procglbnbr + 1) / 2; /* Median cut on number of processors */ + if (orggrafptr->proclocnum < fldprocnbr) { /* Compute color and rank in two subparts */ + fldproccol = 0; + fldprocnum = orggrafptr->proclocnum; + fldproccommtab[1] = MPI_COMM_NULL; + } + else { + fldproccol = 1; + fldprocnum = orggrafptr->proclocnum - fldprocnbr; + fldproccommtab[0] = MPI_COMM_NULL; + } + if (MPI_Comm_split (orggrafptr->proccomm, fldproccol, fldprocnum, &fldproccommtab[fldproccol]) != MPI_SUCCESS) { + errorPrint ("dgraphFoldDup: communication error (1)"); + return (1); + } + +#ifdef SCOTCH_PTHREAD + orggrafdat = *orggrafptr; /* Create a separate graph structure to change its communicator */ + + fldthrdtab[0].orggrafptr = orggrafptr; + fldthrdtab[0].fldgrafptr = fldgrafptr; + fldthrdtab[0].fldproccomm = fldproccommtab[0]; + fldthrdtab[0].partval = 0; + fldthrdtab[0].orgdataptr = orgdataptr; + fldthrdtab[0].flddataptr = flddataptr; + fldthrdtab[0].datatype = datatype; + fldthrdtab[1].orggrafptr = &orggrafdat; + fldthrdtab[1].fldgrafptr = fldgrafptr; + fldthrdtab[1].fldproccomm = fldproccommtab[1]; + fldthrdtab[1].partval = 1; + fldthrdtab[1].orgdataptr = orgdataptr; + fldthrdtab[1].flddataptr = flddataptr; + fldthrdtab[1].datatype = datatype; + + if (MPI_Comm_dup (orggrafptr->proccomm, &orggrafdat.proccomm) != MPI_SUCCESS) { /* Duplicate communicator to avoid interferences in communications */ + errorPrint ("dgraphFoldDup: communication error (2)"); + return (1); + } + + if (pthread_create (&thrdval, NULL, dgraphFoldDup2, (void *) &fldthrdtab[1]) != 0) /* If could not create thread */ + o = (int) (intptr_t) dgraphFold2 (orggrafptr, 0, fldgrafptr, fldproccommtab[0], orgdataptr, flddataptr, datatype) || /* Call routines in sequence */ + (int) (intptr_t) dgraphFold2 (orggrafptr, 1, fldgrafptr, fldproccommtab[1], orgdataptr, flddataptr, datatype); + else { /* Newly created thread is processing subgraph 1, so let's process subgraph 0 */ + void * o2; + + o = (int) (intptr_t) dgraphFoldDup2 ((void *) &fldthrdtab[0]); /* Work on copy with private communicator */ + + pthread_join (thrdval, &o2); + o |= (int) (intptr_t) o2; + } + MPI_Comm_free (&orggrafdat.proccomm); + +#else /* SCOTCH_PTHREAD */ + o = (dgraphFold2 (orggrafptr, 0, fldgrafptr, fldproccommtab[0], orgdataptr, flddataptr, datatype) || /* Call routines in sequence */ + dgraphFold2 (orggrafptr, 1, fldgrafptr, fldproccommtab[1], orgdataptr, flddataptr, datatype)); +#endif /* SCOTCH_PTHREAD */ + + fldgrafptr->prockeyval = fldproccol; /* Discriminate between folded communicators at same level */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_fold_dup.h b/scotch_6.0.3/src/libscotch/dgraph_fold_dup.h new file mode 100644 index 00000000..bc68a305 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_fold_dup.h @@ -0,0 +1,79 @@ +/* Copyright 2007,2010,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_fold_dup.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the distributed graph duplicate **/ +/** folding routine. **/ +/** **/ +/** DATES : # Version 5.0 : from : 13 aug 2006 **/ +/** to 13 aug 2006 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** # Version 6.0 : from : 28 sep 2014 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the data passed to the subgraph building threads. +*/ + +typedef struct DgraphFoldDupData_ { + const Dgraph * orggrafptr; /*+ Pointer to original graph +*/ + Dgraph * fldgrafptr; /*+ Pointer to folded graph +*/ + MPI_Comm fldproccomm; /*+ Communicator to be used in folded graph +*/ + int partval; /*+ Part of processes to which to fold +*/ + void * orgdataptr; /*+ Data associated to vertices, e.g. coarmulttab +*/ + void * flddataptr; /*+ Data associated to vertices, e.g. coarmulttab +*/ + MPI_Datatype datatype; /*+ MPI type of associated information +*/ +} DgraphFoldDupData; + +/* +** The function prototypes. +*/ + +#ifndef DGRAPH_FOLD_DUP +#define static +#endif + +#ifdef SCOTCH_PTHREAD +static void * dgraphFoldDup2 (void *); +#endif /* SCOTCH_PTHREAD */ + +#undef static diff --git a/scotch_6.0.3/src/libscotch/dgraph_gather.c b/scotch_6.0.3/src/libscotch/dgraph_gather.c new file mode 100644 index 00000000..dde54a7e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_gather.c @@ -0,0 +1,129 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_gather.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Francois CHATENET (0.0) **/ +/** Sebastien FOUCAULT (0.0) **/ +/** **/ +/** FUNCTION : This module contains the routine which **/ +/** builds a centralized graph by gathering **/ +/** the pieces of a distributed graph. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 apr 1997 **/ +/** to : 20 jun 1997 **/ +/** # Version 0.1 : from : 14 apr 1998 **/ +/** to : 20 jun 1998 **/ +/** # Version 0.2 : from : 20 may 1999 **/ +/** to : 20 may 1999 **/ +/** # Version 5.0 : from : 07 feb 2006 **/ +/** to : 16 jul 2007 **/ +/** **/ +/** NOTES : # The definitions of MPI_Gather and **/ +/** MPI_Gatherv indicate that elements in **/ +/** the receive array should not be **/ +/** written more than once. Great care **/ +/** should be taken to enforce this rule, **/ +/** especially when the number of **/ +/** vertices in the centralized graph is **/ +/** smaller than the number of **/ +/** processors. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_GATHER + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" + +/* This function gathers the pieces of +** a distributed graph to build a +** centralized graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +dgraphGather ( +const Dgraph * restrict const dgrfptr, /* Distributed graph */ +Graph * restrict cgrfptr) /* Centralized graph */ +{ + Gnum reduloctab[3]; + Gnum reduglbtab[3]; + + if (dgrfptr->edloloctax == NULL) /* Compute sum of edge loads */ + reduloctab[2] = dgrfptr->edgelocnbr; + else { + Gnum vertlocnum; + Gnum edlolocsum; + + for (vertlocnum = dgrfptr->baseval, edlolocsum = 0; + vertlocnum < dgrfptr->vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + Gnum edgelocnnd; + + for (edgelocnum = dgrfptr->vertloctax[vertlocnum], + edgelocnnd = dgrfptr->vendloctax[vertlocnum]; + edgelocnum < edgelocnnd; edgelocnum ++) + edlolocsum += dgrfptr->edloloctax[edgelocnum]; + } + reduloctab[2] = edlolocsum; + } + + if (cgrfptr != NULL) { /* If centralized graph provided */ + reduloctab[0] = 1; /* This process is the root */ + reduloctab[1] = (Gnum) dgrfptr->proclocnum; /* Get its number */ + } + else { + reduloctab[0] = /* This process is not the root */ + reduloctab[1] = 0; + } + if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_SUM, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGather: communication error"); + return (1); + } + if (reduglbtab[0] != 1) { + errorPrint ("dgraphGather: should have only one root"); + return (1); + } + + return (dgraphGatherAll2 (dgrfptr, cgrfptr, reduglbtab[2], (int) reduglbtab[1])); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_gather_all.c b/scotch_6.0.3/src/libscotch/dgraph_gather_all.c new file mode 100644 index 00000000..5830f63c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_gather_all.c @@ -0,0 +1,509 @@ +/* Copyright 2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_gather_all.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the routine which **/ +/** builds a centralized graph on all **/ +/** processes by gathering the pieces of **/ +/** a distributed graph. **/ +/** **/ +/** DATES : # Version 5.0 : from : 07 feb 2006 **/ +/** to 17 jun 2008 **/ +/** # Version 5.1 : from : 30 jul 2010 **/ +/** to 30 jul 2010 **/ +/** # Version 6.0 : from : 27 nov 2012 **/ +/** to 27 nov 2012 **/ +/** **/ +/** NOTES : # The definitions of MPI_Gather and **/ +/** MPI_Gatherv indicate that elements in **/ +/** the receive array should not be **/ +/** written more than once. Great care **/ +/** should be taken to enforce this rule, **/ +/** especially when the number of **/ +/** vertices in the centralized graph is **/ +/** smaller than the number of **/ +/** processes. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "graph.h" +#include "dgraph.h" + +/* This function gathers on all processes +** the pieces of a distributed graph to +** build a centralized graph. This function +** does not compute edlosum on the centralized +** graphs when it is already given in the passed +** value, as a non-negative number. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +static +int +dgraphGatherAll3 ( +Gnum * const senddattab, +const Gnum sendcntnbr, +Gnum * const recvdattab, +Gnum * const recvcnttab, +Gnum * const recvdsptab, +const int rootnum, +MPI_Comm comm) +{ + if (rootnum == -1) /* If collective communication wanted */ + return (commAllgatherv (senddattab, sendcntnbr, GNUM_MPI, recvdattab, recvcnttab, recvdsptab, GNUM_MPI, comm)); + else + return (commGatherv (senddattab, sendcntnbr, GNUM_MPI, recvdattab, recvcnttab, recvdsptab, GNUM_MPI, rootnum, comm)); +} + +int +dgraphGatherAll2 ( +const Dgraph * restrict const dgrfptr, /* Distributed graph */ +Graph * restrict cgrfptr, /* Centralized graph */ +const Gnum edlosum, /* -1 means recompute */ +const int protnum) /* -1 means allgather */ +{ + Gnum baseval; + Gnum * restrict verttax; /* Target vertex array for root, dummy for non-roots */ + Gnum * restrict velotax; /* Target vertex load array for root, dummy for non-roots */ + Gnum * restrict vnumtax; /* Target vertex index array for root, dummy for non-roots */ + Gnum * restrict vlbltax; /* Target vertex label array for root, dummy for non-roots */ + Gnum * restrict edgetax; /* Target edge array for root, dummy for non-roots */ + Gnum * restrict edlotax; /* Target edge load array for root, dummy for non-roots */ + Gnum vertlocnbr; /* Size of temporary distributed vertex array */ + Gnum * restrict vertloctax; /* Temporary vertex array if graph is not compact */ + Gnum edgelocnbr; /* Size of temporary distributed edge array */ + Gnum * restrict edgeloctab; /* Temporary edge array if distributed graph is not compact */ + Gnum * restrict recvcnttab; /* Count array for gather operations */ + Gnum * restrict recvdsptab; /* Displacement array for gather operations */ + int cheklocval; + int chekglbval; + + const Gnum * restrict const edgeloctax = dgrfptr->edgeloctax; + +#ifdef SCOTCH_DEBUG_DGRAPH1 + cheklocval = 0; + if (cgrfptr != NULL) /* Centralized graphs should be provided by all */ + cheklocval = 1; + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (1)"); + return (1); + } + if (protnum == -1) { /* If collective gathering wanted */ + if (chekglbval != dgrfptr->procglbnbr) { + errorPrint ("dgraphGatherAll2: centralized graphs should be provided on every process"); + return (1); + } + } + else { /* Single gathering wanted */ + if (chekglbval != 1) { + errorPrint ("dgraphGatherAll2: should have only one root"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + + baseval = dgrfptr->baseval; + + cheklocval = 0; + if (cgrfptr != NULL) { /* If root process */ + Gnum velonbr; + Gnum vnumnbr; + Gnum vlblnbr; + Gnum edlonbr; + + velonbr = (dgrfptr->veloloctax != NULL) ? dgrfptr->vertglbnbr : 0; + vnumnbr = (dgrfptr->vnumloctax != NULL) ? dgrfptr->vertglbnbr : 0; + vlblnbr = (dgrfptr->vlblloctax != NULL) ? dgrfptr->vertglbnbr : 0; + edlonbr = (dgrfptr->edloloctax != NULL) ? dgrfptr->edgeglbnbr : 0; + + if (memAllocGroup ((void **) (void *) + &cgrfptr->verttax, (size_t) ((dgrfptr->vertglbnbr + 1) * sizeof (Gnum)), + &cgrfptr->velotax, (size_t) (velonbr * sizeof (Gnum)), + &cgrfptr->vnumtax, (size_t) (vnumnbr * sizeof (Gnum)), + &cgrfptr->vlbltax, (size_t) (vlblnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphGatherAll2: out of memory (1)"); + cheklocval = 1; + } + else if (memAllocGroup ((void **) (void *) + &cgrfptr->edgetax, (size_t) (dgrfptr->edgeglbnbr * sizeof (Gnum)), + &cgrfptr->edlotax, (size_t) (edlonbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphGatherAll2: out of memory (2)"); + cheklocval = 1; + } + } + + if (dgrfptr->vendloctax == (dgrfptr->vertloctax + 1)) { /* If distributed graph is compact */ + vertlocnbr = /* No need to recompact arrays */ + edgelocnbr = 0; + } + else { /* Need extra space to compact vertex and edge arrays before sending */ + vertlocnbr = dgrfptr->vertlocnbr; + edgelocnbr = dgrfptr->edgelocnbr; + } + + if (cheklocval == 0) { + if (memAllocGroup ((void **) (void *) + &recvcnttab, (size_t) (dgrfptr->procglbnbr * sizeof (Gnum)), /* Allocated for non-roots too but don't care as these are very small */ + &recvdsptab, (size_t) (dgrfptr->procglbnbr * sizeof (Gnum)), + &vertloctax, (size_t) (vertlocnbr * sizeof (Gnum)), + &edgeloctab, (size_t) (edgelocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphGatherAll2: out of memory (3)"); + cheklocval = 1; + } + } +#ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (2)"); + return (1); + } +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (chekglbval != 0) { + if (recvcnttab != NULL) + memFree (recvcnttab); + if (cgrfptr->verttax != NULL) { + if (cgrfptr->edgetax != NULL) + memFree (cgrfptr->edgetax); /* Arrays are not based yet */ + memFree (cgrfptr->verttax); + } + return (1); + } + + if (cgrfptr != NULL) { + verttax = cgrfptr->verttax - baseval; + velotax = (dgrfptr->veloloctax != NULL) ? (cgrfptr->velotax - baseval) : NULL; + vnumtax = (dgrfptr->vnumloctax != NULL) ? (cgrfptr->vnumtax - baseval) : NULL; + vlbltax = (dgrfptr->vlblloctax != NULL) ? (cgrfptr->vlbltax - baseval) : NULL; + edgetax = cgrfptr->edgetax - baseval; + edlotax = (dgrfptr->edloloctax != NULL) ? (cgrfptr->edlotax - baseval) : NULL; + + cgrfptr->flagval = GRAPHFREEVERT | GRAPHVERTGROUP | GRAPHFREEEDGE | GRAPHEDGEGROUP; /* Other arrays are grouped, too */ + cgrfptr->baseval = baseval; + cgrfptr->vertnbr = dgrfptr->vertglbnbr; + cgrfptr->vertnnd = dgrfptr->vertglbnbr + baseval; + cgrfptr->verttax = verttax; + cgrfptr->vendtax = verttax + 1; /* Compact edge array */ + cgrfptr->velotax = velotax; + cgrfptr->velosum = dgrfptr->veloglbsum; + cgrfptr->vnumtax = vnumtax; + cgrfptr->vlbltax = vlbltax; + cgrfptr->edgenbr = dgrfptr->edgeglbnbr; + cgrfptr->edgetax = edgetax; + cgrfptr->edlotax = edlotax; + cgrfptr->edlosum = edlosum; + cgrfptr->degrmax = dgrfptr->degrglbmax; + cgrfptr->procptr = NULL; /* This field exists only when compiled with SCOTCH_PTSCOTCH */ + } +#ifdef SCOTCH_DEBUG_DGRAPH2 /* Prevent Valgrind from yelling */ + else { /* Process is not root */ + verttax = + velotax = + vlbltax = + edgetax = + edlotax = NULL; + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (dgrfptr->vendloctax == (dgrfptr->vertloctax + 1)) { /* If distributed graph is compact */ + if (dgraphGatherAll3 (dgrfptr->vertloctax + baseval + 1, dgrfptr->vertlocnbr, /* Do not send first index, it is always equal to baseval */ + verttax + 1, /* First index will always be equal to baseval too, and procdsptab holds based values */ + dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (3)"); + return (1); + } + + if (cgrfptr != NULL) { + Gnum procnum; + + verttax[baseval] = baseval; + for (procnum = 1; procnum < dgrfptr->procglbnbr; procnum ++) { /* Adjust index sub-arrays for all processes except the first one */ + Gnum vertnum; + Gnum vertnnd; + Gnum edgedlt; + + for (vertnum = dgrfptr->procdsptab[procnum] + 1, + vertnnd = dgrfptr->proccnttab[procnum] + vertnum, + edgedlt = verttax[vertnum - 1] - baseval; + vertnum < vertnnd; vertnum ++) + verttax[vertnum] += edgedlt; + } + } + } + else { /* Distributed graph is not compact */ + Gnum vertlocnum; + Gnum * restrict edgelocptr; + + vertloctax -= baseval; /* Base temporary vertex array */ + for (vertlocnum = baseval, edgelocptr = edgeloctab; /* Build vertex send array */ + vertlocnum < dgrfptr->vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + + vertloctax[vertlocnum] = dgrfptr->vendloctax[vertlocnum] - dgrfptr->vertloctax[vertlocnum]; /* Get edge counts */ + + for (edgelocnum = dgrfptr->vertloctax[vertlocnum]; edgelocnum < dgrfptr->vendloctax[vertlocnum]; edgelocnum ++) + *edgelocptr ++ = edgeloctax[edgelocnum]; + } + + if (dgraphGatherAll3 (vertloctax + baseval, dgrfptr->vertlocnbr, + verttax + 1, /* First index will always be equal to baseval, and procdsptab holds based values */ + dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (4)"); + return (1); + } + + if (cgrfptr != NULL) { + Gnum vertnum; + Gnum edgenum; + + verttax[baseval] = baseval; + for (vertnum = baseval + 1, edgenum = baseval; /* Create compact centralized vertex array */ + vertnum <= cgrfptr->vertnnd; vertnum ++) { + edgenum += verttax[vertnum]; + verttax[vertnum] = edgenum; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (verttax[cgrfptr->vertnnd] != (cgrfptr->edgenbr + baseval)) { + errorPrint ("dgraphGatherAll2: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + } + } + + if (dgrfptr->veloloctax != NULL) { + if (dgraphGatherAll3 (dgrfptr->veloloctax + baseval, dgrfptr->vertlocnbr, + velotax, /* Based array since procdsptab holds based values */ + dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (6)"); + return (1); + } + } + if (dgrfptr->vnumloctax != NULL) { + if (dgraphGatherAll3 (dgrfptr->vnumloctax + baseval, dgrfptr->vertlocnbr, + vnumtax, /* Based array since procdsptab holds based values */ + dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (5)"); + return (1); + } + } + if (dgrfptr->vlblloctax != NULL) { + if (dgraphGatherAll3 (dgrfptr->vlblloctax + baseval, dgrfptr->vertlocnbr, + vlbltax, /* Based array since procdsptab holds based values */ + dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (7)"); + return (1); + } + } + + if (cgrfptr != NULL) { + Gnum procnum; + Gnum edgenum; + + for (procnum = 0, edgenum = baseval; /* Build arrays for MPI_Gatherv on edge arrays */ + procnum < dgrfptr->procglbnbr; procnum ++) { + recvcnttab[procnum] = verttax[dgrfptr->procdsptab[procnum] + dgrfptr->proccnttab[procnum]] - + verttax[dgrfptr->procdsptab[procnum]]; /* verttax used twice since centralized graph is compact */ + recvdsptab[procnum] = edgenum; + edgenum += recvcnttab[procnum]; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((recvdsptab[dgrfptr->procglbnbr - 1] + recvcnttab[dgrfptr->procglbnbr - 1]) != (cgrfptr->edgenbr + baseval)) { + errorPrint ("dgraphGatherAll2: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + } + + if (dgrfptr->vendloctax == (dgrfptr->vertloctax + 1)) { /* If distributed graph is compact */ + if (dgraphGatherAll3 (dgrfptr->edgeloctax + baseval, dgrfptr->edgelocnbr, /* Send global indices */ + edgetax, /* Based array as recvdsptab holds based values */ + recvcnttab, recvdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (8)"); + return (1); + } + + if (dgrfptr->edloloctax != NULL) { + if (dgraphGatherAll3 (dgrfptr->edloloctax + baseval, dgrfptr->edgelocnbr, + edlotax, /* Based array as recvdsptab holds based values */ + recvcnttab, recvdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (9)"); + return (1); + } + } + } + else { /* Distributed graph is not compact */ + if (dgraphGatherAll3 (edgeloctab, dgrfptr->edgelocnbr, + edgetax, /* Based array as recvdsptab holds based values */ + recvcnttab, recvdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (10)"); + return (1); + } + + if (dgrfptr->edloloctax != NULL) { + Gnum vertlocnum; + Gnum * restrict edlolocptr; + + for (vertlocnum = baseval, edlolocptr = edgeloctab; /* Recycle edge send array to build edge load send array */ + vertlocnum < dgrfptr->vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + + for (edgelocnum = dgrfptr->vertloctax[vertlocnum]; edgelocnum < dgrfptr->vendloctax[vertlocnum]; edgelocnum ++) + *edlolocptr ++ = dgrfptr->edloloctax[edgelocnum]; + } + + if (dgraphGatherAll3 (edgeloctab, dgrfptr->edgelocnbr, /* Send compacted edge load array */ + edlotax, /* Based array as recvdsptab holds based values */ + recvcnttab, recvdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (11)"); + return (1); + } + } + } + + if (cgrfptr != NULL) { + if ((dgrfptr->procdsptab[dgrfptr->procglbnbr] != /* If graph has holes, relabel end vertices */ + dgrfptr->procvrttab[dgrfptr->procglbnbr])) { + Gnum procnum; + + for (procnum = 0; procnum < dgrfptr->procglbnbr; procnum ++) { /* Accelerate search per sender process */ + Gnum vertlocmin; + Gnum vertlocmax; + Gnum vertlocadj; + Gnum edgelocnum; + Gnum edgelocnnd; + + vertlocmin = dgrfptr->procvrttab[procnum]; /* Initialize search accelerator */ + vertlocmax = dgrfptr->procvrttab[procnum + 1]; + vertlocadj = dgrfptr->procdsptab[procnum] - vertlocmin; + + for (edgelocnum = recvdsptab[procnum], edgelocnnd = edgelocnum + recvcnttab[procnum]; + edgelocnum < edgelocnnd; edgelocnum ++) { + Gnum vertlocend; + + vertlocend = cgrfptr->edgetax[edgelocnum]; + + if ((vertlocend >= vertlocmin) && /* If end vertex is local with respect to current process */ + (vertlocend < vertlocmax)) + cgrfptr->edgetax[edgelocnum] = vertlocend + vertlocadj; + else { /* End vertex is not local */ + int procngbmin; + int procngbmax; + + for (procngbmin = 0, procngbmax = dgrfptr->procglbnbr; + procngbmax - procngbmin > 1; ) { + int procngbnum; + + procngbnum = (procngbmax + procngbmin) / 2; + if (dgrfptr->procvrttab[procngbnum] <= vertlocend) + procngbmin = procngbnum; + else + procngbmax = procngbnum; + } + cgrfptr->edgetax[edgelocnum] = vertlocend + dgrfptr->procdsptab[procngbmin] - dgrfptr->procvrttab[procngbmin]; + } + } + } + } + + if (cgrfptr->edlotax == NULL) /* If no edge loads */ + cgrfptr->edlosum = cgrfptr->edgenbr; /* Edge load sum is trivial */ + else { + if (edlosum >= 0) /* If edge load sum already computed by library call */ + cgrfptr->edlosum = edlosum; + else { /* Compute it from scratch on every root process (small graph assumed) */ + Gnum edgenum; + Gnum edgennd; + Gnum edlotmp; + + for (edgenum = cgrfptr->baseval, edgennd = edgenum + cgrfptr->edgenbr, edlotmp = 0; /* Edge load array is always compact */ + edgenum < edgennd; edgenum ++) + edlotmp += cgrfptr->edlotax[edgenum]; + + cgrfptr->edlosum = edlotmp; + } + } + } + + memFree (recvcnttab); + +#ifdef SCOTCH_DEBUG_DGRAPH2 + cheklocval = (cgrfptr != NULL) ? graphCheck (cgrfptr) : 0; + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphGatherAll2: communication error (12)"); + return (1); + } + if (chekglbval != 0) { + errorPrint ("dgraphGatherAll2: inconsistent centralized graph data"); + if (cgrfptr != NULL) + graphFree (cgrfptr); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (0); +} + +/* This function gathers on all processes +** the pieces of a distributed graph to +** build a centralized graph. +** Since the resulting centralized graphs are +** supposed to be small in the general case, +** edlosum is computed without communication +** on each of the processors. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +dgraphGatherAll ( +const Dgraph * restrict const dgrfptr, /* Distributed graph */ +Graph * restrict cgrfptr) /* Centralized graph */ +{ + return (dgraphGatherAll2 (dgrfptr, cgrfptr, -1, -1)); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_ghst.c b/scotch_6.0.3/src/libscotch/dgraph_ghst.c new file mode 100644 index 00000000..8bcb0638 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_ghst.c @@ -0,0 +1,314 @@ +/* Copyright 2007-2009,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_ghst.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Francois CHATENET (P0.0) **/ +/** Sebastien FOUCAULT (P0.0) **/ +/** Nicolas GICQUEL (P0.1) **/ +/** Jerome LACOSTE (P0.1) **/ +/** **/ +/** FUNCTION : Part of a parallel static mapper. **/ +/** This module contains the halo building **/ +/** routine. **/ +/** **/ +/** # Version P0.0 : from : 01 apr 1997 **/ +/** to 20 jun 1997 **/ +/** # Version P0.1 : from : 14 apr 1998 **/ +/** to 20 jun 1998 **/ +/** # Version 5.0 : from : 28 feb 2006 **/ +/** to 10 sep 2007 **/ +/** # Version 5.1 : from : 02 jul 2008 **/ +/** to 20 feb 2011 **/ +/** # Version 6.0 : from : 21 nov 2011 **/ +/** to 21 nov 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_GHST + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_allreduce.h" +#include "dgraph_ghst.h" +#include "dgraph_halo.h" + +/* This routine builds the ghost structures +** required by the halo routines. If flagval +** is set to 0, the ghost edge array is built +** in addition to the local edge array, while +** if flagval is set to 1, the ghost edge array +** replaces the local edge array. This latter +** option is useful to save memory when processing +** intermediate graphs that are not visible to +** the user. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +DGRAPHALLREDUCEMAXSUMOP (2, 1) + +int +dgraphGhst2 ( +Dgraph * restrict const grafptr, /* Graph structure */ +const int flagval) /* Replacement flag */ +{ + int procngbnbr; /* Number of neighboring processes */ + int * restrict procsndtab; + Gnum procsndnbr; + int * restrict procsidtab; /* Send index array */ + int procsidnbr; /* Number of entries in send index array */ + Gnum vertsidnum; /* Last vertex index in send index array */ + Gnum vertlocmin; /* Smallest index of local vertices */ + Gnum vertlocmax; /* Largest index of local vertices, + 1 */ + Gnum vertlocbas; /* Base index for ghost edge array */ + Gnum vertlocnum; /* Current vertex number (based) */ + Gnum * restrict vertsidtab; /* Flag array for building procs(i|n)dtab */ + Gnum vertgstnum; /* Number of current ghost vertex */ + DgraphGhstSort * restrict sortloctab; /* Array for sorting ghost vertices */ + Gnum sortlocnbr; /* Number of ghost edges in sort array */ + Gnum sortlocnum; + Gnum * edgegsttax; /* Pointer to ghost edge array, maybe the same */ + Gnum reduloctab[3]; /* Gnum to perform a maxsum operator */ + Gnum reduglbtab[3]; + int cheklocval; + + const Gnum * restrict const procvrttab = grafptr->procvrttab; + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + const Gnum * restrict const edgeloctax = grafptr->edgeloctax; /* Pointer to original edgeloctax array */ + + if ((grafptr->flagval & DGRAPHHASEDGEGST) != 0) /* If ghost edge array already computed, do nothing */ + return (0); + + cheklocval = 0; + if (grafptr->edgegsttax == NULL) { /* If ghost edge array not allocated yet */ + if ((flagval == 0) || ((grafptr->flagval & DGRAPHFREETABS) == 0)) { /* If no replacement or cannot modify array */ + if ((grafptr->edgegsttax = (Gnum *) memAlloc (grafptr->edgelocsiz * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphGhst: out of memory (1)"); + cheklocval = 1; + } + else { + grafptr->edgegsttax -= grafptr->baseval; + grafptr->flagval |= DGRAPHFREEEDGEGST; /* Free array on exit */ + } + } + else { /* Replace edgeloctab by edgegsttab */ + grafptr->edgegsttax = grafptr->edgeloctax; + grafptr->edgeloctax = NULL; + if ((grafptr->flagval & DGRAPHFREETABS) != 0) + grafptr->flagval |= DGRAPHFREEEDGEGST; /* It is edgegsttax which will free edloloctax if edge arrays are grouped */ + } + } + if ((cheklocval == 0) && + (memAllocGroup ((void **) (void *) + &procsidtab, (size_t) ((grafptr->edgelocnbr + grafptr->vertlocnbr) * sizeof (int)), + &vertsidtab, (size_t) (grafptr->procglbnbr * sizeof (Gnum)), + &sortloctab, (size_t) ((grafptr->edgelocnbr + 1) * sizeof (DgraphGhstSort)), NULL) == NULL)) { + errorPrint ("dgraphGhst: out of memory (2)"); + cheklocval = 1; + } + + reduloctab[0] = 1; /* Assume memory error and prepare data for aborting */ + reduloctab[1] = + reduloctab[2] = 0; + if (cheklocval != 0) { /* TRICK: Processes not on error will perform collective communication at end of routine */ + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) { + errorPrint ("dgraphGhst: communication error (1)"); + return (1); + } + } + + vertlocmin = procvrttab[grafptr->proclocnum]; + vertlocmax = procvrttab[grafptr->proclocnum + 1]; + vertlocbas = vertlocmin - grafptr->baseval; + memSet (grafptr->procrcvtab, 0, grafptr->procglbnbr * sizeof (int)); + memSet (grafptr->procsndtab, 0, grafptr->procglbnbr * sizeof (int)); + memSet (vertsidtab, ~0, grafptr->procglbnbr * sizeof (Gnum)); + + edgegsttax = grafptr->edgegsttax; + procsndtab = grafptr->procsndtab; + for (vertlocnum = vertsidnum = grafptr->baseval, sortlocnbr = 0, procsidnbr = 0; + vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + + for (edgelocnum = vertloctax[vertlocnum]; + edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { + Gnum vertlocend; + + vertlocend = edgeloctax[edgelocnum]; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocend < grafptr->baseval) || (vertlocend >= (procvrttab[grafptr->procglbnbr]))) { + errorPrint ("dgraphGhst: invalid edge array"); + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) + errorPrint ("dgraphGhst: communication error (2)"); + memFree (procsidtab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if ((vertlocend >= vertlocmin) && (vertlocend < vertlocmax)) /* If edge is local */ + edgegsttax[edgelocnum] = vertlocend - vertlocbas; /* Adjust its index */ + else { /* End vertex is not local */ + int procngbnum; + int procngbmax; + + sortloctab[sortlocnbr].vertglbnum = vertlocend; /* Add it to sort array */ + sortloctab[sortlocnbr].edgegstnum = edgelocnum; + sortlocnbr ++; + + for (procngbnum = 0, procngbmax = grafptr->procglbnbr; + procngbmax - procngbnum > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (procvrttab[procngbmed] <= vertlocend) + procngbnum = procngbmed; + else + procngbmax = procngbmed; + } + + if (vertsidtab[procngbnum] != vertlocnum) { /* If vertex not already sent to process */ + vertsidtab[procngbnum] = vertlocnum; /* Neighbor process will receive vertex */ + procsndtab[procngbnum] ++; /* One more vertex to send to this neighbor */ + + while ((vertlocnum - vertsidnum) >= DGRAPHGHSTSIDMAX) { /* If Gnum range too long for int */ + procsidtab[procsidnbr ++] = -DGRAPHGHSTSIDMAX; /* Decrease by maximum int distance */ + vertsidnum += DGRAPHGHSTSIDMAX; + } + if (vertsidnum != vertlocnum) { /* If communication concerns new local vertex */ + procsidtab[procsidnbr ++] = - (vertlocnum - vertsidnum); /* Encode jump in procsidtab */ + vertsidnum = vertlocnum; /* Current local vertex is last send vertex */ + } + procsidtab[procsidnbr ++] = procngbnum; /* Send this vertex data to this processor */ + } + } + } + } + + vertgstnum = grafptr->vertlocnnd; /* No ghost vertices yet */ + procngbnbr = 0; /* No neighbor processes yet */ + procsndnbr = 0; /* No vertex to send yet */ + + if (sortlocnbr > 0) { /* If there are ghost vertices */ + Gnum vertgstbas; /* Number of current ghost vertex */ + int procngbnum; + + intSort2asc1 (sortloctab, sortlocnbr); /* Sort them by ascending end vertex */ + + sortlocnum = 0; /* Start adjacency search from beginning */ + procngbnum = -1; /* Start neighbor search from begnning */ + do { /* For each distinct neighbor process */ + vertgstbas = vertgstnum; /* Record first ghost number used for it */ + edgegsttax[sortloctab[sortlocnum].edgegstnum] = vertgstnum; /* First ghost is always allocated */ + while (procvrttab[++ procngbnum + 1] <= sortloctab[sortlocnum].vertglbnum) { /* Find owner process */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((procngbnum > grafptr->procglbnbr) || /* If we have skipped a neighbor to which we have to send something */ + (procsndtab[procngbnum] != 0)) { + errorPrint ("dgraphGhst: internal error (1)"); + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) + errorPrint ("dgraphGhst: communication error (3)"); + memFree (procsidtab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (procsndtab[procngbnum] == 0) { /* If we had in fact no edges to send to this neighbor */ + errorPrint ("dgraphGhst: internal error (2)"); + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) + errorPrint ("dgraphGhst: communication error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + procsndnbr += procsndtab[procngbnum]; /* Sum-up vertices to send */ + grafptr->procngbtab[procngbnbr ++] = procngbnum; /* Add it to neighbor process array */ + while (++ sortlocnum < sortlocnbr) { /* For all following ghost edges */ + if (sortloctab[sortlocnum].vertglbnum != /* If new ghost vertex */ + sortloctab[sortlocnum - 1].vertglbnum) { + vertgstnum ++; /* Allocate new ghost vertex number */ + if (procvrttab[procngbnum + 1] <= sortloctab[sortlocnum].vertglbnum) { /* If new neighbor */ + grafptr->procrcvtab[procngbnum] = vertgstnum - vertgstbas; /* Sum-up data for old neighbor */ + break; /* Process new neighbor */ + } + } + edgegsttax[sortloctab[sortlocnum].edgegstnum] = vertgstnum; /* Allocate ghost */ + } + } while (sortlocnum < sortlocnbr); + vertgstnum ++; /* Size is one above last number */ + grafptr->procrcvtab[procngbnum] = vertgstnum - vertgstbas; /* Sum-up data for last neighbor */ + } + + grafptr->vertgstnbr = vertgstnum - grafptr->baseval; + grafptr->vertgstnnd = grafptr->vertgstnbr + grafptr->baseval; + grafptr->procngbnbr = procngbnbr; + grafptr->procsndnbr = procsndnbr; + + grafptr->procsidtab = memRealloc (procsidtab, procsidnbr * sizeof (int)); /* Reallocate send index array */ + grafptr->procsidnbr = procsidnbr; + + reduloctab[0] = 0; /* No memory error */ + reduloctab[1] = /* Set maximum number of neighbors */ + reduloctab[2] = grafptr->procngbnbr; + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) { + errorPrint ("dgraphGhst: communication error (5)"); + return (1); + } + if (reduglbtab[0] != 0) /* If error, propagated by some previous reduction operator */ + return (1); + + grafptr->procngbmax = reduglbtab[1]; + grafptr->flagval |= DGRAPHFREEPSID | DGRAPHHASEDGEGST; /* Graph now has a valid ghost edge array */ +#ifndef SCOTCH_COMM_COLL +#ifndef SCOTCH_COMM_PTOP + if (((float) reduglbtab[2]) <= ((float) grafptr->procglbnbr * (float) (grafptr->procglbnbr - 1) * (float) SCOTCH_COMM_PTOP_RAT)) +#endif /* SCOTCH_COMM_PTOP */ + grafptr->flagval |= DGRAPHCOMMPTOP; /* If too few communications, use point-to-point instead */ +#endif /* SCOTCH_COMM_COLL */ + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphHaloCheck (grafptr) != 0) { + errorPrint ("dgraphGhst: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_ghst.h b/scotch_6.0.3/src/libscotch/dgraph_ghst.h new file mode 100644 index 00000000..d9af268e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_ghst.h @@ -0,0 +1,72 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/**********************************************************/ +/* */ +/* NAME : dgraph_ghst.h */ +/* */ +/* AUTHOR : Francois PELLEGRINI */ +/* Francois CHATENET (P0.0) */ +/* Sebastien FOUCAULT (P0.0) */ +/* Nicolas GICQUEL (P0.1) */ +/* Jerome LACOSTE (P0.1) */ +/* */ +/* FUNCTION : Part of a parallel static mapper. */ +/* These lines are the data declarations */ +/* for the halo building routine. */ +/* */ +/* # Version P0.0 : from : 01 apr 1997 */ +/* to 20 jun 1997 */ +/* # Version P0.1 : from : 12 apr 1998 */ +/* to 20 jun 1998 */ +/* # Version 5.0 : from : 28 feb 2006 */ +/* to 31 dec 2006 */ +/* */ +/**********************************************************/ + +/* +** The defines. +*/ + +/* procsidtab-related values. */ + +#define DGRAPHGHSTSIDMAX ((int) ((unsigned int) (1 << (sizeof (int) * 8 - 1)) - 2U)) /* Maximum leap value for procsidtab entries */ + +/* +** The type and structure definitions. +*/ + +/* Sort structure for ghost edges. */ + +typedef struct DgraphGhstSort_ { + Gnum vertglbnum; /* Global end vertex number */ + Gnum edgegstnum; /* Number of ghost edge */ +} DgraphGhstSort; diff --git a/scotch_6.0.3/src/libscotch/dgraph_halo.c b/scotch_6.0.3/src/libscotch/dgraph_halo.c new file mode 100644 index 00000000..8f1af7b4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_halo.c @@ -0,0 +1,407 @@ +/* Copyright 2007-2009,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_halo.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Francois CHATENET (P0.0) **/ +/** Sebastien FOUCAULT (P0.0) **/ +/** Nicolas GICQUEL (P0.1) **/ +/** Jerome LACOSTE (P0.1) **/ +/** **/ +/** FUNCTION : Part of a parallel static mapper. **/ +/** This module contains the halo update **/ +/** routines. **/ +/** **/ +/** # Version P0.0 : from : 01 apr 1997 **/ +/** to 20 jun 1997 **/ +/** # Version P0.1 : from : 14 apr 1998 **/ +/** to 20 jun 1998 **/ +/** # Version 5.0 : from : 28 feb 2006 **/ +/** to 05 feb 2008 **/ +/** # Version 5.1 : from : 28 aug 2008 **/ +/** to 22 feb 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_HALO + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_halo.h" + +/* These routines fill the send arrays used by +** all of the halo routines. +** They return: +** - void : in all cases. +*/ + +#define DGRAPHHALOFILLNAME dgraphHaloFillGeneric +#define DGRAPHHALOFILLSIZE attrglbsiz +#define DGRAPHHALOFILLCOPY(d,s,n) memCpy ((d), (s), (n)) +#include "dgraph_halo_fill.c" +#undef DGRAPHHALOFILLNAME +#undef DGRAPHHALOFILLSIZE +#undef DGRAPHHALOFILLCOPY + +#define DGRAPHHALOFILLNAME dgraphHaloFillGnum +#define DGRAPHHALOFILLSIZE sizeof (Gnum) +#define DGRAPHHALOFILLCOPY(d,s,n) *((Gnum *) (d)) = *((Gnum *) (s)) +#include "dgraph_halo_fill.c" +#undef DGRAPHHALOFILLNAME +#undef DGRAPHHALOFILLSIZE +#undef DGRAPHHALOFILLCOPY + +#define DGRAPHHALOFILLNAME dgraphHaloFillGraphPart +#define DGRAPHHALOFILLSIZE sizeof (GraphPart) +#define DGRAPHHALOFILLCOPY(d,s,n) *((GraphPart *) (d)) = *((GraphPart *) (s)) +#include "dgraph_halo_fill.c" +#undef DGRAPHHALOFILLNAME +#undef DGRAPHHALOFILLSIZE +#undef DGRAPHHALOFILLCOPY + +#define DGRAPHHALOFILLNAME dgraphHaloFillInt /* In case Gnum is not int */ +#define DGRAPHHALOFILLSIZE sizeof (int) +#define DGRAPHHALOFILLCOPY(d,s,n) *((int *) (d)) = *((int *) (s)) +#include "dgraph_halo_fill.c" +#undef DGRAPHHALOFILLNAME +#undef DGRAPHHALOFILLSIZE +#undef DGRAPHHALOFILLCOPY + +static +void +dgraphHaloFill ( +const Dgraph * restrict const grafptr, +const void * restrict const attrgsttab, /* Attribute array to diffuse */ +int attrglbsiz, /* Type extent of attribute */ +byte * restrict const attrsndtab, /* Array for packing data to send */ +int * const senddsptab, /* Temporary displacement array */ +const int * restrict const sendcnttab) /* Count array */ +{ + int procnum; + byte ** attrdsptab; + + attrdsptab = (byte **) senddsptab; /* TRICK: use senddsptab (int *) as attrdsptab (byte **) */ + attrdsptab[0] = attrsndtab; /* Pre-set send arrays for send buffer filling routines */ + for (procnum = 1; procnum < grafptr->procglbnbr; procnum ++) + attrdsptab[procnum] = attrdsptab[procnum - 1] + sendcnttab[procnum - 1] * attrglbsiz; + + if (attrglbsiz == sizeof (Gnum)) + dgraphHaloFillGnum (grafptr, attrgsttab, attrglbsiz, attrdsptab); + else if (attrglbsiz == sizeof (GraphPart)) + dgraphHaloFillGraphPart (grafptr, attrgsttab, attrglbsiz, attrdsptab); + else if (attrglbsiz == sizeof (int)) /* In case Gnum is not int (suitable for float's too) */ + dgraphHaloFillInt (grafptr, attrgsttab, attrglbsiz, attrdsptab); + else /* Generic but slower fallback routine */ + dgraphHaloFillGeneric (grafptr, attrgsttab, attrglbsiz, attrdsptab); + + senddsptab[0] = 0; /* Pre-set send arrays for data sending routines */ + for (procnum = 1; procnum < grafptr->procglbnbr; procnum ++) + senddsptab[procnum] = senddsptab[procnum - 1] + sendcnttab[procnum - 1]; +} + +/* This function checks that the data of proc{snd,rcv}tab +** are consistent. +*/ + +#ifdef SCOTCH_DEBUG_DGRAPH2 +int +dgraphHaloCheck ( +const Dgraph * restrict const grafptr) +{ + int * proctab; /* Array to collect data */ + int procnum; + int o; + + if ((proctab = memAlloc (grafptr->procglbnbr * sizeof (int))) == NULL) { + errorPrint ("dgraphHaloCheck: out of memory"); + return (1); + } + + if (MPI_Alltoall (grafptr->procsndtab, 1, MPI_INT, proctab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphHaloCheck: communication error"); + memFree (proctab); /* Free group leader */ + return (1); + } + + o = 0; + for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { + if (proctab[procnum] != grafptr->procrcvtab[procnum]) { + errorPrint ("dgraphHaloCheck: data error"); + o = 1; + break; + } + } + + memFree (proctab); /* Free group leader */ + + return (o); +} +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + +/* These functions perform a synchronous collective +** halo diffusion operation on the ghost array given +** on input. +** It returns: +** - 0 : if the halo has been successfully propagated. +** - !0 : on error. +*/ + +static +int +dgraphHaloSync2 ( +Dgraph * restrict const grafptr, +void * restrict const attrgsttab, /* Attribute array to share */ +const MPI_Datatype attrglbtype, /* Attribute datatype */ +byte ** const attrsndptr, /* Pointer to array for packing data to send */ +int ** const senddspptr, /* Pointers to communication displacement arrays */ +int ** const recvdspptr, +MPI_Request ** const requptr) /* Pointer to local request array for point-to-point */ +{ + MPI_Aint attrglbsiz; /* Extent of attribute datatype */ + int procngbsiz; /* Size of request array for point-to-point communications */ + int procngbnum; + int * restrict recvdsptab; + const int * restrict procrcvtab; + + if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("dgraphHaloSync2: cannot compute ghost edge array"); + return (1); + } + + procngbsiz = ((grafptr->flagval & DGRAPHCOMMPTOP) != 0) ? grafptr->procngbnbr : 0; + + MPI_Type_extent (attrglbtype, &attrglbsiz); /* Get type extent */ + if (memAllocGroup ((void **) (void *) + attrsndptr, (size_t) (grafptr->procsndnbr * attrglbsiz), + senddspptr, (size_t) (grafptr->procglbnbr * MAX (sizeof (int), sizeof (byte *))), /* TRICK: use senddsptab (int *) as attrdsptab (byte **) */ + recvdspptr, (size_t) (grafptr->procglbnbr * sizeof (int)), + requptr, (size_t) (procngbsiz * 2 * sizeof (MPI_Request)), NULL) == NULL) { + errorPrint ("dgraphHaloSync2: out of memory"); + return (1); + } + + dgraphHaloFill (grafptr, attrgsttab, attrglbsiz, *attrsndptr, *senddspptr, grafptr->procsndtab); /* Fill data arrays */ + + recvdsptab = *recvdspptr; + procrcvtab = grafptr->procrcvtab; + recvdsptab[0] = grafptr->vertlocnbr; + for (procngbnum = 1; procngbnum < grafptr->procglbnbr; procngbnum ++) + recvdsptab[procngbnum] = recvdsptab[procngbnum - 1] + procrcvtab[procngbnum - 1]; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphHaloCheck (grafptr) != 0) { + errorPrint ("dgraphHaloSync2: invalid communication data"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (0); +} + +int +dgraphHaloSync ( +Dgraph * restrict const grafptr, +void * restrict const attrgsttab, /* Attribute array to share */ +const MPI_Datatype attrglbtype) /* Attribute datatype */ +{ + byte * attrsndtab; /* Array for packing data to send */ + int * senddsptab; + int * recvdsptab; + MPI_Request * requtab; + int o; + + if (dgraphHaloSync2 (grafptr, attrgsttab, attrglbtype, &attrsndtab, &senddsptab, &recvdsptab, &requtab) != 0) /* Prepare communication arrays */ + return (1); + + o = 0; /* Assume success */ + if ((grafptr->flagval & DGRAPHCOMMPTOP) != 0) { /* If point-to-point exchange */ + MPI_Aint attrglbsiz; /* Extent of attribute datatype */ + const int * restrict procrcvtab; + const int * restrict procsndtab; + const int * restrict procngbtab; + int procngbnbr; + int procngbnum; + MPI_Comm proccomm; + int requnbr; + + proccomm = grafptr->proccomm; + procngbtab = grafptr->procngbtab; + procngbnbr = grafptr->procngbnbr; + procrcvtab = grafptr->procrcvtab; + MPI_Type_extent (attrglbtype, &attrglbsiz); /* Get type extent */ + for (procngbnum = procngbnbr - 1, requnbr = 0; procngbnum >= 0; procngbnum --, requnbr ++) { /* Post receives first */ + int procglbnum; + + procglbnum = procngbtab[procngbnum]; + if (MPI_Irecv ((byte *) attrgsttab + recvdsptab[procglbnum] * attrglbsiz, procrcvtab[procglbnum], + attrglbtype, procglbnum, TAGHALO, proccomm, requtab + requnbr) != MPI_SUCCESS) { + errorPrint ("dgraphHaloSync: communication error (1)"); + o = 1; + break; + } + } + + procsndtab = grafptr->procsndtab; + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++, requnbr ++) { /* Post sends afterwards */ + int procglbnum; + + procglbnum = procngbtab[procngbnum]; + if (MPI_Isend (attrsndtab + senddsptab[procglbnum] * attrglbsiz, procsndtab[procglbnum], + attrglbtype, procglbnum, TAGHALO, proccomm, requtab + requnbr) != MPI_SUCCESS) { + errorPrint ("dgraphHaloSync: communication error (2)"); + o = 1; + break; + } + } + if (MPI_Waitall (requnbr, requtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { + errorPrint ("dgraphHaloSync: communication error (3)"); + o = 1; + } + } + else { /* Collective communication */ + if (MPI_Alltoallv (attrsndtab, grafptr->procsndtab, senddsptab, attrglbtype, /* Perform diffusion */ + attrgsttab, grafptr->procrcvtab, recvdsptab, attrglbtype, + grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphHaloSync: communication error (4)"); + o = 1; + } + } + + memFree (attrsndtab); /* Free group leader */ + + return (o); +} + +/* This function performs an asynchronous collective +** halo diffusion operation on the ghost array given +** on input. It fills the given request structure with +** the relevant data. +** It returns: +** - 0 : if the halo has been successfully propagated. +** - !0 : on error. +*/ + +#ifdef SCOTCH_PTHREAD +static +void * +dgraphHaloAsync2 ( +DgraphHaloRequest * restrict requptr) +{ + return ((void *) (intptr_t) dgraphHaloSync (requptr->grafptr, requptr->attrgsttab, requptr->attrglbtype)); +} +#endif /* SCOTCH_PTHREAD */ + +void +dgraphHaloAsync ( +Dgraph * restrict const grafptr, +void * restrict const attrgsttab, /* Attribute array to share */ +const MPI_Datatype attrglbtype, /* Attribute datatype */ +DgraphHaloRequest * restrict requptr) +{ +#ifndef SCOTCH_PTHREAD +#ifdef SCOTCH_MPI_ASYNC_COLL + int * senddsptab; + int * recvdsptab; +#endif /* SCOTCH_MPI_ASYNC_COLL */ +#endif /* SCOTCH_PTHREAD */ + +#ifdef SCOTCH_PTHREAD + requptr->flagval = -1; /* Assume thread will be successfully launched */ + requptr->grafptr = grafptr; + requptr->attrgsttab = attrgsttab; + requptr->attrglbtype = attrglbtype; + + if (pthread_create (&requptr->thrdval, NULL, (void * (*) (void *)) dgraphHaloAsync2, (void *) requptr) != 0) /* If could not create thread */ + requptr->flagval = (int) (intptr_t) dgraphHaloAsync2 (requptr); /* Call function synchronously */ +#else /* SCOTCH_PTHREAD */ +#ifdef SCOTCH_MPI_ASYNC_COLL + requptr->flagval = 1; /* Assume error */ + requptr->attrsndtab = NULL; /* No memory */ + + if (dgraphHaloSync2 (grafptr, attrgsttab, attrglbtype, &requptr->attrsndtab, &senddsptab, &recvdsptab) != 0) /* Prepare communication arrays */ + return; + + if (MPE_Ialltoallv (requptr->attrsndtab, grafptr->procsndtab, senddsptab, attrglbtype, /* Perform asynchronous collective communication */ + attrgsttab, grafptr->procrcvtab, recvdsptab, attrglbtype, + grafptr->proccomm, &requptr->requval) != MPI_SUCCESS) { + errorPrint ("dgraphHaloAsync: communication error"); /* Group leader will be freed on wait routine */ + return; + } + requptr->flagval = -1; /* Communication successfully launched */ +#else /* SCOTCH_MPI_ASYNC_COLL */ + requptr->flagval = dgraphHaloSync (grafptr, attrgsttab, attrglbtype); /* Last resort is synchronous communication */ +#endif /* SCOTCH_MPI_ASYNC_COLL */ +#endif /* SCOTCH_PTHREAD */ +} + +/* This function performs an asynchronous collective +** halo diffusion operation on the ghost array given +** on input. It fills the given request structure with +** the relevant data. +** It returns: +** - 0 : if the halo has been successfully propagated. +** - !0 : on error. +*/ + +int +dgraphHaloWait ( +DgraphHaloRequest * restrict requptr) +{ +#ifdef SCOTCH_PTHREAD + void * o; + + if (requptr->flagval == -1) { /* If thread launched */ + pthread_join (requptr->thrdval, &o); /* Wait for its completion */ + requptr->flagval = (int) (intptr_t) o; /* Get thread return value */ + } /* Else return value already known */ +#else /* SCOTCH_PTHREAD */ +#ifdef SCOTCH_MPI_ASYNC_COLL + MPI_Status statval; + + if (requptr->flagval == -1) { /* If communication launched */ + MPI_Wait (&requptr->requval, &statval); /* Wait for completion of asynchronous collective communication */ + requptr->flagval = (statval.MPI_ERROR == MPI_SUCCESS) ? 0 : 1; /* Set return value accordingly */ + } + if (requptr->attrsndtab != NULL) /* Free group leader if it was successfully allocated before */ + memFree (requptr->attrsndtab); +#endif /* SCOTCH_MPI_ASYNC_COLL */ +#endif /* SCOTCH_PTHREAD */ + + return (requptr->flagval); /* Return asynchronous or synchronous error code */ +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_halo.h b/scotch_6.0.3/src/libscotch/dgraph_halo.h new file mode 100644 index 00000000..dab001ef --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_halo.h @@ -0,0 +1,94 @@ +/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_halo.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the asynchronous halo **/ +/** exchange routine. **/ +/** **/ +/** DATES : # Version 5.0 : from : 28 dec 2007 **/ +/** to : 05 feb 2008 **/ +/** # Version 5.1 : from : 28 aug 2008 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/* procsidtab-related values. */ + +#define DGRAPHGHSTSIDMAX ((int) ((unsigned int) (1 << (sizeof (int) * 8 - 1)) - 2U)) /* Maximum leap value for procsidtab entries */ + +/* +** The type and structure definitions. +*/ + +/* Sort structure for ghost edges. */ + +typedef struct DgraphHaloRequest_ { + int flagval; +#ifdef SCOTCH_PTHREAD + Dgraph * grafptr; /* Pointer to graph data */ + void * attrgsttab; /* Attribute array to share */ + MPI_Datatype attrglbtype; /* Attribute datatype */ + pthread_t thrdval; /* Data of asynchronous thread */ +#else /* SCOTCH_PTHREAD */ +#ifdef SCOTCH_MPI_ASYNC_COLL + byte * attrsndtab; /* Group leader for memory freeing */ + MPI_Request requval; /* MPI asynchronous communication request */ +#endif /* SCOTCH_MPI_ASYNC_COLL */ +#endif /* SCOTCH_PTHREAD */ +} DgraphHaloRequest; + +/* +** The function prototypes. +*/ + +#ifndef DGRAPH_HALO +#define static +#endif + +#ifdef SCOTCH_PTHREAD +static void * dgraphHaloAsync2 (DgraphHaloRequest * restrict); +#endif /* SCOTCH_PTHREAD */ +void dgraphHaloAsync (Dgraph * restrict const, void * restrict const, const MPI_Datatype, DgraphHaloRequest * restrict); +int dgraphHaloWait (DgraphHaloRequest * restrict); + +int dgraphHaloCheck (const Dgraph * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/dgraph_halo_fill.c b/scotch_6.0.3/src/libscotch/dgraph_halo_fill.c new file mode 100644 index 00000000..70e34303 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_halo_fill.c @@ -0,0 +1,82 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_halo_fill.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel static mapper. **/ +/** This module contains the halo update **/ +/** routines. **/ +/** **/ +/** # Version 5.0 : from : 31 dec 2006 **/ +/** to 05 feb 2008 **/ +/** # Version 5.1 : from : 28 aug 2008 **/ +/** to 29 aug 2010 **/ +/** **/ +/************************************************************/ + +/* This function fills the send array used by +** all of the halo routines. +** It returns: +** - void : in all cases. +*/ + +static +void +DGRAPHHALOFILLNAME ( +const Dgraph * restrict const grafptr, +const void * restrict const attrgsttab, /* Attribute array to diffuse */ +const int attrglbsiz, /* Type extent of attribute */ +byte ** restrict const attrdsptab) /* Temporary address displacement array */ +{ + byte * restrict attrgstptr; + const int * restrict procsidptr; + const int * restrict procsidnnd; + + for (procsidptr = grafptr->procsidtab, procsidnnd = procsidptr + grafptr->procsidnbr, attrgstptr = (byte *) attrgsttab; + procsidptr < procsidnnd; procsidptr ++) { + int procsidval; + + procsidval = *procsidptr; + if (procsidval < 0) + attrgstptr -= ((Gnum) procsidval) * DGRAPHHALOFILLSIZE; + else { + byte * attrdspptr; + + attrdspptr = attrdsptab[procsidval]; + attrdsptab[procsidval] = attrdspptr + DGRAPHHALOFILLSIZE; /* Skip to next position in send buffer */ + DGRAPHHALOFILLCOPY (attrdspptr, attrgstptr, DGRAPHHALOFILLSIZE); + } + } +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_induce.c b/scotch_6.0.3/src/libscotch/dgraph_induce.c new file mode 100644 index 00000000..21151825 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_induce.c @@ -0,0 +1,425 @@ +/* Copyright 2007-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_induce.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the source graph **/ +/** subgraph-making functions. **/ +/** **/ +/** DATES : # Version 5.0 : from : 08 apr 2006 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 31 mar 2008 **/ +/** to : 30 jul 2010 **/ +/** # Version 6.0 : from : 29 aug 2012 **/ +/** to : 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH +#define DGRAPH_INDUCE + +#include "module.h" +#include "common.h" +#include "dgraph.h" + +/****************************************/ +/* */ +/* These routines handle source graphs. */ +/* */ +/****************************************/ + +int +dgraphInduce2 ( +Dgraph * restrict const orggrafptr, +Gnum (* orgfuncptr) (Dgraph * restrict const, Dgraph * restrict const, const void * restrict const, Gnum * restrict const), +const void * const orgdataptr, /* Pointer to routine-specific data */ +const Gnum indvertlocnbr, /* Number of vertices in induced subgraph */ +Gnum * indvnumloctmp, /* Pointer to temporary index array; TRICK: [alias] */ +Dgraph * restrict const indgrafptr) +{ + Gnum * restrict orgindxgsttax; /* Based access to vertex translation array */ + Gnum indvertlocnnd; /* Based index of end of local vertex array */ + Gnum indvertlocnum; /* Number of current vertex in induced graph */ + Gnum indvertglbnum; /* Number of current vertex in global ordering */ + Gnum indvelolocnbr; /* Size of local vertex load array */ + Gnum indvelolocsum; /* Sum of vertex loads */ + Gnum * indvnumloctax; /* TRICK: maybe alias of indvnumloctmp */ + Gnum indvlbllocnbr; /* Size of local vertex label array */ + Gnum indedgelocmax; /* (Approximate) number of edges in induced graph */ + Gnum indedgelocnbr; /* Real number of edges in induced graph */ + Gnum indedgelocnum; + Gnum * restrict indedloloctax; + Gnum inddegrlocmax; /* Local maximum degree */ + const Gnum * restrict indlisttax; + Gnum baseval; + int cheklocval; + int chekglbval; + + const Gnum * restrict const orgvertloctax = orggrafptr->vertloctax; + const Gnum * restrict const orgvendloctax = orggrafptr->vendloctax; + const Gnum * restrict const orgvnumloctax = orggrafptr->vnumloctax; + const Gnum * restrict const orgvlblloctax = orggrafptr->vlblloctax; + const Gnum * restrict const orgveloloctax = orggrafptr->veloloctax; + const Gnum * restrict const orgedloloctax = orggrafptr->edloloctax; + + if (dgraphGhst (orggrafptr) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("dgraphInduce2: cannot compute ghost edge array"); + return (1); + } + + baseval = orggrafptr->baseval; + indgrafptr->flagval |= (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; + indgrafptr->baseval = baseval; + indgrafptr->vertlocnbr = indvertlocnbr; /* Must be set before orgfuncptr() is called */ + indgrafptr->vertlocnnd = indvertlocnbr + baseval; + + if (orgveloloctax != NULL) { + indvelolocnbr = indvertlocnbr; + indvelolocsum = 0; + } + else { + indvelolocnbr = 0; + indvelolocsum = indvertlocnbr; + } + indvlbllocnbr = (orgvlblloctax != NULL) ? indvertlocnbr : 0; + indedgelocmax = orggrafptr->edgelocnbr; /* Choose best upper bound on number of edges (avoid multiply overflow) */ + if ((orggrafptr->degrglbmax > 0) && (indvertlocnbr < (indedgelocmax / orggrafptr->degrglbmax))) + indedgelocmax = indvertlocnbr * orggrafptr->degrglbmax; + if (orggrafptr->edloloctax != NULL) /* If graph has edge weights */ + indedgelocmax *= 2; /* Account for edge weights */ + + cheklocval = + chekglbval = 0; + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ + &indgrafptr->procdsptab, (size_t) ((orggrafptr->procglbnbr + 1) * sizeof (Gnum)), + &indgrafptr->proccnttab, (size_t) (orggrafptr->procglbnbr * sizeof (Gnum)), + &indgrafptr->procngbtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), + &indgrafptr->procrcvtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), + &indgrafptr->procsndtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("dgraphInduce2: out of memory (1)"); + cheklocval = 1; + } + else if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ + &indgrafptr->vertloctax, (size_t) ((indvertlocnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ + &indgrafptr->vnumloctax, (size_t) (indvertlocnbr * sizeof (Gnum)), + &indgrafptr->veloloctax, (size_t) (indvelolocnbr * sizeof (Gnum)), + &indgrafptr->vlblloctax, (size_t) (indvlbllocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphInduce2: out of memory (2)"); + cheklocval = 1; + } + else if (indgrafptr->vertloctax -= baseval, + indgrafptr->vnumloctax -= baseval, + indgrafptr->veloloctax = (orgveloloctax != NULL) ? indgrafptr->veloloctax - baseval : NULL, + indgrafptr->vlblloctax = indgrafptr->vlblloctax - baseval, /* If no vertex labels, vlblloctax will point to vnumloctax afterward */ + memAllocGroup ((void **) (void *) + &indgrafptr->edgeloctax, (size_t) (indedgelocmax * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab) */ + &orgindxgsttax, (size_t) (orggrafptr->vertgstnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxgsttab is at the end */ + errorPrint ("dgraphInduce2: out of memory (3)"); + cheklocval = 1; + } + else + indgrafptr->edgeloctax -= baseval; + + if (cheklocval != 0) { /* In case of memory error */ + Gnum procngbnum; + Gnum dummyval; + + dummyval = -1; + chekglbval = 1; + if (MPI_Allgather (&dummyval, 1, GNUM_MPI, /* Use proccnttab of orggraf as dummy receive array (will be regenerated) */ + orggrafptr->proccnttab, 1, GNUM_MPI, indgrafptr->proccomm) != MPI_SUCCESS) + errorPrint ("dgraphInduce2: communication error (1)"); + + for (procngbnum = 1; procngbnum <= orggrafptr->procglbnbr; procngbnum ++) /* Rebuild proccnttab of orggraf */ + orggrafptr->proccnttab[procngbnum - 1] = orggrafptr->procdsptab[procngbnum] - orggrafptr->procdsptab[procngbnum - 1]; + } + else { + indgrafptr->procdsptab[0] = indvertlocnbr; + if (MPI_Allgather (&indgrafptr->procdsptab[0], 1, GNUM_MPI, + &indgrafptr->proccnttab[0], 1, GNUM_MPI, indgrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphInduce2: communication error (2)"); + chekglbval = 1; + } + else { + Gnum procngbnum; + + indgrafptr->procdsptab[0] = baseval; /* Build vertex-to-process array */ + for (procngbnum = 0; procngbnum < indgrafptr->procglbnbr; procngbnum ++) { /* Process potential error flags from other processes */ + if (indgrafptr->procdsptab[procngbnum] < 0) { /* If error notified by another process */ + chekglbval = 1; + break; + } + indgrafptr->procdsptab[procngbnum + 1] = indgrafptr->procdsptab[procngbnum] + indgrafptr->proccnttab[procngbnum]; + } + } + indgrafptr->procvrttab = indgrafptr->procdsptab; /* Graph does not have holes */ + } + if (chekglbval != 0) { /* If something went wrong in all of the above */ + dgraphFree (indgrafptr); + return (1); + } + + memSet (orgindxgsttax, ~0, orggrafptr->vertlocnbr * sizeof (Gnum)); /* Preset index array */ + orgindxgsttax -= baseval; + + indedgelocmax = orgfuncptr (indgrafptr, orggrafptr, orgdataptr, orgindxgsttax); /* Call flagging subroutine */ + + if (dgraphHaloSync (orggrafptr, (byte *) (orgindxgsttax + baseval), GNUM_MPI) != 0) { /* Share global indexing of subgraph vertices */ + errorPrint ("dgraphInduce2: cannot perform halo exchange"); + dgraphFree (indgrafptr); + return (1); + } + + if (indvnumloctmp == NULL) /* indgrafptr->vnumloctax did not exist when function was called */ + indvnumloctmp = indgrafptr->vnumloctax; + + indedloloctax = (orggrafptr->edloloctax != NULL) ? indgrafptr->edgeloctax + indedgelocmax : NULL; + inddegrlocmax = 0; + for (indvertlocnum = indedgelocnum = baseval, indvertlocnnd = indvertlocnbr + baseval; + indvertlocnum < indvertlocnnd; indvertlocnum ++) { + Gnum orgvertlocnum; + Gnum orgedgelocnum; + + orgvertlocnum = indvnumloctmp[indvertlocnum]; + indgrafptr->vertloctax[indvertlocnum] = indedgelocnum; + if (orgveloloctax != NULL) { /* If graph has vertex weights */ + indvelolocsum += /* Accumulate vertex loads */ + indgrafptr->veloloctax[indvertlocnum] = orgveloloctax[orgvertlocnum]; + } + if (orgvlblloctax != NULL) /* If graph has vertex labels */ + indgrafptr->vlblloctax[indvertlocnum] = orgvlblloctax[orgvertlocnum]; + + for (orgedgelocnum = orgvertloctax[orgvertlocnum]; + orgedgelocnum < orgvendloctax[orgvertlocnum]; orgedgelocnum ++) { + Gnum indvertgstend; + + indvertgstend = orgindxgsttax[orggrafptr->edgegsttax[orgedgelocnum]]; + if (indvertgstend != ~0) { /* If edge should be kept */ + indgrafptr->edgeloctax[indedgelocnum] = indvertgstend; + if (indedloloctax != NULL) + indedloloctax[indedgelocnum] = orgedloloctax[orgedgelocnum]; + indedgelocnum ++; + } + } + if (inddegrlocmax < (indedgelocnum - indgrafptr->vertloctax[indvertlocnum])) + inddegrlocmax = (indedgelocnum - indgrafptr->vertloctax[indvertlocnum]); + } + indedgelocnbr = indedgelocnum - baseval; + indgrafptr->vertloctax[indvertlocnum] = indedgelocnum; /* Mark end of edge array */ + indgrafptr->vendloctax = indgrafptr->vertloctax + 1; /* Induced graph is compact */ + indgrafptr->velolocsum = indvelolocsum; + indgrafptr->edgelocnbr = indedgelocnbr; + indgrafptr->edgelocsiz = indedgelocnbr; + if (orgvlblloctax == NULL) /* If we didn't have vertex labels, use vertex index array as vertex label array */ + indgrafptr->vlblloctax = indgrafptr->vnumloctax; + + if (indedloloctax != NULL) { /* Re-allocate arrays and delete orgindxtab */ + size_t indedlooftval; /* Offset of edge load array with respect to edge array */ + + indedlooftval = indedloloctax - indgrafptr->edgeloctax; + indgrafptr->edgeloctax = memRealloc (indgrafptr->edgeloctax + baseval, (indedlooftval + indedgelocnbr) * sizeof (Gnum)); + indgrafptr->edgeloctax -= baseval; + indedloloctax = indgrafptr->edgeloctax + indedlooftval; /* Use old index into old array as new index to avoid alignment problems */ + } + else { + indgrafptr->edgeloctax = memRealloc (indgrafptr->edgeloctax + baseval, indedgelocnbr * sizeof (Gnum)); + indgrafptr->edgeloctax -= baseval; + } + + indvertlocnum = baseval; + indvnumloctax = indgrafptr->vnumloctax; /* TRICK: maybe alias */ + if (orgvnumloctax != NULL) { /* Adjust vnumloctax */ + for ( ; indvertlocnum < indvertlocnnd; indvertlocnum ++) + indvnumloctax[indvertlocnum] = orgvnumloctax[indvnumloctmp[indvertlocnum]]; /* TRICK: indvnumloctmp and indgrafptr->vnumloctax may be aliases */ + } + else { + Gnum orgvertglbadj; + + orgvertglbadj = orggrafptr->procvrttab[orggrafptr->proclocnum] - baseval; /* Set adjustement for global indexing */ + for ( ; indvertlocnum < indvertlocnnd; indvertlocnum ++) + indvnumloctax[indvertlocnum] = indvnumloctmp[indvertlocnum] + orgvertglbadj; /* TRICK: indvnumloctmp and indgrafptr->vnumloctax may be aliases */ + } + + indgrafptr->edloloctax = indedloloctax; + indgrafptr->degrglbmax = inddegrlocmax; /* Local maximum degree will be turned into global maximum degree */ + if (dgraphBuild4 (indgrafptr) != 0) { + errorPrint ("dgraphInduce2: cannot build induced graph"); + return (1); + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphCheck (indgrafptr) != 0) { /* Check graph consistency */ + errorPrint ("dgraphInduce2: inconsistent graph data"); + dgraphFree (indgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (0); +} + +/* This routine builds the graph induced +** by the original graph and the list of +** selected vertices. +** The induced vnumtab array is the global +** translation of the list array if the +** original graph does not have a vnumtab, +** or the proper subset of the original +** vnumtab else. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +Gnum +dgraphInduceList2 ( +Dgraph * restrict const indgrafptr, +Dgraph * restrict const orggrafptr, +const void * restrict const orgdataptr, /* Data pointer is list array pointer */ +Gnum * restrict const orgindxgsttax) +{ + Gnum orglistnbr; + Gnum orglistnum; + Gnum indvertglbnum; + Gnum indedgelocmax; + + const Gnum * restrict const orgvertloctax = orggrafptr->vertloctax; + const Gnum * restrict const orgvendloctax = orggrafptr->vendloctax; + const Gnum * restrict const orglisttab = (const Gnum * restrict) orgdataptr; + + for (orglistnum = 0, indvertglbnum = indgrafptr->procvrttab[indgrafptr->proclocnum], /* Fill index array while recomputing tighter upper bound on arcs */ + orglistnbr = indgrafptr->vertlocnbr, indedgelocmax = 0; + orglistnum < orglistnbr; orglistnum ++, indvertglbnum ++) { + Gnum orgvertlocnum; + + orgvertlocnum = orglisttab[orglistnum]; + orgindxgsttax[orgvertlocnum] = indvertglbnum; /* Mark selected vertices */ + indedgelocmax += orgvendloctax[orgvertlocnum] - orgvertloctax[orgvertlocnum]; + } + + return (indedgelocmax); +} + +int +dgraphInduceList ( +Dgraph * restrict const orggrafptr, +const Gnum orglistnbr, +const Gnum * const orglisttab, /* Local list of kept vertices */ +Dgraph * restrict const indgrafptr) +{ + return (dgraphInduce2 (orggrafptr, dgraphInduceList2, (const void * const) orglisttab, orglistnbr, (Gnum * const) (orglisttab - orggrafptr->baseval), indgrafptr)); +} + +/* This routine builds the graph induced +** by the original graph and the vector of +** selected vertices. +** The induced vnumtab array is the global +** translation of the list array if the +** original graph does not have a vnumtab, +** or the proper subset of the original +** vnumtab else. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +typedef struct DgraphInducePartData_ { + const GraphPart * orgpartloctax; + GraphPart indpartval; +} DgraphInducePartData; + +static +Gnum +dgraphInducePart2 ( +Dgraph * restrict const indgrafptr, +Dgraph * restrict const orggrafptr, +const void * restrict const orgdataptr, +Gnum * restrict const orgindxgsttax) +{ + Gnum orgvertlocnnd; + Gnum orgvertlocnum; + Gnum indvertlocnum; + Gnum indvertglbnum; + Gnum indedgelocmax; + + const Gnum * restrict const orgvertloctax = orggrafptr->vertloctax; + const Gnum * restrict const orgvendloctax = orggrafptr->vendloctax; + const GraphPart * restrict const orgpartloctax = ((const DgraphInducePartData * restrict const) orgdataptr)->orgpartloctax; + const GraphPart indpartval = ((const DgraphInducePartData * restrict const) orgdataptr)->indpartval; + Gnum * restrict const indvnumloctax = indgrafptr->vnumloctax; + + for (orgvertlocnum = indvertlocnum = orggrafptr->baseval, indvertglbnum = indgrafptr->procvrttab[indgrafptr->proclocnum], /* Fill index array while recomputing tighter upper bound on arcs */ + orgvertlocnnd = orggrafptr->vertlocnnd, indedgelocmax = 0; + orgvertlocnum < orgvertlocnnd; orgvertlocnum ++) { + if (orgpartloctax[orgvertlocnum] == indpartval) { + orgindxgsttax[orgvertlocnum] = indvertglbnum; /* Mark selected vertices */ + indvnumloctax[indvertlocnum] = orgvertlocnum; + indedgelocmax += orgvendloctax[orgvertlocnum] - orgvertloctax[orgvertlocnum]; + indvertlocnum ++, indvertglbnum ++; + } + else + orgindxgsttax[orgvertlocnum] = ~0; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((indvertlocnum - orggrafptr->baseval) != indgrafptr->vertlocnbr) { + errorPrint ("dgraphInducePart2: inconsistent data"); + dgraphFree (indgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (indedgelocmax); +} + +int +dgraphInducePart ( +Dgraph * restrict const orggrafptr, /* Pointer to original distributed graph */ +const GraphPart * restrict const orgpartloctax, /* Based array of local vertex partition flags */ +const Gnum indvertlocnbr, /* Number of local vertices in selected part */ +const GraphPart indpartval, +Dgraph * restrict const indgrafptr) +{ + DgraphInducePartData orgdatadat; + + orgdatadat.orgpartloctax = orgpartloctax; + orgdatadat.indpartval = indpartval; + + return (dgraphInduce2 (orggrafptr, dgraphInducePart2, &orgdatadat, indvertlocnbr, NULL, indgrafptr)); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_io_load.c b/scotch_6.0.3/src/libscotch/dgraph_io_load.c new file mode 100644 index 00000000..60143c7f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_io_load.c @@ -0,0 +1,907 @@ +/* Copyright 2007-2009,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_io_load.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the input/output routines for **/ +/** distributed graphs. **/ +/** **/ +/** # Version 5.0 : from : 28 apr 2007 **/ +/** to : 24 mar 2008 **/ +/** # Version 5.1 : from : 23 jun 2008 **/ +/** to : 27 jan 2009 **/ +/** # Version 6.0 : from : 25 aug 2012 **/ +/** to : 18 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_IO_LOAD + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" +#include "dgraph_allreduce.h" +#include "dgraph_io_load.h" + +/* This routine loads a distributed source +** graph from the given stream(s). Either +** one processor holds a non-NULL stream +** of a centralized graph, or all of them +** hold valid streams to either a centralized +** or a distributed graph. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +DGRAPHALLREDUCEMAXSUMOP (6, 3) +DGRAPHALLREDUCEMAXSUMOP (10, 2) + +int +dgraphLoad ( +Dgraph * restrict const grafptr, /* Not const since halo may update structure */ +FILE * const stream, /* One single centralized stream or distributed ones */ +const Gnum baseval, /* Base value (-1 means keep file base) */ +const DgraphFlag flagval) /* Graph loading flags */ +{ + Gnum reduloctab[12]; + Gnum reduglbtab[12]; + Gnum versval; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { /* Synchronize for debugging */ + errorPrint ("dgraphLoad: communication error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + reduloctab[0] = baseval; /* Exchange baseval to check it is the same for all */ + reduloctab[1] = - baseval; + reduloctab[2] = flagval; /* Exchange flagval to check it is the same for all */ + reduloctab[3] = - flagval; + reduloctab[4] = 0; /* Set uneffective values for versval */ + reduloctab[5] = -2; + reduloctab[6] = /* Assume everything will be fine */ + reduloctab[7] = /* Assume does not have a stream */ + reduloctab[8] = 0; + if (stream != NULL) { + if (intLoad (stream, &versval) != 1) { /* Read version number */ + errorPrint ("dgraphLoad: bad input (1)"); + versval = 0; + reduloctab[6] = 1; + } + else if ((versval != 0) && (versval != 2)) { /* If not a graph format */ + errorPrint ("dgraphLoad: not a graph format"); + reduloctab[6] = 1; + } + reduloctab[4] = versval; + reduloctab[5] = - versval; + reduloctab[7] = 1; /* One more process involved in loading */ + reduloctab[8] = grafptr->proclocnum; + } + + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 6, 3, grafptr->proccomm) != 0) { + errorPrint ("dgraphLoad: communication error (2)"); + return (1); + } + + if (reduglbtab[6] != 0) /* Return from previous errors */ + return (1); + + if ((reduglbtab[0] != - reduglbtab[1])) { + errorPrint ("dgraphLoad: inconsistent base value"); + return (1); + } + if ((reduglbtab[2] != - reduglbtab[3])) { + errorPrint ("dgraphLoad: inconsistent flag value"); + return (1); + } + if ((reduglbtab[7] != 0) && + (reduglbtab[4] != - reduglbtab[5])) { + errorPrint ("dgraphLoad: inconsistent graph file version value"); + return (1); + } + + if (reduglbtab[4] == 2) { /* If distributed graph format */ + if (reduglbtab[7] == grafptr->procglbnbr) /* If as many input streams as processors */ + return (dgraphLoadDist (grafptr, stream, baseval, flagval)); /* Read distributed graph */ + } + else { /* If centralized graph format */ + if (reduglbtab[7] == 1) /* If only one reader stream */ + return (dgraphLoadCent (grafptr, stream, baseval, flagval, reduglbtab[8])); /* Distribute centralized graph from known root */ + else if (reduglbtab[7] == grafptr->procglbnbr) + return (dgraphLoadMulti (grafptr, stream, baseval, flagval)); /* Read multi-centralized graph */ + } + + errorPrint ((reduglbtab[7] == 0) + ? "dgraphLoad: no input stream provided" + : "dgraphLoad: invalid number of input streams"); + return (1); +} + +/* This routine loads a centralized source +** graph from a single stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +int +dgraphLoadCent ( +Dgraph * restrict const grafptr, /* Distributed graph to load */ +FILE * const stream, /* One single centralized stream */ +Gnum baseval, /* Base value (-1 means keep file base) */ +const DgraphFlag flagval, /* Graph loading flags */ +const int protnum) /* Root process number */ +{ + Gnum vertglbnbr; + Gnum vertglbmax; + Gnum vertlocnbr; + Gnum * vertloctax; /* [norestrict:async] */ + Gnum * vertlocptr; + Gnum * restrict vertredtax; + Gnum velolocnbr; + Gnum velolocsum; + Gnum * veloloctax; + Gnum * restrict veloredtax; + Gnum vlbllocnbr; + Gnum * vlblloctax; + Gnum * restrict vlblredtax; + Gnum edgelocnbr; + Gnum * edgeloctax; + Gnum edgeredmnd; + Gnum * restrict edgeredtax; + Gnum * edloloctax; + Gnum * restrict edloredtax; + Gnum degrglbmax; + Gnum baseadj; + Gnum reduglbtab[5]; + char proptab[4]; /* Property string array */ + int cheklocval; + int chekglbval; + int o; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (((stream != NULL) && (protnum != grafptr->proclocnum)) || /* Enforce single stream */ + ((stream == NULL) && (protnum == grafptr->proclocnum))) { + errorPrint ("dgraphLoadCent: invalid parameter (1)"); + return (1); + } + if ((protnum < 0) || (protnum >= grafptr->procglbnbr)) { + errorPrint ("dgraphLoadCent: invalid parameter (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + reduglbtab[0] = 0; /* Assume everything will be fine */ + if (stream != NULL) { + if ((intLoad (stream, &reduglbtab[1]) != 1) || /* Read rest of header */ + (intLoad (stream, &reduglbtab[2]) != 1) || + (intLoad (stream, &reduglbtab[3]) != 1) || + (intLoad (stream, &reduglbtab[4]) != 1) || + (reduglbtab[4] < 0) || + (reduglbtab[4] > 111)) { + errorPrint ("dgraphLoadCent: bad input (1)"); + cheklocval = 1; + } + } + + if (MPI_Bcast (&reduglbtab[0], 5, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (1)"); + return (1); + } + if (reduglbtab[0] != 0) + return (1); + + if (baseval == -1) { /* If keep file graph base */ + baseval = reduglbtab[3]; /* Set graph base as file base */ + baseadj = 0; /* No base adjustment needed */ + } + else /* If set graph base */ + baseadj = baseval - reduglbtab[3]; /* Update base adjust */ + + vertglbnbr = reduglbtab[1]; + vertglbmax = DATASIZE (vertglbnbr, grafptr->procglbnbr, 0); + vertlocnbr = DATASIZE (vertglbnbr, grafptr->procglbnbr, grafptr->proclocnum); + + sprintf (proptab, "%3.3d", (int) reduglbtab[4]); /* Compute file properties */ + proptab[0] -= '0'; /* Vertex labels flag */ + proptab[1] -= '0'; /* Edge weights flag */ + proptab[2] -= '0'; /* Vertex loads flag */ + + velolocnbr = ((proptab[2] != 0) && ((flagval & GRAPHIONOLOADVERT) == 0)) ? vertglbmax : 0; + vlbllocnbr = (proptab[0] != 0) ? vertglbmax : 0; + vlblloctax = + veloloctax = + vertloctax = + edgeloctax = /* Send arrays not allocated yet for root process */ + edgeredtax = NULL; /* No read edge array yet */ + cheklocval = 0; + if ((vertlocptr = memAlloc ((vertglbmax + 2 + velolocnbr + vlbllocnbr) * sizeof (Gnum))) == NULL) { /* TRICK: "+2" for space for velolocsum */ + errorPrint ("dgraphLoadCent: out of memory (1)"); + cheklocval = 1; + } + else { + vertloctax = + vertlocptr -= baseval; + vertlocptr += vertglbmax + 2; /* TRICK: "+2" for space for velolocsum */ + if (proptab[2] != 0) { + veloloctax = vertlocptr; + vertlocptr += vertglbmax; + } + if (proptab[0] != 0) { + vlblloctax = vertlocptr; + baseadj = 0; /* No vertex adjustments if vertex labels */ + } + + if (stream != NULL) { /* Allocate read edge array */ + Gnum edgeredmax; + Gnum edloredmax; + + edgeredmax = reduglbtab[2] / grafptr->procglbnbr + 1; + edgeredmax += (edgeredmax >> 2) + 4; /* Add 25% more space for edges than average */ + edloredmax = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? edgeredmax : 0; + + if ((edgeredtax = memAlloc ((edgeredmax + edloredmax) * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphLoadCent: out of memory (2)"); + cheklocval = 1; + } + else { + edgeredtax -= baseval; + edloredtax = (edloredmax != 0) ? (edgeredtax + edgeredmax) : NULL; + + vertredtax = vertloctax; /* Prepare read vertex arrays, which will never move */ + veloredtax = veloloctax; + vlblredtax = vlblloctax; + } + edgeredmnd = edgeredmax + baseval; + } + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (2)"); + chekglbval = 1; + } + if (chekglbval != 0) { + if (edgeredtax != NULL) + memFree (edgeredtax + baseval); + if (vertloctax != NULL) + memFree (vertloctax + baseval); + return (1); + } + + degrglbmax = 0; /* No maximum degree yet */ + + if (stream != NULL) { + Gnum procnum; + + for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { + Gnum vertrednnd; + Gnum vertrednum; + Gnum edgerednum; + Gnum veloredsum; + + for (vertrednum = edgerednum = baseval, veloredsum = 0, + vertrednnd = DATASIZE (vertglbnbr, grafptr->procglbnbr, procnum) + baseval; + vertrednum < vertrednnd; vertrednum ++) { + Gnum degrredval; + + if (vlblredtax != NULL) { /* If must read label */ + Gnum vlblredval; /* Vertex label value to be read */ + + if (intLoad (stream, &vlblredval) != 1) { /* Read label data */ + errorPrint ("dgraphLoadCent: bad input (2)"); + cheklocval = 1; + break; + } + vlblredtax[vertrednum] = vlblredval; + } + if (proptab[2] != 0) { /* If must read vertex load */ + Gnum veloredval; + + if (intLoad (stream, &veloredval) != 1) { /* Read vertex load data */ + errorPrint ("dgraphLoadCent: bad input (3)"); + cheklocval = 1; + break; + } + if (veloredtax != NULL) + veloredsum += + veloredtax[vertrednum] = veloredval; + } + if (intLoad (stream, °rredval) != 1) { /* Read vertex degree */ + errorPrint ("dgraphLoadCent: bad input (4)"); + cheklocval = 1; + break; + } + if (degrglbmax < degrredval) /* Set maximum degree */ + degrglbmax = degrredval; + + vertredtax[vertrednum] = edgerednum; /* Set index in edge array */ + degrredval += edgerednum; + if (degrredval > edgeredmnd) { /* Check if edge array overflows */ + Gnum edgeredmax; + Gnum edgenewmax; + Gnum edgenewsiz; + Gnum * restrict edgenewtab; + + edgenewmax = + edgeredmax = edgeredmnd - baseval; + do /* Increase edge array size by 25 % */ + edgenewmax += (edgenewmax >> 2) + 4; + while (edgenewmax < (degrredval - baseval)); + edgenewsiz = (edloredtax != NULL) ? (2 * edgenewmax) : edgenewmax; + if ((edgenewtab = memRealloc (edgeredtax + baseval, edgenewsiz * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphLoadCent: out of memory (3)"); + cheklocval = 1; + break; + } + edgeredtax = edgenewtab - baseval; + edgeredmnd = edgenewmax + baseval; + if (edloredtax != NULL) { /* Move edge load array if present */ + memMov (edgenewtab + edgenewmax, edgenewtab + edgeredmax, (edgerednum - baseval) * sizeof (Gnum)); + edloredtax = edgeredtax + edgenewmax; + } + } + + for ( ; edgerednum < degrredval; edgerednum ++) { + Gnum edgeredval; /* Value where to read edge end */ + + if (proptab[1] != 0) { /* If must read edge load */ + Gnum edloredval; /* Value where to read edge load */ + + if (intLoad (stream, &edloredval) != 1) { /* Read edge load data */ + errorPrint ("dgraphLoadCent: bad input (5)"); + cheklocval = 1; + break; + } + if (edloredtax != NULL) + edloredtax[edgerednum] = edloredval; + } + if (intLoad (stream, &edgeredval) != 1) { /* Read edge data */ + errorPrint ("dgraphLoadCent: bad input (6)"); + cheklocval = 1; + break; + } + edgeredtax[edgerednum] = edgeredval + baseadj; + } + if (cheklocval != 0) + break; + } + vertredtax[vertrednum ++] = edgerednum; /* Set end of edge array */ + + if (cheklocval == 0) { + if (procnum != grafptr->proclocnum) { /* If arrays have to be sent */ + MPI_Request requtab[5]; + MPI_Status stattab[5]; + int requnbr; + + vertredtax[baseval] = edgerednum - baseval; /* First slot is number of edges */ + vertredtax[vertrednum] = (veloredtax != NULL) ? veloredsum : (vertrednnd - baseval); /* Add vertex load sum to send vertex array */ + if (MPI_Isend (vertredtax + baseval, vertrednnd - baseval + 2, /* TRICK: "+2" and not "+1" because of space for velolocsum */ + GNUM_MPI, procnum, TAGVERTLOCTAB, grafptr->proccomm, &requtab[0]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (5)"); + return (1); /* Dirty exit as we can do nothing */ + } + requnbr = 1; + if (veloredtax != NULL) { + if (MPI_Isend (veloredtax + baseval, vertrednnd - baseval, GNUM_MPI, + procnum, TAGVELOLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (6)"); + return (1); + } + } + if (vlblredtax != NULL) { + if (MPI_Isend (vlblredtax + baseval, vertrednnd - baseval, GNUM_MPI, + procnum, TAGVLBLLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (7)"); + return (1); + } + } + if (MPI_Recv (&reduglbtab[0], 0, MPI_INT, procnum, MPI_ANY_TAG, grafptr->proccomm, &stattab[0]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (8)"); + return (1); + } + if (stattab[0].MPI_TAG != TAGOK) /* If receiver could not allocate memory for edge arrays */ + cheklocval = 1; + else { + if (MPI_Isend (edgeredtax + baseval, edgerednum - baseval, GNUM_MPI, + procnum, TAGEDGELOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (9)"); + return (1); + } + if (edloredtax != NULL) { + if (MPI_Isend (edloredtax + baseval, edgerednum - baseval, GNUM_MPI, + procnum, TAGEDLOLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (10)"); + return (1); + } + } + MPI_Waitall (requnbr, &requtab[0], &stattab[0]); + } + } + else { /* Arrays are local */ + velolocsum = (veloredtax != NULL) ? veloredsum : vertlocnbr; /* Save accumulated values as local data */ + edgelocnbr = edgerednum - baseval; + if (edgeredmnd - edgerednum > 10000) { /* If array can be compacted */ + if (edloredtax != NULL) { + memMov (edgeredtax + edgerednum, edloredtax + baseval, edgelocnbr * sizeof (Gnum)); + edgeredtax = memRealloc (edgeredtax + baseval, edgelocnbr * 2 * sizeof (Gnum)); + edgeredtax -= baseval; + edloredtax = edgeredtax + edgelocnbr; + } + else { + edgeredtax = memRealloc (edgeredtax + baseval, edgelocnbr * sizeof (Gnum)); + edgeredtax -= baseval; + } + } + edgeloctax = edgeredtax; /* Keep read edge array as local edge array */ + edloloctax = edloredtax; + + if (grafptr->proclocnum == (grafptr->procglbnbr - 1)) { /* If root process is last process */ + vertredtax = /* No need to reallocate read arrays */ + edgeredtax = NULL; + break; /* And we can exit now */ + } + + if ((vertlocptr = memAlloc ((vertglbmax + 2 + velolocnbr + vlbllocnbr) * sizeof (Gnum))) == NULL) { /* TRICK: "+2" for space for velolocsum */ + errorPrint ("dgraphLoadCent: out of memory (4)"); + cheklocval = 1; + } + else { + Gnum edgeredmax; + Gnum edloredmax; + + vertredtax = + vertlocptr -= baseval; + vertlocptr += vertglbmax + 2; /* TRICK: "+2" for space for velolocsum */ + if (veloredtax != NULL) { + veloredtax = vertlocptr; + vertlocptr += vertglbmax; + } + if (vlblredtax != NULL) + vlblredtax = vertlocptr; + + edgeredmax = edgeredmnd - baseval; + edloredmax = (edloloctax != NULL) ? edgeredmax : 0; + if ((edgeredtax = memAlloc ((edgeredmax + edloredmax) * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphLoadCent: out of memory (5)"); + cheklocval = 1; + } + else { + edgeredtax -= baseval; + if (edloredtax != NULL) + edloredtax = edgeredtax + edgeredmax; + } + } + } + } + + if (cheklocval != 0) { /* If error encountered */ + for ( ; procnum < grafptr->procglbnbr; procnum ++) { /* Send abortion messages */ + if (procnum != grafptr->proclocnum) { /* Abortion messages complete vertloctab receives */ + if (MPI_Send (vertredtax + baseval, 0, GNUM_MPI, procnum, TAGVERTLOCTAB, grafptr->proccomm) != MPI_SUCCESS) + errorPrint ("dgraphLoadCent: communication error (11)"); + } + } + break; + } + } + + if (vertredtax != NULL) { /* Free reader arrays if reallocated */ + if (vertredtax != vertloctax) /* If equal, vertloctax will be deallocated afterwards */ + memFree (vertredtax + baseval); + memFree (edgeredtax + baseval); + } + } + else { /* Process is not reader */ + MPI_Request requtab[5]; + MPI_Status stattab[5]; + int requnbr; + int vertrcvnbr; /* int because of the MPI API */ + + if (MPI_Irecv (vertloctax + baseval, vertlocnbr + 2, GNUM_MPI, /* TRICK: "+2" and not "+1" because of velolocsum */ + protnum, TAGVERTLOCTAB, grafptr->proccomm, &requtab[2]) != MPI_SUCCESS) { /* requtab[2] is first surely available slot */ + errorPrint ("dgraphLoadCent: communication error (10)"); + return (1); /* Dirty exit as we can do nothing */ + } + requnbr = 0; + if (veloloctax != NULL) { + if (MPI_Irecv (veloloctax + baseval, vertlocnbr, GNUM_MPI, + protnum, TAGVELOLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (11)"); + return (1); + } + } + if (vlblloctax != NULL) { + if (MPI_Irecv (vlblloctax + baseval, vertlocnbr, GNUM_MPI, + protnum, TAGVLBLLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (12)"); + return (1); + } + } + + MPI_Wait (&requtab[2], &stattab[2]); /* Wait until vertloctab received */ + MPI_Get_count (&stattab[2], GNUM_MPI, &vertrcvnbr); /* Get size of received array */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (((Gnum) vertrcvnbr != 0) && /* vertrcvnbr == 0 in the case of abortion message */ + ((Gnum) vertrcvnbr != (vertlocnbr + 2))) { /* TRICK: "+2" and not "+1" because of velolocsum */ + errorPrint ("dgraphLoadCent: invalid vertex array size"); + vertrcvnbr = 0; + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (vertrcvnbr == 0) { /* Empty message means abortion wanted */ + while (requnbr > 0) { /* Cancel all pending requests */ + requnbr --; + MPI_Cancel (&requtab[requnbr]); + MPI_Request_free (&requtab[requnbr]); + } /* No more pending requests */ + } + else { + Gnum edlolocnbr; + + edgelocnbr = vertloctax[baseval]; /* edgelocnbr is first cell */ + vertloctax[baseval] = baseval; /* First cell is always baseval */ + velolocsum = vertloctax[vertlocnbr + baseval + 1]; /* TRICK: get velolocsum */ + edlolocnbr = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? edgelocnbr : 0; + edloloctax = NULL; /* Assume no edge load array */ + + if ((edgeloctax = memAlloc ((edgelocnbr + edlolocnbr) * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphLoadCent: out of memory (6)"); + MPI_Send (&cheklocval, 0, MPI_INT, protnum, TAGBAD, grafptr->proccomm); /* Memory could not be allocated */ + cheklocval = 1; + } + else { + if (MPI_Irecv (edgeloctax, edgelocnbr, GNUM_MPI, protnum, TAGEDGELOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (13)"); + return (1); + } + if (edlolocnbr != 0) { + edloloctax = edgeloctax + edgelocnbr; + if (MPI_Irecv (edloloctax, edgelocnbr, GNUM_MPI, protnum, TAGEDLOLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (14)"); + return (1); + } + edloloctax -= baseval; + } + edgeloctax -= baseval; + MPI_Isend (&cheklocval, 0, MPI_INT, protnum, TAGOK, grafptr->proccomm, &requtab[requnbr ++]); /* Send ready to receive */ + } + } + + MPI_Waitall (requnbr, &requtab[0], &stattab[0]); /* Wait until all pending communications completed and all arrays received */ + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphLoadCent: communication error (15)"); + chekglbval = 1; + } + if (chekglbval != 0) { + if (edgeloctax != NULL) + memFree (edgeloctax + baseval); + memFree (vertloctax + baseval); + return (1); + } + + o = dgraphBuild2 (grafptr, baseval, /* Build distributed graph */ + vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, veloloctax, velolocsum, NULL, vlblloctax, + edgelocnbr, edgelocnbr, edgeloctax, NULL, edloloctax, degrglbmax); /* Non-readers will have degrglbmax set to 0 */ + grafptr->flagval |= DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; + + return (o); +} + +/* This routine loads a distributed source +** graph from a distributed source graph +** file spread across all of the streams. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +int +dgraphLoadDist ( +Dgraph * restrict const grafptr, /* Distributed graph to load */ +FILE * const stream, /* One single centralized stream */ +Gnum baseval, /* Base value (-1 means keep file base) */ +const DgraphFlag flagval) /* Graph loading flags */ +{ + Gnum proclocnum; + Gnum vertlocnbr; + Gnum vertlocnnd; + Gnum vertlocnum; + Gnum * restrict vertloctax; + Gnum * vertlocptr; + Gnum velolocnbr; + Gnum velolocsum; + Gnum * restrict veloloctax; + Gnum vlbllocnbr; + Gnum * restrict vlblloctax; + Gnum edgelocnbr; + Gnum edgelocnnd; + Gnum edgelocnum; + Gnum * restrict edgeloctax; + Gnum * restrict edloloctax; + Gnum degrlocmax; + Gnum baseadj; + Gnum reduloctab[12]; + Gnum reduglbtab[12]; + char proptab[4]; /* Property string array */ + int cheklocval; + int chekglbval; + int o; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (stream == NULL) { + errorPrint ("dgraphLoadDist: invalid parameter"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + reduloctab[0] = 0; /* Assume everything will be fine */ + o = intLoad (stream, &reduloctab[1]); /* Read rest of header */ + o += intLoad (stream, &proclocnum); + o += intLoad (stream, &reduloctab[3]); + o += intLoad (stream, &reduloctab[5]); + o += intLoad (stream, &reduloctab[10]); + o += intLoad (stream, &reduloctab[11]); + o += intLoad (stream, &reduloctab[7]); + o += intLoad (stream, &reduloctab[9]); + if ((o != 8) || + (reduloctab[9] < 0) || + (reduloctab[9] > 111)) { + errorPrint ("dgraphLoadDist: bad input (1)"); + reduloctab[0] = 2; /* Immediate abort has maximum value so as to be propagated by MAX reduce */ + } + reduloctab[2] = - reduloctab[1]; + reduloctab[4] = - reduloctab[3]; + reduloctab[6] = - reduloctab[5]; + reduloctab[8] = - reduloctab[7]; + if ((int) proclocnum != grafptr->proclocnum) /* If fragment is not read by proper process */ + reduloctab[0] |= 1; + if ((int) reduloctab[1] != grafptr->procglbnbr) { + errorPrint ("dgraphLoadDist: wrong number of processors to read distributed graph"); + reduloctab[0] = 2; + } + + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 10, 2, grafptr->proccomm) != 0) { + errorPrint ("dgraphLoadDist: communication error (1)"); + reduglbtab[0] = 2; + } + if (reduglbtab[0] >= 2) /* If has to abort immediately */ + return (1); + + if ((reduglbtab[2] != - reduglbtab[1]) || + (reduglbtab[4] != - reduglbtab[3]) || + (reduglbtab[6] != - reduglbtab[5]) || + (reduglbtab[8] != - reduglbtab[7])) { + errorPrint ("dgraphLoadDist: inconsistent distributed graph headers"); + return (1); + } + if (reduloctab[0] == 1) + errorPrint ("dgraphLoadDist: distributed graph file not read by proper process"); + if (reduglbtab[0] != 0) /* If cannot go on anyway */ + return (1); + + if ((reduglbtab[10] != reduloctab[3]) || + (reduglbtab[11] != reduloctab[5])) + errorPrint ("dgraphLoadDist: bad input (2)"); + if ((reduglbtab[10] != reduglbtab[3]) || + (reduglbtab[11] != reduglbtab[5])) + return (1); + + if (baseval == -1) { /* If keep file graph base */ + baseval = reduglbtab[7]; /* Set graph base as file base */ + baseadj = 0; /* No base adjustment needed */ + } + else /* If set graph base */ + baseadj = baseval - reduglbtab[7]; /* Update base adjust */ + + vertlocnbr = reduloctab[10]; + edgelocnbr = reduloctab[11]; + + sprintf (proptab, "%3.3d", (int) reduglbtab[9]); /* Compute file properties */ + proptab[0] -= '0'; /* Vertex labels flag */ + proptab[1] -= '0'; /* Edge weights flag */ + proptab[2] -= '0'; /* Vertex loads flag */ + + velolocnbr = ((proptab[2] != 0) && ((flagval & GRAPHIONOLOADVERT) == 0)) ? vertlocnbr : 0; + vlbllocnbr = (proptab[0] != 0) ? vertlocnbr : 0; + vlblloctax = + veloloctax = + vertloctax = + edgeloctax = NULL; + cheklocval = 0; + if ((vertlocptr = memAlloc ((vertlocnbr + 1 + velolocnbr + vlbllocnbr) * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphLoadDist: out of memory (1)"); + cheklocval = 1; + } + else { + Gnum edlolocnbr; + + vertloctax = + vertlocptr -= baseval; + vertlocptr += vertlocnbr + 1; + if ((proptab[2] != 0) && ((flagval & GRAPHIONOLOADVERT) == 0)) { + veloloctax = vertlocptr; + vertlocptr += vertlocnbr; + } + if (proptab[0] != 0) { + vlblloctax = vertlocptr; + baseadj = 0; /* No vertex adjustments if vertex labels */ + } + + edlolocnbr = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? edgelocnbr : 0; + if ((edgeloctax = memAlloc ((edgelocnbr + edlolocnbr) * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphLoadDist: out of memory (2)"); + cheklocval = 1; + } + else { + edgeloctax -= baseval; + edloloctax = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? (edgeloctax + edgelocnbr) : NULL; + } + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphLoadDist: communication error (2)"); + chekglbval = 1; + } + if (chekglbval != 0) { + if (edgeloctax != NULL) + memFree (edgeloctax + baseval); + if (vertloctax != NULL) + memFree (vertloctax + baseval); + return (1); + } + + degrlocmax = 0; /* No maximum degree yet */ + velolocsum = (veloloctax != NULL) ? 0 : vertlocnbr; + for (vertlocnum = edgelocnum = baseval, vertlocnnd = vertlocnbr + baseval, edgelocnnd = edgelocnbr + baseval; + vertlocnum < vertlocnnd; vertlocnum ++) { + Gnum degrlocval; + + if (vlblloctax != NULL) { /* If must read label */ + Gnum vlbllocval; /* Vertex label value to be read */ + + if (intLoad (stream, &vlbllocval) != 1) { /* Read label data */ + errorPrint ("dgraphLoadDist: bad input (2)"); + cheklocval = 1; + break; + } + vlblloctax[vertlocnum] = vlbllocval; + } + if (proptab[2] != 0) { /* If must read vertex load */ + Gnum velolocval; + + if (intLoad (stream, &velolocval) != 1) { /* Read vertex load data */ + errorPrint ("dgraphLoadDist: bad input (3)"); + cheklocval = 1; + break; + } + if (veloloctax != NULL) + velolocsum += + veloloctax[vertlocnum] = velolocval; + } + if (intLoad (stream, °rlocval) != 1) { /* Read vertex degree */ + errorPrint ("dgraphLoadDist: bad input (4)"); + cheklocval = 1; + break; + } + if (degrlocmax < degrlocval) /* Set maximum degree */ + degrlocmax = degrlocval; + + vertloctax[vertlocnum] = edgelocnum; /* Set index in edge array */ + degrlocval += edgelocnum; + if (degrlocval > edgelocnnd) { /* Check if edge array overflows */ + errorPrint ("dgraphLoadDist: invalid arc count (1)"); + cheklocval = 1; + break; + } + + for ( ; edgelocnum < degrlocval; edgelocnum ++) { + Gnum edgelocval; /* Value where to read edge end */ + + if (proptab[1] != 0) { /* If must read edge load */ + Gnum edlolocval; /* Value where to read edge load */ + + if (intLoad (stream, &edlolocval) != 1) { /* Read edge load data */ + errorPrint ("dgraphLoadDist: bad input (5)"); + cheklocval = 1; + break; + } + if (edloloctax != NULL) + edloloctax[edgelocnum] = edlolocval; + } + if (intLoad (stream, &edgelocval) != 1) { /* Read edge data */ + errorPrint ("dgraphLoadDist: bad input (6)"); + cheklocval = 1; + break; + } + edgeloctax[edgelocnum] = edgelocval + baseadj; + } + if (cheklocval != 0) + break; + } + vertloctax[vertlocnum] = edgelocnum; /* Set end of edge array */ + if (edgelocnum != edgelocnnd) { /* Check if number of edges is valid */ + errorPrint ("dgraphLoadDist: invalid arc count (2)"); + cheklocval = 1; + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphLoadDist: communication error (17)"); + chekglbval = 1; + } + if (chekglbval != 0) { + memFree (edgeloctax + baseval); + memFree (vertloctax + baseval); + return (1); + } + + o = dgraphBuild2 (grafptr, baseval, /* Build distributed graph */ + vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, veloloctax, velolocsum, NULL, vlblloctax, + edgelocnbr, edgelocnbr, edgeloctax, NULL, edloloctax, degrlocmax); + grafptr->flagval |= DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; + + return (o); +} + +/* This routine loads a distributed source +** graph from a centralized source graph +** file replicated on all of the streams. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +int +dgraphLoadMulti ( +Dgraph * restrict const grafptr, /* Distributed graph to load */ +FILE * const stream, /* One single centralized stream */ +Gnum baseval, /* Base value (-1 means keep file base) */ +const DgraphFlag flagval) /* Graph loading flags */ +{ + errorPrint ("dgraphLoadMulti: not implemented"); + return (1); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_io_load.h b/scotch_6.0.3/src/libscotch/dgraph_io_load.h new file mode 100644 index 00000000..565381f3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_io_load.h @@ -0,0 +1,59 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_io_load.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the distributed graph loading **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 12 may 2007 **/ +/** to 13 may 2007 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef DGRAPH_IO_LOAD +#define static +#endif + +static int dgraphLoadCent (Dgraph * restrict const, FILE * const, Gnum, const GraphFlag, const int); +static int dgraphLoadDist (Dgraph * restrict const, FILE * const, Gnum, const GraphFlag); +static int dgraphLoadMulti (Dgraph * restrict const, FILE * const, Gnum, const GraphFlag); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/dgraph_io_save.c b/scotch_6.0.3/src/libscotch/dgraph_io_save.c new file mode 100644 index 00000000..34f566c6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_io_save.c @@ -0,0 +1,164 @@ +/* Copyright 2007,2010,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_io.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the input/output routines for **/ +/** distributed graphs. **/ +/** **/ +/** # Version P0.2 : from : 11 may 1999 **/ +/** to 12 may 1999 **/ +/** # Version 5.0 : from : 22 jul 2005 **/ +/** to : 22 apr 2008 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to : 11 aug 2010 **/ +/** # Version 6.0 : from : 18 sep 2013 **/ +/** to : 18 sep 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_IO + +#include "module.h" +#include "common.h" +#include "dgraph.h" + +/* This routine saves a distributed source +** graph to the given streams. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphSave ( +Dgraph * restrict const grafptr, /* Not const since halo may update structure */ +FILE * const stream) +{ + Gnum * restrict vlblgsttax; /* Based index to ghost label array */ + Gnum vertlocnum; + char propstr[4]; /* Property string */ + int o; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { /* Synchronize for debugging */ + errorPrint ("dgraphSave: communication error"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + vlblgsttax = NULL; /* Assume ghost label array is free */ + if ((grafptr->vlblloctax != NULL) || /* If graph has vertex labels or */ + (grafptr->edgeloctax == NULL) || /* If no global index edge array present or */ + (grafptr->procvrttab[grafptr->procglbnbr] != grafptr->procdsptab[grafptr->procglbnbr])) { /* If graph may have holes in its numbering */ + if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array */ + errorPrint ("dgraphSave: cannot compute ghost edge array"); + return (1); + } + if ((vlblgsttax = (Gnum *) memAlloc (grafptr->vertgstnbr * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphSave: out of memory"); + return (1); + } + + if (grafptr->vlblloctax != NULL) + memCpy (vlblgsttax, grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr * sizeof (Gnum)); + else { + for (vertlocnum = 0; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) /* vlblgsttax is not based yet at this time */ + vlblgsttax[vertlocnum] = grafptr->procvrttab[grafptr->proclocnum] + vertlocnum; + } + + if (dgraphHaloSync (grafptr, (byte *) vlblgsttax, GNUM_MPI) != 0) { /* vlblgsttax is not based yet at this time */ + errorPrint ("dgraphSave: cannot halo labels"); + memFree (vlblgsttax); + return (1); + } + vlblgsttax -= grafptr->baseval; + } + + propstr[0] = (vlblgsttax != NULL) ? '1' : '0'; /* Set property string */ + propstr[1] = (grafptr->edloloctax != NULL) ? '1' : '0'; + propstr[2] = (grafptr->veloloctax != NULL) ? '1' : '0'; + propstr[3] = '\0'; + + if (fprintf (stream, "2\n" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t%3s\n", /* Write file header */ + (Gnum) grafptr->procglbnbr, + (Gnum) grafptr->proclocnum, + (Gnum) grafptr->vertglbnbr, + (Gnum) grafptr->edgeglbnbr, + (Gnum) grafptr->vertlocnbr, + (Gnum) grafptr->edgelocnbr, + (Gnum) grafptr->baseval, + propstr) == EOF) { + errorPrint ("dgraphSave: bad output (1)"); + return (1); + } + + o = 0; + for (vertlocnum = grafptr->baseval; (vertlocnum < grafptr->vertlocnnd) && (o == 0); vertlocnum ++) { + Gnum edgelocnum; + + if (vlblgsttax != NULL) /* Write vertex label if necessary */ + o = (fprintf (stream, GNUMSTRING "\t", (Gnum) vlblgsttax[vertlocnum]) == EOF); + if (grafptr->veloloctax != NULL) /* Write vertex load if necessary */ + o |= (fprintf (stream, GNUMSTRING "\t", (Gnum) grafptr->veloloctax[vertlocnum]) == EOF); + + o |= (fprintf (stream, GNUMSTRING, (Gnum) (grafptr->vendloctax[vertlocnum] - grafptr->vertloctax[vertlocnum])) == EOF); /* Write vertex degree */ + + for (edgelocnum = grafptr->vertloctax[vertlocnum]; + edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { + o |= (putc ('\t', stream) == EOF); + if (grafptr->edloloctax != NULL) /* Write edge load if necessary */ + o |= (fprintf (stream, "\t" GNUMSTRING " ", (Gnum) grafptr->edloloctax[edgelocnum]) == EOF); + o |= (fprintf (stream, GNUMSTRING, (Gnum) ((vlblgsttax != NULL) /* Write edge end */ + ? vlblgsttax[grafptr->edgegsttax[edgelocnum]] + : grafptr->edgeloctax[edgelocnum])) == EOF); + } + o |= (putc ('\n', stream) == EOF); + } + + if (o != 0) + errorPrint ("dgraphSave: bad output (2)"); + + if (vlblgsttax != NULL) /* Free ghost label array if used */ + memFree (vlblgsttax + grafptr->baseval); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_match.c b/scotch_6.0.3/src/libscotch/dgraph_match.c new file mode 100644 index 00000000..568c3608 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_match.c @@ -0,0 +1,284 @@ +/* Copyright 2008-2010,2012,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_match.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed graph matching **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2008 **/ +/** to : 30 jul 2010 **/ +/** # Version 6.0 : from : 03 oct 2012 **/ +/** to : 10 oct 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_MATCH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "dgraph_match.h" + +/*************************************/ +/* */ +/* These routines handle distributed */ +/* source graphs. */ +/* */ +/*************************************/ + +/* This routine initializes a distributed graph +** structure. In order to avoid collective +** communication whenever possible, the allocation +** of send and receive index arrays is not performed +** in the routine itself, but rather delegated to +** subsequent routines such as dgraphBuild. +** However, these arrays will not be freed by +** dgraphFree, but by dgraphExit. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphMatchInit ( +DgraphMatchData * restrict const mateptr, +const float probval) +{ + Gnum * restrict procvgbtab; + int procngbnum; + Gnum vertlocnbr; + Gnum vertgstnbr; + + Dgraph * restrict const grafptr = mateptr->c.finegrafptr; + const int * restrict const procngbtab = grafptr->procngbtab; + const Gnum * restrict const procvrttab = grafptr->procvrttab; + + vertlocnbr = grafptr->vertlocnbr; + vertgstnbr = grafptr->vertgstnbr; + + if (memAllocGroup ((void **) (void *) + &mateptr->procvgbtab, (size_t) ((grafptr->procngbnbr + 1) * sizeof (Gnum)), + &mateptr->queuloctab, (size_t) (vertlocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphMatchInit: out of memory"); + return (1); + } + + mateptr->c.multlocnbr = 0; + mateptr->mategsttax = mateptr->c.coargsttax; /* TRICK: re-use array */ + mateptr->matelocnbr = 0; /* All vertices need to be processed */ + mateptr->queulocnbr = 0; + mateptr->probval = (grafptr->procngbnbr == 0) ? 1.0F : probval; + + memSet (mateptr->mategsttax + grafptr->vertlocnnd, ~0, (vertgstnbr - vertlocnbr) * sizeof (Gnum)); /* No ghost vertices matched to date */ + + for (procngbnum = 0, procvgbtab = mateptr->procvgbtab; procngbnum < grafptr->procngbnbr; procngbnum ++) + procvgbtab[procngbnum] = (Gnum) procvrttab[procngbtab[procngbnum]]; + procvgbtab[procngbnum] = (Gnum) procvrttab[grafptr->procglbnbr]; /* Mark end */ + + return (0); +} + +/* This routine frees the contents of a matching +** data structure. +** It returns: +** - VOID : in all cases. +*/ + +void +dgraphMatchExit ( +DgraphMatchData * restrict const mateptr) +{ + memFree (mateptr->procvgbtab); +} + +/* These routines perform a round of computations +** among enqueued vertices to produce matching requests. +** They return: +** - 0 : on success. +** - !0 : on error. +*/ + +#define DGRAPHMATCHSCANNAME dgraphMatchSc /* Scan matching (no edge weights) */ +#define DGRAPHMATCHSCANINIT \ + probmax = (Gnum) (mateptr->probval * 32768.0); /* Compute integer threshold of random value */ +#define DGRAPHMATCHSCANCOUNTDECL ; +#define DGRAPHMATCHSCANCOUNTINIT \ + probval = intRandVal (32768); /* Get proba for this vertex */ +#define DGRAPHMATCHSCANCOUNTSELECT \ + edgefrenbr ++; +#define DGRAPHMATCHSCANFINDSELECT \ + (edgefrenbr -- == 0) +#include "dgraph_match_scan.c" +#undef DGRAPHMATCHSCANFINDSELECT +#undef DGRAPHMATCHSCANCOUNTSELECT +#undef DGRAPHMATCHSCANCOUNTINIT +#undef DGRAPHMATCHSCANCOUNTDECL +#undef DGRAPHMATCHSCANINIT +#undef DGRAPHMATCHSCANNAME + +#define DGRAPHMATCHSCANNAME dgraphMatchHy /* Heavy edge matching */ +#define DGRAPHMATCHSCANINIT \ + const Gnum * restrict const edloloctax = grafptr->edloloctax; \ + if (edloloctax == NULL) { \ + dgraphMatchSc (mateptr); \ + return; \ + } \ + probmax = (Gnum) (mateptr->probval * 32768.0); /* Compute integer threshold of random value */ +#define DGRAPHMATCHSCANCOUNTDECL \ + Gnum edlolocmax; +#define DGRAPHMATCHSCANCOUNTINIT \ + edlolocmax = 0; \ + probval = intRandVal (32768); /* Get proba for this vertex */ +#define DGRAPHMATCHSCANCOUNTSELECT \ + Gnum edlolocval; \ + edlolocval = edloloctax[edgelocnum]; \ + if (edlolocval > edlolocmax) { \ + edlolocmax = edlolocval; \ + edgefrenbr = 1; \ + } \ + else if (edlolocval == edlolocmax) \ + edgefrenbr ++; +#define DGRAPHMATCHSCANFINDSELECT \ + ((edloloctax[edgelocnum] == edlolocmax) && \ + (edgefrenbr -- == 0)) +#include "dgraph_match_scan.c" +#undef DGRAPHMATCHSCANFINDSELECT +#undef DGRAPHMATCHSCANCOUNTSELECT +#undef DGRAPHMATCHSCANCOUNTINIT +#undef DGRAPHMATCHSCANCOUNTDECL +#undef DGRAPHMATCHSCANINIT +#undef DGRAPHMATCHSCANNAME + +#define DGRAPHMATCHSCANNAME dgraphMatchHl /* Heavy edge matching of lightest vertices */ +#define DGRAPHMATCHSCANINIT \ + const Gnum * restrict const veloloctax = grafptr->veloloctax; \ + const Gnum * restrict const edloloctax = grafptr->edloloctax; \ + if ((veloloctax == NULL) || (edloloctax == NULL)) { \ + dgraphMatchHy (mateptr); \ + return; \ + } \ + probmax = (1 * grafptr->veloglbsum) / (5 * grafptr->vertglbnbr); +#define DGRAPHMATCHSCANCOUNTDECL \ + Gnum edlolocmax; +#define DGRAPHMATCHSCANCOUNTINIT \ + edlolocmax = 0; \ + probval = veloloctax[vertlocnum]; /* Process vertex if vertex weight smaller than threshold */ +#define DGRAPHMATCHSCANCOUNTSELECT \ + Gnum edlolocval; \ + edlolocval = edloloctax[edgelocnum]; \ + if (edlolocval > edlolocmax) { \ + edlolocmax = edlolocval; \ + edgefrenbr = 1; \ + } \ + else if (edlolocval == edlolocmax) \ + edgefrenbr ++; +#define DGRAPHMATCHSCANFINDSELECT \ + ((edloloctax[edgelocnum] == edlolocmax) && \ + (edgefrenbr -- == 0)) +#include "dgraph_match_scan.c" +#undef DGRAPHMATCHSCANFINDSELECT +#undef DGRAPHMATCHSCANCOUNTSELECT +#undef DGRAPHMATCHSCANCOUNTINIT +#undef DGRAPHMATCHSCANCOUNTDECL +#undef DGRAPHMATCHSCANINIT +#undef DGRAPHMATCHSCANNAME + +#define DGRAPHMATCHSCANNAME dgraphMatchLc /* Local scan matching */ +#define DGRAPHMATCHSCANINIT \ + probmax = 0; /* Vertices will always be active */ +#define DGRAPHMATCHSCANCOUNTDECL ; +#define DGRAPHMATCHSCANCOUNTINIT \ + probval = 0; /* Vertices will always be active */ +#define DGRAPHMATCHSCANCOUNTSELECT \ + if (vertgstend < vertlocnnd) \ + edgefrenbr ++; \ + else \ + edgeendnbr --; +#define DGRAPHMATCHSCANFINDSELECT \ + ((vertgstend < vertlocnnd) && \ + (edgefrenbr -- == 0)) +#include "dgraph_match_scan.c" +#undef DGRAPHMATCHSCANFINDSELECT +#undef DGRAPHMATCHSCANCOUNTSELECT +#undef DGRAPHMATCHSCANCOUNTINIT +#undef DGRAPHMATCHSCANCOUNTDECL +#undef DGRAPHMATCHSCANINIT +#undef DGRAPHMATCHSCANNAME + +#define DGRAPHMATCHSCANNAME dgraphMatchLy /* Local heavy edge matching */ +#define DGRAPHMATCHSCANINIT \ + const Gnum * restrict const edloloctax = mateptr->c.finegrafptr->edloloctax; \ + if (edloloctax == NULL) { \ + dgraphMatchLc (mateptr); \ + return; \ + } \ + probmax = 0; /* Vertices will always be active */ +#define DGRAPHMATCHSCANCOUNTDECL \ + Gnum edlolocmax; +#define DGRAPHMATCHSCANCOUNTINIT \ + edlolocmax = 0; \ + probval = 0; /* Vertices will always be active */ +#define DGRAPHMATCHSCANCOUNTSELECT \ + if (vertgstend < vertlocnnd) { \ + Gnum edlolocval; \ + edlolocval = edloloctax[edgelocnum]; \ + if (edlolocval > edlolocmax) { \ + edlolocmax = edlolocval; \ + edgefrenbr = 1; \ + } \ + else if (edlolocval == edlolocmax) \ + edgefrenbr ++; \ + } \ + else \ + edgeendnbr --; +#define DGRAPHMATCHSCANFINDSELECT \ + ((vertgstend < vertlocnnd) && \ + (edloloctax[edgelocnum] == edlolocmax) && \ + (edgefrenbr -- == 0)) +#include "dgraph_match_scan.c" +#undef DGRAPHMATCHSCANFINDSELECT +#undef DGRAPHMATCHSCANCOUNTSELECT +#undef DGRAPHMATCHSCANCOUNTINIT +#undef DGRAPHMATCHSCANCOUNTDECL +#undef DGRAPHMATCHSCANINIT +#undef DGRAPHMATCHSCANNAME diff --git a/scotch_6.0.3/src/libscotch/dgraph_match.h b/scotch_6.0.3/src/libscotch/dgraph_match.h new file mode 100644 index 00000000..32fdfd1a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_match.h @@ -0,0 +1,83 @@ +/* Copyright 2007-2009,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_match.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : This file provides the structure **/ +/** definitions for the coasening phase of **/ +/** the multi-level method. **/ +/** **/ +/** DATES : # Version 5.0 : from : 04 may 2006 **/ +/** to : 21 jun 2007 **/ +/** # Version 5.1 : from : 23 nov 2008 **/ +/** to : 04 apr 2009 **/ +/** # Version 6.0 : from : 03 oct 2012 **/ +/** to : 03 oct 2012 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/* This structure contains all the tables describing the matching state */ + +typedef struct DgraphMatchData_ { + DgraphCoarsenData c; /*+ Coarsening structure +*/ + Gnum * mategsttax; /*+ Mating table for local and ghost vertices +*/ + Gnum matelocnbr; /*+ Number of local matchings +*/ + Gnum * queuloctab; /*+ Queue of unmated local vertex +*/ + Gnum queulocnbr; /*+ Number of enqueued unmated vertices +*/ + Gnum * procvgbtab; /*+ Global vertex number bounds for neighboring processors [+1] +*/ + float probval; /*+ Vertex mating probability (1.0 is certain) +*/ +} DgraphMatchData; + +/* +** The function prototypes. +*/ + +int dgraphMatchInit (DgraphMatchData * restrict const, const float); +void dgraphMatchExit (DgraphMatchData * restrict const); +int dgraphMatchSync (DgraphMatchData * restrict const); +int dgraphMatchSyncColl (DgraphMatchData * restrict const); +int dgraphMatchSyncPtop (DgraphMatchData * restrict const); +int dgraphMatchCheck (DgraphMatchData * restrict const); + +void dgraphMatchHl (DgraphMatchData * restrict const); +void dgraphMatchSc (DgraphMatchData * restrict const); +void dgraphMatchHy (DgraphMatchData * restrict const); +void dgraphMatchLc (DgraphMatchData * restrict const); +void dgraphMatchLy (DgraphMatchData * restrict const); diff --git a/scotch_6.0.3/src/libscotch/dgraph_match_check.c b/scotch_6.0.3/src/libscotch/dgraph_match_check.c new file mode 100644 index 00000000..291316bf --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_match_check.c @@ -0,0 +1,277 @@ +/* Copyright 2008,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_match_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed graph matching **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 25 dec 2008 **/ +/** to : 08 apr 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_MATCH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "dgraph_match.h" + +/*************************************/ +/* */ +/* These routines handle distributed */ +/* matchings. */ +/* */ +/*************************************/ + +/* This routine checks the consistency of a +** given complete matching. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphMatchCheck ( +DgraphMatchData * restrict const mateptr) +{ + Gnum baseval; + Gnum * restrict flaggsttax; + int procngbnum; + Gnum multlocnbr; + Gnum multlocnum; + Gnum vertglbnnd; + Gnum vertlocnbr; + Gnum vertlocnnd; + Gnum vertlocnum; + Gnum vertlocadj; + int cheklocval; + int chekglbval; + + Dgraph * restrict const grafptr = mateptr->c.finegrafptr; + const int * restrict const procngbtab = grafptr->procngbtab; + const Gnum * restrict const mategsttax = mateptr->mategsttax; + DgraphCoarsenVert * restrict const vsnddattab = mateptr->c.vsnddattab; + const DgraphCoarsenMulti * restrict const multloctab = mateptr->c.multloctab; + const int * restrict const procgsttax = mateptr->c.procgsttax; + const Gnum * restrict const edgeloctax = grafptr->edgeloctax; + const Gnum * restrict const edgegsttax = grafptr->edgegsttax; + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + int * restrict const nsndidxtab = mateptr->c.nsndidxtab; + + baseval = grafptr->baseval; + + cheklocval = 0; + + multlocnbr = mateptr->c.multlocnbr; + if ((multlocnbr < 0) || (multlocnbr > grafptr->vertlocnbr)) { + errorPrint ("dgraphMatchCheck: invalid number of multinodes"); + cheklocval = 1; + } + + vertlocnbr = grafptr->vertlocnbr; + for (vertlocnum = baseval; vertlocnum < vertlocnbr; vertlocnum ++) { + if (mategsttax[vertlocnum] < 0) { + errorPrint ("dgraphMatchCheck: unmatched local vertex"); + cheklocval = 1; + break; + } + } + + if ((flaggsttax = memAlloc (grafptr->vertgstnbr * sizeof (Gnum))) == NULL) { + errorPrint ("dgraphMatchCheck: out of memory"); + cheklocval = 1; + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, mateptr->c.finegrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchCheck: communication error (1)"); + chekglbval = 1; + } + if (chekglbval != 0) { + if (flaggsttax != NULL) + memFree (flaggsttax); + return (1); + } + + for (procngbnum = 0; procngbnum < grafptr->procngbnbr; procngbnum ++) /* Reset indices for sending messages */ + nsndidxtab[procngbnum] = mateptr->c.vsnddsptab[procngbtab[procngbnum]]; + + memSet (flaggsttax, ~0, grafptr->vertgstnbr * sizeof (Gnum)); + flaggsttax -= baseval; + + vertglbnnd = grafptr->vertglbnbr + baseval; + vertlocnnd = grafptr->vertlocnnd; + vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - baseval; + for (multlocnum = 0; multlocnum < multlocnbr; multlocnum ++) { + Gnum vertglbnum; + Gnum vertlocnum; + Gnum vertglbend; + + vertglbnum = multloctab[multlocnum].vertglbnum[0]; + vertlocnum = vertglbnum - vertlocadj; /* First vertex is always local */ + if ((vertlocnum < baseval) || (vertlocnum >= vertlocnnd)) { + errorPrint ("dgraphMatchCheck: invalid multinode vertex (1)"); + goto abort; + } + if (flaggsttax[vertlocnum] != -1) { + errorPrint ("dgraphMatchCheck: duplicate multinode vertex (1)"); + goto abort; + } + flaggsttax[vertlocnum] = multlocnum + vertlocadj; + + vertglbend = multloctab[multlocnum].vertglbnum[1]; + if (vertglbend < 0) { /* If end vertex is remote */ + Gnum edgelocnum; + Gnum vertgstend; + int vsndidxnum; + int procngbnum; + + edgelocnum = -2 - vertglbend; + if ((edgelocnum < grafptr->baseval) || + (edgelocnum >= (grafptr->edgelocsiz + grafptr->baseval))) { + errorPrint ("dgraphMatchCheck: invalid multinode vertex (2)"); + goto abort; + } + + vertglbend = edgeloctax[edgelocnum]; + + if (mategsttax[vertlocnum] != vertglbend) { + errorPrint ("dgraphMatchCheck: invalid mate array (1)"); + goto abort; + } + + vertgstend = edgegsttax[edgelocnum]; + + if (flaggsttax[vertgstend] != -1) { + errorPrint ("dgraphMatchCheck: duplicate multinode vertex (2)"); + goto abort; + } + flaggsttax[vertgstend] = multlocnum + vertlocadj; + + if (mategsttax[vertgstend] != vertglbnum) { + errorPrint ("dgraphMatchCheck: invalid mate array (2)"); + goto abort; + } + + procngbnum = procgsttax[vertgstend]; /* Find neighbor owner process */ + if ((procngbnum < 0) || (procngbnum >= grafptr->procngbnbr)) { /* If neighbor had not been computed or is wrong */ + errorPrint ("dgraphMatchCheck: internal error (1)"); + goto abort; + } + if ((grafptr->procvrttab[procngbtab[procngbnum]] > vertglbend) || + (grafptr->procvrttab[procngbtab[procngbnum] + 1] <= vertglbend)) { + errorPrint ("dgraphMatchCheck: internal error (2)"); + goto abort; + } + + vsndidxnum = nsndidxtab[procngbnum] ++; /* Get position of message in send array */ + if (vsndidxnum >= mateptr->c.vsnddsptab[procngbtab[procngbnum] + 1]) { + errorPrint ("dgraphMatchCheck: internal error (3)"); + goto abort; + } + vsnddattab[vsndidxnum].datatab[0] = vertglbnum; + vsnddattab[vsndidxnum].datatab[1] = vertglbend; + } + else { /* End vertex is local */ + Gnum vertlocend; + Gnum edgelocnum; + Gnum edgelocnnd; + + if (mategsttax[vertlocnum] != vertglbend) { + errorPrint ("dgraphMatchCheck: invalid mate array (3)"); + goto abort; + } + + if (vertglbend == vertglbnum) /* If single multinode */ + continue; + + vertlocend = vertglbend - vertlocadj; + if ((vertlocend < baseval) || (vertlocend >= vertlocnnd)) { + errorPrint ("dgraphMatchCheck: invalid multinode vertex (3)"); + goto abort; + } + + edgelocnum = vertloctax[vertlocnum]; + edgelocnnd = vendloctax[vertlocnum]; + if (edgelocnum != edgelocnnd) { /* If first multinode vertex is not an isolated vertex */ + for ( ; ; edgelocnum ++) { /* Loop on edges of first multinode vertex */ + if (edgelocnum >= edgelocnnd) { /* If not a valid neighbor */ + errorPrint ("dgraphMatchCheck: invalid multinode vertex (4)"); + goto abort; + } + if (edgeloctax[edgelocnum] == vertglbend) /* If edge to end vertex found */ + break; + } + } + + if (flaggsttax[vertlocend] != -1) { + errorPrint ("dgraphMatchCheck: duplicate multinode vertex (3)"); + goto abort; + } + flaggsttax[vertlocend] = multlocnum + vertlocadj; + + if (mategsttax[vertlocend] != vertglbnum) { + errorPrint ("dgraphMatchCheck: invalid mate array (4)"); + goto abort; + } + } + } + cheklocval = -1; +abort: + cheklocval ++; + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, mateptr->c.finegrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchCheck: communication error (2)"); + chekglbval = 1; + } + if (chekglbval != 0) { + memFree (flaggsttax + baseval); + return (1); + } + +/* TODO: Send messages and check consistency of matching on the receiving side */ + + memFree (flaggsttax + baseval); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_match_scan.c b/scotch_6.0.3/src/libscotch/dgraph_match_scan.c new file mode 100644 index 00000000..b2e6a83c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_match_scan.c @@ -0,0 +1,282 @@ +/* Copyright 2008,2012,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_match_scan.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines define a generic scanning **/ +/** framework for distributed graph **/ +/** matching routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 04 dec 2008 **/ +/** to : 10 oct 2013 **/ +/** **/ +/************************************************************/ + +void +DGRAPHMATCHSCANNAME ( +DgraphMatchData * restrict const mateptr) +{ + int flagval; + Gnum vertlocnnd; + Gnum vertlocadj; + Gnum edgekptnbr; + Gnum queulocnbr; + Gnum matelocnbr; /* TRICK: Initial number of local mated vertices, from which are subtracted single multinodes */ + Gnum multlocnbr; + Gnum probmax; + + const Dgraph * restrict const grafptr = mateptr->c.finegrafptr; + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + const Gnum * restrict const edgegsttax = grafptr->edgegsttax; + Gnum * restrict const queuloctab = mateptr->queuloctab; + Gnum * restrict const mategsttax = mateptr->mategsttax; + DgraphCoarsenMulti * restrict const multloctab = mateptr->c.multloctab; + DGRAPHMATCHSCANINIT + + flagval = mateptr->c.flagval; /* Get flag value */ + vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; + vertlocnnd = grafptr->vertlocnnd; + matelocnbr = mateptr->matelocnbr; + multlocnbr = mateptr->c.multlocnbr; + edgekptnbr = mateptr->c.edgekptnbr; + + if (matelocnbr == 0) { /* If initial pass or nothing useful done */ + Gnum vertlocnnt; /* End of useable local vertices */ + Gnum vertlocnum; + + memSet (mategsttax + grafptr->baseval, ~0, grafptr->vertlocnbr * sizeof (Gnum)); /* No local vertices matched to date: wipe all unsatisfied queries */ + + queulocnbr = 0; /* Build queue from scratch */ + for (vertlocnum = grafptr->baseval, vertlocnnt = vertlocnnd; + vertlocnum < vertlocnnt; vertlocnum ++) { + Gnum edgelocnum; + Gnum edgelocnnd; + Gnum edgeendnbr; + Gnum edgefrenbr; + Gnum probval; + DGRAPHMATCHSCANCOUNTDECL + + if (mategsttax[vertlocnum] >= 0) /* If vertex has been matched by one of the previous ones, skip it */ + continue; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (mategsttax[vertlocnum] < -1) { /* Vertex must not be requesting yet */ + errorPrint ("dgraphMatchSc: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + DGRAPHMATCHSCANCOUNTINIT + + if (probval > probmax) { /* If vertex not active this turn */ + queuloctab[queulocnbr ++] = vertlocnum; /* Enqueue it for next time */ + continue; /* Skip to next vertex */ + } + + edgelocnum = vertloctax[vertlocnum]; + edgelocnnd = vendloctax[vertlocnum]; + if (((flagval & DGRAPHCOARSENNOMERGE) == 0) && /* If merging isolated vertices is allowed */ + ((edgelocnnd - edgelocnum) == 0)) { /* And if vertex is isolated */ + while (mategsttax[-- vertlocnnt] != ~0) ; /* Search for first matchable local "neighbor" */ + + mategsttax[vertlocnum] = (vertlocnnt + vertlocadj); /* At worst we will stop at vertlocnum */ + mategsttax[vertlocnnt] = (vertlocnum + vertlocadj); + multloctab[multlocnbr].vertglbnum[0] = (vertlocnum + vertlocadj); + multloctab[multlocnbr].vertglbnum[1] = (vertlocnnt + vertlocadj); + multlocnbr ++; /* One more coarse vertex created (two more local mates) */ + edgekptnbr += vendloctax[vertlocnnt] - vertloctax[vertlocnnt]; /* Add edges of other vertex only */ + continue; + } + + for (edgeendnbr = edgefrenbr = 0; edgelocnum < edgelocnnd; edgelocnum ++) { /* For all edges, count yet unmatched ends */ + Gnum vertgstend; + + vertgstend = edgegsttax[edgelocnum]; + if (mategsttax[vertgstend] == -1) { /* Count relevant free end vertices */ + DGRAPHMATCHSCANCOUNTSELECT + } + if (mategsttax[vertgstend] < 0) /* Count not yet assigned end vertices */ + edgeendnbr ++; + } + if (edgeendnbr <= 0) { /* If vertex has no possible neighbor */ + mategsttax[vertlocnum] = /* Create single multinode */ + multloctab[multlocnbr].vertglbnum[0] = + multloctab[multlocnbr].vertglbnum[1] = vertlocnum + vertlocadj; + multlocnbr ++; /* One more coarse vertex created */ + matelocnbr --; /* TRICK: But with only one vertex */ + edgekptnbr += edgelocnnd - vertloctax[vertlocnum]; + continue; + } + + if (edgefrenbr > 0) { /* If vertex has some free neighbor */ + Gnum vertgstend; + + edgefrenbr = intRandVal (edgefrenbr); /* Select one of them randomly */ + + for (edgelocnum = vertloctax[vertlocnum]; ; edgelocnum ++) { /* Loop again on edges */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgelocnum >= edgelocnnd) { + errorPrint ("dgraphMatchSc: internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + vertgstend = edgegsttax[edgelocnum]; + if (mategsttax[vertgstend] == -1) { /* If free end vertex found */ + if (DGRAPHMATCHSCANFINDSELECT) /* If it is the one we want */ + break; /* Exit loop */ + } + } + + if (vertgstend >= vertlocnnd) { /* If end vertex is a ghost vertex */ + queuloctab[queulocnbr ++] = vertlocnum; /* Enqueue vertex for communication processing */ + mategsttax[vertlocnum] = -2 - edgelocnum; /* Local vertex index codes edge number */ + } + else { /* Perform local matching */ + mategsttax[vertlocnum] = (vertgstend + vertlocadj); + mategsttax[vertgstend] = (vertlocnum + vertlocadj); + multloctab[multlocnbr].vertglbnum[0] = (vertlocnum + vertlocadj); + multloctab[multlocnbr].vertglbnum[1] = (vertgstend + vertlocadj); + multlocnbr ++; /* One more coarse vertex created (two more local mates) */ + edgekptnbr += (edgelocnnd - vertloctax[vertlocnum]) + (vendloctax[vertgstend] - vertloctax[vertgstend]) - 2; /* "-2" for collapsed arcs */ + } + } + else + queuloctab[queulocnbr ++] = vertlocnum; /* Enqueue vertex for next time */ + } + } + else { /* Vertices to consider are already enqueued */ + Gnum queulocnum; + Gnum queulocnew; + + for (queulocnum = queulocnew = 0, queulocnbr = mateptr->queulocnbr; queulocnum < queulocnbr; queulocnum ++) { /* For all vertices in queue */ + Gnum vertlocnum; + Gnum mategstnum; + + vertlocnum = queuloctab[queulocnum]; /* Get current vertex */ + mategstnum = mategsttax[vertlocnum]; + if (mategstnum > -1) /* If already mated */ + continue; /* Find another one */ + queuloctab[queulocnew ++] = vertlocnum; + if (mategstnum < -1) + mategsttax[vertlocnum] = -1; + } + queulocnbr = queulocnew; + + for (queulocnum = 0; queulocnum < queulocnbr; queulocnum ++) { /* For all vertices in queue */ + Gnum vertlocnum; + Gnum edgelocnum; + Gnum edgelocnnd; + Gnum edgeendnbr; + Gnum edgefrenbr; + Gnum probval; + DGRAPHMATCHSCANCOUNTDECL + + vertlocnum = queuloctab[queulocnum]; /* Get current vertex */ + if (mategsttax[vertlocnum] >= 0) /* If already mated */ + continue; /* Find another one */ + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (mategsttax[vertlocnum] < -1) { /* Vertex must not be requesting yet */ + errorPrint ("dgraphMatchSc: internal error (3)"); + return; + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + DGRAPHMATCHSCANCOUNTINIT + + if (probval > probmax) /* If vertex not active this turn */ + continue; /* Keep vertex enqueued and skip to next vertex */ + + edgelocnum = vertloctax[vertlocnum]; + edgelocnnd = vendloctax[vertlocnum]; /* No need to test for isolated vertices this turn */ + + for (edgeendnbr = edgefrenbr = 0; edgelocnum < edgelocnnd; edgelocnum ++) { /* For all edges, count yet unmatched ends */ + Gnum vertgstend; + + vertgstend = edgegsttax[edgelocnum]; + if (mategsttax[vertgstend] == -1) { /* Count free end vertices */ + DGRAPHMATCHSCANCOUNTSELECT + } + if (mategsttax[vertgstend] < 0) /* Count not yet assigned end vertices */ + edgeendnbr ++; + } + if (edgeendnbr <= 0) { /* If vertex has no possible neighbor */ + mategsttax[vertlocnum] = /* Create single multinode */ + multloctab[multlocnbr].vertglbnum[0] = + multloctab[multlocnbr].vertglbnum[1] = vertlocnum + vertlocadj; + multlocnbr ++; /* One more coarse vertex created */ + matelocnbr --; /* TRICK: But with only one vertex */ + edgekptnbr += edgelocnnd - vertloctax[vertlocnum]; + continue; + } + + if (edgefrenbr > 0) { /* If vertex has some free neighbor */ + Gnum vertgstend; + + edgefrenbr = intRandVal (edgefrenbr); /* Select one of them randomly */ + + for (edgelocnum = vertloctax[vertlocnum]; ; edgelocnum ++) { /* Loop again on edges */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgelocnum >= edgelocnnd) { + errorPrint ("dgraphMatchSc: internal error (4)"); + return; + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + vertgstend = edgegsttax[edgelocnum]; + if (mategsttax[vertgstend] == -1) { /* If free end vertex found */ + if (DGRAPHMATCHSCANFINDSELECT) /* If it is the one we want */ + break; /* Exit loop */ + } + } + + if (vertgstend >= vertlocnnd) /* If end vertex is a ghost vertex */ + mategsttax[vertlocnum] = -2 - edgelocnum; /* Local vertex index codes edge number */ + else { /* Perform local matching */ + mategsttax[vertlocnum] = (vertgstend + vertlocadj); + mategsttax[vertgstend] = (vertlocnum + vertlocadj); + multloctab[multlocnbr].vertglbnum[0] = (vertlocnum + vertlocadj); + multloctab[multlocnbr].vertglbnum[1] = (vertgstend + vertlocadj); + multlocnbr ++; /* One more coarse vertex created (two more local mates) */ + edgekptnbr += (edgelocnnd - vertloctax[vertlocnum]) + (vendloctax[vertgstend] - vertloctax[vertgstend]) - 1; + } + } /* Else vertex stays enqueued */ + } + } + + mateptr->matelocnbr = matelocnbr + 2 * (multlocnbr - mateptr->c.multlocnbr); /* TRICK: Two times new multinodes, minus single multinode adjustment */ + mateptr->queulocnbr = queulocnbr; + mateptr->c.multlocnbr = multlocnbr; + mateptr->c.edgekptnbr = edgekptnbr; +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_match_sync_coll.c b/scotch_6.0.3/src/libscotch/dgraph_match_sync_coll.c new file mode 100644 index 00000000..ba9dcf64 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_match_sync_coll.c @@ -0,0 +1,433 @@ +/* Copyright 2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_match_sync_coll.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This routine synchronizes the fragments **/ +/** of a distributed matching by means of **/ +/** collective communications. **/ +/** **/ +/** DATES : # Version 5.1 : from : 06 feb 2009 **/ +/** to : 22 apr 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_MATCH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "dgraph_match.h" + +/*************************************/ +/* */ +/* These routines handle distributed */ +/* source graphs. */ +/* */ +/*************************************/ + +/* This routine performs a round of communication +** to synchronize enqueued matching requests across +** processors. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphMatchSyncColl ( +DgraphMatchData * restrict const mateptr) +{ + Gnum queulocnbr; + Gnum queulocnum; + Gnum matelocnbr; + Gnum multlocnbr; + Gnum vertlocadj; + Gnum edgekptnbr; + int procngbnbr; + int procngbidx; + int procngbnum; + int * restrict vsndcnttab; + int * restrict vrcvcnttab; + int * restrict vsnddsptab; + int * restrict vrcvdsptab; + + Dgraph * restrict const grafptr = mateptr->c.finegrafptr; + const int * restrict const procngbtab = grafptr->procngbtab; + int * restrict const procgsttax = mateptr->c.procgsttax; + const Gnum * restrict const procvgbtab = mateptr->procvgbtab; + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + const Gnum * restrict const edgeloctax = grafptr->edgeloctax; + const Gnum * restrict const edgegsttax = grafptr->edgegsttax; + Gnum * restrict const queuloctab = mateptr->queuloctab; + Gnum * restrict const mategsttax = mateptr->mategsttax; + DgraphCoarsenMulti * restrict const multloctab = mateptr->c.multloctab; + int * restrict const nsndidxtab = mateptr->c.nsndidxtab; + DgraphCoarsenVert * const vsnddattab = mateptr->c.vsnddattab; /* [norestrict:async] */ + + procngbnbr = grafptr->procngbnbr; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgeloctax == NULL) { + errorPrint ("dgraphMatchSyncColl: not implemented"); + return (1); + } + if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncColl: communication error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if ((vsnddsptab = memAlloc (4 * grafptr->procglbnbr * sizeof (int))) == NULL) { + errorPrint ("dgraphMatchSyncColl: out of memory"); + return (1); + } + vsndcnttab = vsnddsptab + grafptr->procglbnbr; /* TRICK: put vsnddsptab, vsndcnttab, vrcvdsptab in order for memSet() */ + vrcvdsptab = vsndcnttab + grafptr->procglbnbr; + vrcvcnttab = vrcvdsptab + grafptr->procglbnbr; + + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) /* Reset indices for sending messages */ + nsndidxtab[procngbnum] = mateptr->c.vsnddsptab[procngbtab[procngbnum]]; + + vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; + for (queulocnum = 0, queulocnbr = mateptr->queulocnbr; queulocnum < queulocnbr; queulocnum ++) { + Gnum vertlocnum; + Gnum vertgstnum; + Gnum edgelocnum; + Gnum mategstnum; + Gnum mateglbnum; + int procngbnum; + int vsndidxnum; + + vertlocnum = queuloctab[queulocnum]; /* Get local vertex index */ + mategstnum = mategsttax[vertlocnum]; /* Get mate (edge ?) index */ + + if (mategstnum >= -1) /* If vertex not willing to mate or matched locally after being considered during matching phase */ + continue; + + edgelocnum = -2 - mategstnum; /* Get local edge to mate ghost vertex */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((edgelocnum < grafptr->baseval) || + (edgelocnum >= (grafptr->edgelocsiz + grafptr->baseval)) || + (mategsttax[edgegsttax[edgelocnum]] != -1)) { + errorPrint ("dgraphMatchSyncColl: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + mateglbnum = edgeloctax[edgelocnum]; + + vertgstnum = edgegsttax[edgelocnum]; + procngbnum = procgsttax[vertgstnum]; /* Find neighbor owner process */ + if (procngbnum < 0) { /* If neighbor not yet computed */ + int procngbmax; + + procngbnum = 0; + procngbmax = procngbnbr; + while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (procvgbtab[procngbmed] > mateglbnum) + procngbmax = procngbmed; + else + procngbnum = procngbmed; + } + procgsttax[vertgstnum] = procngbnum; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((grafptr->procvrttab[procngbtab[procngbnum]] > mateglbnum) || + (grafptr->procvrttab[procngbtab[procngbnum] + 1] <= mateglbnum)) { + errorPrint ("dgraphMatchSyncColl: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + vsndidxnum = nsndidxtab[procngbnum] ++; /* Get position of message in send array */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (vsndidxnum >= mateptr->c.vsnddsptab[procngbtab[procngbnum] + 1]) { + errorPrint ("dgraphMatchSyncColl: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + vsnddattab[vsndidxnum].datatab[0] = vertlocnum + vertlocadj; + vsnddattab[vsndidxnum].datatab[1] = mateglbnum; + } + + memSet (vsnddsptab, 0, 3 * grafptr->procglbnbr * sizeof (int)); /* TRICK: resets vsnddsptab, vsndcnttab, vrcvdsptab */ + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { + int procglbnum; + + procglbnum = procngbtab[procngbnum]; + vrcvdsptab[procglbnum] = 2 * mateptr->c.vrcvdsptab[procglbnum]; /* Times 2 because a "DgraphCoarsenVert" is two "Gnum"s */ + vsnddsptab[procglbnum] = 2 * mateptr->c.vsnddsptab[procglbnum]; + vsndcnttab[procglbnum] = 2 * (nsndidxtab[procngbnum] - mateptr->c.vsnddsptab[procglbnum]); + } + + if (MPI_Alltoall (vsndcnttab, 1, MPI_INT, vrcvcnttab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncColl: communication error (2)"); + return (1); + } + if (MPI_Alltoallv (vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, + mateptr->c.vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncColl: communication error (3)"); + return (1); + } + + matelocnbr = mateptr->matelocnbr; + multlocnbr = mateptr->c.multlocnbr; + edgekptnbr = mateptr->c.edgekptnbr; + + for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { + int procngbnum; + int procglbnum; + int vrcvidxnnd; + int requrcvnum; + int requnxtnum; /* Index of location where to pack requests to process when all messages arrive */ + + procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; + procglbnum = procngbtab[procngbnum]; + vrcvidxnnd = mateptr->c.vrcvdsptab[procglbnum]; + if (vrcvcnttab[procglbnum] > 0) { /* If query message is not empty */ + Gnum vertsndnbr; /* Number of vertices to be sent to requesting neighbor */ + Gnum edgesndnbr; /* Number of edges to be sent to requesting neighbor */ + + DgraphCoarsenVert * restrict const vrcvdattab = mateptr->c.vrcvdattab; /* Local restrict pointer only when data available */ + + vertsndnbr = + edgesndnbr = 0; + for (requrcvnum = requnxtnum = vrcvidxnnd, vrcvidxnnd += (vrcvcnttab[procglbnum] / 2); /* TRICK: each message item costs 2 Gnum's */ + requrcvnum < vrcvidxnnd; requrcvnum ++) { + Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ + Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ + Gnum vmatglbnum; /* Global number of requesting mate (sender of message) */ + Gnum mategstnum; /* The mate we wanted to ask for */ + + vmatglbnum = vrcvdattab[requrcvnum].datatab[0]; /* Names are opposite because receiving side */ + vertglbnum = vrcvdattab[requrcvnum].datatab[1]; + vertlocnum = vertglbnum - vertlocadj; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocnum < grafptr->baseval) || /* If matching request is not directed towards our process */ + (vertlocnum >= grafptr->vertlocnnd)) { + errorPrint ("dgraphMatchSyncColl: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + mategstnum = mategsttax[vertlocnum]; /* Get our local mating decision data */ + if (mategstnum == -1) { /* If local vertex wanted for mating is free */ + Gnum edgelocnum; + + for (edgelocnum = vertloctax[vertlocnum]; edgeloctax[edgelocnum] != vmatglbnum; edgelocnum ++) { +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgelocnum >= vendloctax[vertlocnum]) { + errorPrint ("dgraphMatchSyncColl: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + } + mategsttax[edgegsttax[edgelocnum]] = vertglbnum; /* We are no longer free */ + mategsttax[vertlocnum] = vmatglbnum; /* Leave message as is to acknowledge it */ + matelocnbr ++; + vertsndnbr ++; + edgesndnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + } + else if (mategstnum < -1) { /* If local vertex is also asking for mating */ + Gnum edgelocnum; + Gnum mateglbnum; + + edgelocnum = -2 - mategstnum; + mateglbnum = edgeloctax[edgelocnum]; /* Get global number of our remote mate */ + if (mateglbnum == vmatglbnum) { /* If it is with the sender */ + Gnum flagval; /* Flag for choosing side to create multinode */ + + mategsttax[vertlocnum] = mateglbnum; /* Say we are mated to inform future requesting processes in same pass */ + mategsttax[edgegsttax[edgelocnum]] = vertglbnum; + flagval = (mateglbnum > vertglbnum) ? 1 : 0; /* Compute pseudo-random flag always opposite for both ends */ + flagval = ((mateglbnum + (mateglbnum - vertglbnum) * flagval) & 1) ^ flagval; + if (flagval == 0) { /* If flag is even, create multinode */ + multloctab[multlocnbr].vertglbnum[0] = vertglbnum; + multloctab[multlocnbr].vertglbnum[1] = mategstnum; /* Remote mate: negative value */ + multlocnbr ++; /* One more coarse vertex created */ + edgekptnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + } + else { /* If flag is odd, prepare to send vertex data at build time */ + vertsndnbr ++; + edgesndnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + } /* Go on by destroying message in all cases since both ends know what it is about */ + + vrcvdattab[requrcvnum --] = vrcvdattab[-- vrcvidxnnd]; /* Replace current message with another one and process it */ + matelocnbr ++; /* One more local vertex mated on each side; no messages will tell it */ + } + else { /* If willing to mate but not with the sender, tell later with whom */ + DgraphCoarsenVert vertdat; /* Temporary storage data for swapping vertices */ + + vertdat = vrcvdattab[requnxtnum]; /* Pack requests to process later at beginning of message */ + vrcvdattab[requnxtnum].datatab[0] = vmatglbnum; + vrcvdattab[requnxtnum].datatab[1] = -2 - vertlocnum; /* Build appropriate answer to mating request later, when all messages arrived */ + if (requnxtnum ++ != requrcvnum) + vrcvdattab[requrcvnum] = vertdat; /* Swap vertices if not already at the right place */ + } + } + else /* If already matched, inform sender */ + vrcvdattab[requrcvnum].datatab[1] = mategstnum; + } + mateptr->c.dcntloctab[procglbnum].vertsndnbr += vertsndnbr; + mateptr->c.dcntloctab[procglbnum].edgesndnbr += edgesndnbr; + } + mateptr->c.nrcvidxtab[procngbnum] = vrcvidxnnd; + } + + for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { + int procngbnum; + int procglbnum; + int vsndidxnnd; + int vsndidxnum; + + DgraphCoarsenVert * restrict const vrcvdattab = mateptr->c.vrcvdattab; /* Local restrict pointer only once data received */ + + procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; + procglbnum = procngbtab[procngbnum]; + vsndidxnnd = mateptr->c.nrcvidxtab[procngbnum]; /* Re-send the messages we have received to acknowledge */ + + for (vsndidxnum = mateptr->c.vrcvdsptab[procglbnum]; /* Finalize unfinished messages */ + vsndidxnum < vsndidxnnd; vsndidxnum ++) { + Gnum vertlocnum; + Gnum mateglbnum; + + vertlocnum = vrcvdattab[vsndidxnum].datatab[1]; + if (vertlocnum >= 0) /* If no more unfinished messages to process, quit scanning */ + break; + vertlocnum = -2 - vertlocnum; + mateglbnum = mategsttax[vertlocnum]; + if (mateglbnum >= 0) /* If vertex we wanted to mate with has been mated in this round */ + vrcvdattab[vsndidxnum].datatab[1] = mateglbnum; /* Propagate this information back to the requester */ + else { /* Vertex mating data not yet available (maybe in answer) */ + vrcvdattab[vsndidxnum] = vrcvdattab[-- vsndidxnnd]; /* Remove message as no reply means not willing */ + if (vrcvdattab[vsndidxnum].datatab[1] < 0) /* If replacing message is also to be processed */ + vsndidxnum --; /* Do not skip replaced message in next iteration */ + } + } + + if (vsndidxnnd < (mateptr->c.vrcvdsptab[procglbnum] + (vrcvcnttab[procglbnum] / 2))) { /* If space created */ + vrcvdattab[vsndidxnnd].datatab[0] = /* Indicate end of useful data */ + vrcvdattab[vsndidxnnd].datatab[1] = -1; + } + } + + if (MPI_Alltoallv (mateptr->c.vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, + vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncColl: communication error (3)"); + return (1); + } + + for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { + int procngbnum; + int procglbnum; + int vrcvidxnnd; + int vrcvidxnum; + + procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; + procglbnum = procngbtab[procngbnum]; + for (vrcvidxnum = mateptr->c.vsnddsptab[procglbnum], + vrcvidxnnd = vrcvidxnum + (vsndcnttab[procglbnum] / 2); /* TRICK: each message item costs 2 Gnum's */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum edgelocnum; + Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ + Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ + Gnum vmatglbnum; /* Global number of vertex to which the mate is mated */ + Gnum mategstnum; /* The mate we wanted to ask for */ + + vertglbnum = vsnddattab[vrcvidxnum].datatab[0]; + if (vertglbnum == -1) /* If end of useful space reached */ + break; + + vmatglbnum = vsnddattab[vrcvidxnum].datatab[1]; + vertlocnum = vertglbnum - vertlocadj; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocnum < grafptr->baseval) || /* If matching reply is not directed towards our process */ + (vertlocnum >= grafptr->vertlocnnd)) { + errorPrint ("dgraphMatchSyncColl: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + mategstnum = mategsttax[vertlocnum]; /* Get our local mating decision data */ + edgelocnum = -2 - mategstnum; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((mategstnum >= -1) || /* If we did not ask anything or if we were already matched, no reply message should come to us */ + ((mategsttax[edgegsttax[edgelocnum]] >= 0) && /* Also, if our prospective mate was itself already set as matched by a previous reply */ + (mategsttax[edgegsttax[edgelocnum]] != vertglbnum) && /* And this message is not the positive reply which acknowledges this mating */ + (mategsttax[edgegsttax[edgelocnum]] != vmatglbnum))) { /* Or an informative negative reply which gives again the mate of the ghost */ + errorPrint ("dgraphMatchSyncColl: internal error (9)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (edgeloctax[edgelocnum] == vmatglbnum) { /* If positive answer from the mate we wanted */ + mategsttax[vertlocnum] = vmatglbnum; /* Set local vertex as matched with the mate */ + mategsttax[edgegsttax[edgelocnum]] = vertglbnum; /* Update state of ghost mate */ + multloctab[multlocnbr].vertglbnum[0] = vertglbnum; + multloctab[multlocnbr].vertglbnum[1] = mategstnum; /* Remote mate: negative value */ + multlocnbr ++; /* One more coarse vertex created */ + matelocnbr ++; + edgekptnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + } + else { /* If negative answer from the mate we wanted */ + mategsttax[vertlocnum] = -1; /* Reset local vertex as free for mating */ + mategsttax[edgegsttax[edgelocnum]] = vmatglbnum; /* Update state of unwilling ghost mate */ + } + } + } + + mateptr->matelocnbr = matelocnbr; + mateptr->c.multlocnbr = multlocnbr; + mateptr->c.edgekptnbr = edgekptnbr; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncColl: communication error (11)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + memFree (vsnddsptab); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_match_sync_ptop.c b/scotch_6.0.3/src/libscotch/dgraph_match_sync_ptop.c new file mode 100644 index 00000000..ccde4963 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_match_sync_ptop.c @@ -0,0 +1,512 @@ +/* Copyright 2008,2009,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_match_sync_ptop.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed graph matching **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2008 **/ +/** to : 22 apr 2009 **/ +/** # Version 6.0 : from : 03 apr 2012 **/ +/** to : 03 apr 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_MATCH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "dgraph_match.h" + +/*************************************/ +/* */ +/* These routines handle distributed */ +/* source graphs. */ +/* */ +/*************************************/ + +/* This routine performs a round of point-to-point +** communication to synchronize enqueued matching +** requests across processors. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphMatchSyncPtop ( +DgraphMatchData * restrict const mateptr) +{ + Gnum queulocnbr; + Gnum queulocnum; + Gnum matelocnbr; + Gnum multlocnbr; + Gnum vertlocadj; + Gnum edgekptnbr; + int procngbnbr; + int procngbidx; + int procngbnum; + int vrcvreqnbr; + + Dgraph * restrict const grafptr = mateptr->c.finegrafptr; + const int * restrict const procngbtab = grafptr->procngbtab; + int * restrict const procgsttax = mateptr->c.procgsttax; + const Gnum * restrict const procvgbtab = mateptr->procvgbtab; + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + const Gnum * restrict const edgeloctax = grafptr->edgeloctax; + const Gnum * restrict const edgegsttax = grafptr->edgegsttax; + Gnum * restrict const queuloctab = mateptr->queuloctab; + Gnum * restrict const mategsttax = mateptr->mategsttax; + DgraphCoarsenMulti * restrict const multloctab = mateptr->c.multloctab; + int * restrict const nsndidxtab = mateptr->c.nsndidxtab; + DgraphCoarsenVert * const vsnddattab = mateptr->c.vsnddattab; /* [norestrict:async] */ + + procngbnbr = grafptr->procngbnbr; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgeloctax == NULL) { + errorPrint ("dgraphMatchSyncPtop: not implemented"); + return (1); + } + if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncPtop: communication error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) /* Reset indices for sending messages */ + nsndidxtab[procngbnum] = mateptr->c.vsnddsptab[procngbtab[procngbnum]]; + + vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; + for (queulocnum = 0, queulocnbr = mateptr->queulocnbr; queulocnum < queulocnbr; queulocnum ++) { + Gnum vertlocnum; + Gnum vertgstnum; + Gnum edgelocnum; + Gnum mategstnum; + Gnum mateglbnum; + int procngbnum; + int vsndidxnum; + + vertlocnum = queuloctab[queulocnum]; /* Get local vertex index */ + mategstnum = mategsttax[vertlocnum]; /* Get mate (edge ?) index */ + + if (mategstnum >= -1) /* If vertex not willing to mate or matched locally after being considered during matching phase */ + continue; + + edgelocnum = -2 - mategstnum; /* Get local edge to mate ghost vertex */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((edgelocnum < grafptr->baseval) || + (edgelocnum >= (grafptr->edgelocsiz + grafptr->baseval)) || + (mategsttax[edgegsttax[edgelocnum]] != -1)) { + errorPrint ("dgraphMatchSyncPtop: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + mateglbnum = edgeloctax[edgelocnum]; + + vertgstnum = edgegsttax[edgelocnum]; + procngbnum = procgsttax[vertgstnum]; /* Find neighbor owner process */ + if (procngbnum < 0) { /* If neighbor not yet computed */ + int procngbmax; + + procngbnum = 0; + procngbmax = procngbnbr; + while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (procvgbtab[procngbmed] > mateglbnum) + procngbmax = procngbmed; + else + procngbnum = procngbmed; + } + procgsttax[vertgstnum] = procngbnum; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((grafptr->procvrttab[procngbtab[procngbnum]] > mateglbnum) || + (grafptr->procvrttab[procngbtab[procngbnum] + 1] <= mateglbnum)) { + errorPrint ("dgraphMatchSyncPtop: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + vsndidxnum = nsndidxtab[procngbnum] ++; /* Get position of message in send array */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (vsndidxnum >= mateptr->c.vsnddsptab[procngbtab[procngbnum] + 1]) { + errorPrint ("dgraphMatchSyncPtop: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + vsnddattab[vsndidxnum].datatab[0] = vertlocnum + vertlocadj; + vsnddattab[vsndidxnum].datatab[1] = mateglbnum; + } + + for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { /* Post receives of mating requests in descending order */ + int procngbnum; + int procglbnum; + + procngbnum = (mateptr->c.procngbnxt + (procngbnbr - 1) - procngbidx) % procngbnbr; + procglbnum = procngbtab[procngbnum]; + if (MPI_Irecv (mateptr->c.vrcvdattab + mateptr->c.vrcvdsptab[procglbnum], + 2 * (mateptr->c.vrcvdsptab[procglbnum + 1] - mateptr->c.vrcvdsptab[procglbnum]), GNUM_MPI, + procglbnum, TAGMATCH, grafptr->proccomm, &mateptr->c.nrcvreqtab[procngbnum]) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncPtop: communication error (2)"); + return (1); + } + } + + for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { /* Post sends of mating requests in ascending order */ + int procngbnum; + int procglbnum; + + procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; + procglbnum = procngbtab[procngbnum]; + if (MPI_Isend (vsnddattab + mateptr->c.vsnddsptab[procglbnum], + 2 * (nsndidxtab[procngbnum] - mateptr->c.vsnddsptab[procglbnum]), GNUM_MPI, + procglbnum, TAGMATCH, grafptr->proccomm, &mateptr->c.nsndreqtab[procngbnum]) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncPtop: communication error (3)"); + return (1); + } + } + + matelocnbr = mateptr->matelocnbr; + multlocnbr = mateptr->c.multlocnbr; + edgekptnbr = mateptr->c.edgekptnbr; + + for (vrcvreqnbr = procngbnbr; vrcvreqnbr > 0; vrcvreqnbr --) { /* For all pending receive requests */ + int procglbnum; + int procngbnum; + int vrcvidxnnd; + int requrcvnum; + int requnxtnum; /* Index of location where to pack requests to process when all messages arrive */ + MPI_Status statdat; + int statsiz; + int o; + +#ifdef SCOTCH_DETERMINISTIC + procngbnum = vrcvreqnbr - 1; + o = MPI_Wait (&mateptr->c.nrcvreqtab[procngbnum], &statdat); +#else /* SCOTCH_DETERMINISTIC */ + o = MPI_Waitany (procngbnbr, mateptr->c.nrcvreqtab, &procngbnum, &statdat); +#endif /* SCOTCH_DETERMINISTIC */ + if ((o != MPI_SUCCESS) || + (MPI_Get_count (&statdat, GNUM_MPI, &statsiz) != MPI_SUCCESS)) { + errorPrint ("dgraphMatchSyncPtop: communication error (4)"); + return (1); + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (statdat.MPI_SOURCE != procngbtab[procngbnum]) { + errorPrint ("dgraphMatchSyncPtop: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + procglbnum = procngbtab[procngbnum]; + vrcvidxnnd = mateptr->c.vrcvdsptab[procglbnum]; + if (statsiz <= 0) { /* If query message is empty */ + mateptr->c.nrcvidxtab[procngbnum] = -1; /* No need to send a reply */ + continue; /* Skip message processing */ + } + else { + Gnum vertsndnbr; /* Number of vertices to be sent to requesting neighbor */ + Gnum edgesndnbr; /* Number of edges to be sent to requesting neighbor */ + + DgraphCoarsenVert * restrict const vrcvdattab = mateptr->c.vrcvdattab; /* Local restrict pointer only when data available (has been received) */ + + vertsndnbr = + edgesndnbr = 0; + for (requrcvnum = requnxtnum = vrcvidxnnd, vrcvidxnnd += (statsiz / 2); /* TRICK: each message item costs 2 Gnum's */ + requrcvnum < vrcvidxnnd; requrcvnum ++) { + Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ + Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ + Gnum vmatglbnum; /* Global number of requesting mate (sender of message) */ + Gnum mategstnum; /* The mate we wanted to ask for */ + + vmatglbnum = vrcvdattab[requrcvnum].datatab[0]; /* Names are opposite because receiving side */ + vertglbnum = vrcvdattab[requrcvnum].datatab[1]; + vertlocnum = vertglbnum - vertlocadj; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocnum < grafptr->baseval) || /* If matching request is not directed towards our process */ + (vertlocnum >= grafptr->vertlocnnd)) { + errorPrint ("dgraphMatchSyncPtop: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + mategstnum = mategsttax[vertlocnum]; /* Get our local mating decision data */ + if (mategstnum == -1) { /* If local vertex wanted for mating is free */ + Gnum edgelocnum; + + for (edgelocnum = vertloctax[vertlocnum]; edgeloctax[edgelocnum] != vmatglbnum; edgelocnum ++) { +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (edgelocnum >= vendloctax[vertlocnum]) { + errorPrint ("dgraphMatchSyncPtop: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + } + mategsttax[edgegsttax[edgelocnum]] = vertglbnum; /* We are no longer free */ + mategsttax[vertlocnum] = vmatglbnum; /* Leave message as is to acknowledge it */ + matelocnbr ++; + vertsndnbr ++; + edgesndnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + } + else if (mategstnum < -1) { /* If local vertex is also asking for mating */ + Gnum edgelocnum; + Gnum mateglbnum; + + edgelocnum = -2 - mategstnum; + mateglbnum = edgeloctax[edgelocnum]; /* Get global number of our remote mate */ + if (mateglbnum == vmatglbnum) { /* If it is with the sender */ + Gnum flagval; /* Flag for choosing side to create multinode */ + + mategsttax[vertlocnum] = mateglbnum; /* Say we are mated to inform future requesting processes in same pass */ + mategsttax[edgegsttax[edgelocnum]] = vertglbnum; + flagval = (mateglbnum > vertglbnum) ? 1 : 0; /* Compute pseudo-random flag always opposite for both ends */ + flagval = ((mateglbnum + (mateglbnum - vertglbnum) * flagval) & 1) ^ flagval; + if (flagval == 0) { /* If flag is even, create multinode */ + multloctab[multlocnbr].vertglbnum[0] = vertglbnum; + multloctab[multlocnbr].vertglbnum[1] = mategstnum; /* Remote mate: negative value */ + multlocnbr ++; /* One more coarse vertex created */ + edgekptnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + } + else { /* If flag is odd, prepare to send vertex data at build time */ + vertsndnbr ++; + edgesndnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + } /* Go on by destroying message in all cases since both ends know what it is about */ + + vrcvdattab[requrcvnum --] = vrcvdattab[-- vrcvidxnnd]; /* Replace current message with another one and process it */ + matelocnbr ++; /* One more local vertex mated on each side; no messages will tell it */ + } + else { /* If willing to mate but not with the sender, tell later with whom */ + DgraphCoarsenVert vertdat; /* Temporary storage data for swapping vertices */ + + vertdat = vrcvdattab[requnxtnum]; /* Pack requests to process later at beginning of message */ + vrcvdattab[requnxtnum].datatab[0] = vmatglbnum; + vrcvdattab[requnxtnum].datatab[1] = -2 - vertlocnum; /* Build appropriate answer to mating request later, when all messages arrived */ + if (requnxtnum ++ != requrcvnum) + vrcvdattab[requrcvnum] = vertdat; /* Swap vertices if not already at the right place */ + } + } + else /* If already matched, inform sender */ + vrcvdattab[requrcvnum].datatab[1] = mategstnum; + } + mateptr->c.dcntloctab[procglbnum].vertsndnbr += vertsndnbr; + mateptr->c.dcntloctab[procglbnum].edgesndnbr += edgesndnbr; + } + mateptr->c.nrcvidxtab[procngbnum] = vrcvidxnnd; + } + + if (MPI_Waitall (procngbnbr, mateptr->c.nsndreqtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for send requests of mating requests to complete */ + errorPrint ("dgraphMatchSyncPtop: communication error (5)"); + return (1); + } + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncPtop: communication error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + vrcvreqnbr = procngbnbr; /* Count number of receive requests we will have to consider */ + for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { /* Post receives of mating replies in descending order */ + int procngbnum; + int procglbnum; + + procngbnum = (mateptr->c.procngbnxt + (procngbnbr - 1) - procngbidx) % procngbnbr; + procglbnum = procngbtab[procngbnum]; + + if (nsndidxtab[procngbnum] <= mateptr->c.vsnddsptab[procglbnum]) { /* If we had sent an empty query message, do not expect any reply */ + mateptr->c.nrcvreqtab[procngbnum] = MPI_REQUEST_NULL; + vrcvreqnbr --; /* One less receive request to wait for */ + continue; + } + + if (MPI_Irecv (vsnddattab + mateptr->c.vsnddsptab[procglbnum], + 2 * (mateptr->c.vsnddsptab[procglbnum + 1] - mateptr->c.vsnddsptab[procglbnum]), GNUM_MPI, + procglbnum, TAGMATCH + 1, grafptr->proccomm, &mateptr->c.nrcvreqtab[procngbnum]) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncPtop: communication error (7)"); + return (1); + } + } + + for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { /* Post sends of mating requests in ascending order */ + int procngbnum; + int procglbnum; + int vsndidxnnd; + + procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; + procglbnum = procngbtab[procngbnum]; + vsndidxnnd = mateptr->c.nrcvidxtab[procngbnum]; /* Re-send (or not) the messages we have received to acknowledge */ + if (vsndidxnnd >= 0) { /* If we had received a non-empty message (but reply might be empty) */ + int vsndidxnum; + + DgraphCoarsenVert * restrict const vrcvdattab = mateptr->c.vrcvdattab; /* Local restrict pointer only when data available */ + + for (vsndidxnum = mateptr->c.vrcvdsptab[procglbnum]; /* Finalize unfinished messages */ + vsndidxnum < vsndidxnnd; vsndidxnum ++) { + Gnum vertlocnum; + Gnum mateglbnum; + + vertlocnum = vrcvdattab[vsndidxnum].datatab[1]; + if (vertlocnum >= 0) /* If no more unfinished messages to process, quit scanning */ + break; + vertlocnum = -2 - vertlocnum; + mateglbnum = mategsttax[vertlocnum]; + if (mateglbnum >= 0) /* If vertex we wanted to mate with has been mated in this round */ + vrcvdattab[vsndidxnum].datatab[1] = mateglbnum; /* Propagate this information back to the requester */ + else { /* Vertex mating data not yet available (maybe in answer) */ + vrcvdattab[vsndidxnum] = vrcvdattab[-- vsndidxnnd]; /* Remove message as no reply means not willing */ + if (vrcvdattab[vsndidxnum].datatab[1] < 0) /* If replacing message is also to be processed */ + vsndidxnum --; /* Do not skip replaced message in next iteration */ + } + } + + if (MPI_Isend (vrcvdattab + mateptr->c.vrcvdsptab[procglbnum], 2 * (vsndidxnnd - mateptr->c.vrcvdsptab[procglbnum]), GNUM_MPI, + procglbnum, TAGMATCH + 1, grafptr->proccomm, &mateptr->c.nsndreqtab[procngbnum]) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncPtop: communication error (8)"); + return (1); + } + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + else { + if (mateptr->c.nsndreqtab[procngbnum] != MPI_REQUEST_NULL) { /* Should have been set by previous MPI_Waitall() */ + errorPrint ("dgraphMatchSyncPtop: internal error (7)"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + } + +#ifdef SCOTCH_DETERMINISTIC + vrcvreqnbr = procngbnbr; /* For deterministic behavior, consider all neighbors in order, whether communicating or not */ +#endif /* SCOTCH_DETERMINISTIC */ + for ( ; vrcvreqnbr > 0; vrcvreqnbr --) { /* For all pending receive requests */ + int vrcvidxnnd; + int vrcvidxnum; + int procngbnum; + MPI_Status statdat; + int statsiz; + int o; + +#ifdef SCOTCH_DETERMINISTIC + procngbnum = vrcvreqnbr - 1; + if (mateptr->c.nrcvreqtab[procngbnum] == MPI_REQUEST_NULL) /* If we do not expect this message, skip it */ + continue; + o = MPI_Wait (&mateptr->c.nrcvreqtab[procngbnum], &statdat); +#else /* SCOTCH_DETERMINISTIC */ + o = MPI_Waitany (procngbnbr, mateptr->c.nrcvreqtab, &procngbnum, &statdat); +#endif /* SCOTCH_DETERMINISTIC */ + if ((o != MPI_SUCCESS) || + (MPI_Get_count (&statdat, GNUM_MPI, &statsiz) != MPI_SUCCESS)) { + errorPrint ("dgraphMatchSyncPtop: communication error (9)"); + return (1); + } + + for (vrcvidxnum = mateptr->c.vsnddsptab[procngbtab[procngbnum]], vrcvidxnnd = vrcvidxnum + (statsiz / 2); /* TRICK: each message item costs 2 Gnum's */ + vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { + Gnum edgelocnum; + Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ + Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ + Gnum vmatglbnum; /* Global number of vertex to which the mate is mated */ + Gnum mategstnum; /* The mate we wanted to ask for */ + + vertglbnum = vsnddattab[vrcvidxnum].datatab[0]; + vmatglbnum = vsnddattab[vrcvidxnum].datatab[1]; + vertlocnum = vertglbnum - vertlocadj; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((vertlocnum < grafptr->baseval) || /* If matching reply is not directed towards our process */ + (vertlocnum >= grafptr->vertlocnnd)) { + errorPrint ("dgraphMatchSyncPtop: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + mategstnum = mategsttax[vertlocnum]; /* Get our local mating decision data */ + edgelocnum = -2 - mategstnum; +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((mategstnum >= -1) || /* If we did not ask anything or if we were already matched, no reply message should come to us */ + ((mategsttax[edgegsttax[edgelocnum]] >= 0) && /* Also, if our prospective mate was itself already set as matched by a previous reply */ + (mategsttax[edgegsttax[edgelocnum]] != vertglbnum) && /* And this message is not the positive reply which acknowledges this mating */ + (mategsttax[edgegsttax[edgelocnum]] != vmatglbnum))) { /* Or an informative negative reply which gives again the mate of the ghost */ + errorPrint ("dgraphMatchSyncPtop: internal error (9)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (edgeloctax[edgelocnum] == vmatglbnum) { /* If positive answer from the mate we wanted */ + mategsttax[vertlocnum] = vmatglbnum; /* Set local vertex as matched with the mate */ + mategsttax[edgegsttax[edgelocnum]] = vertglbnum; /* Update state of ghost mate */ + multloctab[multlocnbr].vertglbnum[0] = vertglbnum; + multloctab[multlocnbr].vertglbnum[1] = mategstnum; /* Remote mate: negative value */ + multlocnbr ++; /* One more coarse vertex created */ + matelocnbr ++; + edgekptnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; + } + else { /* If negative answer from the mate we wanted */ + mategsttax[vertlocnum] = -1; /* Reset local vertex as free for mating */ + mategsttax[edgegsttax[edgelocnum]] = vmatglbnum; /* Update state of unwilling ghost mate */ + } + } + } + + mateptr->matelocnbr = matelocnbr; + mateptr->c.multlocnbr = multlocnbr; + mateptr->c.edgekptnbr = edgekptnbr; + + if (MPI_Waitall (procngbnbr, mateptr->c.nsndreqtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for send requests of mating requests to complete */ + errorPrint ("dgraphMatchSyncPtop: communication error (10)"); + return (1); + } + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphMatchSyncPtop: communication error (11)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_redist.c b/scotch_6.0.3/src/libscotch/dgraph_redist.c new file mode 100644 index 00000000..a9b82a4c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_redist.c @@ -0,0 +1,515 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_redist.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file implements the distributed **/ +/** graph redistribution method. **/ +/** **/ +/** DATES : # Version 6.0 : from : 10 may 2010 **/ +/** to : 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_REDIST + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_redist.h" + +/**********************************/ +/* */ +/* Graph redistribution routines. */ +/* */ +/**********************************/ + +/* This routine creates a redistributed +** destination graph by redistributing +** the contents of the given source graph +** according to the provided information. +** It returns: +** - 0 : if the redistributed graph has been created. +** - !0 : on error. +*/ + +int +dgraphRedist ( +Dgraph * restrict const srcgrafptr, /* Source distributed graph */ +const Gnum * restrict const srcpartloctax, /* Array of process destinations */ +const Gnum * restrict const srcpermgsttax, /* Redistribution permutation array */ +const Gnum dstvertlocdlt, /* Extra size of local vertex array */ +const Gnum dstedgelocdlt, /* Extra size of local edge array */ +Dgraph * restrict const dstgrafptr) /* Destination distributed graph */ +{ + Gnum * restrict permgsttax; + const Gnum * restrict permgsttmp; + Gnum permgstnbr; + Gnum * restrict procdsptab; + Gnum * restrict procvrttab; + Gnum * restrict vadjloctab; + Gnum * restrict vadjglbtab; + Gnum vadjglbnbr; + Gnum vertlocnum; + int cheklocval; + int chekglbval; + Gnum procdspval; + Gnum procvrtval; + int procglbnbr; + int procnum; + int o; + + if (srcpartloctax == NULL) { + errorPrint ("dgraphRedist: part array must be provided"); + return (1); + } + + cheklocval = 0; + procglbnbr = srcgrafptr->procglbnbr; + if (srcpermgsttax != NULL) { /* Do not allocate permutation array if already provided */ + permgstnbr = + vadjglbnbr = 0; + } + else { + if (dgraphGhst (srcgrafptr) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("dgraphRedist: cannot compute ghost edge array"); + return (1); + } + + permgstnbr = srcgrafptr->vertgstnbr; + vadjglbnbr = procglbnbr; + } + if (memAllocGroup ((void **) (void *) + &procvrttab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), + &procdsptab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), + &vadjloctab, (size_t) (procglbnbr * sizeof (Gnum)), + &vadjglbtab, (size_t) (vadjglbnbr * sizeof (Gnum)), + &permgsttax, (size_t) (permgstnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphRedist: out of memory"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, srcgrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphRedist: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_DGRAPH2 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (chekglbval != 0) { + if (procvrttab != NULL) + memFree (procvrttab); + return (1); + } + + memSet (vadjloctab, 0, procglbnbr * sizeof (Gnum)); + + for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) /* Count number of vertices for each processor */ + vadjloctab[srcpartloctax[vertlocnum]] ++; + + if (MPI_Allreduce (vadjloctab, procdsptab, procglbnbr, GNUM_MPI, MPI_SUM, srcgrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphRedist: communication error (2)"); + return (1); + } + + for (procnum = 0, procdspval = procvrtval = srcgrafptr->baseval; procnum < procglbnbr; procnum ++) { /* Create vertex range arrays */ + Gnum procglbval; + + procglbval = procdsptab[procnum]; + procdsptab[procnum] = procdspval; /* Build displacement array */ + procdspval += procglbval; + procvrttab[procnum] = procvrtval; /* Build vertex index array by adding vertlocdlt */ + procvrtval += procglbval + dstvertlocdlt; + } + procdsptab[procnum] = procdspval; /* Set end of vertex range arrays */ + procvrttab[procnum] = procvrtval; + + if (srcpermgsttax == NULL) { + permgsttax -= srcgrafptr->baseval; + + if (MPI_Scan (vadjloctab, vadjglbtab, procglbnbr, GNUM_MPI, MPI_SUM, srcgrafptr->proccomm) != MPI_SUCCESS) { /* Compute permutation start indices */ + errorPrint ("dgraphRedist: communication error (3)"); + return (1); + } + for (procnum = 0; procnum < procglbnbr; procnum ++) /* Finalize permutation start indices */ + vadjglbtab[procnum] -= vadjloctab[procnum] - procvrttab[procnum]; + + for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) /* Renumber local vertices */ + permgsttax[vertlocnum] = vadjglbtab[srcpartloctax[vertlocnum]] ++; + + if (dgraphHaloSync (srcgrafptr, permgsttax + srcgrafptr->baseval, GNUM_MPI) != 0) { + errorPrint ("dgraphRedist: cannot compute halo"); + memFree (procvrttab); /* Free group leader */ + return (1); + } + + permgsttmp = permgsttax; + } + else + permgsttmp = srcpermgsttax; + + o = dgraphRedist2 (srcgrafptr, srcpartloctax, permgsttmp, procdsptab, procvrttab, 0, dstedgelocdlt, dstgrafptr); + + memFree (procvrttab); /* Free group leader */ + + return (o); +} + +static +int +dgraphRedist2 ( +Dgraph * restrict const srcgrafptr, /* Source distributed graph */ +const Gnum * restrict const srcpartloctax, /* Array of process destinations */ +const Gnum * restrict const srcpermgsttax, /* Redistribution permutation array */ +const Gnum * const dstprocdsptab, /* New distribution of graph vertices */ +const Gnum * const dstprocvrttab, /* New distribution of graph vertices */ +const Gnum dstvertlocdlt, /* Extra size of local vertex array */ +const Gnum dstedgelocdlt, /* Extra size of local edge array */ +Dgraph * restrict const dstgrafptr) /* Destination distributed graph */ +{ + Gnum baseval; + int flveval; /* Number of data to send per vertex */ + int fledval; /* Number of data to send per edge */ + Gnum * drcvdattab; /* Receive array for vertex and edge data [norestrict] */ + Gnum * dsnddattab; /* Send array for vertex and edge data [norestrict] */ + int * restrict drcvcnttab; /* Count array for received data */ + int * restrict dsndcnttab; /* Count array for sent data */ + int * restrict drcvdsptab; /* Displacement array for received data */ + int * restrict dsnddsptab; /* Displacement array for sent data */ + int drcvdatnbr; /* Amount of data to allocate */ + int dsnddatnbr; + int drcvdatidx; + int dsnddatidx; + Gnum srcvertlocnum; + Gnum srcvertlocnnd; + Gnum srcvertlocadj; + Gnum * restrict dstvertloctax; + Gnum dstvertlocadj; + Gnum dstvertlocnbr; + Gnum dstvertlocnnd; + Gnum dstvertlocnum; + Gnum * restrict dstveloloctax; + Gnum dstvelolocsiz; + Gnum dstvelolocsum; + Gnum * restrict dstvlblloctax; + Gnum * dstedgeloctax; /* Pointer to destination edge array [norestrict] */ + Gnum dstedgelocnbr; + Gnum dstedgelocsiz; + Gnum dstedgelocnum; + Gnum * dstedloloctax; /* Pointer to destination edge load array [norestrict] */ + Gnum dstedlolocsiz; + int dstvertloctmp; /* Vertex and edge numbers, as (int)s */ + int dstedgeloctmp; + Gnum procdspval; + int procglbnbr; + int cheklocval; + int chekglbval; + int procnum; + + const Gnum * restrict const srcvertloctax = srcgrafptr->vertloctax; + const Gnum * restrict const srcvendloctax = srcgrafptr->vendloctax; + const Gnum * restrict const srcveloloctax = srcgrafptr->veloloctax; + const Gnum * restrict const srcvlblloctax = srcgrafptr->vlblloctax; + const Gnum * restrict const srcedgegsttax = srcgrafptr->edgegsttax; + const Gnum * restrict const srcedloloctax = srcgrafptr->edloloctax; + + dstgrafptr->flagval |= (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; + + cheklocval = 0; + procglbnbr = srcgrafptr->procglbnbr; + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ + &dstgrafptr->procdsptab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), + &dstgrafptr->procvrttab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), + &dstgrafptr->proccnttab, (size_t) (procglbnbr * sizeof (Gnum)), + &dstgrafptr->procngbtab, (size_t) (procglbnbr * sizeof (int)), + &dstgrafptr->procrcvtab, (size_t) (procglbnbr * sizeof (int)), + &dstgrafptr->procsndtab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("dgraphRedist2: out of memory (1)"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, srcgrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphRedist2: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_DGRAPH2 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (chekglbval != 0) { + dgraphFree (dstgrafptr); + return (1); + } + + dsndcnttab = (int *) dstgrafptr->procdsptab; /* TRICK: use procdsptab and procvrttab as paired send count arrays */ + drcvcnttab = (int *) dstgrafptr->proccnttab; /* TRICK: use proccnttab and procngbtab as paired receive arrays */ + dsnddsptab = (int *) dstgrafptr->procrcvtab; + drcvdsptab = (int *) dstgrafptr->procsndtab; + + memSet (dsndcnttab, 0, procglbnbr * 2 * sizeof (int)); /* TRICK: Pairs of vertex and edge counts will be exchanged */ + + baseval = srcgrafptr->baseval; + for (srcvertlocnum = baseval, srcvertlocnnd = srcgrafptr->vertlocnnd; + srcvertlocnum < srcvertlocnnd; srcvertlocnum ++) { + Gnum procngbnum; + + procngbnum = srcpartloctax[srcvertlocnum]; + dsndcnttab[2 * procngbnum] ++; /* One more vertex */ + dsndcnttab[2 * procngbnum + 1] += (int) (srcvendloctax[srcvertlocnum] - srcvertloctax[srcvertlocnum]); /* More edges */ + } + + if (MPI_Alltoall (dsndcnttab, 2, MPI_INT, /* Get amounts of vertex and edge data to receive */ + drcvcnttab, 2, MPI_INT, srcgrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphRedist2: communication error (2)"); + return (1); + } + + fledval = ((srcgrafptr->edloloctax != NULL) ? 1 : 0) + 1; /* Amount of data to exchange per edge */ + flveval = ((srcgrafptr->veloloctax != NULL) ? 1 : 0) + 3; /* Number, degree and label count for 3 */ + + for (procnum = 0, drcvdatidx = dsnddatidx = 0, dstvertloctmp = dstedgeloctmp = 0; + procnum < procglbnbr; procnum ++) { /* Compute start indices for data send and receive arrays */ + int dsndcntval; + int drcvcntval; + + dsndcntval = dsndcnttab[2 * procnum] * flveval + dsndcnttab[2 * procnum + 1] * fledval; + drcvcntval = drcvcnttab[2 * procnum] * flveval + drcvcnttab[2 * procnum + 1] * fledval; + dstvertloctmp += drcvcnttab[2 * procnum]; /* Accumulate number of vertices and edges */ + dstedgeloctmp += drcvcnttab[2 * procnum + 1]; + + dsnddsptab[procnum] = dsnddatidx; + dsnddatidx += dsndcntval; + drcvdsptab[procnum] = drcvdatidx; + drcvdatidx += drcvcntval; + } + + dsnddatnbr = dsnddatidx; /* Preserve amount of data to allocate for sending and receiving */ + drcvdatnbr = drcvdatidx; + + for (procnum = procglbnbr - 1; procnum >= 0; procnum --) { /* Compute count arrays for data send and receive arrays */ + int dsnddspval; + int drcvdspval; + + dsnddspval = dsnddsptab[procnum]; + dsndcnttab[procnum] = dsnddatidx - dsnddspval; + dsnddatidx = dsnddspval; + drcvdspval = drcvdsptab[procnum]; + drcvcnttab[procnum] = drcvdatidx - drcvdspval; + drcvdatidx = drcvdspval; + } + + dstvertlocnbr = (Gnum) dstvertloctmp; + dstedgelocnbr = (Gnum) dstedgeloctmp; + dstedgelocsiz = dstedgelocnbr + dstedgelocdlt; + dstvelolocsiz = (srcgrafptr->veloloctax != NULL) ? dstvertlocnbr + dstvertlocdlt : 0; + dstedlolocsiz = (srcgrafptr->edloloctax != NULL) ? dstedgelocsiz : 0; + if (memAllocGroup ((void **) (void *) + &dstvertloctax, (size_t) ((dstvertlocnbr + dstvertlocdlt + 1) * sizeof (Gnum)), /* Create compact array */ + &dstveloloctax, (size_t) ( dstvelolocsiz * sizeof (Gnum)), + &dstvlblloctax, (size_t) ((dstvertlocnbr + dstvertlocdlt) * sizeof (Gnum)), NULL) == NULL) { /* Vertex labels always present */ + errorPrint ("dgraphRedist2: out of memory (2)"); + cheklocval = 1; + } + else if (dstvertloctax -= baseval, + dstveloloctax = ((srcgrafptr->veloloctax != NULL) ? dstveloloctax - baseval : NULL), + dstvlblloctax -= baseval, + memAllocGroup ((void **) (void *) + &dstedgeloctax, (size_t) ((dstedlolocsiz + /* TRICK: extra space required only if edge loads */ + MAX (dstedgelocdlt, srcgrafptr->degrglbmax)) * sizeof (Gnum)), /* TRICK: degrmax to avoid overlap */ + &dsnddattab, (size_t) (dsnddatnbr * sizeof (Gnum)), /* TRICK: send space will be edgeloctab or edloloctab */ + &drcvdattab, (size_t) (drcvdatnbr * sizeof (Gnum)), NULL) == NULL) { /* TRICK: Remaining space will be freed */ + errorPrint ("dgraphRedist2: out of memory (3)"); + cheklocval = 1; + } + else { + dstedgeloctax -= baseval; + dstedloloctax = (srcgrafptr->edloloctax != NULL) ? (dstedgeloctax + dstedgelocsiz) : NULL; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, srcgrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphRedist2: communication error (3)"); + return (1); + } +#else /* SCOTCH_DEBUG_DGRAPH2 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + if (chekglbval != 0) { + dgraphFree (dstgrafptr); + return (1); + } + + srcvertlocadj = srcgrafptr->procvrttab[srcgrafptr->proclocnum] - baseval; + for (srcvertlocnum = baseval; srcvertlocnum < srcvertlocnnd; srcvertlocnum ++) { /* Record data to send */ + Gnum procngbnum; + int dsnddatidx; + Gnum srcedgelocnum; + Gnum srcedgelocnnd; + Gnum srcdegrval; + + procngbnum = srcpartloctax[srcvertlocnum]; /* Retrieve destination process number */ + dsnddatidx = dsnddsptab[procngbnum]; + + srcedgelocnum = srcvertloctax[srcvertlocnum]; + srcedgelocnnd = srcvendloctax[srcvertlocnum]; + srcdegrval = srcedgelocnnd - srcedgelocnum; + + dsnddattab[dsnddatidx ++] = srcpermgsttax[srcvertlocnum]; /* Record destination vertex global number */ + dsnddattab[dsnddatidx ++] = srcdegrval; /* Record number of edges */ + dsnddattab[dsnddatidx ++] = (srcvlblloctax != NULL) /* Record source vertex global number or label */ + ? srcvlblloctax[srcvertlocnum] + : srcvertlocnum + srcvertlocadj; + if (srcveloloctax != NULL) + dsnddattab[dsnddatidx ++] = srcveloloctax[srcvertlocnum]; /* Record vertex load if needed */ + + if (srcedloloctax != NULL) { /* If edge loads have to be sent too */ + memCpy (dsnddattab + dsnddatidx, srcedloloctax + srcedgelocnum, srcdegrval * sizeof (Gnum)); /* Copy edge loads */ + dsnddatidx += srcdegrval; + } + + for ( ; srcedgelocnum < srcedgelocnnd; srcedgelocnum ++) /* Record translated edge array */ + dsnddattab[dsnddatidx ++] = srcpermgsttax[srcedgegsttax[srcedgelocnum]]; + + dsnddsptab[procngbnum] = dsnddatidx; + } + + for (procnum = 0, dsnddatidx = 0; /* Recompute dsnddsptab */ + procnum < procglbnbr; procnum ++) { + dsnddsptab[procnum] = dsnddatidx; + dsnddatidx += dsndcnttab[procnum]; + } + + if (MPI_Alltoallv (dsnddattab, dsndcnttab, dsnddsptab, GNUM_MPI, /* Exchange graph data */ + drcvdattab, drcvcnttab, drcvdsptab, GNUM_MPI, srcgrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphRedist2: communication error (4)"); + return (1); + } + + dstvertlocadj = dstprocvrttab[srcgrafptr->proclocnum] - baseval; + for (drcvdatidx = 0; drcvdatidx < drcvdatnbr; ) { + Gnum dstvertlocnum; + Gnum dstdegrval; + + dstvertlocnum = drcvdattab[drcvdatidx ++] - dstvertlocadj; /* Get vertex index */ + dstdegrval = drcvdattab[drcvdatidx ++]; /* Get number of edges */ + + dstvertloctax[dstvertlocnum] = dstdegrval; /* Record vertex degree to compute index array */ + dstvlblloctax[dstvertlocnum] = drcvdatidx; /* TRICK: record data position in label array */ + + drcvdatidx += dstdegrval * fledval + (flveval - 2); /* Increase index by proper value */ + } + + dstvelolocsum = (dstveloloctax != NULL) ? 0 : dstvertlocnbr; /* Set local vertex load sum if no vertex loads present */ + for (dstvertlocnum = dstedgelocnum = baseval, dstvertlocnnd = dstvertlocnbr + baseval; /* Copy edge information in due place */ + dstvertlocnum < dstvertlocnnd; dstvertlocnum ++) { + int drcvdatidx; + Gnum dstdegrval; + + drcvdatidx = dstvlblloctax[dstvertlocnum]; + dstdegrval = dstvertloctax[dstvertlocnum]; + dstvertloctax[dstvertlocnum] = dstedgelocnum; + dstvlblloctax[dstvertlocnum] = drcvdattab[drcvdatidx ++]; /* Set vertex label */ + if (dstveloloctax != NULL) { + dstvelolocsum += + dstveloloctax[dstvertlocnum] = drcvdattab[drcvdatidx ++]; /* Set vertex load */ + } + + if (dstedloloctax != NULL) { +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (abs ((dstedloloctax + dstedgelocnum) - (drcvdattab + drcvdatidx)) < dstdegrval) { /* Memory areas should never overlap */ + errorPrint ("dgraphRedist2: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + memCpy (dstedloloctax + dstedgelocnum, drcvdattab + drcvdatidx, dstdegrval * sizeof (Gnum)); + drcvdatidx += dstdegrval; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (abs ((dstedgeloctax + dstedgelocnum) - (drcvdattab + drcvdatidx)) < dstdegrval) { /* TRICK: memory areas should never overlap because of degrmax */ + errorPrint ("dgraphRedist2: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + memCpy (dstedgeloctax + dstedgelocnum, drcvdattab + drcvdatidx, dstdegrval * sizeof (Gnum)); /* TRICK: will never overlap */ + + dstedgelocnum += dstdegrval; + } + dstvertloctax[dstvertlocnum] = dstedgelocnum; /* Set end of compact vertex array */ + + dstedgeloctax = memRealloc (dstedgeloctax + baseval, dstedgelocsiz * fledval * sizeof (Gnum)); +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dstedgeloctax == NULL) { /* Shrinking should never fail */ + errorPrint ("dgraphRedist2: out of memory (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + dstedgeloctax -= baseval; + if (dstedloloctax != NULL) + dstedloloctax = dstedgeloctax + dstedgelocsiz; + + dstgrafptr->procglbnbr = procglbnbr; + dstgrafptr->proclocnum = srcgrafptr->proclocnum; + memCpy (dstgrafptr->procvrttab, dstprocvrttab, (procglbnbr + 1) * sizeof (Gnum)); /* Set vertex range array (possibly with holes) */ + memCpy (dstgrafptr->procdsptab, dstprocdsptab, (procglbnbr + 1) * sizeof (Gnum)); /* Set vertex displacement array */ + for (procnum = procglbnbr - 1, procdspval = dstprocdsptab[procglbnbr]; /* Set vertex count array */ + procnum >= 0; procnum --) { + Gnum procdsptmp; + + procdsptmp = dstprocdsptab[procnum]; + dstgrafptr->proccnttab[procnum] = procdspval - procdsptmp; + procdspval = procdsptmp; + } + + if (dgraphBuild3 (dstgrafptr, baseval, + dstvertlocnbr, dstvertloctax, dstvertloctax + 1, dstveloloctax, dstvelolocsum, NULL, NULL, + dstedgelocnbr, dstedgelocsiz, dstedgeloctax, NULL, dstedloloctax, srcgrafptr->degrglbmax) != 0) { + errorPrint ("dgraphRedist2: cannot build redistributed graph"); + dgraphFree (dstgrafptr); + return (1); + } + + dstgrafptr->vlblloctax = dstvlblloctax; /* Set label array after building so that labels not taken into account at build time */ + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphCheck (dstgrafptr) != 0) { /* Check graph consistency */ + errorPrint ("dgraphRedist2: inconsistent graph data"); + dgraphFree (dstgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_redist.h b/scotch_6.0.3/src/libscotch/dgraph_redist.h new file mode 100644 index 00000000..27918f5b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_redist.h @@ -0,0 +1,59 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_redist.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the graph redistribution **/ +/** routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 10 may 2010 **/ +/** to : 11 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef DGRAPH_REDIST +#define static +#endif + +int dgraphRedist (Dgraph * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum, const Gnum, Dgraph * restrict const); + +static int dgraphRedist2 (Dgraph * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum * const, const Gnum * const, const Gnum, const Gnum, Dgraph * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/dgraph_scatter.c b/scotch_6.0.3/src/libscotch/dgraph_scatter.c new file mode 100644 index 00000000..ad4290ff --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_scatter.c @@ -0,0 +1,376 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_scatter.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Francois CHATENET (P0.0) **/ +/** Sebastien FOUCAULT (P0.0) **/ +/** **/ +/** FUNCTION : This module contains the routine that **/ +/** builds a distributed graph by evenly **/ +/** distributing the pieces of a central- **/ +/** ized graph across processors. **/ +/** **/ +/** # Version P0.0 : from : 01 apr 1997 **/ +/** to 20 jun 1997 **/ +/** # Version P0.1 : from : 14 apr 1998 **/ +/** to 20 jun 1998 **/ +/** # Version P0.2 : from : 19 may 1999 **/ +/** to 19 may 1999 **/ +/** # Version 5.0 : from : 27 apr 2006 **/ +/** to : 10 sep 2007 **/ +/** **/ +/** NOTES : # The definitions of MPI_Scatter and **/ +/** MPI_Scatterv indicate that elements **/ +/** in the send array should not be read **/ +/** more than once. Great care should be **/ +/** taken to enforce this rule, especial- **/ +/** ly when the number of vertices in the **/ +/** centralized graph is smaller than the **/ +/** number of processors. **/ +/** **/ +/** # When the source graph is not compact, **/ +/** compacted arrays are created prior to **/ +/** sending parts of them. In a really **/ +/** efficient implementation, these **/ +/** should be created by pieces and sent **/ +/** in a one-to-one way so as to save as **/ +/** much memory as possible. This is yet **/ +/** to be done. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH_SCATTER + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" + +/* Service function which creates compact +** arrays from non-compact ones. +*/ + +static +void +dgraphScatter2 ( +const Graph * restrict const cgrfptr, +Gnum * restrict verttax, +Gnum * restrict edgetax, +Gnum * restrict edlotax) +{ + Gnum vertnum; /* Current vertex number in compacted arrays */ + Gnum edgenum; /* Current edge number in compacted arrays */ + + for (vertnum = edgenum = cgrfptr->baseval; + vertnum < cgrfptr->vertnnd; vertnum ++) { + Gnum edgetmp; + Gnum edgetnd; + + verttax[vertnum] = edgenum; + edgetmp = cgrfptr->verttax[vertnum]; + edgetnd = cgrfptr->vendtax[vertnum]; + + for ( ; edgetmp < edgetnd; edgetmp ++, edgenum ++) + edgetax[edgenum] = cgrfptr->edgetax[edgetmp]; + + if (edlotax != NULL) { + for (edgetmp = cgrfptr->verttax[vertnum], edgenum = verttax[vertnum]; + edgetmp < edgetnd; edgetmp ++, edgenum ++) + edlotax[edgenum] = cgrfptr->edlotax[edgetmp]; + } + } + verttax[vertnum] = edgenum; +} + +/* This function evenly distributes the pieces +** of a centralized graph across processors. +** It returns: +** - 0 : if scattering has succeeded. +** - !0 : on error. +*/ + +int +dgraphScatter ( +Dgraph * restrict const grafptr, /* Distributed graph */ +const Graph * restrict const cgrfptr) /* Centralized graph to scatter */ +{ + Gnum baseval; /* Base value */ + Gnum * restrict verttax; /* Array of vertices when edge array is not compact */ + Gnum * restrict edgetax; /* Compact array of edges when edge aray is not compact */ + Gnum * restrict edlotax; /* Compact array of edges weights */ + Gnum vertlocnum; /* Current local vertex number */ + Gnum vertlocnbr; /* Number of local vertices */ + Gnum vertlocnnd; + Gnum * restrict vertloctax; /* Array of local vertices */ + Gnum * restrict veloloctax; /* Array of local vertex weights */ + Gnum velolocnbr; + Gnum vlbllocnbr; + Gnum * restrict vlblloctax; /* Array of local vertex labels */ + Gnum edgelocnbr; /* Number of local edges */ + Gnum edlolocnbr; + Gnum * restrict edgeloctax; /* Array of local edges */ + Gnum * restrict edloloctax; /* Array of local edge weights */ + int * restrict attrdsptab; /* Displacement array for scatter operations */ + int * restrict attrcnttab; /* Count array for scatter operations */ + Gnum * restrict attrdattab; /* Temporary array to avoid multiple scatter reads */ + Gnum reduloctab[9]; /* Arrays for reductions */ + Gnum reduglbtab[9]; + Gnum vertlocadj; /* Local vertex array adjust */ + int protnum; /* Root process */ + + if (cgrfptr != NULL) { /* If centralized graph provided */ + if (cgrfptr->vendtax != (cgrfptr->verttax + 1)) { /* If edge array is not compact */ + Gnum edlonbr; + + edlonbr = (cgrfptr->edlotax != NULL) ? cgrfptr->edgenbr : 0; + if (memAllocGroup ((void **) (void *) + &verttax, (size_t) ((cgrfptr->vertnbr + 1) * sizeof (Gnum)), + &edgetax, (size_t) (cgrfptr->edgenbr * sizeof (Gnum)), + &edlotax, (size_t) (edlonbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphScatter: out of memory (1)"); + return (1); + } + verttax -= cgrfptr->baseval; + edgetax -= cgrfptr->baseval; + edlotax = (cgrfptr->edlotax != NULL) ? (edlotax - cgrfptr->baseval) : NULL; + dgraphScatter2 (cgrfptr, verttax, edgetax, edlotax); + } + else { + verttax = cgrfptr->verttax; + edgetax = cgrfptr->edgetax; + edlotax = cgrfptr->edlotax; + } + reduloctab[0] = 1; /* This process is the root */ + reduloctab[1] = (Gnum) grafptr->proclocnum; /* Get its number */ + reduloctab[2] = cgrfptr->baseval; + reduloctab[3] = cgrfptr->vertnbr; + reduloctab[4] = cgrfptr->edgenbr; + reduloctab[5] = cgrfptr->velosum; + reduloctab[6] = (cgrfptr->velotax != NULL) ? 1 : 0; + reduloctab[7] = (cgrfptr->vlbltax != NULL) ? 1 : 0; + reduloctab[8] = (cgrfptr->edlotax != NULL) ? 1 : 0; + } + else { + reduloctab[0] = /* This process is not the root */ + reduloctab[1] = + reduloctab[2] = + reduloctab[3] = + reduloctab[4] = + reduloctab[5] = + reduloctab[6] = + reduloctab[7] = + reduloctab[8] = 0; + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 9, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (1)"); + return (1); + } + if (reduglbtab[0] != 1) { + errorPrint ("dgraphScatter: should have only one root"); + return (1); + } + + baseval = reduglbtab[2]; + vertlocnbr = DATASIZE (reduglbtab[3], grafptr->procglbnbr, grafptr->proclocnum); + velolocnbr = (reduglbtab[6] != 0) ? vertlocnbr : 0; + vlbllocnbr = (reduglbtab[7] != 0) ? vertlocnbr : 0; + if (memAllocGroup ((void **) (void *) + &vertloctax, (size_t) ((vertlocnbr + 1) * sizeof (Gnum)), + &veloloctax, (size_t) (velolocnbr * sizeof (Gnum)), + &vlblloctax, (size_t) (vlbllocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphScatter: out of memory (2)"); + if ((cgrfptr != NULL) && (cgrfptr->verttax != verttax)) + memFree (verttax + baseval); /* Free group leader */ + return (1); + } + vertloctax -= baseval; + veloloctax = (reduglbtab[6] != 0) ? (veloloctax - baseval) : NULL; + vlblloctax = (reduglbtab[7] != 0) ? (vlblloctax - baseval) : NULL; + + protnum = (int) reduglbtab[1]; + if (cgrfptr != NULL) { /* If root process */ + Gnum procnum; + + if (memAllocGroup ((void **) (void *) + &attrdattab, (size_t) (grafptr->procglbnbr * sizeof (Gnum)), + &attrdsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &attrcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("dgraphScatter: out of memory (3)"); + memFree (vertloctax + baseval); + if (cgrfptr->verttax != verttax) + memFree (verttax + baseval); /* Free group leader */ + return (1); + } + + attrdsptab[0] = 0; /* Build arrays for MPI_Scatterv */ + attrcnttab[0] = DATASIZE (reduglbtab[3], grafptr->procglbnbr, 0); + attrdattab[0] = verttax[attrdsptab[0] + attrcnttab[0] + baseval]; + for (procnum = 1; procnum < grafptr->procglbnbr; procnum ++) { + attrdsptab[procnum] = attrdsptab[procnum - 1] + attrcnttab[procnum - 1]; + attrcnttab[procnum] = DATASIZE (reduglbtab[3], grafptr->procglbnbr, procnum); + attrdattab[procnum] = verttax[attrdsptab[procnum] + attrcnttab[procnum] + baseval]; + } + + if (MPI_Scatterv (verttax + baseval, attrcnttab, attrdsptab, GNUM_MPI, /* Perform two scatters since cannot avoid multiple reads with only one scatter */ + vertloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (2)"); + return (1); + } + if (MPI_Scatter (attrdattab, 1, GNUM_MPI, + vertloctax + baseval + vertlocnbr, 1, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (3)"); + return (1); + } + if (reduglbtab[6] != 0) { /* Scatter vertex loads */ + if (MPI_Scatterv (cgrfptr->velotax + baseval, attrcnttab, attrdsptab, GNUM_MPI, + veloloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (4)"); + return (1); + } + } + if (reduglbtab[7] != 0) { /* Scatter labels */ + if (MPI_Scatterv (cgrfptr->vlbltax + baseval, attrcnttab, attrdsptab, GNUM_MPI, + vlblloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (5)"); + return (1); + } + } + } + else { /* Process is not root */ + if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, + vertloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (6)"); + return (1); + } + if (MPI_Scatter (NULL, 1, GNUM_MPI, vertloctax + baseval + vertlocnbr, 1, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (7)"); + return (1); + } + if (reduglbtab[6] != 0) { /* Scatter vertex loads */ + if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, + veloloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (8)"); + return (1); + } + } + if (reduglbtab[7] != 0) { /* Scatter labels */ + if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, + vlblloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (9)"); + return (1); + } + } + } + + vertlocadj = vertloctax[baseval] - baseval; /* Compute local indices */ + for (vertlocnum = baseval, vertlocnnd = vertlocnbr + baseval; + vertlocnum <= vertlocnnd; vertlocnum ++) + vertloctax[vertlocnum] -= vertlocadj; + + edgelocnbr = vertloctax[vertlocnnd] - vertloctax[baseval]; + edlolocnbr = (reduglbtab[8] != 0) ? edgelocnbr : 0; + if (memAllocGroup ((void **) (void *) + &edgeloctax, (size_t) (edgelocnbr * sizeof (Gnum)), + &edloloctax, (size_t) (edlolocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dgraphScatter: out of memory (4)"); + if (cgrfptr != NULL) { + memFree (attrdattab); /* Free group leader */ + if (cgrfptr->verttax != verttax) + memFree (verttax + baseval); /* Free group leader */ + } + memFree (vertloctax + baseval); + return (1); + } + edgeloctax -= baseval; + edloloctax = (reduglbtab[8] != 0) ? edloloctax - baseval : NULL; + + if (cgrfptr != NULL) { /* If root process */ + Gnum procnum; + + for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { /* Build arrays for MPI_Scatterv */ + attrcnttab[procnum] = verttax[attrdsptab[procnum] + attrcnttab[procnum]+baseval] - + verttax[attrdsptab[procnum] + baseval]; + attrdsptab[procnum] = verttax[attrdsptab[procnum] + baseval] - baseval; + } + + if (MPI_Scatterv (edgetax + baseval, attrcnttab, attrdsptab, GNUM_MPI, + edgeloctax + baseval, edgelocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (10)"); + return (1); + } + if (reduglbtab[8] != 0) { + if (MPI_Scatterv (edlotax + baseval, attrcnttab, attrdsptab, GNUM_MPI, + edloloctax + baseval, edgelocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (11)"); + return (1); + } + } + memFree (attrdattab); /* Free group leader */ + if (cgrfptr->verttax != verttax) + memFree (verttax + baseval); + } + else { /* Process is not root */ + if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, + edgeloctax + baseval , edgelocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (12)"); + return (1); + } + if (reduglbtab[8] != 0) { + if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, + edloloctax + baseval , edgelocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dgraphScatter: communication error (13)"); + return (1); + } + } + } + + if (dgraphBuild (grafptr, baseval, + vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, veloloctax, NULL, NULL, + edgelocnbr, edgelocnbr, edgeloctax, NULL, edloloctax) != 0) { + memFree (edgeloctax + baseval); + memFree (vertloctax + baseval); + return (1); + } + + grafptr->flagval |= DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* Give ownership of arrays to graph */ + grafptr->vlblloctax = vlblloctax; /* Add labels afterwards, since relabeling already done */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dgraph_view.c b/scotch_6.0.3/src/libscotch/dgraph_view.c new file mode 100644 index 00000000..a92f7360 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dgraph_view.c @@ -0,0 +1,169 @@ +/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgraph_view.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed graph general **/ +/** purpose routines. **/ +/** **/ +/** DATES : # Version P0.0 : from : 01 apr 1997 **/ +/** to 01 apr 1997 **/ +/** # Version P0.1 : from : 12 apr 1998 **/ +/** to 20 jun 1998 **/ +/** # Version 5.0 : from : 16 feb 2005 **/ +/** to : 15 aug 2006 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to : 12 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" + +/*************************************/ +/* */ +/* These routines handle distributed */ +/* source graphs. */ +/* */ +/*************************************/ + +/* This routine displays the contents +** of the given graph structure. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dgraphView ( +const Dgraph * restrict const grafptr, +FILE * const stream) +{ + MPI_Comm proccomm; /* Graph communicator */ + int procglbnbr; /* Number of processes sharing graph data */ + int proclocnum; /* Number of this process */ + int procngbnbr; + int procngbnum; + Gnum vertlocnum; + Gnum edgelocnum; + Gnum * edgelocptr; + + proccomm = grafptr->proccomm; /* Simplify */ + MPI_Comm_size (proccomm, &procglbnbr); /* Rely on communicator data */ + MPI_Comm_rank (proccomm, &proclocnum); + + fflush (stream); /* Flush previous data */ + for (procngbnbr = 0; procngbnbr < procglbnbr; procngbnbr ++) { + MPI_Barrier (proccomm); + if (procngbnbr == proclocnum) { + fprintf (stream, "Process %d:\n", + proclocnum); + fprintf (stream, " vertglbnbr: " GNUMSTRING "\n vertgstnbr: " GNUMSTRING "\n vertgstnnd: " GNUMSTRING "\n vertlocnbr: " GNUMSTRING "\n vertlocnnd: " GNUMSTRING "\n", + (Gnum) grafptr->vertglbnbr, + (Gnum) grafptr->vertgstnbr, + (Gnum) grafptr->vertgstnnd, + (Gnum) grafptr->vertlocnbr, + (Gnum) grafptr->vertlocnnd); + fprintf (stream, " vertloctax:"); + if (grafptr->vendloctax == grafptr->vertloctax + 1) { + for (vertlocnum = grafptr->baseval; vertlocnum <= grafptr->vertlocnnd; vertlocnum ++)/**/ + fprintf (stream, " " GNUMSTRING, + (Gnum) grafptr->vertloctax[vertlocnum]); + fprintf (stream, " x\n vendloctax: = vertloctax + 1"); + } + else { + for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) + fprintf (stream, " " GNUMSTRING, + (Gnum) grafptr->vertloctax[vertlocnum]); + fprintf (stream, " vendloctax: x"); + for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) + fprintf (stream, " " GNUMSTRING, + (Gnum) grafptr->vendloctax[vertlocnum]); + } + fprintf (stream, "\n edgeglbnbr: " GNUMSTRING "\n edgelocnbr: " GNUMSTRING "\n", + (Gnum) grafptr->edgeglbnbr, + (Gnum) grafptr->edgelocnbr); + fprintf (stream, " edgeloctax:"); + for (edgelocnum = grafptr->baseval, edgelocptr = grafptr->edgeloctax; + edgelocnum < grafptr->edgelocnbr + grafptr->baseval; + edgelocnum ++, edgelocptr ++) + fprintf (stream, " " GNUMSTRING, + (Gnum) *edgelocptr); + if ((grafptr->flagval & DGRAPHHASEDGEGST) != 0) { + fprintf (stream, "\n edgegsttax:"); + for (edgelocnum = grafptr->baseval, edgelocptr = grafptr->edgegsttax; + edgelocnum < grafptr->edgelocnbr + grafptr->baseval; + edgelocnum ++, edgelocptr ++) + fprintf (stream, " " GNUMSTRING, + (Gnum) *edgelocptr); + } + fprintf (stream, "\n procdsptab:"); + for (procngbnum = 0; procngbnum <= procglbnbr ; procngbnum ++) + fprintf (stream, " " GNUMSTRING, + (Gnum) grafptr->procdsptab[procngbnum]); + fprintf (stream, "\n procngbnbr: %d", + grafptr->procngbnbr); + fprintf (stream, "\n procngbtab:"); + for (procngbnum = 0; procngbnum < grafptr->procngbnbr; procngbnum ++) + fprintf (stream, " %d", + grafptr->procngbtab[procngbnum]); + fprintf (stream, "\n procrcvtab:"); + for (procngbnum = 0; procngbnum < grafptr->procglbnbr; procngbnum ++) + fprintf (stream, " %d", + grafptr->procrcvtab[procngbnum]); + fprintf (stream, "\n procsndnbr: %d", + grafptr->procsndnbr); + fprintf (stream, "\n procsndtab:"); + for (procngbnum = 0; procngbnum < grafptr->procglbnbr; procngbnum ++) + fprintf (stream, " %d", + grafptr->procsndtab[procngbnum]); + fprintf (stream, "\n degrglbmax: " GNUMSTRING, + (Gnum) grafptr->degrglbmax); + fprintf (stream, "\n"); + fflush (stream); /* Flush data */ + } + } + MPI_Barrier (proccomm); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dmapping.c b/scotch_6.0.3/src/libscotch/dmapping.c new file mode 100644 index 00000000..3ab2f27f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dmapping.c @@ -0,0 +1,304 @@ +/* Copyright 2008,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dmapping.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles (partial) mappings. **/ +/** **/ +/** DATES : # Version 5.1 : from : 31 mar 2008 **/ +/** to 09 nov 2008 **/ +/** # Version 6.0 : from : 03 sep 2013 **/ +/** to 03 sep 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DMAPPING + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "arch.h" +#include "dmapping.h" + +/***********************************/ +/* */ +/* These routines handle mappings. */ +/* */ +/***********************************/ + +/* This routine builds a mapping. +** It returns: +** - 0 : if mapping successfully initialized. +** - !0 : on error. +*/ + +int +dmapInit ( +Dmapping * restrict const dmapptr, +const Arch * restrict const archptr) +{ + dmapptr->fragptr = NULL; + dmapptr->fragnbr = + dmapptr->vertlocmax = + dmapptr->vertlocnbr = 0; + dmapptr->archdat = *archptr; + +#ifdef SCOTCH_PTHREAD + pthread_mutex_init (&dmapptr->mutelocdat, NULL); /* Initialize local mutex */ +#endif /* SCOTCH_PTHREAD */ + + return (0); +} + +/* This routine frees the contents of the given +** mapping. The architecture data is never freed +** as it is usually a copy of an existing Arch +** structure. +** It returns: +** - VOID : in all cases. +*/ + +void +dmapExit ( +Dmapping * const dmapptr) +{ + DmappingFrag * fragptr; + DmappingFrag * fragtmp; + + for (fragptr = dmapptr->fragptr; fragptr != NULL; fragptr = fragtmp) { + memFree (fragptr->vnumtab); + memFree (fragptr->parttab); + memFree (fragptr->domntab); + fragtmp = fragptr->nextptr; + memFree (fragptr); + } + +#ifdef SCOTCH_PTHREAD + pthread_mutex_destroy (&dmapptr->mutelocdat); /* Destroy local mutex */ +#endif /* SCOTCH_PTHREAD */ + +#ifdef SCOTCH_DEBUG_DMAP2 + memSet (dmapptr, ~0, sizeof (Dmapping)); +#endif /* SCOTCH_DEBUG_DMAP2 */ +} + +/* This routine adds a fragment to the given +** distributed mapping. +** It returns: +** - void : in all cases. +*/ + +void +dmapAdd ( +Dmapping * restrict const dmapptr, +DmappingFrag * restrict const fragptr) +{ +#ifdef SCOTCH_PTHREAD + pthread_mutex_lock (&dmapptr->mutelocdat); /* Lock local mutex */ +#endif /* SCOTCH_PTHREAD */ + + if (dmapptr->vertlocmax < fragptr->vertnbr) + dmapptr->vertlocmax = fragptr->vertnbr; + dmapptr->vertlocnbr += fragptr->vertnbr; + + dmapptr->fragnbr ++; + fragptr->nextptr = dmapptr->fragptr; /* Link fragment to mapping */ + dmapptr->fragptr = fragptr; + +#ifdef SCOTCH_PTHREAD + pthread_mutex_unlock (&dmapptr->mutelocdat); /* Unlock local mutex */ +#endif /* SCOTCH_PTHREAD */ +} + +/* This routine propagates back distributed mapping +** information to a part array associated with a +** distributed graph structure. +** It returns: +** - 0 : if partition data successfully obtained. +** - !0 : on error. +*/ + +int +dmapTerm ( +const Dmapping * restrict const dmapptr, +const Dgraph * restrict const grafptr, +Gnum * restrict const termloctab) +{ + Gnum * restrict termloctax; + int * restrict sendcnttab; + int * restrict senddsptab; + int * restrict recvcnttab; + int * restrict recvdsptab; + DmappingTermSort * restrict sortsndtab; + DmappingTermSort * restrict sortrcvtab; + Gnum vertlocnum; + int vertrcvnbr; + int vertsndnbr; + int procnum; + DmappingFrag * restrict fragptr; + Gnum reduloctab[2]; + Gnum reduglbtab[2]; + + reduloctab[0] = dmapptr->vertlocnbr; + reduloctab[1] = 0; + if (memAllocGroup ((void **) (void *) + &senddsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &sendcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &recvdsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &recvcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &sortsndtab, (size_t) ((dmapptr->vertlocnbr + 1) * sizeof (DmappingTermSort)), /* "+1" for end marker */ + &sortrcvtab, (size_t) (grafptr->vertlocnbr * sizeof (DmappingTermSort)), NULL) == NULL) { + errorPrint ("dmapTerm: out of memory"); + reduloctab[1] = 1; + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 2, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dmapTerm: communication error (1)"); + reduglbtab[1] = 1; + } + if (reduglbtab[1] != 0) { + if (senddsptab != NULL) + memFree (senddsptab); /* Free group leader */ + return (1); + } + + if (reduglbtab[0] == 0) { /* If mapping structure is empty, create an empty mapping */ + memSet (termloctab, 0, grafptr->vertlocnbr * sizeof (Gnum)); + memFree (senddsptab); /* Free group leader */ + return (0); + } + if (reduglbtab[0] != grafptr->vertglbnbr) { + errorPrint ("dmapTerm: invalid mapping (1)"); + memFree (senddsptab); /* Free group leader */ + return (1); + } + + for (fragptr = dmapptr->fragptr, vertlocnum = 0; fragptr != NULL; fragptr = fragptr->nextptr) { + Gnum fraglocnum; + + for (fraglocnum = 0; fraglocnum < fragptr->vertnbr; fraglocnum ++, vertlocnum ++) { +#ifdef SCOTCH_DEBUG_DMAP2 + if ((vertlocnum >= dmapptr->vertlocnbr) || (fragptr->parttab[fraglocnum] < 0) || (fragptr->parttab[fraglocnum] >= fragptr->domnnbr)) { + errorPrint ("dmapTerm: invalid mapping (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + sortsndtab[vertlocnum].vertnum = fragptr->vnumtab[fraglocnum]; + sortsndtab[vertlocnum].termnum = (Gnum) archDomNum (&dmapptr->archdat, &fragptr->domntab[fragptr->parttab[fraglocnum]]); + } + } +#ifdef SCOTCH_DEBUG_DMAP2 + if (vertlocnum != dmapptr->vertlocnbr) { + errorPrint ("dmapTerm: invalid mapping (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + + sortsndtab[vertlocnum].vertnum = /* Set end marker */ + sortsndtab[vertlocnum].termnum = GNUMMAX; + intSort2asc1 (sortsndtab, dmapptr->vertlocnbr); /* Sort mapping array by original vertex numbers, without marker */ + + for (vertlocnum = 0, procnum = 0; procnum < grafptr->procglbnbr; ) { + Gnum vertsndnbr; + Gnum procvrtval; + + vertsndnbr = 0; + procvrtval = grafptr->procvrttab[procnum + 1]; + while (sortsndtab[vertlocnum].vertnum < procvrtval) { + vertsndnbr ++; + vertlocnum ++; +#ifdef SCOTCH_DEBUG_DMAP2 + if (vertlocnum > dmapptr->vertlocnbr) { /* If beyond regular indices plus end marker */ + errorPrint ("dmapTerm: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + } + sendcnttab[procnum ++] = (int) (vertsndnbr * 2); /* Communication array for MPI, so (int), and "*2" because a Sort is 2 Gnums */ + } +#ifdef SCOTCH_DEBUG_DMAP2 + if (vertlocnum != dmapptr->vertlocnbr) { + errorPrint ("dmapTerm: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + + if (MPI_Alltoall (sendcnttab, 1, MPI_INT, recvcnttab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dmapTerm: communication error (2)"); + return (1); + } + + for (procnum = 0, vertrcvnbr = vertsndnbr = 0; procnum < grafptr->procglbnbr; procnum ++) { /* Accumulate send and receive indices */ + recvdsptab[procnum] = vertrcvnbr; + vertrcvnbr += recvcnttab[procnum]; /* Accumulate "*2" values as counts */ + senddsptab[procnum] = vertsndnbr; + vertsndnbr += sendcnttab[procnum]; + } + + if (MPI_Alltoallv (sortsndtab, sendcnttab, senddsptab, GNUM_MPI, sortrcvtab, recvcnttab, recvdsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dmapTerm: communication error (3)"); + return (1); + } + + memSet (termloctab, ~0, grafptr->vertlocnbr * sizeof (Gnum)); + + termloctax = termloctab - grafptr->procvrttab[grafptr->proclocnum]; /* Base local array through global indices */ + for (vertlocnum = 0; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) { +#ifdef SCOTCH_DEBUG_DMAP2 + if (termloctax[sortrcvtab[vertlocnum].vertnum] != ~0) { + errorPrint ("dmapTerm: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + termloctax[sortrcvtab[vertlocnum].vertnum] = sortrcvtab[vertlocnum].termnum; + } +#ifdef SCOTCH_DEBUG_DMAP2 + for (vertlocnum = 0; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) { + if (termloctab[vertlocnum] == ~0) { + errorPrint ("dmapTerm: internal error (4)"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + + memFree (senddsptab); /* Free group leader */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dmapping.h b/scotch_6.0.3/src/libscotch/dmapping.h new file mode 100644 index 00000000..8a4b3e00 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dmapping.h @@ -0,0 +1,102 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dmapping.h **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the declarations for **/ +/** the parallel mapping handling routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 31 mar 2008 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +#define DMAPPING_H + +/* +** The type definitions. +*/ + +/*+ This structure defines a mapping fragment. +*/ + +typedef struct DmappingFrag_ { + struct DmappingFrag_ * nextptr; /*+ Pointer to next fragment +*/ + Gnum vertnbr; /*+ Number of local vertices in mapping +*/ + Gnum * vnumtab; /*+ Vertex index array +*/ + Anum * parttab; /*+ Mapping array [vertlocnbr] +*/ + Anum domnnbr; /*+ Local number of domains +*/ + ArchDom * domntab; /*+ Array of domains [domnnbr] +*/ +} DmappingFrag; + +/*+ This structure defines an (eventually + partial) mapping of a source graph to + a target architecture. +*/ + +typedef struct Dmapping_ { + struct DmappingFrag_ * fragptr; /*+ Pointer to first mapping fragment +*/ + Gnum fragnbr; /*+ Number of local fragments +*/ + Gnum vertlocmax; /*+ Size of biggest local fragment +*/ + Gnum vertlocnbr; /*+ Number of local vertices in mapping +*/ + Arch archdat; /*+ Architecture data +*/ +#ifdef SCOTCH_PTHREAD + pthread_mutex_t mutelocdat; /*+ Local mutex for updates +*/ +#endif /* SCOTCH_PTHREAD */ +} Dmapping; + +/*+ The sort structure, used to sort mapped vertices. + Field vertnum is first and field termnum is a Gnum + and not an Anum because of intSort2asc1. +*/ + +typedef struct DmappingTermSort_ { + Gnum vertnum; /*+ Vertex number: FIRST +*/ + Gnum termnum; /*+ Direct permutation index +*/ +} DmappingTermSort; + +/* +** The function prototypes. +*/ + +#ifndef DMAPPING +#define static +#endif + +int dmapInit (Dmapping * restrict const, const Arch * restrict const); +void dmapExit (Dmapping * const); +void dmapAdd (Dmapping * restrict const, DmappingFrag * restrict const); +int dmapSave (const Dmapping * restrict const, const Dgraph * restrict const, FILE * restrict const); +int dmapTerm (const Dmapping * restrict const, const Dgraph * restrict const, Gnum * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/dmapping_io.c b/scotch_6.0.3/src/libscotch/dmapping_io.c new file mode 100644 index 00000000..a36ea7cd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dmapping_io.c @@ -0,0 +1,284 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dmapping_io.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles distributed **/ +/** mappings. **/ +/** **/ +/** DATES : # Version 5.1 : from : 13 jun 2008 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DORDER + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "dgraph.h" +#include "dgraph_allreduce.h" +#include "arch.h" +#include "dmapping.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +DGRAPHALLREDUCEMAXSUMOP (1, 5) + +/* This routine saves a distributed mapping. +** The distributed graph structure is provided +** to access the distribution of vertex labels, +** whenever present. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dmapSave ( +const Dmapping * restrict const dmapptr, +const Dgraph * restrict const grafptr, +FILE * restrict const stream) +{ + const DmappingFrag * restrict fragptr; + Gnum fragglbnbr; + Gnum * restrict termloctab; + Gnum * restrict termrcvtab; + Gnum vertrcvmax; + Gnum vertglbnbr; + Gnum * restrict vlbltax; + Gnum reduloctab[6]; + Gnum reduglbtab[6]; + int protnum; + + reduloctab[0] = dmapptr->vertlocmax; + reduloctab[1] = dmapptr->vertlocnbr; + reduloctab[2] = dmapptr->fragnbr; + if (stream != NULL) { /* If file provided */ + reduloctab[3] = 1; /* This process is the root */ + reduloctab[4] = grafptr->proclocnum; /* Get its rank */ + } + else { + reduloctab[3] = /* This process is not the root */ + reduloctab[4] = 0; + } + reduloctab[5] = (grafptr->vlblloctax != NULL) ? 1 : 0; /* See if vertex labels provided */ + + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 1, 5, grafptr->proccomm) != 0) { + errorPrint ("dmapSave: communication error (1)"); + return (1); + } + if (reduglbtab[3] != 1) { + errorPrint ("dmapSave: should have only one root"); + return (1); + } + if ((reduglbtab[5] != 0) && (reduglbtab[5] != grafptr->procglbnbr)) { + errorPrint ("dmapSave: inconsistent parameters"); + return (1); + } + if ((reduglbtab[1] < 0) && (reduglbtab[1] > grafptr->procglbnbr)) { + errorPrint ("dmapSave: invalid mapping (1)"); + return (1); + } + vertrcvmax = reduglbtab[0]; /* Size of largest fragment to receive */ + vertglbnbr = reduglbtab[1]; + fragglbnbr = reduglbtab[2]; + protnum = (int) reduglbtab[4]; /* Get rank of root process */ + + reduloctab[0] = 0; + if (protnum == grafptr->proclocnum) { + Gnum vlblnbr; + + vlblnbr = (grafptr->vlblloctax != NULL) ? grafptr->vertglbnbr : 0; + if ((termloctab = memAllocGroup ((void **) (void *) /* termloctab not used on root processor, but used only for freeing the block */ + &termrcvtab, (size_t) (vertrcvmax * 2 * sizeof (Gnum)), /* TRICK: "*2" as vnumrcvtab is sent after termrcvtab */ + &vlbltax, (size_t) (vlblnbr * sizeof (Gnum)), NULL)) == NULL) { + errorPrint ("dmapSave: out of memory (1)"); + reduloctab[0] = 1; + } + else if (fprintf (stream, GNUMSTRING "\n", (Gnum) vertglbnbr) == EOF) { + errorPrint ("dmapSave: bad output (1)"); + reduloctab[0] = 1; + } + } + else { + vlbltax = NULL; /* Prevent Valgrind from yelling */ + if ((termloctab = memAlloc (dmapptr->vertlocmax * sizeof (Gnum))) == NULL) { + errorPrint ("dmapSave: out of memory (2)"); + reduloctab[0] = 1; + } + } +#ifdef SCOTCH_DEBUG_DMAP1 /* This communication cannot be covered by a useful one */ + if (MPI_Allreduce (reduloctab, reduglbtab, 1, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dmapSave: communication error (2)"); + reduglbtab[0] = 1; + } +#else /* SCOTCH_DEBUG_DMAP1 */ + reduglbtab[0] = reduloctab[0]; +#endif /* SCOTCH_DEBUG_DMAP1 */ + if (reduglbtab[0] != 0) { + if (termloctab != NULL) + memFree (termloctab); /* Free group leader */ + return (1); + } + + if (grafptr->vlblloctax != NULL) { + if (commGatherv (grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI, + vlbltax, grafptr->proccnttab, grafptr->procdsptab, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dmapSave: communication error (3)"); + return (1); + } + vlbltax -= grafptr->baseval; /* Base label array */ + } + + if (protnum == grafptr->proclocnum) { + Gnum vertrcvnbr; + Gnum * restrict vnumrcvptr; + Gnum * restrict termrcvptr; + + for (fragptr = dmapptr->fragptr; fragptr != NULL; fragptr = fragptr->nextptr) { /* Output local fragments */ + Gnum fraglocnum; + + for (fraglocnum = 0; fraglocnum < fragptr->vertnbr; fraglocnum ++) { + Gnum vnumnum; + Gnum termnum; + + vnumnum = fragptr->vnumtab[fraglocnum]; +#ifdef SCOTCH_DEBUG_DMAP2 + if ((vnumnum < 0) || (vnumnum >= (grafptr->vertglbnbr + grafptr->baseval))) { + errorPrint ("dmapSave: invalid mapping (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + termnum = archDomNum (&dmapptr->archdat, &fragptr->domntab[fragptr->parttab[fraglocnum]]); + + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) ((grafptr->vlblloctax != NULL) ? vlbltax[vnumnum] : vnumnum), + (Gnum) termnum) == EOF) { + errorPrint ("dmapSave: bad output (2)"); + reduloctab[0] = 1; + break; + } + } + } + + for (fragglbnbr -= dmapptr->fragnbr; fragglbnbr > 0; fragglbnbr --) { /* For all non-local fragments */ + Gnum * restrict termrcvnnd; + MPI_Status statdat; + int recvnbr; + + if (MPI_Recv (termrcvtab, (int) (vertrcvmax * 2), GNUM_MPI, MPI_ANY_SOURCE, MPI_ANY_TAG, grafptr->proccomm, &statdat) != MPI_SUCCESS) { + errorPrint ("dmapSave: communication error (4)"); /* TRICK: "*2" as vnumrcvtab is sent after termrcvtab */ + return (1); + } + + if (reduloctab[0] != 0) + continue; + + MPI_Get_count (&statdat, GNUM_MPI, &recvnbr); + vertrcvnbr = (Gnum) (recvnbr / 2); /* We received a composite message made of both vectors */ + vnumrcvptr = termrcvtab + vertrcvnbr; /* Vertex index array is just after terminal number array */ + + for (termrcvptr = termrcvtab, termrcvnnd = termrcvtab + vertrcvnbr; termrcvptr < termrcvnnd; termrcvptr ++, vnumrcvptr ++) { + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) ((grafptr->vlblloctax != NULL) ? vlbltax[*vnumrcvptr] : *vnumrcvptr), + (Gnum) *termrcvptr) == EOF) { + errorPrint ("dmapSave: bad output (3)"); + reduloctab[0] = 1; + break; + } + } + } + } + else { + int typecnttab[2]; + MPI_Aint typedsptab[2]; + MPI_Datatype typedat; + + for (fragptr = dmapptr->fragptr; fragptr != NULL; fragptr = fragptr->nextptr) { /* Output local fragments */ + Gnum fraglocnum; + + for (fraglocnum = 0; fraglocnum < fragptr->vertnbr; fraglocnum ++) { +#ifdef SCOTCH_DEBUG_DMAP2 + Gnum vnumnum; + + vnumnum = fragptr->vnumtab[fraglocnum]; + if ((vnumnum < 0) || (vnumnum >= (grafptr->vertglbnbr + grafptr->baseval))) { + errorPrint ("dmapSave: invalid mapping (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + termloctab[fraglocnum] = archDomNum (&dmapptr->archdat, &fragptr->domntab[fragptr->parttab[fraglocnum]]); + } + + MPI_Address (termloctab, &typedsptab[0]); + MPI_Address (fragptr->vnumtab, &typedsptab[1]); + typedsptab[1] -= typedsptab[0]; + typedsptab[0] = 0; + typecnttab[0] = + typecnttab[1] = (int) fragptr->vertnbr; + MPI_Type_hindexed (2, typecnttab, typedsptab, GNUM_MPI, &typedat); + MPI_Type_commit (&typedat); + + if (MPI_Send (termloctab, 1, typedat, protnum, 0, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dmapSave: communication error (5)"); + return (1); + } + + MPI_Type_free (&typedat); + } + } + + memFree (termloctab); /* Free group leader */ + +#ifdef SCOTCH_DEBUG_DMAP1 /* This communication cannot be covered by a useful one */ + if (MPI_Allreduce (reduloctab, reduglbtab, 1, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dmapSave: communication error (6)"); + reduglbtab[0] = 1; + } +#else /* SCOTCH_DEBUG_DMAP1 */ + reduglbtab[0] = reduloctab[0]; +#endif /* SCOTCH_DEBUG_DMAP1 */ + + return ((int) reduglbtab[0]); +} diff --git a/scotch_6.0.3/src/libscotch/dorder.c b/scotch_6.0.3/src/libscotch/dorder.c new file mode 100644 index 00000000..b6a8c03a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder.c @@ -0,0 +1,367 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles distributed **/ +/** orderings. **/ +/** **/ +/** DATES : # Version 5.0 : from : 18 apr 2006 **/ +/** to 28 jul 2006 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DORDER + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dorder.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This routine initializes a distributed +** ordering with respect to the given parameters. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dorderInit ( +Dorder * restrict const ordeptr, +const Gnum baseval, +const Gnum vnodglbnbr, +MPI_Comm proccomm) +{ + ordeptr->baseval = baseval; + ordeptr->vnodglbnbr = vnodglbnbr; + ordeptr->cblklocnbr = 0; + + ordeptr->linkdat.nextptr = &ordeptr->linkdat; /* Loop double-chained list */ + ordeptr->linkdat.prevptr = &ordeptr->linkdat; + + MPI_Comm_dup (proccomm, &ordeptr->proccomm); /* Duplicate communicator to avoid lifespan problems */ + MPI_Comm_rank (ordeptr->proccomm, &ordeptr->proclocnum); + +#ifdef SCOTCH_PTHREAD + pthread_mutex_init (&ordeptr->mutelocdat, NULL); /* Initialize local mutex */ +#endif /* SCOTCH_PTHREAD */ + + return (0); +} + +/* This routine frees the column blocks +** of the given distributed ordering. +** It returns: +** - void : in all cases. +*/ + +static +void +dorderFreeCblk ( +DorderCblk * restrict const cblkptr) +{ +#ifdef SCOTCH_DEBUG_DORDER2 + if ((cblkptr->typeval < DORDERCBLKNEDI) || + (cblkptr->typeval > (DORDERCBLKNEDI | DORDERCBLKLEAF))) + errorPrint ("dorderFreeCblk: invalid column block type"); +#endif /* SCOTCH_DEBUG_DORDER2 */ + + if ((cblkptr->typeval & DORDERCBLKLEAF) != 0) { + memFree (cblkptr->data.leaf.periloctab); + if (cblkptr->data.leaf.nodeloctab != NULL) + memFree (cblkptr->data.leaf.nodeloctab); + } + + memFree (cblkptr); /* Free column block structure */ +} + +void +dorderFree ( +Dorder * restrict const ordeptr) +{ + DorderCblk * cblkptr; + DorderLink * linkptr; + + for (linkptr = ordeptr->linkdat.nextptr; linkptr != &ordeptr->linkdat; ) { + cblkptr = (DorderCblk *) linkptr; /* TRICK: FIRST */ + linkptr = linkptr->nextptr; + + dorderFreeCblk (cblkptr); + } + + ordeptr->linkdat.nextptr = /* Loop double-chained list */ + ordeptr->linkdat.prevptr = &ordeptr->linkdat; +} + +/* This routine frees the contents +** of the given ordering. +** It returns: +** - void : in all cases. +*/ + +void +dorderExit ( +Dorder * restrict const ordeptr) +{ + dorderFree (ordeptr); + + MPI_Comm_free (&ordeptr->proccomm); /* Free duplicated communicator */ + +#ifdef SCOTCH_PTHREAD + pthread_mutex_destroy (&ordeptr->mutelocdat); /* Destroy local mutex */ +#endif /* SCOTCH_PTHREAD */ + +#ifdef SCOTCH_DEBUG_DORDER2 + memSet (ordeptr, ~0, sizeof (Dorder)); +#endif /* SCOTCH_DEBUG_DORDER2 */ +} + +/* This routine creates the root column +** block slot in the given distributed +** ordering structure. +** It returns: +** - !NULL : root column block. +** - NULL : on error. +*/ + +DorderCblk * +dorderFrst ( +Dorder * const ordeptr) +{ + DorderCblk cblkdat; + DorderCblk * cblkptr; + + cblkdat.ordelocptr = ordeptr; /* Fake father node */ + cblkdat.cblknum.proclocnum = 0; /* Belongs to process 0 to ease displacement computations */ + cblkdat.cblknum.cblklocnum = -1; + + if ((cblkptr = dorderNew (&cblkdat, ordeptr->proccomm)) == NULL) + return (NULL); + + cblkptr->ordeglbval = 0; /* Un-based inverse permutation index */ + cblkptr->vnodglbnbr = ordeptr->vnodglbnbr; + cblkptr->cblkfthnum = 0; + + return (cblkptr); +} + +/* This routine gives back a new distributed +** column block slot in the same ordering +** structure as the given column block. +** It returns: +** - !NULL : new column block. +** - NULL : on error. +*/ + +DorderCblk * +dorderNew ( +DorderCblk * const cblkptr, /* One of the column blocks */ +MPI_Comm proccomm) /* Communicator sharing the block */ +{ + Dorder * restrict ordeptr; + DorderCblk * restrict cblknewptr; + Gnum reduloctab[3]; + Gnum reduglbtab[3]; + int proclocnum; + + MPI_Comm_rank (proccomm, &proclocnum); + + ordeptr = cblkptr->ordelocptr; + + reduloctab[1] = /* Assume process is not root for this column block */ + reduloctab[2] = 0; + if ((cblknewptr = (DorderCblk *) memAlloc (sizeof (DorderCblk))) == NULL) { + errorPrint ("dorderNew: out of memory"); + reduloctab[0] = 2; /* Indicate error without doubt */ + } + else { + reduloctab[0] = 0; + if (proclocnum == 0) { /* If root of sub-tree */ + reduloctab[0] = 1; /* Indicate it is the root */ + reduloctab[1] = ordeptr->proclocnum; /* Broadcast global rank of block root */ +#ifdef SCOTCH_PTHREAD + pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ +#endif /* SCOTCH_PTHREAD */ + reduloctab[2] = ordeptr->cblklocnbr ++; /* One more root block in local ordering */ +#ifdef SCOTCH_PTHREAD + pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ +#endif /* SCOTCH_PTHREAD */ + } + } + if (MPI_Allreduce (&reduloctab, &reduglbtab, 3, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { + errorPrint ("dorderNew: communication error"); + return (NULL); + } + if (reduglbtab[0] != 1) { + errorPrint ("dorderNew: cannot create new node"); + if (cblknewptr != NULL) + memFree (cblknewptr); + return (NULL); + } + + cblknewptr->ordelocptr = ordeptr; + cblknewptr->typeval = DORDERCBLKNONE; + cblknewptr->fathnum = cblkptr->cblknum; + cblknewptr->cblknum.proclocnum = (int) reduglbtab[1]; + cblknewptr->cblknum.cblklocnum = reduglbtab[2]; + +#ifdef SCOTCH_PTHREAD + pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ +#endif /* SCOTCH_PTHREAD */ + cblknewptr->linkdat.nextptr = &ordeptr->linkdat; /* Link new block at end of local ordering node list */ + cblknewptr->linkdat.prevptr = ordeptr->linkdat.prevptr; + ordeptr->linkdat.prevptr->nextptr = &cblknewptr->linkdat; + ordeptr->linkdat.prevptr = &cblknewptr->linkdat; +#ifdef SCOTCH_PTHREAD + pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ +#endif /* SCOTCH_PTHREAD */ + + return (cblknewptr); +} + +/* This routine gives back a new centralized +** column block slot in the same ordering +** structure as the given column block. +** It returns: +** - !NULL : new column block. +** - NULL : on error. +*/ + +DorderCblk * +dorderNewSequ ( +DorderCblk * const cblkptr) /* One of the column blocks */ +{ + Dorder * restrict ordeptr; + DorderCblk * restrict cblknewptr; + + if ((cblknewptr = (DorderCblk *) memAlloc (sizeof (DorderCblk))) == NULL) { + errorPrint ("dorderNewSequ: out of memory"); + return (NULL); + } + + ordeptr = cblkptr->ordelocptr; + + cblknewptr->ordelocptr = ordeptr; + cblknewptr->typeval = DORDERCBLKNONE; + cblknewptr->fathnum = cblkptr->cblknum; + cblknewptr->cblknum.proclocnum = ordeptr->proclocnum; /* Node belongs to this process */ +#ifdef SCOTCH_PTHREAD + pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ +#endif /* SCOTCH_PTHREAD */ + cblknewptr->cblknum.cblklocnum = ordeptr->cblklocnbr ++; /* One more locally-rooted block in ordering */ + + cblknewptr->linkdat.nextptr = &ordeptr->linkdat; /* Link new block at end of local ordering node list */ + cblknewptr->linkdat.prevptr = ordeptr->linkdat.prevptr; + ordeptr->linkdat.prevptr->nextptr = &cblknewptr->linkdat; + ordeptr->linkdat.prevptr = &cblknewptr->linkdat; +#ifdef SCOTCH_PTHREAD + pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ +#endif /* SCOTCH_PTHREAD */ + + return (cblknewptr); +} + +/* This routine gives back a new centralized +** index range in the same ordering structure +** as the given column block. +** It returns: +** - !NULL : new column block. +** - NULL : on error. +*/ + +Gnum +dorderNewSequIndex ( +DorderCblk * const cblkptr, /* One of the column blocks */ +const Gnum cblknbr) /* Number of indices to reserve */ +{ + Dorder * restrict ordeptr; + Gnum cblklocnum; + + ordeptr = cblkptr->ordelocptr; + +#ifdef SCOTCH_PTHREAD + pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ +#endif /* SCOTCH_PTHREAD */ + cblklocnum = ordeptr->cblklocnbr; /* Get current local index number */ + ordeptr->cblklocnbr += cblknbr; /* These more root blocks in local ordering */ +#ifdef SCOTCH_PTHREAD + pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ +#endif /* SCOTCH_PTHREAD */ + + return (cblklocnum); +} + +/* This routine removes a no longer used +** column block from the given distributed +** ordering. Leaves or locally-rooted column +** blocks are kept, others are removed. +** It returns: +** - void : in all cases. +*/ + +void +dorderDispose ( +DorderCblk * const cblkptr) /* Column block to consider */ +{ + Dorder * restrict ordeptr; + + ordeptr = cblkptr->ordelocptr; + + if (cblkptr->cblknum.proclocnum == ordeptr->proclocnum) /* If node is local root of column block, keep it */ + return; + + if ((cblkptr->typeval & DORDERCBLKLEAF) == 0) { /* If node is not non-rooted leaf of distributed ordering */ +#ifdef SCOTCH_PTHREAD + pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ +#endif /* SCOTCH_PTHREAD */ + cblkptr->linkdat.nextptr->prevptr = cblkptr->linkdat.prevptr; /* Unchain node from double-chained list */ + cblkptr->linkdat.prevptr->nextptr = cblkptr->linkdat.nextptr; +#ifdef SCOTCH_PTHREAD + pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ +#endif /* SCOTCH_PTHREAD */ + + memFree (cblkptr); + } +} diff --git a/scotch_6.0.3/src/libscotch/dorder.h b/scotch_6.0.3/src/libscotch/dorder.h new file mode 100644 index 00000000..559eb51d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder.h @@ -0,0 +1,191 @@ +/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data **/ +/** declarations for the generic **/ +/** distributed ordering structure. **/ +/** **/ +/** DATES : # Version 5.0 : from : 15 apr 2006 **/ +/** to 14 oct 2007 **/ +/** # Version 5.1 : from : 28 nov 2007 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Tag for MPI communications. +*/ + +#define DORDERTAGPERI 0 + +/*+ Column block separation tree cell flags. + The DORDERCBLKNEDI value must correspond + to a single bit and be equal to the + ORDERCBLKNEDI value. +*/ + +#define DORDERCBLKNONE 0x0000 /*+ Not yet assigned +*/ +#define DORDERCBLKNEDI 0x0001 /*+ Nested dissection separator node +*/ +#define DORDERCBLKLEAF 0x0002 /*+ Distributed leaf +*/ + +/* +** The type and structure definitions. +*/ + +/*+ Distributed index of column block + tree cell. +*/ + +typedef struct DorderIndex_ { + int proclocnum; /*+ Number of this process +*/ + Gnum cblklocnum; /*+ Local index of column block +*/ +} DorderIndex; + +/*+ Link structure to double-chain all column blocks + into the distributed ordering structure. Nodes + are inserted at end of list such that a simple + traversal gives nodes in ascending creation + order, which is essential for locally-rooted + nodes when gathering them on a centralized + ordering. +*/ + +typedef struct DorderLink_ { + struct DorderLink_ * nextptr; /*+ Pointer to previous column block +*/ + struct DorderLink_ * prevptr; /*+ Pointer to next column block +*/ +} DorderLink; + +/*+ Centralized column block node. +*/ + +typedef struct DorderNode_ { + Gnum fathnum; /*+ Number of father in centralized node array +*/ + int typeval; /*+ Centralized type of tree node +*/ + Gnum vnodnbr; /*+ Number of nodes in this column block +*/ + Gnum cblknum; /*+ Rank of column block in father column block array +*/ +} DorderNode; + +/*+ Distributed column-block tree cell. Each + cell defines a distributed column block, + which is either a nested dissection node, + with its two subgraphs and its separator, + or a leaf. Leaves which are located on a + single process can be nested dissection + sequential nodes, with the sequential tree + folded as a node array. + Column blocks are given in ascending order + within all sub-arrays, for proper infix + traversal. +*/ + +typedef struct DorderCblk_ { + DorderLink linkdat; /*+ Link to other blocks. TRICK: FIRST +*/ + struct Dorder_ * ordelocptr; /*+ Pointer to local distributed ordering +*/ + int typeval; /*+ Distributed type of tree node +*/ + DorderIndex fathnum; /*+ Master index of parent column block +*/ + DorderIndex cblknum; /*+ Master index of this column block +*/ + Gnum ordeglbval; /*+ Un-based starting index of inverse permutation +*/ + Gnum vnodglbnbr; /*+ Number of node vertices in subtree +*/ + Gnum cblkfthnum; /*+ Rank of node in father column block array +*/ + union { + struct { /*+ Fragment of inverse permutation +*/ + Gnum ordelocval; /*+ Starting index of inverse permutation +*/ + Gnum vnodlocnbr; /*+ Number of node vertices in fragment +*/ + Gnum * periloctab; /*+ Pointer to inverse permutation fragment +*/ + Gnum nodelocnbr; /*+ Number of local column blocks +*/ + DorderNode * nodeloctab; /*+ Array of local column blocks +*/ + Gnum cblklocnum; /*+ Local number of first local column block +*/ + } leaf; + struct { /*+ Fragment of inverse permutation +*/ + Gnum cblkglbnbr; /*+ Number of descendent nodes (2 or 3) +*/ + } nedi; + } data; +} DorderCblk; + +/*+ Distributed ordering structure. A distributed + block ordering is defined by fragments of its + inverse permutation, distributed across all + of the participating processes. + For the sake of consistency between orderings + that have been produced either from graphs or + meshes, whether centralized or distributed, all + ordering values are based from baseval. +*/ + +typedef struct Dorder_ { + Gnum baseval; /*+ Base value for structures +*/ + Gnum vnodglbnbr; /*+ Global number of node vertices +*/ + Gnum cblklocnbr; /*+ Local number of unique locally-rooted distributed and sequential column blocks +*/ + DorderLink linkdat; /*+ Link to column blocks +*/ + MPI_Comm proccomm; /*+ Ordering global communicator +*/ + int proclocnum; /*+ Rank of this process in the communicator +*/ +#ifdef SCOTCH_PTHREAD + pthread_mutex_t mutelocdat; /*+ Local mutex for counter and link updates +*/ +#endif /* SCOTCH_PTHREAD */ +} Dorder; + +/* +** The function prototypes. +*/ + +#ifndef DORDER +#define static +#endif + +int dorderInit (Dorder * const, const Gnum, const Gnum, MPI_Comm); +void dorderExit (Dorder * const); +void dorderFree (Dorder * const); +#ifdef DGRAPH_H +int dorderPerm (const Dorder * const, const Dgraph * const, Gnum * const); +int dorderSave (const Dorder * const, const Dgraph * const, FILE * const); +int dorderSaveBlock (const Dorder * const, const Dgraph * const, FILE * const); +int dorderSaveMap (const Dorder * const, const Dgraph * const, FILE * const); +int dorderSaveTree (const Dorder * const, const Dgraph * const, FILE * const); +#ifdef ORDER_H +int dorderSaveTree2 (const Dorder * restrict const, const Dgraph * restrict const, FILE * restrict const, int (*) (const Order * const, const Gnum * const, FILE * const)); +#endif /* ORDER_H */ +#endif /* DGRAPH_H */ +Gnum dorderCblkDist (const Dorder * restrict const); +int dorderTreeDist (const Dorder * restrict const, const Dgraph * restrict const, Gnum * restrict const, Gnum * restrict const); +#ifdef ORDER_H +int dorderGather (const Dorder * const, Order * const); +int dorderGatherTree (const Dorder * const, Order * const, const int); +#endif /* ORDER_H */ + +DorderCblk * dorderFrst (Dorder * const); +DorderCblk * dorderNew (DorderCblk * const, MPI_Comm); +DorderCblk * dorderNewSequ (DorderCblk * const); +Gnum dorderNewSequIndex (DorderCblk * const, const Gnum); +void dorderDispose (DorderCblk * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/dorder_gather.c b/scotch_6.0.3/src/libscotch/dorder_gather.c new file mode 100644 index 00000000..fb86579c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder_gather.c @@ -0,0 +1,546 @@ +/* Copyright 2007,2008,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder_gather.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles distributed **/ +/** orderings. **/ +/** **/ +/** DATES : # Version 5.0 : from : 19 jul 2007 **/ +/** to 10 sep 2007 **/ +/** # Version 5.1 : from : 28 sep 2008 **/ +/** to 28 sep 2008 **/ +/** # Version 6.0 : from : 10 oct 2013 **/ +/** to 10 oct 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DORDER + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_allreduce.h" +#include "order.h" +#include "dorder.h" +#include "dorder_gather.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This function gathers the pieces of +** a distributed ordering to build a +** centralized ordering. +** It returns: +** - 0 : if ordering data are consistent. +** - !0 : on error. +*/ + +DGRAPHALLREDUCEMAXSUMOP (1, 1) + +int +dorderGather ( +const Dorder * restrict const dordptr, +Order * restrict const cordptr) +{ + Gnum leaflocnbr; + int leafrcvnbr; + DorderGatherLeaf * restrict leafrcvtab; + int leafsndnbr; /* "int" since used as count in MPI_Gatherv */ + DorderGatherLeaf * restrict leafsndtab; + Gnum * restrict perircvtab; + int perisndnbr; /* "int" since used as count in MPI_Gatherv */ + Gnum * restrict perisndtab; + int * restrict recvcnttab; + int * restrict recvdsptab; + const DorderLink * restrict linklocptr; + Gnum vnodlocnbr; + int procglbnbr; + int protnum; + Gnum reduloctab[2]; + Gnum reduglbtab[2]; + int cheklocval; + int chekglbval; + +#ifdef SCOTCH_DEBUG_DORDER2 + if ((DORDERCBLKNEDI == 0) || (DORDERCBLKNEDI != ORDERCBLKNEDI)) { + errorPrint ("dorderGather: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + + for (linklocptr = dordptr->linkdat.nextptr, leaflocnbr = vnodlocnbr = 0; /* For all nodes in local ordering structure */ + linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) { + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) { /* If node is leaf */ + leaflocnbr ++; /* One more leaf fragment */ + vnodlocnbr += cblklocptr->data.leaf.vnodlocnbr; /* And more node vertices */ + } +#ifdef SCOTCH_DEBUG_DORDER2 + else if (cblklocptr->typeval != DORDERCBLKNEDI) { + errorPrint ("dorderGather: invalid parameters"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + } + + MPI_Comm_size (dordptr->proccomm, &procglbnbr); + + if (cordptr != NULL) { + Gnum vnodglbnbr; + + reduloctab[0] = (Gnum) dordptr->proclocnum; + reduloctab[1] = 1; + + vnodglbnbr = 2 * procglbnbr; /* TRICK: use perircvtab array as gather array */ + if (vnodglbnbr < (dordptr->vnodglbnbr - vnodlocnbr)) /* But should receive permutation indices too! */ + vnodglbnbr = dordptr->vnodglbnbr - vnodlocnbr; /* TRICK: root will not receive from itself */ + + if (memAllocGroup ((void **) (void *) + &recvcnttab, (size_t) (procglbnbr * sizeof (int)), + &recvdsptab, (size_t) (procglbnbr * sizeof (int)), + &perircvtab, (size_t) (vnodglbnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dorderGather: out of memory (1)"); + reduloctab[0] = (Gnum) procglbnbr; /* Indicate memory error */ + } + } + else { + recvcnttab = NULL; /* Prepare possible freeing on error */ + reduloctab[0] = + reduloctab[1] = 0; + } + if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 1, 1, dordptr->proccomm) != 0) { + errorPrint ("dorderGather: communication error (1)"); + return (1); + } + if (reduglbtab[1] != 1) { + errorPrint ("dorderGather: should have only one root"); + reduglbtab[0] = (Gnum) procglbnbr; + } + if (reduglbtab[0] >= (Gnum) procglbnbr) { + if (recvcnttab != NULL) + memFree (recvcnttab); + return (1); + } + protnum = (int) reduglbtab[0]; + + reduloctab[0] = leaflocnbr; + reduloctab[1] = vnodlocnbr; + if (MPI_Gather (reduloctab, 2, GNUM_MPI, perircvtab, 2, GNUM_MPI, protnum, dordptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderGather: communication error (2)"); + return (1); + } + + if (dordptr->proclocnum == protnum) { + int procnum; + + perircvtab[2 * protnum] = 0; /* TRICK: root will not send to nor receive from itself to avoid unnecessary memory copy */ + for (procnum = 0, leafrcvnbr = 0; procnum < procglbnbr; procnum ++) { + recvdsptab[procnum] = leafrcvnbr; + recvcnttab[procnum] = (int) (perircvtab[2 * procnum] * 2); /* TRICK: DorderGatherLeaf structures are made of 2 GNUM_MPI fields */ + leafrcvnbr += recvcnttab[procnum]; + } + leafrcvnbr /= 2; /* TRICK: restore real number of leaf structures to be received */ + leafsndnbr = 0; + perisndnbr = 0; + } + else { + leafrcvnbr = 0; + leafsndnbr = (int) leaflocnbr; + perisndnbr = (int) vnodlocnbr; + } + + cheklocval = 0; + if (memAllocGroup ((void **) (void *) + &leafrcvtab, (size_t) (leafrcvnbr * sizeof (DorderGatherLeaf)), + &leafsndtab, (size_t) (leafsndnbr * sizeof (DorderGatherLeaf)), + &perisndtab, (size_t) (perisndnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dorderGather: out of memory (2)"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dordptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderGather: communication error (3)"); + return (1); + } +#else /* SCOTCH_DEBUG_DORDER1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DORDER1 */ + if (chekglbval != 0) { + if (recvcnttab != NULL) + memFree (recvcnttab); + return (1); + } + + if (dordptr->proclocnum == protnum) { /* If root process */ +#ifdef SCOTCH_DEBUG_DORDER2 + memSet (cordptr->peritab, ~0, dordptr->vnodglbnbr * sizeof (Gnum)); +#endif /* SCOTCH_DEBUG_DORDER2 */ + + for (linklocptr = dordptr->linkdat.nextptr; linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) { /* For all nodes */ + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) /* If tree node is leaf, copy fragment */ + memCpy (cordptr->peritab + cblklocptr->data.leaf.ordelocval, cblklocptr->data.leaf.periloctab, cblklocptr->data.leaf.vnodlocnbr * sizeof (Gnum)); + } + } + else { + Gnum leaflocnum; + Gnum vnodlocnum; + + for (linklocptr = dordptr->linkdat.nextptr, leaflocnum = vnodlocnum = 0; + linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) { /* For all nodes */ + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) { /* If node is leaf */ + leafsndtab[leaflocnum].ordelocval = cblklocptr->data.leaf.ordelocval; /* Fill send structures with permutation data */ + leafsndtab[leaflocnum].vnodlocnbr = cblklocptr->data.leaf.vnodlocnbr; + memCpy (perisndtab + vnodlocnum, cblklocptr->data.leaf.periloctab, cblklocptr->data.leaf.vnodlocnbr * sizeof (Gnum)); + vnodlocnum += cblklocptr->data.leaf.vnodlocnbr; + leaflocnum ++; + } + } + leafsndnbr *= 2; /* TRICK: DorderGatherLeaf structures are made of 2 GNUM_MPI fields */ + } + + if (MPI_Gatherv (leafsndtab, leafsndnbr, GNUM_MPI, leafrcvtab, recvcnttab, recvdsptab, GNUM_MPI, protnum, dordptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderGather: communication error (4)"); + return (1); + } + + if (dordptr->proclocnum == protnum) { + int vnodglbnbr; + int procnum; + + perircvtab[2 * protnum + 1] = 0; /* TRICK: root will not send to nor receive from itself to avoid unnecessary memory copy */ + for (procnum = 0, vnodglbnbr = 0; procnum < procglbnbr; procnum ++) { + recvdsptab[procnum] = vnodglbnbr; + recvcnttab[procnum] = (int) perircvtab[2 * procnum + 1]; + vnodglbnbr += recvcnttab[procnum]; + } +#ifdef SCOTCH_DEBUG_DORDER2 + if (((Gnum) vnodglbnbr + vnodlocnbr) != dordptr->vnodglbnbr) { + errorPrint ("dorderGather: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + } + + if (MPI_Gatherv (perisndtab, perisndnbr, GNUM_MPI, perircvtab, recvcnttab, recvdsptab, GNUM_MPI, protnum, dordptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderGather: communication error (5)"); + return (1); + } + + if (dordptr->proclocnum == protnum) { /* If root process */ + int leafglbnum; + int vnodglbnum; + + for (leafglbnum = vnodglbnum = 0; leafglbnum < leafrcvnbr; leafglbnum ++) { + memCpy (cordptr->peritab + leafrcvtab[leafglbnum].ordelocval, perircvtab + vnodglbnum, leafrcvtab[leafglbnum].vnodlocnbr * sizeof (Gnum)); + vnodglbnum += leafrcvtab[leafglbnum].vnodlocnbr; + } + + memFree (recvcnttab); /* Free group leader */ + } + memFree (leafrcvtab); /* Free group leader */ + + if (dorderGatherTree (dordptr, cordptr, protnum) != 0) /* Gather ordering tree */ + return (1); + +#ifdef SCOTCH_DEBUG_DORDER2 + if (dordptr->proclocnum == protnum) { + if (orderCheck (cordptr) != 0) { + errorPrint ("dorderGather: invalid centralized ordering"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + + return (0); +} + +/* This function gathers the pieces of +** a distributed ordering tree to build a +** centralized ordering tree. +** It returns: +** - 0 : if ordering data are consistent. +** - !0 : on error. +*/ + +int +dorderGatherTree ( +const Dorder * restrict const dordptr, +Order * restrict const cordptr, +const int protnum) +{ + int treelocnbr; /* "int" since used as way to fill count array in MPI_Allgather */ + Gnum treeglbnbr; + DorderGatherNode * restrict treercvtab; + int treesndnbr; /* "int" since used as count in MPI_Gatherv */ + DorderGatherNode * treesndtab; + DorderGatherNode * restrict treesndptr; + int * restrict treecnttab; + int * restrict treedsptab; + DorderGatherCblk * restrict cblkglbtab; + const DorderLink * restrict linklocptr; + int procglbnbr; + int procnum; + int cheklocval; + int chekglbval; + + for (linklocptr = dordptr->linkdat.nextptr, treelocnbr = 0; /* Count only purely local nodes */ + linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) { + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ +#ifdef SCOTCH_DEBUG_DORDER2 + if ((cblklocptr->cblknum.proclocnum != dordptr->proclocnum) && /* Local sub-nodes of non-locally rooted node not implemented */ + ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) && + (cblklocptr->data.leaf.nodelocnbr != 0)) { + errorPrint ("dorderGatherTree: not implemented"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + + if (cblklocptr->cblknum.proclocnum == dordptr->proclocnum) { + treelocnbr ++; + if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) + treelocnbr += (int) cblklocptr->data.leaf.nodelocnbr; + } + } + + MPI_Comm_size (dordptr->proccomm, &procglbnbr); + + treesndnbr = (dordptr->proclocnum == protnum) ? 0 : treelocnbr; /* TRICK: root will not send nor receive */ + cheklocval = 0; + if (memAllocGroup ((void **) (void *) + &treecnttab, (size_t) (procglbnbr * sizeof (int)), + &treedsptab, (size_t) (procglbnbr * sizeof (int)), + &treesndtab, (size_t) (treesndnbr * sizeof (DorderGatherNode)), NULL) == NULL) { + errorPrint ("dorderGatherTree: out of memory (1)"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dordptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderGatherTree: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_DORDER1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DORDER1 */ + if (chekglbval != 0) { + if (treecnttab != NULL) + memFree (treecnttab); + return (1); + } + + if (MPI_Allgather (&treelocnbr, 1, MPI_INT, treecnttab, 1, MPI_INT, dordptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderGatherTree: communication error (2)"); + return (1); + } + + for (procnum = 0, treeglbnbr = 0; procnum < procglbnbr; procnum ++) { /* Compute prefix sum of local numbers for global numbering */ + treedsptab[procnum] = treeglbnbr; + treeglbnbr += treecnttab[procnum]; + } + if (dordptr->proclocnum == protnum) { + treecnttab[protnum] = 0; /* TRICK: root will not send to nor receive from itself to avoid unnecessary memory copy */ + + cordptr->treenbr = treeglbnbr; + + if (memAllocGroup ((void **) (void *) + &treercvtab, (size_t) (treeglbnbr * sizeof (DorderGatherNode)), + &cblkglbtab, (size_t) (treeglbnbr * sizeof (DorderGatherCblk)), NULL) == NULL) { + errorPrint ("dorderGatherTree: out of memory (2)"); + cheklocval = 1; + } + treesndptr = treercvtab + treedsptab[protnum]; /* TRICK: root process will build its column blocks in place as if received */ + } + else + treesndptr = treesndtab; + +#ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dordptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderGather: communication error (3)"); + return (1); + } +#else /* SCOTCH_DEBUG_DORDER1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DORDER1 */ + if (chekglbval != 0) { + memFree (treecnttab); + return (1); + } + + for (linklocptr = dordptr->linkdat.nextptr; linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) { /* For all nodes */ + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if (cblklocptr->cblknum.proclocnum != dordptr->proclocnum) /* Skip non-local nodes */ + continue; + + treesndptr->fathnum = treedsptab[cblklocptr->fathnum.proclocnum] + cblklocptr->fathnum.cblklocnum; /* If node is (part of) the root node */ + treesndptr->typeval = (Gnum) (((cblklocptr->typeval & DORDERCBLKNEDI) != 0) ? ORDERCBLKNEDI : ORDERCBLKOTHR); + treesndptr->vnodnbr = cblklocptr->vnodglbnbr; + treesndptr->cblknum = cblklocptr->cblkfthnum; + treesndptr ++; + + if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) { /* If node is a distributed leaf */ + Gnum cblkglbnum; + Gnum cblkglbadj; + const DorderNode * restrict nodelocptr; + const DorderNode * restrict nodeloctnd; + + cblkglbnum = treedsptab[cblklocptr->cblknum.proclocnum] + cblklocptr->cblknum.cblklocnum; + cblkglbadj = treedsptab[cblklocptr->cblknum.proclocnum] + cblklocptr->data.leaf.cblklocnum; + + for (nodelocptr = cblklocptr->data.leaf.nodeloctab, nodeloctnd = nodelocptr + cblklocptr->data.leaf.nodelocnbr; + nodelocptr < nodeloctnd; nodelocptr ++) { /* Build nodes for all local nodes */ + treesndptr->fathnum = (nodelocptr->fathnum == -1) ? cblkglbnum : (nodelocptr->fathnum + cblkglbadj); + treesndptr->typeval = (Gnum) nodelocptr->typeval; + treesndptr->vnodnbr = nodelocptr->vnodnbr; + treesndptr->cblknum = nodelocptr->cblknum; + treesndptr ++; + } + } +#ifdef SCOTCH_DEBUG_DORDER2 + else if (cblklocptr->typeval != DORDERCBLKNEDI) { + errorPrint ("dorderGatherTree: invalid column block type"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + } +#ifdef SCOTCH_DEBUG_DORDER2 + if (treesndptr != ((dordptr->proclocnum == protnum) ? (treercvtab + treedsptab[protnum]) : treesndtab) + treelocnbr) { + errorPrint ("dorderGatherTree: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + + if (dordptr->proclocnum == protnum) { /* If node is root, adjust displacements in terms of Gnum and not DorderGatherNode */ + for (procnum = 0; procnum < procglbnbr; procnum ++) { + treecnttab[procnum] *= DORDERGATHERNODESIZE; + treedsptab[procnum] *= DORDERGATHERNODESIZE; + } + } + if (MPI_Gatherv (treesndtab, treesndnbr * DORDERGATHERNODESIZE, GNUM_MPI, + treercvtab, treecnttab, treedsptab, GNUM_MPI, protnum, dordptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderGatherTree: communication error (4)"); + return (1); + } + + if (dordptr->proclocnum == protnum) { + Gnum treeglbnum; + Gnum cblkglbnbr; + + memSet (cblkglbtab, 0, treeglbnbr * sizeof (DorderGatherCblk)); /* Set all son counters to zero and all array pointers to NULL */ + + for (treeglbnum = 1; treeglbnum < treeglbnbr; treeglbnum ++) { /* For all local and received tree nodes except root node */ + Gnum cblkfthnum; + + cblkfthnum = treercvtab[treeglbnum].fathnum; +#ifdef SCOTCH_DEBUG_DORDER2 + if ((cblkfthnum < 0) || /* Father of non-root node cannot be -1 */ + (cblkfthnum >= treeglbnum)) { /* Father should always have smaller global node number */ + errorPrint ("dorderGatherTree: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + cblkglbtab[cblkfthnum].cblknbr ++; /* Add a son to its father */ + } + + for (treeglbnum = 0, cblkglbnbr = treeglbnbr; treeglbnum < treeglbnbr; treeglbnum ++) { /* For all local and received tree nodes */ + if (cblkglbtab[treeglbnum].cblknbr > 0) { +#ifdef SCOTCH_DEBUG_DORDER2 + if (cblkglbtab[treeglbnum].cblknbr < 2) { /* Descendent nodes should comprise at least two column block slots */ + errorPrint ("dorderGatherTree: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + cblkglbnbr --; /* One new subblock means one more shared frontier, so one less column block than nodes */ + if ((cblkglbtab[treeglbnum].cblktab = memAlloc (cblkglbtab[treeglbnum].cblknbr * sizeof (OrderCblk))) == NULL) { + errorPrint ("dorderGather: out of memory (3)"); + while (-- treeglbnum >= 0) { + if (cblkglbtab[treeglbnum].cblktab != NULL) + memFree (cblkglbtab[treeglbnum].cblktab); + } + memFree (treercvtab); + memFree (treecnttab); + return (1); + } + } + } + cordptr->cblknbr = cblkglbnbr; + + cordptr->cblktre.typeval = (int) treercvtab[0].typeval; /* Process root node of separator tree */ + cordptr->cblktre.vnodnbr = treercvtab[0].vnodnbr; + cordptr->cblktre.cblknbr = cblkglbtab[0].cblknbr; + cordptr->cblktre.cblktab = cblkglbtab[0].cblktab; /* Link its sons array */ + + for (treeglbnum = 1; treeglbnum < treeglbnbr; treeglbnum ++) { /* For all nodes except the root */ + Gnum cblkfthnum; + OrderCblk * restrict cblksonptr; + + cblkfthnum = treercvtab[treeglbnum].cblknum; +#ifdef SCOTCH_DEBUG_DORDER2 + if ((cblkfthnum < 0) || (cblkfthnum >= cblkglbtab[treercvtab[treeglbnum].fathnum].cblknbr)) { + errorPrint ("dorderGatherTree: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + cblksonptr = &cblkglbtab[treercvtab[treeglbnum].fathnum].cblktab[cblkfthnum]; /* Point to son's slot in father array */ + cblksonptr->typeval = (int) treercvtab[treeglbnum].typeval; + cblksonptr->vnodnbr = treercvtab[treeglbnum].vnodnbr; + cblksonptr->cblknbr = cblkglbtab[treeglbnum].cblknbr; /* Link son column block array to column block structure */ + cblksonptr->cblktab = cblkglbtab[treeglbnum].cblktab; + } + + memFree (treercvtab); + } + memFree (treecnttab); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dorder_gather.h b/scotch_6.0.3/src/libscotch/dorder_gather.h new file mode 100644 index 00000000..4dea65c7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder_gather.h @@ -0,0 +1,85 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder_gather.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the distributed ordering gathering **/ +/** function. **/ +/** **/ +/** DATES : # Version 5.0 : from : 20 jul 2007 **/ +/** to : 27 jul 2007 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Tag for MPI communications. +*/ + +#define DORDERGATHERNODESIZE (sizeof (DorderGatherNode) / sizeof (Gnum)) + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the tree definition. +*/ + +typedef struct DorderGatherLeaf_ { + Gnum ordelocval; /*+ Starting index of inverse permutation +*/ + Gnum vnodlocnbr; /*+ Number of node vertices in fragment +*/ +} DorderGatherLeaf; + +/*+ This structure holds the separator tree structure. + Because arrays of this structure is to be sent as + a single contiguous array, all its fields must be + of the same type. +*/ + +typedef struct DorderGatherNode_ { + Gnum fathnum; /*+ Global number of father node +*/ + Gnum typeval; /*+ Node type +*/ + Gnum vnodnbr; /*+ Number of node vertices +*/ + Gnum cblknum; /*+ Rank of node in father column block array +*/ +} DorderGatherNode; + +/*+ This structure holds the separator tree structure. +*/ + +typedef struct DorderGatherCblk_ { + Gnum cblknbr; /*+ Number of sons +*/ + OrderCblk * cblktab; /*+ Pointer to sub-array +*/ +} DorderGatherCblk; diff --git a/scotch_6.0.3/src/libscotch/dorder_io.c b/scotch_6.0.3/src/libscotch/dorder_io.c new file mode 100644 index 00000000..c6a04bac --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder_io.c @@ -0,0 +1,261 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder_io.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles distributed **/ +/** orderings. **/ +/** **/ +/** DATES : # Version 5.0 : from : 27 apr 2006 **/ +/** to 13 jun 2008 **/ +/** # Version 5.1 : from : 30 jul 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DORDER + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "dgraph.h" +#include "dorder.h" +#include "order.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This routine saves a distributed ordering. +** The distributed graph structure is provided +** to access the distribution of vertex labels, +** whenever present. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dorderSave ( +const Dorder * restrict const ordeptr, +const Dgraph * restrict const grafptr, +FILE * restrict const stream) +{ + Gnum * restrict peritab; + Gnum * restrict permtab; + Gnum * restrict vlbltax; + int procglbnbr; + int reduloctab[3]; + int reduglbtab[3]; + int protnum; + + if (stream != NULL) { /* If file provided */ + reduloctab[0] = 1; /* This process is the root */ + reduloctab[1] = ordeptr->proclocnum; /* Get its rank */ + } + else { + reduloctab[0] = /* This process is not the root */ + reduloctab[1] = 0; + } + reduloctab[2] = (grafptr->vlblloctax != NULL) ? 1 : 0; /* See if vertex labels provided */ + if (MPI_Allreduce (reduloctab, reduglbtab, 3, MPI_INT, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSave: communication error (1)"); + return (1); + } + if (reduglbtab[0] != 1) { + errorPrint ("dorderSave: should have only one root"); + return (1); + } + MPI_Comm_size (ordeptr->proccomm, &procglbnbr); + if ((reduglbtab[2] != 0) && (reduglbtab[2] != procglbnbr)) { + errorPrint ("dorderSave: inconsistent parameters"); + return (1); + } + protnum = (int) reduglbtab[1]; /* Get rank of root process */ + + reduloctab[0] = 0; + permtab = NULL; + if (protnum == ordeptr->proclocnum) { + Gnum vlblnbr; + + vlblnbr = (grafptr->vlblloctax != NULL) ? ordeptr->vnodglbnbr : 0; + if (memAllocGroup ((void **) (void *) + &permtab, (size_t) (ordeptr->vnodglbnbr * sizeof (Gnum)), + &peritab, (size_t) (ordeptr->vnodglbnbr * sizeof (Gnum)), + &vlbltax, (size_t) (vlblnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("dorderSave: out of memory"); +#ifdef SCOTCH_DEBUG_DORDER1 + reduloctab[0] = 1; +#else /* SCOTCH_DEBUG_DORDER1 */ + return (1); +#endif /* SCOTCH_DEBUG_DORDER1 */ + } + } +#ifdef SCOTCH_DEBUG_DORDER1 /* This communication cannot be covered by a useful one */ + if (MPI_Bcast (&reduloctab[0], 1, MPI_INT, protnum, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSave: communication error (2)"); + if (permtab != NULL); + memFree (permtab); /* Free group leader */ + return (1); + } + if (reduloctab[0] != 0) + return (1); +#endif /* SCOTCH_DEBUG_DORDER1 */ + + if (grafptr->vlblloctax != NULL) { + if (commGatherv (grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI, + vlbltax, grafptr->proccnttab, grafptr->procdsptab, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSave: communication error (3)"); + return (1); + } + } + + if (protnum == ordeptr->proclocnum) { + Gnum vertnum; + + for (vertnum = 0; vertnum < ordeptr->vnodglbnbr; ) { /* Till all inverse permutation indices collected */ + const DorderLink * linkptr; + + for (linkptr = ordeptr->linkdat.nextptr; linkptr != &ordeptr->linkdat; linkptr = linkptr->nextptr) { + const DorderCblk * cblkptr; + + cblkptr = (DorderCblk *) linkptr; /* TRICK: FIRST */ + if (((cblkptr->typeval & DORDERCBLKLEAF) != 0) && + (cblkptr->data.leaf.ordelocval == vertnum) && /* If column block fragment starts at proper index */ + (cblkptr->data.leaf.vnodlocnbr > 0)) { /* And is not an empty local block with relevent data elsewhere */ + memCpy (peritab + vertnum, cblkptr->data.leaf.periloctab, cblkptr->data.leaf.vnodlocnbr * sizeof (Gnum)); + vertnum += cblkptr->data.leaf.vnodlocnbr; + break; + } + } + if (linkptr == &ordeptr->linkdat) { /* If fragment not found locally */ + MPI_Status statdat; + int recvnbr; + + if (MPI_Bcast (&vertnum, 1, GNUM_MPI, protnum, ordeptr->proccomm) != MPI_SUCCESS) { /* Broadcast missing fragment */ + errorPrint ("dorderSave: communication error (4)"); + memFree (permtab); /* Free group leader */ + return (1); + } + if (MPI_Recv (peritab + vertnum, ordeptr->vnodglbnbr - vertnum, GNUM_MPI, + MPI_ANY_SOURCE, DORDERTAGPERI, ordeptr->proccomm, &statdat) != MPI_SUCCESS) { + errorPrint ("dorderSave: communication error (5)"); + return (1); + } + MPI_Get_count (&statdat, GNUM_MPI, &recvnbr); + vertnum += recvnbr; + } + } + vertnum = -1; /* Indicate termination */ + if (MPI_Bcast (&vertnum, 1, GNUM_MPI, protnum, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSave: communication error (6)"); + memFree (permtab); /* Free group leader */ + return (1); + } + + if (fprintf (stream, GNUMSTRING "\n", (Gnum) ordeptr->vnodglbnbr) == EOF) { + errorPrint ("dorderSave: bad output (1)"); + memFree (permtab); + return (1); + } + + orderPeri (peritab, ordeptr->baseval, ordeptr->vnodglbnbr, permtab, ordeptr->baseval); /* Compute direct permutation */ + + if (grafptr->vlblloctax != NULL) { /* If ordering has label array */ + vlbltax -= ordeptr->baseval; /* Base label array */ + + for (vertnum = 0; vertnum < ordeptr->vnodglbnbr; vertnum ++) { + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) vlbltax[vertnum + ordeptr->baseval], + (Gnum) vlbltax[permtab[vertnum]]) == EOF) { + errorPrint ("dorderSave: bad output (2)"); + memFree (permtab); + return (1); + } + } + } + else { + for (vertnum = 0; vertnum < ordeptr->vnodglbnbr; vertnum ++) { + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) (vertnum + ordeptr->baseval), + (Gnum) permtab[vertnum]) == EOF) { + errorPrint ("dorderSave: bad output (3)"); + memFree (permtab); + return (1); + } + } + } + + memFree (permtab); /* Free group leader */ + } + else { + while (1) { + const DorderLink * linkptr; + Gnum vertnum; + + if (MPI_Bcast (&vertnum, 1, GNUM_MPI, protnum, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSave: communication error (7)"); + return (1); + } + if (vertnum == -1) /* If asked to quit */ + break; /* Finish */ + + for (linkptr = ordeptr->linkdat.nextptr; linkptr != &ordeptr->linkdat; linkptr = linkptr->nextptr) { + const DorderCblk * cblkptr; + + cblkptr = (DorderCblk *) linkptr; /* TRICK: FIRST */ + + if (((cblkptr->typeval & DORDERCBLKLEAF) != 0) && /* If matching column block fragment found */ + (cblkptr->data.leaf.ordelocval == vertnum) && + (cblkptr->data.leaf.vnodlocnbr > 0)) { /* And is not an empty local block with relevent data elsewhere */ + if (MPI_Send (cblkptr->data.leaf.periloctab, cblkptr->data.leaf.vnodlocnbr, + GNUM_MPI, protnum, DORDERTAGPERI, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSave: communication error (8)"); + return (1); + } + break; + } + } + } + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dorder_io_block.c b/scotch_6.0.3/src/libscotch/dorder_io_block.c new file mode 100644 index 00000000..7f32fcb7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder_io_block.c @@ -0,0 +1,130 @@ +/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder_io_block.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles distributed **/ +/** orderings. **/ +/** **/ +/** DATES : # Version 5.0 : from : 26 may 2008 **/ +/** to 26 may 2008 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DORDER + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "order.h" +#include "dorder.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This routine saves a distributed ordering on +** a combined block ordering format. +** The distributed graph structure is provided +** to access the distribution of vertex labels, +** whenever present. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +int +dorderSaveBlock2 ( +const Order * const cordptr, +const Gnum * const vlbltab, +FILE * const stream) +{ + Gnum vertnum; + Gnum * restrict rangtab; + Gnum cblknum; + int o; + + if ((rangtab = memAlloc ((cordptr->vnodnbr + 1) * sizeof (Gnum))) == NULL) { + errorPrint ("dorderSaveBlock2: out of memory"); + return (1); + } + orderRang (cordptr, rangtab); + + if (fprintf (stream, "0\n" GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) cordptr->cblknbr, + (Gnum) cordptr->vnodnbr) < 0) { + errorPrint ("dorderSaveBlock2: bad output (1)"); + return (1); + } + + for (cblknum = 0, o = 1; (o == 1) && (cblknum < cordptr->cblknbr); cblknum ++) { /* Save column-block range array */ + o = intSave (stream, rangtab[cblknum]); + putc (((cblknum & 7) == 7) ? '\n' : '\t', stream); + } + o = intSave (stream, rangtab[cblknum]); + putc ('\n', stream); + + orderPeri (cordptr->peritab, cordptr->baseval, cordptr->vnodnbr, rangtab, cordptr->baseval); /* TRICK: re-use rangtab as permtab */ + + for (vertnum = 0; (o == 1) && (vertnum < (cordptr->vnodnbr - 1)); vertnum ++) { /* Save direct permutation */ + o = intSave (stream, rangtab[vertnum]); + putc (((vertnum & 7) == 7) ? '\n' : '\t', stream); + } + o = intSave (stream, rangtab[vertnum]); + putc ('\n', stream); + + if (o != 1) + errorPrint ("dorderSaveBlock2: bad output (2)"); + + return (1 - o); +} + +int +dorderSaveBlock ( +const Dorder * restrict const ordeptr, +const Dgraph * restrict const grafptr, +FILE * restrict const stream) +{ + return (dorderSaveTree2 (ordeptr, grafptr, stream, dorderSaveBlock2)); +} diff --git a/scotch_6.0.3/src/libscotch/dorder_io_tree.c b/scotch_6.0.3/src/libscotch/dorder_io_tree.c new file mode 100644 index 00000000..92a7c66e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder_io_tree.c @@ -0,0 +1,202 @@ +/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder_io_tree.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles distributed **/ +/** orderings. **/ +/** **/ +/** DATES : # Version 5.0 : from : 26 jul 2007 **/ +/** to 26 jul 2007 **/ +/** # Version 5.1 : from : 30 jul 2010 **/ +/** to 30 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DORDER + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "dgraph.h" +#include "order.h" +#include "dorder.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This routine saves a distributed ordering. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dorderSaveTree2 ( +const Dorder * restrict const ordeptr, +const Dgraph * restrict const grafptr, +FILE * restrict const stream, +int (* funcptr) (const Order * const, const Gnum * const, FILE * const)) +{ + Order corddat; /* Centralized ordering for tree structure */ + Gnum * restrict vlbltab; + int procglbnbr; + int protnum; + int reduloctab[3]; + int reduglbtab[3]; + int cheklocval; + int chekglbval; + + if (stream != NULL) { /* If file provided */ + reduloctab[0] = 1; /* This process is the root */ + reduloctab[1] = ordeptr->proclocnum; /* Get its rank */ + } + else { + reduloctab[0] = /* This process is not the root */ + reduloctab[1] = 0; + } + reduloctab[2] = (grafptr->vlblloctax != NULL) ? 1 : 0; /* See if vertex labels provided */ + if (MPI_Allreduce (reduloctab, reduglbtab, 3, MPI_INT, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSaveTree2: communication error (1)"); + return (1); + } + if (reduglbtab[0] != 1) { + errorPrint ("dorderSaveTree2: should have only one root"); + return (1); + } + MPI_Comm_size (ordeptr->proccomm, &procglbnbr); + if ((reduglbtab[2] != 0) && (reduglbtab[2] != procglbnbr)) { + errorPrint ("dorderSaveTree2: inconsistent parameters"); + return (1); + } + protnum = (int) reduglbtab[1]; /* Get rank of root process */ + + cheklocval = 0; + vlbltab = NULL; + if (reduglbtab[2] != 0) { + if (protnum == ordeptr->proclocnum) + if ((vlbltab = memAlloc (ordeptr->vnodglbnbr * sizeof (Gnum))) == NULL) { + errorPrint ("dorderSaveTree2: out of memory"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ + if (MPI_Bcast (&cheklocval, 1, MPI_INT, protnum, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSaveTree2: communication error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER1 */ + if (cheklocval != 0) + return (1); + if (commGatherv (grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI, + vlbltab, grafptr->proccnttab, grafptr->procdsptab, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSaveTree2: communication error (3)"); + return (1); + } + } + + if (protnum == ordeptr->proclocnum) + cheklocval = orderInit (&corddat, ordeptr->baseval, ordeptr->vnodglbnbr, NULL); +#ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ + if (MPI_Bcast (&cheklocval, 1, MPI_INT, protnum, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSaveTree2: communication error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER1 */ + if (cheklocval != 0) + return (1); + + if (protnum == ordeptr->proclocnum) { + cheklocval = dorderGather (ordeptr, &corddat); /* Need inverse permutation too */ + if (cheklocval == 0) + cheklocval = funcptr (&corddat, vlbltab, stream); + orderExit (&corddat); + } + else + cheklocval = dorderGather (ordeptr, NULL); + + if (vlbltab != NULL) + memFree (vlbltab); + +#ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderSaveTree2: communication error (3)"); + return (1); + } +#else /* SCOTCH_DEBUG_DORDER1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DORDER1 */ + + return (chekglbval); +} + +/* This routine saves the separator tree +** data of the given distributed ordering. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dorderSaveTree ( +const Dorder * restrict const ordeptr, +const Dgraph * restrict const grafptr, +FILE * restrict const stream) +{ + return (dorderSaveTree2 (ordeptr, grafptr, stream, orderSaveTree)); +} + +/* This routine saves the column block +** mapping data of the given distributed +** ordering. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +dorderSaveMap ( +const Dorder * restrict const ordeptr, +const Dgraph * restrict const grafptr, +FILE * restrict const stream) +{ + return (dorderSaveTree2 (ordeptr, grafptr, stream, orderSaveMap)); +} diff --git a/scotch_6.0.3/src/libscotch/dorder_perm.c b/scotch_6.0.3/src/libscotch/dorder_perm.c new file mode 100644 index 00000000..9ca58e3d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder_perm.c @@ -0,0 +1,249 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder_gather.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles distributed **/ +/** orderings. **/ +/** **/ +/** DATES : # Version 5.0 : from : 13 oct 2007 **/ +/** to 21 oct 2007 **/ +/** # Version 5.1 : from : 26 sep 2008 **/ +/** to 26 sep 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DORDER + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dorder.h" +#include "dorder_perm.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This function builds a distributed direct +** permutation from the information stored +** in the distributed ordering structure. +** It returns: +** - 0 : if the distributed permutation could be computed. +** - !0 : on error. +*/ + +int +dorderPerm ( +const Dorder * restrict const ordeptr, +const Dgraph * restrict const grafptr, +Gnum * restrict const permloctab) +{ + Gnum * restrict permloctax; + int * restrict sendcnttab; + int * restrict senddsptab; + int * restrict recvcnttab; + int * restrict recvdsptab; + DorderPermSort * restrict sortsndtab; + DorderPermSort * restrict sortrcvtab; + const DorderLink * restrict linklocptr; + Gnum vnodlocnbr; + Gnum vnodlocnum; + int vnodrcvnbr; + int vnodsndnbr; + int procnum; + Gnum reduloctab[2]; + Gnum reduglbtab[2]; + + for (linklocptr = ordeptr->linkdat.nextptr, vnodlocnbr = 0; /* For all nodes in local ordering structure */ + linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) /* If node is leaf */ + vnodlocnbr += cblklocptr->data.leaf.vnodlocnbr; /* And more node vertices */ +#ifdef SCOTCH_DEBUG_DORDER2 + else if (cblklocptr->typeval != DORDERCBLKNEDI) { + errorPrint ("dorderPerm: invalid parameters (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + } + + reduloctab[0] = vnodlocnbr; + reduloctab[1] = 0; + if (memAllocGroup ((void **) (void *) + &senddsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &sendcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &recvdsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &recvcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &sortsndtab, (size_t) ((vnodlocnbr + 1) * sizeof (DorderPermSort)), /* "+1" for end marker */ + &sortrcvtab, (size_t) (grafptr->vertlocnbr * sizeof (DorderPermSort)), NULL) == NULL) { + errorPrint ("dorderPerm: out of memory"); + reduloctab[1] = 1; + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 2, GNUM_MPI, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderPerm: communication error (1)"); + reduglbtab[1] = 1; + } + if (reduglbtab[1] != 0) { + if (senddsptab != NULL) + memFree (senddsptab); /* Free group leader */ + return (1); + } + + if (reduglbtab[0] == 0) { /* If ordering structure is empty */ + Gnum ordelocval; /* Based permutation start index */ + + memFree (senddsptab); /* Free group leader */ + + for (vnodlocnum = 0, ordelocval = grafptr->procvrttab[grafptr->proclocnum]; /* Build identity permutation */ + vnodlocnum < grafptr->vertlocnbr; vnodlocnum ++) + permloctab[vnodlocnum] = ordelocval ++; + + return (0); + } + if (reduglbtab[0] != grafptr->vertglbnbr) { + errorPrint ("dorderPerm: invalid parameters (2)"); + memFree (senddsptab); /* Free group leader */ + return (1); + } + + for (linklocptr = ordeptr->linkdat.nextptr, vnodlocnum = 0; /* For all nodes in local ordering structure */ + linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) { /* If node is leaf */ + Gnum leaflocnbr; + Gnum leaflocnum; + Gnum ordelocval; /* Based permutation start index */ + + for (leaflocnum = 0, leaflocnbr = cblklocptr->data.leaf.vnodlocnbr, ordelocval = cblklocptr->data.leaf.ordelocval + ordeptr->baseval; + leaflocnum < leaflocnbr; leaflocnum ++, vnodlocnum ++) { + sortsndtab[vnodlocnum].vertnum = cblklocptr->data.leaf.periloctab[leaflocnum]; + sortsndtab[vnodlocnum].permnum = ordelocval + leaflocnum; +#ifdef SCOTCH_DEBUG_DORDER2 + if ((sortsndtab[vnodlocnum].vertnum < ordeptr->baseval) || + (sortsndtab[vnodlocnum].vertnum > (ordeptr->baseval + ordeptr->vnodglbnbr)) || + (sortsndtab[vnodlocnum].permnum < ordeptr->baseval) || + (sortsndtab[vnodlocnum].permnum > (ordeptr->baseval + ordeptr->vnodglbnbr))) { + errorPrint ("dorderPerm: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + } + } + } + sortsndtab[vnodlocnbr].vertnum = /* Set end marker */ + sortsndtab[vnodlocnbr].permnum = GNUMMAX; + intSort2asc1 (sortsndtab, vnodlocnbr); /* Sort permutation array by original vertex numbers, without marker */ + + for (vnodlocnum = 0, procnum = 0; procnum < grafptr->procglbnbr; ) { + Gnum vnodsndnbr; + Gnum procdspval; + + vnodsndnbr = 0; + procdspval = grafptr->procdsptab[procnum + 1]; + while (sortsndtab[vnodlocnum].vertnum < procdspval) { + vnodsndnbr ++; + vnodlocnum ++; +#ifdef SCOTCH_DEBUG_DORDER2 + if (vnodlocnum > vnodlocnbr) { /* If beyond regular indices plus end marker */ + errorPrint ("dorderPerm: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + } + sendcnttab[procnum ++] = (int) (vnodsndnbr * 2); /* Communication array for MPI, so (int), and "*2" because a Sort is 2 Gnums */ + } +#ifdef SCOTCH_DEBUG_DORDER2 + if (vnodlocnum != vnodlocnbr) { + errorPrint ("dorderPerm: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + + if (MPI_Alltoall (sendcnttab, 1, MPI_INT, recvcnttab, 1, MPI_INT, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderPerm: communication error (2)"); + return (1); + } + + for (procnum = 0, vnodrcvnbr = vnodsndnbr = 0; procnum < grafptr->procglbnbr; procnum ++) { /* Accumulate send and receive indices */ + recvdsptab[procnum] = vnodrcvnbr; + vnodrcvnbr += recvcnttab[procnum]; /* Accumulate "*2" values as counts */ + senddsptab[procnum] = vnodsndnbr; + vnodsndnbr += sendcnttab[procnum]; + } + + if (MPI_Alltoallv (sortsndtab, sendcnttab, senddsptab, GNUM_MPI, sortrcvtab, recvcnttab, recvdsptab, GNUM_MPI, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderPerm: communication error (3)"); + return (1); + } + +#ifdef SCOTCH_DEBUG_DORDER2 + memSet (permloctab, ~0, grafptr->vertlocnbr * sizeof (Gnum)); +#endif /* SCOTCH_DEBUG_DORDER2 */ + + permloctax = permloctab - grafptr->procdsptab[grafptr->proclocnum]; /* Base local array through global indices */ + for (vnodlocnum = 0; vnodlocnum < grafptr->vertlocnbr; vnodlocnum ++) { +#ifdef SCOTCH_DEBUG_DORDER2 + if (permloctax[sortrcvtab[vnodlocnum].vertnum] != ~0) { + errorPrint ("dorderPerm: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + permloctax[sortrcvtab[vnodlocnum].vertnum] = sortrcvtab[vnodlocnum].permnum; + } +#ifdef SCOTCH_DEBUG_DORDER2 + for (vnodlocnum = 0; vnodlocnum < grafptr->vertlocnbr; vnodlocnum ++) { + if (permloctab[vnodlocnum] == ~0) { + errorPrint ("dorderPerm: internal error (5)"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + + memFree (senddsptab); /* Free group leader */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dorder_perm.h b/scotch_6.0.3/src/libscotch/dorder_perm.h new file mode 100644 index 00000000..bb4f19dc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder_perm.h @@ -0,0 +1,57 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/**********************************************************/ +/* */ +/* NAME : dorder_perm.h */ +/* */ +/* AUTHOR : Francois PELLEGRINI */ +/* */ +/* FUNCTION : These lines are the data declarations */ +/* for the distributed source graph */ +/* folding routines. */ +/* */ +/* # Version 5.0 : from : 14 oct 2007 */ +/* to 14 oct 2007 */ +/* */ +/**********************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ The sort structure, used to sort permuted vertices. + Field vertnum is first because of intSort2asc1. +*/ + +typedef struct DorderPermSort_ { + Gnum vertnum; /*+ Vertex number: FIRST +*/ + Gnum permnum; /*+ Direct permutation index +*/ +} DorderPermSort; diff --git a/scotch_6.0.3/src/libscotch/dorder_tree_dist.c b/scotch_6.0.3/src/libscotch/dorder_tree_dist.c new file mode 100644 index 00000000..8160dbb7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dorder_tree_dist.c @@ -0,0 +1,305 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dorder_tree_dist.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles distributed **/ +/** orderings. **/ +/** **/ +/** DATES : # Version 5.1 : from : 28 nov 2007 **/ +/** to 09 may 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DORDER + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dorder.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This function returns to all processes the +** number of distributed leaf column blocks +** possessed by the ordering. +** It returns: +** - >=0 : number of distributed column blocks. +** - <0 : on error. +*/ + +Gnum +dorderCblkDist ( +const Dorder * restrict const ordeptr) +{ + const DorderLink * restrict linklocptr; + Gnum dblklocnbr; /* Local number of locally-rooted distributed column blocks */ + Gnum dblkglbnbr; + + for (linklocptr = ordeptr->linkdat.nextptr, dblklocnbr = 0; /* For all nodes in local ordering structure */ + linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if (cblklocptr->cblknum.proclocnum == ordeptr->proclocnum) + dblklocnbr ++; + } + + if (MPI_Allreduce (&dblklocnbr, &dblkglbnbr, 1, GNUM_MPI, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderCblkDist: communication error"); + return ((Gnum) -1); + } + + return (dblkglbnbr); +} + +/* This function returns on all of the procesors the +** distributed part of the distributed structure of +** the given distributed ordering. The two array +** pointers which must be passed should both point to +** arrays of size dorderCblkDist(). +** It returns: +** - 0 : if the distributed tree structure could be computed. +** - !0 : on error. +*/ + +int +dorderTreeDist ( +const Dorder * restrict const ordeptr, +const Dgraph * restrict const grafptr, +Gnum * restrict const treeglbtab, +Gnum * restrict const sizeglbtab) +{ + const DorderLink * restrict linklocptr; + Gnum * restrict dataloctab; + Gnum * restrict dataglbtab; + Gnum dblklocnum; + Gnum dblklocnbr; /* Local number of distributed column blocks */ + Gnum dblkglbnbr; /* Global number of distributed column blocks */ + Gnum dblkglbnum; + Gnum dblkglbtmp; + int * restrict dblkcnttab; + int * restrict dblkdsptab; + int * restrict cblkdsptab; + Gnum cblkglbtmp; + Gnum * restrict srt1glbtab; + Gnum * restrict srt2glbtab; + int procglbnbr; + int procnum; + Gnum reduloctab[3]; + Gnum reduglbtab[3]; + + for (linklocptr = ordeptr->linkdat.nextptr, dblklocnbr = 0; /* For all nodes in local ordering structure */ + linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if (cblklocptr->cblknum.proclocnum == ordeptr->proclocnum) { +#ifdef SCOTCH_DEBUG_DORDER2 + Gnum cblklocnum; + + cblklocnum = cblklocptr->cblknum.cblklocnum; + if ((cblklocnum < 0) || (cblklocnum >= ordeptr->cblklocnbr)) { + errorPrint ("dorderTreeDist: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + dblklocnbr ++; + } + } + if (MPI_Allreduce (&dblklocnbr, &dblkglbnbr, 1, GNUM_MPI, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { /* Get overall number of distributed blocks */ + errorPrint ("dorderTreeDist: communication error (1)"); + return (1); + } + + MPI_Comm_size (ordeptr->proccomm, &procglbnbr); + + reduloctab[0] = + reduloctab[1] = + reduloctab[2] = 0; + if (memAllocGroup ((void **) (void *) + &dblkcnttab, (size_t) ( procglbnbr * sizeof (int)), + &dblkdsptab, (size_t) ( procglbnbr * sizeof (int)), /* TRICK: cblkdsptab used as secondary array after cblkcnttab */ + &cblkdsptab, (size_t) ((procglbnbr + 1) * sizeof (int)), /* TRICK: have an array at least of size 2 */ + &dataloctab, (size_t) ( dblklocnbr * 4 * sizeof (Gnum)), + &dataglbtab, (size_t) ( dblkglbnbr * 4 * sizeof (Gnum)), + &srt1glbtab, (size_t) ( dblkglbnbr * 2 * sizeof (Gnum)), /* TRICK: one more slot for root node */ + &srt2glbtab, (size_t) ( dblkglbnbr * 2 * sizeof (Gnum)), NULL) == NULL) { /* TRICK: one more slot for root node */ + errorPrint ("dorderTreeDist: out of memory"); + reduloctab[0] = 1; /* Memory error */ + } + else { + if (treeglbtab != NULL) + reduloctab[1] = 1; /* Compute the "or" of any array being non-null */ + if (sizeglbtab != NULL) { + reduloctab[2] = reduloctab[1]; /* Compute the "and" of any array being non-null */ + reduloctab[1] = 1; + } + } +#ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderTreeDist: communication error (1)"); + reduglbtab[0] = /* Post-process error below */ + reduglbtab[1] = /* Prevent Valgrind from yelling */ + reduglbtab[2] = 1; + } +#else /* SCOTCH_DEBUG_DORDER1 */ + reduglbtab[0] = reduloctab[0]; + reduglbtab[1] = procglbnbr - 1 + reduloctab[1]; + reduglbtab[2] = procglbnbr - 1 + reduloctab[2]; +#endif /* SCOTCH_DEBUG_DORDER1 */ + + if (reduglbtab[1] != reduglbtab[2]) { /* If not both arrays provided on each of the candidate processors */ + if (reduloctab[1] != reduloctab[2]) + errorPrint ("dorderTreeDist: invalid parameters (1)"); + reduglbtab[0] = 1; + } + if (reduglbtab[2] != procglbnbr) { + errorPrint ("dorderTreeDist: invalid parameters (2)"); + reduglbtab[0] = 1; + } + if (reduglbtab[0] != 0) { + if (dblkcnttab != NULL) + memFree (dblkcnttab); /* Free group leader */ + return (1); + } + + cblkdsptab[0] = (int) dblklocnbr; /* MPI only supports int as count type */ + cblkdsptab[1] = (int) ordeptr->cblklocnbr; /* TRICK: cblkdsptab is at least of size 2 */ + if (MPI_Allgather (cblkdsptab, 2, MPI_INT, dblkcnttab, 2, MPI_INT, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderTreeDist: communication error (2)"); + return (1); + } + for (procnum = cblkglbtmp = 0; procnum < procglbnbr; procnum ++) { /* Accumulate un-based global start indices for all column blocks */ + cblkdsptab[procnum] = cblkglbtmp; + dblkcnttab[procnum] = dblkcnttab[2 * procnum] * 4; /* Four times for dataloctab */ + cblkglbtmp += dblkcnttab[2 * procnum + 1]; + } + for (procnum = dblkglbtmp = 0; procnum < procglbnbr; procnum ++) { /* Accumulate un-based global start indices for distributed column blocks */ + dblkdsptab[procnum] = dblkglbtmp; + dblkglbtmp += dblkcnttab[procnum]; + } + + for (linklocptr = ordeptr->linkdat.nextptr, dblklocnum = 0; /* For all nodes in local ordering structure */ + linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { + const DorderCblk * restrict cblklocptr; + + cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ + if (cblklocptr->cblknum.proclocnum == ordeptr->proclocnum) { /* If node is local */ + dataloctab[4 * dblklocnum] = cblkdsptab[ordeptr->proclocnum] + cblklocptr->cblknum.cblklocnum; + dataloctab[4 * dblklocnum + 1] = cblklocptr->ordeglbval; + dataloctab[4 * dblklocnum + 2] = cblkdsptab[cblklocptr->fathnum.proclocnum] + cblklocptr->fathnum.cblklocnum; + dataloctab[4 * dblklocnum + 3] = cblklocptr->vnodglbnbr; + dblklocnum ++; + } + } + if (MPI_Allgatherv (dataloctab, 4 * dblklocnbr, GNUM_MPI, dataglbtab, dblkcnttab, dblkdsptab, GNUM_MPI, ordeptr->proccomm) != MPI_SUCCESS) { + errorPrint ("dorderTreeDist: communication error (3)"); + return (1); + } + + for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { + srt1glbtab[2 * dblkglbnum] = dataglbtab[4 * dblkglbnum + 1]; + srt1glbtab[2 * dblkglbnum + 1] = dataglbtab[4 * dblkglbnum]; + } + intSort2asc2 (srt1glbtab, dblkglbnbr); /* Sort nodes by ascending inverse start index to get permutation of column block indices */ + for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { + srt1glbtab[2 * dblkglbnum] = srt1glbtab[2 * dblkglbnum + 1]; + srt1glbtab[2 * dblkglbnum + 1] = dblkglbnum; + } + intSort2asc2 (srt1glbtab, dblkglbnbr); /* Sort nodes by ascending column block index to match with the ones of dataglbtab */ + + for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { + srt2glbtab[2 * dblkglbnum] = dataglbtab[4 * dblkglbnum + 2]; + srt2glbtab[2 * dblkglbnum + 1] = dblkglbnum; + } + intSort2asc2 (srt2glbtab, dblkglbnbr); /* Sort father indices by ascending column block indices */ +#ifdef SCOTCH_DEBUG_DORDER2 + if (srt2glbtab[0] != -1) { /* If tree has no root */ + errorPrint ("dorderTreeDist: internal error (2)"); + memFree (dblkcnttab); /* Free group leader */ + return (1); + } + if ((dblkglbnbr > 1) && (srt2glbtab[2] == -1)) { /* If tree has multiple roots */ + errorPrint ("dorderTreeDist: internal error (3)"); + memFree (dblkcnttab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + for (dblkglbnum = 1, dblkglbtmp = 0; dblkglbnum < dblkglbnbr; ) { /* Replace in block data the father column block indices by the new permuted indices */ + if (srt2glbtab[2 * dblkglbnum] == srt1glbtab[2 * dblkglbtmp]) + dataglbtab[4 * srt2glbtab[2 * (dblkglbnum ++) + 1] + 2] = srt1glbtab[2 * dblkglbtmp + 1]; + else { +#ifdef SCOTCH_DEBUG_DORDER2 + if ((srt2glbtab[2 * dblkglbnum] < srt1glbtab[2 * dblkglbtmp]) || /* If column block index not found in table */ + (dblkglbtmp >= (dblkglbnbr - 1))) { + errorPrint ("dorderTreeDist: internal error (4)"); + memFree (dblkcnttab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + dblkglbtmp ++; + } + } + + for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { + srt2glbtab[2 * dblkglbnum] = dataglbtab[4 * dblkglbnum]; + srt2glbtab[2 * dblkglbnum + 1] = dblkglbnum; + } + intSort2asc2 (srt2glbtab, dblkglbnbr); /* Sort father indices by ascending column block indices */ + for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { +#ifdef SCOTCH_DEBUG_DORDER2 + if (srt1glbtab[2 * dblkglbnum] != srt2glbtab[2 * dblkglbnum]) { + errorPrint ("dorderTreeDist: internal error (5)"); + memFree (dblkcnttab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DORDER2 */ + treeglbtab[srt1glbtab[2 * dblkglbnum + 1]] = dataglbtab[4 * srt2glbtab[2 * dblkglbnum + 1] + 2]; + sizeglbtab[srt1glbtab[2 * dblkglbnum + 1]] = dataglbtab[4 * srt2glbtab[2 * dblkglbnum + 1] + 3]; + } + + memFree (dblkcnttab); /* Free group leader */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/dummysizes.c b/scotch_6.0.3/src/libscotch/dummysizes.c new file mode 100644 index 00000000..de8a8c91 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/dummysizes.c @@ -0,0 +1,276 @@ +/* Copyright 2004,2007-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dummysizes.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of the libScotch compilation job. **/ +/** This small program processes files that **/ +/** are in fact pattern header files for **/ +/** the libScotch library, and replaces **/ +/** symbolic sizes of the opaque libScotch **/ +/** by the proper integer values according **/ +/** to the machine on which it is run. **/ +/** **/ +/** DATES : # Version 3.4 : from : 22 oct 2001 **/ +/** to : 22 nov 2001 **/ +/** # Version 4.0 : from : 25 nov 2001 **/ +/** to : 06 jan 2006 **/ +/** # Version 5.0 : from : 26 apr 2006 **/ +/** to : 03 apr 2008 **/ +/** # Version 5.1 : from : 16 jun 2008 **/ +/** to : 15 aug 2010 **/ +/** # Version 6.0 : from : 01 dec 2012 **/ +/** to : 01 dec 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DUMMYSIZES + +#define CHARMAX 2048 /* Maximum line size */ + +#define SUBSMAX 48 /* Maximum number of substitutions */ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamehedinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenamehedout C_fileTab[1].name /* Statistics output file name */ + +#define C_filepntrhedinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrhedout C_fileTab[1].pntr /* Statistics output file */ + +#define EXPAND(s) EXPANDTWO(s) +#define EXPANDTWO(s) #s + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "geom.h" +#include "mesh.h" +#include "arch.h" +#include "mapping.h" +#include "order.h" +#ifdef SCOTCH_PTSCOTCH +#include "dgraph.h" +#include "dgraph_halo.h" +#include "dmapping.h" +#include "dorder.h" +#include "library_dmapping.h" +#endif /* SCOTCH_PTSCOTCH */ +#include "library_mapping.h" +#include "library_order.h" + +/* +** The static definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +void +subsFill ( +char * substab[2], +char * origptr, +int subsval) +{ + char * subsptr; + + subsptr = malloc (32 * sizeof (char)); + sprintf (subsptr, "%d", (int) ((subsval + sizeof (double) - 1) / sizeof (double))); + + substab[0] = origptr; + substab[1] = subsptr; +} + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + char chartab[CHARMAX]; + char chartmp[CHARMAX]; + char * substab[SUBSMAX][2]; /* Substitution array */ + int subsnbr; + int i; + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + printf ("Usage is:\ndummysizes [ []]\n"); + return (((argv[1][0] == '?') && argv[1][1] == '\0') ? 0 : 1); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '+') && /* If found a file name */ + ((argv[i][0] != '-') || (argv[i][1] == '\0'))) { + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + fprintf (stderr, "dummysizes: ERROR: main: too many file names given"); + exit (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + printf ("Usage is:\ndummysizes [ []]\n"); + exit (0); + case 'V' : + fprintf (stderr, "dummysizes, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007-2010 ENSEIRB, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + fprintf (stderr, "dummysizes: ERROR: main: unprocessed option (\"%s\")", argv[i]); + exit (1); + } + } + } + + for (i = 0; i < C_FILENBR; i ++) { /* For all file names */ + if ((C_fileTab[i].name[0] != '-') || /* If not standard stream */ + (C_fileTab[i].name[1] != '\0')) { + if ((C_fileTab[i].pntr = fopen (C_fileTab[i].name, C_fileTab[i].mode)) == NULL) { /* Open the file */ + fprintf (stderr, "dummysizes: ERROR: main: cannot open file (%d)", i); + exit (1); + } + } + } + +#ifdef SCOTCH_PTSCOTCH + substab[0][0] = "library_pt.h"; + substab[0][1] = "ptscotch.h "; + substab[1][0] = "library_pt_f.h"; + substab[1][1] = "ptscotchf.h "; +#else /* SCOTCH_PTSCOTCH */ + substab[0][0] = "library.h"; + substab[0][1] = "scotch.h "; + substab[1][0] = "library_f.h"; + substab[1][1] = "scotchf.h "; +#endif /* SCOTCH_PTSCOTCH */ + substab[2][0] = "DUMMYIDX"; + substab[2][1] = EXPAND (IDX); + substab[3][0] = "DUMMYINT"; + substab[3][1] = EXPAND (INT); + substab[4][0] = "DUMMYMAXINT"; + substab[4][1] = EXPAND (INTVALMAX); + substab[5][0] = "DUMMYNUMSTRING"; + substab[5][1] = "\"" GNUMSTRING "\""; + substab[6][0] = "DUMMYVERSION"; + substab[6][1] = EXPAND (SCOTCH_VERSION); + substab[7][0] = "DUMMYRELEASE"; + substab[7][1] = EXPAND (SCOTCH_RELEASE); + substab[8][0] = "DUMMYPATCHLEVEL"; + substab[8][1] = EXPAND (SCOTCH_PATCHLEVEL); + subsnbr = 9; + subsFill (substab[subsnbr ++], "DUMMYSIZEARCH", sizeof (Arch)); + subsFill (substab[subsnbr ++], "DUMMYSIZEGEOM", sizeof (Geom)); + subsFill (substab[subsnbr ++], "DUMMYSIZEGRAPH", sizeof (Graph)); + subsFill (substab[subsnbr ++], "DUMMYSIZEMESH", sizeof (Mesh)); + subsFill (substab[subsnbr ++], "DUMMYSIZEMAP", sizeof (LibMapping)); + subsFill (substab[subsnbr ++], "DUMMYSIZEORDER", sizeof (LibOrder)); + subsFill (substab[subsnbr ++], "DUMMYSIZESTRAT", sizeof (Strat *)); +#ifdef SCOTCH_PTSCOTCH + subsFill (substab[subsnbr ++], "DUMMYSIZEDGRAPHHALOREQ", sizeof (DgraphHaloRequest)); /* TRICK: before DUMMYSIZEDGRAPH */ + subsFill (substab[subsnbr ++], "DUMMYSIZEDGRAPH", sizeof (Dgraph)); + subsFill (substab[subsnbr ++], "DUMMYSIZEDMAP", sizeof (LibDmapping)); + subsFill (substab[subsnbr ++], "DUMMYSIZEDORDER", sizeof (Dorder)); +#else /* SCOTCH_PTSCOTCH */ + subsFill (substab[subsnbr ++], "DUMMYSIZEDGRAPHHALOREQ", 1); /* TRICK: before DUMMYSIZEDGRAPH */ + subsFill (substab[subsnbr ++], "DUMMYSIZEDGRAPH", 1); + subsFill (substab[subsnbr ++], "DUMMYSIZEDMAP", 1); + subsFill (substab[subsnbr ++], "DUMMYSIZEDORDER", 1); +#endif /* SCOTCH_PTSCOTCH */ + + while (fgets (chartab, CHARMAX, C_filepntrhedinp) != NULL) { /* Infinite loop on file lines */ + int charnbr; + int subsnum; + + if (((charnbr = strlen (chartab)) >= (CHARMAX - 1)) && /* If line read is at least as long as maximum size */ + (chartab[CHARMAX - 1] != '\n')) { /* And last character is not a newline, that is, some is missing */ + fprintf (stderr, "dummysizes: ERROR: line too long\n"); + exit (1); + } + + for (subsnum = 0; subsnum < subsnbr; subsnum ++) { /* Perform substitutions */ + char * charptr; /* Place where token found */ + + while ((charptr = strstr (chartab, substab[subsnum][0])) != NULL) { /* As long as substitution can be performed */ + int charnbr; + int charnum; + + charnum = charptr - chartab; /* Position where token found */ + charnbr = strlen (substab[subsnum][0]); /* Length of token */ + + strcpy (chartmp, charptr + charnbr); /* Save end of line */ + + sprintf (charptr, "%s%s", substab[subsnum][1], chartmp); /* Replace end of line with substituted token */ + } + } + + fputs (chartab, C_filepntrhedout); /* Output possibly updated line */ + } + +#ifdef SCOTCH_DEBUG_MAIN1 + for (i = 0; i < C_FILENBR; i ++) { /* For all file names */ + if ((C_fileTab[i].name[0] != '-') || /* If not standard stream */ + (C_fileTab[i].name[1] != '\0')) { + fclose (C_fileTab[i].pntr); /* Close the stream */ + } + } +#endif /* SCOTCH_DEBUG_MAIN1 */ + + exit (0); +} diff --git a/scotch_6.0.3/src/libscotch/fibo.c b/scotch_6.0.3/src/libscotch/fibo.c new file mode 100644 index 00000000..cb5a7b0a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/fibo.c @@ -0,0 +1,355 @@ +/* Copyright 2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : fibo.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles Fibonacci trees. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 may 2010 **/ +/** to 12 may 2010 **/ +/** # Version 6.0 : from : 22 oct 2011 **/ +/** to 22 oct 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define FIBO + +#include "module.h" +#include "common.h" +#include "fibo.h" + +/*********************************************/ +/* */ +/* These routines deal with Fibonacci trees. */ +/* */ +/*********************************************/ + +/* This routine initializes a Fibonacci +** tree structure. +** It returns: +** - 0 : in case of success. +** - !0 : on error. +*/ + +int +fiboTreeInit ( +FiboTree * const treeptr, +int (* cmpfptr) (const FiboNode * const, const FiboNode * const)) +{ + if ((treeptr->degrtab = (FiboNode **) memAlloc ((sizeof (INT) << 3) * sizeof (FiboNode *))) == NULL) /* As many cells as there are bits in an INT */ + return (1); + + memSet (treeptr->degrtab, 0, (sizeof (INT) << 3) * sizeof (FiboNode *)); /* Make degree array ready for consolidation: all cells set to NULL */ + + treeptr->rootdat.linkdat.prevptr = /* Link root node to itself */ + treeptr->rootdat.linkdat.nextptr = &treeptr->rootdat; + treeptr->cmpfptr = cmpfptr; + + return (0); +} + +/* This routine flushes the contents of +** the given Fibonacci tree. +** It returns: +** - VOID : in all cases. +*/ + +void +fiboTreeExit ( +FiboTree * const treeptr) +{ + if (treeptr->degrtab != NULL) + memFree (treeptr->degrtab); +} + +/* This routine flushes the contents of +** the given Fibonacci tree. +** It returns: +** - VOID : in all cases. +*/ + +void +fiboTreeFree ( +FiboTree * const treeptr) +{ + treeptr->rootdat.linkdat.prevptr = /* Link root node to itself */ + treeptr->rootdat.linkdat.nextptr = &treeptr->rootdat; +} + +/* This routine perform the consolidation +** of roots per degree. It returns the best +** element found because this element is not +** recorded in the data structure itself. +** It returns: +** - !NULL : pointer to best element found. +** - NULL : Fibonacci tree is empty. +*/ + +FiboNode * +fiboTreeConsolidate ( +FiboTree * const treeptr) +{ + FiboNode ** restrict degrtab; + int degrmax; + int degrval; + FiboNode * rootptr; + FiboNode * nextptr; + FiboNode * bestptr; + + degrtab = treeptr->degrtab; + + for (rootptr = treeptr->rootdat.linkdat.nextptr, nextptr = rootptr->linkdat.nextptr, degrmax = 0; /* For all roots in root list */ + rootptr != &treeptr->rootdat; ) { + degrval = rootptr->deflval >> 1; /* Get degree, getting rid of flag part */ +#ifdef SCOTCH_DEBUG_FIBO2 + if (degrval >= (sizeof (INT) << 3)) + errorPrint ("fiboTreeConsolidate: invalid node degree"); +#endif /* SCOTCH_DEBUG_FIBO2 */ + if (degrtab[degrval] == NULL) { /* If no tree with same degree already found */ + if (degrval > degrmax) /* Record highest degree found */ + degrmax = degrval; + + degrtab[degrval] = rootptr; /* Record tree as first tree with this degree */ + rootptr = nextptr; /* Process next root in list during next iteration */ + nextptr = rootptr->linkdat.nextptr; + } + else { + FiboNode * oldrptr; /* Root which will no longer be a root */ + FiboNode * chldptr; + + oldrptr = degrtab[degrval]; /* Assume old root is worse */ + if (treeptr->cmpfptr (oldrptr, rootptr) <= 0) { /* If old root is still better */ + oldrptr = rootptr; /* This root will be be linked to it */ + rootptr = degrtab[degrval]; /* We will go on processing this root */ + } + + degrtab[degrval] = NULL; /* Remaining root changes degree so leaves this cell */ + fiboTreeUnlink (oldrptr); /* Old root is no longer a root */ + oldrptr->deflval &= ~1; /* Whatever old root flag was, it is reset to 0 */ + oldrptr->pareptr = rootptr; /* Remaining root is now father of old root */ + + chldptr = rootptr->chldptr; /* Get first child of remaining root */ + if (chldptr != NULL) { /* If remaining root had already some children, link old root with them */ + rootptr->deflval += 2; /* Increase degree by 1, that is, by 2 with left shift in deflval */ + fiboTreeLinkAfter (chldptr, oldrptr); + } + else { /* Old root becomes first child of remaining root */ + rootptr->deflval = 2; /* Real degree set to 1, and flag set to 0 */ + rootptr->chldptr = oldrptr; + oldrptr->linkdat.prevptr = /* Chain old root to oneself as only child */ + oldrptr->linkdat.nextptr = oldrptr; + } + } /* Process again remaining root as its degree has changed */ + } + + bestptr = NULL; + for (degrval = 0; degrval <= degrmax; degrval ++) { + if (degrtab[degrval] != NULL) { /* If some tree is found */ + bestptr = degrtab[degrval]; /* Record it as potential best */ + degrtab[degrval] = NULL; /* Clean-up used part of array */ + degrval ++; /* Go on at next cell in next loop */ + break; + } + } + for ( ; degrval <= degrmax; degrval ++) { /* For remaining roots once a potential best root has been found */ + if (degrtab[degrval] != NULL) { + if (treeptr->cmpfptr (degrtab[degrval], bestptr) < 0) /* If new root is better */ + bestptr = degrtab[degrval]; /* Record new root as best root */ + degrtab[degrval] = NULL; /* Clean-up used part of array */ + } + } + + return (bestptr); +} + +/* This routine returns the node of minimum +** key in the given tree. The node is searched +** for each time this routine is called, so this +** information should be recorded if needed. +** This is the non-macro version, for testing +** and setting up breakpoints. +** It returns: +** - !NULL : pointer to best element found. +** - NULL : Fibonacci tree is empty. +*/ + +#ifndef fiboTreeMinIsMacro + +FiboNode * +fiboTreeMin ( +FiboTree * const treeptr) +{ + FiboNode * bestptr; + + bestptr = fiboTreeMinMacro (treeptr); + +#ifdef SCOTCH_DEBUG_FIBO3 + fiboTreeCheck (treeptr); +#endif /* SCOTCH_DEBUG_FIBO3 */ + + return (bestptr); +} + +#endif /* fiboTreeMinIsMacro */ + +/* This routine adds the given node to the +** given tree. This is the non-macro version, +** for testing and setting up breakpoints. +** It returns: +** - void : in all cases. +*/ + +#ifndef fiboTreeAddIsMacro + +void +fiboTreeAdd ( +FiboTree * const treeptr, +FiboNode * const nodeptr) +{ + fiboTreeAddMacro (treeptr, nodeptr); + +#ifdef SCOTCH_DEBUG_FIBO3 + fiboTreeCheck (treeptr); +#endif /* SCOTCH_DEBUG_FIBO3 */ +} + +#endif /* fiboTreeAddIsMacro */ + +/* This routine deletes the given node from +** the given tree, whatever ths node is (root +** or non root). This is the non-macro version, +** for testing and setting up breakpoints. +** It returns: +** - void : in all cases. +*/ + +#ifndef fiboTreeDelIsMacro + +void +fiboTreeDel ( +FiboTree * const treeptr, +FiboNode * const nodeptr) +{ + fiboTreeDelMacro (treeptr, nodeptr); + +#ifdef SCOTCH_DEBUG_FIBO3 + nodeptr->pareptr = + nodeptr->chldptr = + nodeptr->linkdat.prevptr = + nodeptr->linkdat.nextptr = NULL; + + fiboTreeCheck (treeptr); +#endif /* SCOTCH_DEBUG_FIBO3 */ +} + +#endif /* fiboTreeDelIsMacro */ + +/* This routine checks the consistency of the +** given linked list. +** It returns: +** - !NULL : pointer to the vertex. +** - NULL : if no such vertex available. +*/ + +#ifdef SCOTCH_DEBUG_FIBO3 + +static +int +fiboTreeCheck2 ( +const FiboNode * const nodeptr) +{ + FiboNode * chldptr; + int degrval; + + degrval = 0; + chldptr = nodeptr->chldptr; + if (chldptr != NULL) { + do { + if (chldptr->linkdat.nextptr->linkdat.prevptr != chldptr) { + errorPrint ("fiboTreeCheck: bad child linked list"); + return (1); + } + + if (chldptr->pareptr != nodeptr) { + errorPrint ("fiboTreeCheck: bad child parent"); + return (1); + } + + if (fiboTreeCheck2 (chldptr) != 0) + return (1); + + degrval ++; + chldptr = chldptr->linkdat.nextptr; + } while (chldptr != nodeptr->chldptr); + } + + if (degrval != (nodeptr->deflval >> 1)) { /* Real node degree is obtained by discarding lowest bit */ + errorPrint ("fiboTreeCheck2: invalid child information"); + return (1); + } + + return (0); +} + +int +fiboTreeCheck ( +const FiboTree * const treeptr) +{ + FiboNode * nodeptr; + + for (nodeptr = treeptr->rootdat.linkdat.nextptr; + nodeptr != &treeptr->rootdat; nodeptr = nodeptr->linkdat.nextptr) { + if (nodeptr->linkdat.nextptr->linkdat.prevptr != nodeptr) { + errorPrint ("fiboTreeCheck: bad root linked list"); + return (1); + } + + if (nodeptr->pareptr != NULL) { + errorPrint ("fiboTreeCheck: bad root parent"); + return (1); + } + + if (fiboTreeCheck2 (nodeptr) != 0) + return (1); + } + + return (0); +} + +#endif /* SCOTCH_DEBUG_FIBO3 */ diff --git a/scotch_6.0.3/src/libscotch/fibo.h b/scotch_6.0.3/src/libscotch/fibo.h new file mode 100644 index 00000000..abc12099 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/fibo.h @@ -0,0 +1,197 @@ +/* Copyright 2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : fibo.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the definitions of **/ +/** the generic Fibonacci trees. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 may 2010 **/ +/** to 12 may 2010 **/ +/** # Version 6.0 : from : 22 oct 2011 **/ +/** to 22 oct 2011 **/ +/** **/ +/** NOTES : # Since this module is to be used as **/ +/** the gain keeping data structure for **/ +/** local optimization algorithms, the **/ +/** computation of the best node needs **/ +/** only to be done when actually picking **/ +/** the vertex, while many insertions and **/ +/** deletions (neighbor vertices) can **/ +/** take place in the mean time. This is **/ +/** why this data structure does not keep **/ +/** track of the best node, as most **/ +/** implementations do. **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/* The doubly linked list structure. */ + +typedef struct FiboLink_ { + struct FiboNode_ * prevptr; /*+ Pointer to previous sibling element +*/ + struct FiboNode_ * nextptr; /*+ Pointer to next sibling element +*/ +} FiboLink; + +/* The tree node data structure. The deflval + variable merges degree and flag variables. + The degree of a node is smaller than + "bitsizeof (INT)", so it can hold on an + "int". The flag value is stored in the + lowest bit of the value. */ + + +typedef struct FiboNode_ { + struct FiboNode_ * pareptr; /*+ Pointer to parent element, if any +*/ + struct FiboNode_ * chldptr; /*+ Pointer to first child element, if any +*/ + FiboLink linkdat; /*+ Pointers to sibling elements +*/ + int deflval; /*+ Lowest bit: flag value; other bits: degree value +*/ +} FiboNode; + +/* The tree data structure. The fake dummy node aims + at handling root node insertion without any test. + This is important as many insertions have to be + performed. */ + +typedef struct FiboTree_ { + FiboNode rootdat; /*+ Dummy node for fast root insertion +*/ + FiboNode ** restrict degrtab; /*+ Consolidation array of size "bitsizeof (INT)" +*/ + int (* cmpfptr) (const FiboNode * const, const FiboNode * const); /*+ Comparison routine +*/ +} FiboTree; + +/* +** The marco definitions. +*/ + +#define fiboTreeLinkAfter(o,n) do { \ + FiboNode * nextptr; \ + nextptr = (o)->linkdat.nextptr; \ + (n)->linkdat.nextptr = nextptr; \ + (n)->linkdat.prevptr = (o); \ + nextptr->linkdat.prevptr = (n); \ + (o)->linkdat.nextptr = (n); \ + } while (0) + +#define fiboTreeUnlink(n) do { \ + (n)->linkdat.prevptr->linkdat.nextptr = (n)->linkdat.nextptr; \ + (n)->linkdat.nextptr->linkdat.prevptr = (n)->linkdat.prevptr; \ + } while (0) + +#define fiboTreeAddMacro(t,n) do { \ + (n)->pareptr = NULL; \ + (n)->chldptr = NULL; \ + (n)->deflval = 0; \ + fiboTreeLinkAfter (&((t)->rootdat), (n)); \ + } while (0) + +#define fiboTreeMinMacro(t) (fiboTreeConsolidate (t)) + +#define fiboTreeCutChildren(t,n) do { \ + FiboNode * chldptr; \ + chldptr = (n)->chldptr; \ + if (chldptr != NULL) { \ + FiboNode * cendptr; \ + cendptr = chldptr; \ + do { \ + FiboNode * nextptr; \ + nextptr = chldptr->linkdat.nextptr; \ + chldptr->pareptr = NULL; \ + fiboTreeLinkAfter (&((t)->rootdat), chldptr); \ + chldptr = nextptr; \ + } while (chldptr != cendptr); \ + } \ + } while (0) + +#define fiboTreeDelMacro(t,n) do { \ + FiboNode * pareptr; \ + FiboNode * rghtptr; \ + pareptr = (n)->pareptr; \ + fiboTreeUnlink (n); \ + fiboTreeCutChildren ((t), (n)); \ + if (pareptr == NULL) \ + break; \ + rghtptr = (n)->linkdat.nextptr; \ + while (1) { \ + FiboNode * gdpaptr; \ + int deflval; \ + deflval = pareptr->deflval - 2; \ + pareptr->deflval = deflval | 1; \ + gdpaptr = pareptr->pareptr; \ + pareptr->chldptr = (deflval <= 1) ? NULL : rghtptr; \ + if (((deflval & 1) == 0) || (gdpaptr == NULL)) \ + break; \ + rghtptr = pareptr->linkdat.nextptr; \ + fiboTreeUnlink (pareptr); \ + pareptr->pareptr = NULL; \ + fiboTreeLinkAfter (&((t)->rootdat), pareptr); \ + pareptr = gdpaptr; \ + } \ + } while (0) + +/* +** The function prototypes. +*/ + +#define fiboTreeAddIsMacro +#define fiboTreeAdd fiboTreeAddMacro +/* #define fiboTreeDel fiboTreeDelMacro */ +/* #define fiboTreeMin fiboTreeMinMacro */ + +#ifndef FIBO +#define static +#endif + +int fiboTreeInit (FiboTree * const, int (*) (const FiboNode * const, const FiboNode * const)); +void fiboTreeExit (FiboTree * const); +void fiboTreeFree (FiboTree * const); +FiboNode * fiboTreeConsolidate (FiboTree * const); +#ifndef fiboTreeAddIsMacro +void fiboTreeAdd (FiboTree * const, FiboNode * const); +#endif /* fiboTreeAddIsMacro */ +#ifndef fiboTreeDelIsMacro +void fiboTreeDel (FiboTree * const, FiboNode * const); +#endif /* fiboTreeDelIsMacro */ +#ifndef fiboTreeMinIsMacro +FiboNode * fiboTreeMin (FiboTree * const); +#endif /* fiboTreeMinIsMacro */ +#ifdef SCOTCH_DEBUG_FIBO3 +int fiboTreeCheck (const FiboTree * const); +static int fiboTreeCheck2 (const FiboNode * const); +#endif /* SCOTCH_DEBUG_FIBO3 */ + +#undef static diff --git a/scotch_6.0.3/src/libscotch/gain.c b/scotch_6.0.3/src/libscotch/gain.c new file mode 100644 index 00000000..4b05e2e4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/gain.c @@ -0,0 +1,417 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gain.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles logarithmic gain **/ +/** table structures. **/ +/** **/ +/** DATES : # Version 0.0 : from : 26 oct 1996 **/ +/** to 30 nov 1996 **/ +/** # Version 0.1 : from : 10 may 1999 **/ +/** to 10 may 1999 **/ +/** # Version 4.0 : from : 10 jan 2004 **/ +/** to 18 mar 2005 **/ +/** # Version 5.0 : from : 24 mar 2008 **/ +/** to 24 mar 2008 **/ +/** **/ +/** NOTES : # Most of the contents of this module **/ +/** comes from "map_b_fm" of the SCOTCH **/ +/** project (v3.2). **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GAIN + +#include "module.h" +#include "common.h" +#include "gain.h" + +/* +** The static variables. +*/ + +static GainLink gainLinkDummy; /*+ Dummy link space for fast linked list operations +*/ + +/*************************************************/ +/* */ +/* These routines deal with generic gain tables. */ +/* */ +/*************************************************/ + +/* This routine allocates and initializes +** a gain table structure with the proper +** number of subbits. +** It returns: +** - !NULL : pointer to the gain table; +** - NULL : on error. +*/ + +GainTabl * +gainTablInit ( +const INT gainmax, +const INT subbits) +{ + GainEntr * entrptr; + GainTabl * tablptr; + INT totsize; + + if (gainmax >= GAIN_LINMAX) { /* If logarithmic indexing */ + totsize = ((sizeof (INT) << 3) - subbits) << (subbits + 1); /* Allocate gain table */ + + if ((tablptr = (GainTabl *) memAlloc (sizeof (GainTabl) + (totsize - 1) * sizeof (GainEntr))) == NULL) + return (NULL); + + tablptr->tablAdd = gainTablAddLog; + + tablptr->subbits = subbits; /* Fill gain table fields */ + tablptr->submask = (1 << (subbits + 1)) - 1; /* Mask with all subbits, plus one, set to 1 */ + } + else { /* Linear indexing */ + totsize = 2 * GAIN_LINMAX; /* Allocate gain table */ + + if ((tablptr = (GainTabl *) memAlloc (sizeof (GainTabl) + (totsize - 1) * sizeof (GainEntr))) == NULL) + return (NULL); + + tablptr->tablAdd = gainTablAddLin; + tablptr->subbits = 0; /* Fill gain table fields */ + tablptr->submask = 0; + } + + tablptr->totsize = totsize; + tablptr->tabl = tablptr->tabk + (totsize / 2); + tablptr->tend = tablptr->tabk + (totsize - 1); /* End of gain entry array */ + tablptr->tmin = tablptr->tend; /* Entries of extremal gain */ + tablptr->tmax = tablptr->tabk; + + for (entrptr = tablptr->tabk; /* Initialize gain table entries */ + entrptr <= tablptr->tend; + entrptr ++) + entrptr->next = &gainLinkDummy; /* Point to dummy link area */ + + return (tablptr); +} + +/* This routine deletes a gain list +** It returns: +** - VOID : in all cases. +*/ + +void +gainTablExit ( +GainTabl * const tablptr) +{ + memFree (tablptr); /* Free table structure itself */ +} + +/* This routine flushes the contents of +** the given gain table. +** It returns: +** - VOID : in all cases. +*/ + +void +gainTablFree ( +GainTabl * const tablptr) +{ + GainEntr * entrptr; + + for (entrptr = tablptr->tmin; /* Flush only used area */ + entrptr <= tablptr->tmax; + entrptr ++) + entrptr->next = &gainLinkDummy; /* Point to dummy link area */ + + tablptr->tmin = tablptr->tend; /* Entries of extremal gain */ + tablptr->tmax = tablptr->tabk; +} + +/* This routine adds a vertex to the table +** and table gain indicated in the vertex +** fields. +** It returns: +** - VOID : in all cases. +*/ + +void +gainTablAddLin ( +GainTabl * const tablptr, /*+ Pointer to gain table +*/ +GainLink * const linkptr, /*+ Pointer to entry to add +*/ +const INT gain) /*+ Gain value +*/ +{ + GainEntr * entrptr; /* Pointer to gain entry */ + GainLink * headptr; /* Pointer to head of list */ + +#ifdef SCOTCH_DEBUG_GAIN2 + if (tablptr->tablAdd != gainTablAddLin) { + errorPrint ("gainTablAddLin: table type mismatch"); + return; + } +#endif /* SCOTCH_DEBUG_GAIN2 */ + + entrptr = tablptr->tabl + gain; + if (entrptr < tablptr->tabk) + entrptr = tablptr->tabk; + else if (entrptr > tablptr->tend) + entrptr = tablptr->tend; + + if (entrptr < tablptr->tmin) + tablptr->tmin = entrptr; + if (entrptr > tablptr->tmax) + tablptr->tmax = entrptr; + + headptr = (GainLink *) entrptr; /* TRICK: assume gain entry is a link */ + linkptr->tabl = entrptr; /* Set table position */ + headptr->next->prev = linkptr; /* Link vertex in gain list: TRICK */ + linkptr->prev = headptr; + linkptr->next = headptr->next; + headptr->next = linkptr; +} + +/* This routine adds a vertex to the table +** and table gain indicated in the vertex +** fields. +** It returns: +** - VOID : in all cases. +*/ + +void +gainTablAddLog ( +GainTabl * const tablptr, /*+ Pointer to gain table +*/ +GainLink * const linkptr, /*+ Pointer to entry to add +*/ +const INT gain) /*+ Gain value +*/ +{ + GainEntr * entrptr; /* Pointer to gain entry */ + INT i, j; + +#ifdef SCOTCH_DEBUG_GAIN2 + if (tablptr->tablAdd != gainTablAddLog) { + errorPrint ("gainTablAddLog: table type mismatch"); + return; + } +#endif /* SCOTCH_DEBUG_GAIN2 */ + + if (gain >= 0) { /* Compute table entry for gain */ + for (i = 0, j = gain; j > tablptr->submask; i ++, j >>= 1) ; + i = (i << tablptr->subbits) + j; + } + else { + for (i = 0, j = - (gain + 1); j > tablptr->submask; i ++, j >>= 1) ; + i = - ((i << tablptr->subbits) + j + 1); + } + entrptr = tablptr->tabl + i; + + if (entrptr < tablptr->tmin) + tablptr->tmin = entrptr; + if (entrptr > tablptr->tmax) + tablptr->tmax = entrptr; + +#ifdef SCOTCH_DEBUG_GAIN3 + if ((entrptr->next != &gainLinkDummy) && + (entrptr->next->prev != (GainLink *) entrptr)) { + errorPrint ("gainTablAddLog: bad first element"); + return; + } + if (gainTablCheck (entrptr) != 0) { + errorPrint ("gainTablAddLog: bad chaining"); + } +#endif /* SCOTCH_DEBUG_GAIN3 */ + + entrptr->next->prev = linkptr; /* Link vertex in gain list: TRICK */ + linkptr->prev = (GainLink *) entrptr; + linkptr->next = entrptr->next; + linkptr->tabl = entrptr; /* Set table position */ + entrptr->next = linkptr; +} + +/* This routine removes a link +** from the table. +** It returns: +** - VOID : in all cases. +*/ + +#ifdef SCOTCH_DEBUG_GAIN1 /* Compiled only in debug mode */ +void +gainTablDel ( +GainTabl * const tablptr, +GainLink * const linkptr) /*+ Pointer to link to delete +*/ +{ +#ifdef SCOTCH_DEBUG_GAIN3 + if (linkptr->tabl != NULL) { + if ((linkptr->tabl->next != &gainLinkDummy) && + (linkptr->tabl->next->prev != (GainLink *) linkptr->tabl)) { + errorPrint ("gainTablDel: bad first element"); + return; + } + if (gainTablCheck (linkptr->tabl) != 0) { + errorPrint ("gainTablDel: bad chaining"); + return; + } + } +#endif /* SCOTCH_DEBUG_GAIN3 */ + + linkptr->next->prev = linkptr->prev; /* TRICK: may write in dummy link area */ + linkptr->prev->next = linkptr->next; +} +#endif /* SCOTCH_DEBUG_GAIN1 */ + +/* This routine returns the link of best +** gain in the table structure. +** It returns: +** - !NULL : pointer to the vertex. +** - NULL : if no such vertex available. +*/ + +GainLink * +gainTablFrst ( +GainTabl * const tablptr) +{ + GainEntr * entrptr; + + for (entrptr = tablptr->tmin; + entrptr <= tablptr->tend; + entrptr ++) { + if (entrptr->next != &gainLinkDummy) { + tablptr->tmin = entrptr; +#ifdef SCOTCH_DEBUG_GAIN3 + if (gainTablCheck (entrptr) != 0) { + errorPrint ("gainTablFrst: bad chaining"); + return (NULL); + } +#endif /* SCOTCH_DEBUG_GAIN3 */ + return (entrptr->next); + } + } + tablptr->tmin = tablptr->tend; + tablptr->tmax = tablptr->tabk; + + return (NULL); +} + +/* This routine returns the next best vertex +** following the given vertex. +** It returns: +** - !NULL : pointer to the vertex. +** - NULL : if no such vertex available. +*/ + +GainLink * +gainTablNext ( +GainTabl * const tablptr, +const GainLink * const linkptr) +{ + GainEntr * entrptr; + + if (linkptr->next != &gainLinkDummy) { +#ifdef SCOTCH_DEBUG_GAIN3 + if (gainTablCheck (linkptr->tabl) != 0) { + errorPrint ("gainTablNext: bad chaining (1)"); + return (NULL); + } +#endif /* SCOTCH_DEBUG_GAIN3 */ + return (linkptr->next); + } + + for (entrptr = linkptr->tabl + 1; + entrptr < tablptr->tend; + entrptr ++) { + if (entrptr->next != &gainLinkDummy) { +#ifdef SCOTCH_DEBUG_GAIN3 + if (gainTablCheck (entrptr) != 0) { + errorPrint ("gainTablNext: bad chaining (2)"); + return (NULL); + } +#endif /* SCOTCH_DEBUG_GAIN3 */ + return (entrptr->next); + } + } + + return (NULL); +} + +/* This routine checks the consistency of the +** given linked list. +** It returns: +** - !NULL : pointer to the vertex. +** - NULL : if no such vertex available. +*/ + +#ifdef SCOTCH_DEBUG_GAIN3 + +static +int +gainTablCheck2 ( +GainEntr * const entrptr, +GainLink * const linkptr) +{ + GainLink * nextptr; + int o; + + if (linkptr->next == &gainLinkDummy) /* If end of list successfully reached */ + return (0); + if (linkptr->next == NULL) /* If loop discovered */ + return (1); + + if (linkptr->tabl != entrptr) + return (1); + + nextptr = linkptr->next; /* Save pointer to next cell */ + linkptr->next = NULL; /* Flag cell as already visited */ + o = gainTablCheck2 (entrptr, nextptr); /* Process next cell */ + linkptr->next = nextptr; /* Restore cell state */ + + return (o); +} + +int +gainTablCheck ( +GainEntr * const entrptr) +{ + if (entrptr->next == &gainLinkDummy) /* If end of list successfully reached */ + return (0); + + if ((entrptr->next == NULL) || /* If problem with link */ + (gainTablCheck2 (entrptr, entrptr->next) != 0)) { + errorPrint ("gainTablCheck: bad linked list"); + return (1); + } + + return (0); +} + +#endif /* SCOTCH_DEBUG_GAIN3 */ diff --git a/scotch_6.0.3/src/libscotch/gain.h b/scotch_6.0.3/src/libscotch/gain.h new file mode 100644 index 00000000..a94d85a4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/gain.h @@ -0,0 +1,130 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gain.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the definitions of **/ +/** the generic gain tables. **/ +/** **/ +/** DATES : # Version 0.0 : from : 26 oct 1996 **/ +/** to 17 nov 1997 **/ +/** # Version 0.1 : from : 10 may 1999 **/ +/** to 18 mar 2005 **/ +/** # Version 5.0 : from : 24 mar 2008 **/ +/** to 01 jun 2008 **/ +/** **/ +/** NOTES : # Most of the contents of this module **/ +/** comes from "map_b_fm" of the SCOTCH **/ +/** project. **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#define GAINMAX ((INT) (((UINT) 1 << ((sizeof (INT) << 3) - 1)) - 2)) + +#define GAIN_LINMAX 1024 + +/* +** The type and structure definitions. +*/ + +/* The gain link data structure. This must be the + first item of objects that are linked into gain + tables. */ + +typedef struct GainLink_ { + struct GainLink_ * next; /*+ Pointer to next element: FIRST +*/ + struct GainLink_ * prev; /*+ Pointer to previous element +*/ + struct GainEntr_ * tabl; /*+ Index into the gain table +*/ +} GainLink; + +/* Gain table entry structure. */ + +typedef struct GainEntr_ { + GainLink * next; /*+ Pointer to first element: FIRST +*/ +} GainEntr; + +/* The gain table structure, built from table entries. + For trick reasons, the pointer to the first entry + must be the first field of the structure. */ + +typedef struct GainTabl_ { + void (* tablAdd) (struct GainTabl_ * const, GainLink * const, const INT); /*+ Add method +*/ + INT subbits; /*+ Number of subbits +*/ + INT submask; /*+ Subbit mask +*/ + INT totsize; /*+ Total table size +*/ + GainEntr * tmin; /*+ Non-empty entry of minimum gain +*/ + GainEntr * tmax; /*+ Non-empty entry of maximum gain +*/ + GainEntr * tend; /*+ Point after last valid gain entry +*/ + GainEntr * tabl; /*+ Gain table structure is.. [SIZE - ADJ] +*/ + GainEntr tabk[1]; /*+ Split in two for relative access [ADJ] +*/ +} GainTabl; + +/* +** The function prototypes. +*/ + +#ifndef GAIN +#define static +#endif + +GainTabl * gainTablInit (const INT, const INT); +void gainTablExit (GainTabl * const); +void gainTablFree (GainTabl * const); +void gainTablAddLin (GainTabl * const, GainLink * const, const INT); +void gainTablAddLog (GainTabl * const, GainLink * const, const INT); +void gainTablDel (GainTabl * const, GainLink * const); +GainLink * gainTablFrst (GainTabl * const); +GainLink * gainTablNext (GainTabl * const, const GainLink * const); +#ifdef SCOTCH_DEBUG_GAIN3 +int gainTablCheck (GainEntr * const); +static int gainTablCheck2 (GainEntr * const, GainLink * const); +#endif /* SCOTCH_DEBUG_GAIN3 */ + +#undef static + +/* +** The marco definitions. +*/ + +#define gainTablEmpty(tabl) ((tabl)->tmin == (tabl)->tend) +#define gainTablAdd(tabl,link,gain) ((tabl)->tablAdd ((tabl), (link), (gain))) +#if ((! defined GAIN) && (! defined SCOTCH_DEBUG_GAIN1)) +#define gainTablDel(tabl,link) (((GainLink *) (link))->next->prev = ((GainLink *) (link))->prev, \ + ((GainLink *) (link))->prev->next = ((GainLink *) (link))->next) +#endif /* ((! defined GAIN) && (! defined SCOTCH_DEBUG_GAIN1)) */ diff --git a/scotch_6.0.3/src/libscotch/geom.c b/scotch_6.0.3/src/libscotch/geom.c new file mode 100644 index 00000000..ab333083 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/geom.c @@ -0,0 +1,94 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : geom.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the geometric **/ +/** source graph functions. **/ +/** **/ +/** DATES : # Version 3.3 : from : 12 dec 1998 **/ +/** to 21 dec 1998 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 26 nov 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GEOM + +#include "module.h" +#include "common.h" +#include "geom.h" + +/********************************************/ +/* */ +/* These routines handle geometrical gdata. */ +/* */ +/********************************************/ + +/* This routine initializes a geometrical +** data structure. +** It returns: +** - 0 : in all cases. +*/ + +int +geomInit ( +Geom * restrict const geomptr) +{ + geomptr->dimnnbr = 0; /* Initialize geometry */ + geomptr->geomtab = NULL; + + return (0); +} + +/* This routine frees a geometrical graph structure. +** It returns: +** - VOID : in all cases. +*/ + +void +geomExit ( +Geom * restrict const geomptr) +{ + if (geomptr->geomtab != NULL) + memFree (geomptr->geomtab); + + geomptr->dimnnbr = 0; + geomptr->geomtab = NULL; +} diff --git a/scotch_6.0.3/src/libscotch/geom.h b/scotch_6.0.3/src/libscotch/geom.h new file mode 100644 index 00000000..c94516d9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/geom.h @@ -0,0 +1,77 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : geom.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the geometrical data handling **/ +/** routines. **/ +/** **/ +/** DATES : # Version 3.3 : from : 13 dec 1998 **/ +/** to 15 dec 1998 **/ +/** # Version 3.4 : from : 10 oct 1999 **/ +/** to 12 oct 1999 **/ +/** # Version 4.0 : from : 24 nov 2001 **/ +/** to 18 jan 2004 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +#define GEOM_H + +/* +** The type and structure definitions. +*/ + +/*+ Geometrical graph structure. +*/ + +typedef struct Geom_ { + int dimnnbr; /*+ Geometry type (1, 2, or 3D) +*/ + double * geomtab; /*+ Geometrical vertex array +*/ +} Geom; + +/* +** The function prototypes. +*/ + +#ifndef GEOM +#define static +#endif + +int geomInit (Geom * restrict const); +void geomExit (Geom * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/graph.c b/scotch_6.0.3/src/libscotch/graph.c new file mode 100644 index 00000000..fc6e2612 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph.c @@ -0,0 +1,154 @@ +/* Copyright 2004,2007,2011,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the source graph **/ +/** functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 31 oct 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 08 jun 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 15 sep 1998 **/ +/** # Version 3.3 : from : 22 sep 1998 **/ +/** to 31 dec 1998 **/ +/** # Version 4.0 : from : 24 nov 2001 **/ +/** to 22 apr 2004 **/ +/** # Version 5.1 : from : 08 mar 2011 **/ +/** to 08 mar 2011 **/ +/** # Version 6.0 : from : 09 sep 2012 **/ +/** to 09 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" + +/****************************************/ +/* */ +/* These routines handle source graphs. */ +/* */ +/****************************************/ + +/* This routine initializes a source graph +** structure. +** It returns: +** - 0 : in all cases. +*/ + +int +graphInit ( +Graph * const grafptr) +{ + memSet (grafptr, 0, sizeof (Graph)); /* Initialize graph fields */ + grafptr->flagval = GRAPHFREETABS; /* By default, free all arrays */ + + return (0); +} + +/* This routine frees a source graph structure. +** It returns: +** - VOID : in all cases. +*/ + +void +graphExit ( +Graph * const grafptr) +{ + graphFree (grafptr); /* Free graph data */ + +#ifdef SCOTCH_DEBUG_GRAPH2 + memSet (grafptr, ~0, sizeof (Graph)); /* Purge graph fields */ +#endif /* SCOTCH_DEBUG_GRAPH2 */ +} + +/* This routine frees the graph data. +** It returns: +** - VOID : in all cases. +*/ + +void +graphFree ( +Graph * const grafptr) +{ + if (((grafptr->flagval & GRAPHFREEEDGE) != 0) && /* If edgetab must be freed */ + (grafptr->edgetax != NULL)) /* And if it exists */ + memFree (grafptr->edgetax + grafptr->baseval); /* Free it */ + + if ((grafptr->flagval & GRAPHFREEVERT) != 0) { /* If verttab/vendtab must be freed */ + if ((grafptr->vendtax != NULL) && /* If vendtax is distinct from verttab */ + (grafptr->vendtax != grafptr->verttax + 1) && /* (if vertex arrays grouped, vendtab not distinct anyway) */ + ((grafptr->flagval & GRAPHVERTGROUP) == 0)) + memFree (grafptr->vendtax + grafptr->baseval); /* Then free vendtax */ + if (grafptr->verttax != NULL) /* Free verttab anyway, as it is the array group leader */ + memFree (grafptr->verttax + grafptr->baseval); + } + if ((grafptr->flagval & GRAPHFREEVNUM) != 0) { /* If vnumtab must be freed */ + if ((grafptr->vnumtax != NULL) && /* And is not in vertex array group */ + ((grafptr->flagval & GRAPHVERTGROUP) == 0)) + memFree (grafptr->vnumtax + grafptr->baseval); + } + if ((grafptr->flagval & GRAPHFREEOTHR) != 0) { /* If other arrays must be freed */ + if ((grafptr->velotax != NULL) && /* Free graph tables */ + ((grafptr->flagval & GRAPHVERTGROUP) == 0)) + memFree (grafptr->velotax + grafptr->baseval); + if ((grafptr->vlbltax != NULL) && + ((grafptr->flagval & GRAPHVERTGROUP) == 0)) + memFree (grafptr->vlbltax + grafptr->baseval); + if ((grafptr->edlotax != NULL) && + ((grafptr->flagval & GRAPHEDGEGROUP) == 0)) + memFree (grafptr->edlotax + grafptr->baseval); + } + +#ifdef SCOTCH_DEBUG_GRAPH2 + memSet (grafptr, ~0, sizeof (Graph)); /* Purge graph fields */ +#endif /* SCOTCH_DEBUG_GRAPH2 */ + grafptr->flagval = GRAPHNONE; /* Allow to double-call graphFree or call graphExit */ +} diff --git a/scotch_6.0.3/src/libscotch/graph.h b/scotch_6.0.3/src/libscotch/graph.h new file mode 100644 index 00000000..4b8c651d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph.h @@ -0,0 +1,193 @@ +/* Copyright 2004,2007,2008,2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source graph functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 02 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 18 aug 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 28 nov 1995 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 15 sep 1998 **/ +/** # Version 3.3 : from : 28 sep 1998 **/ +/** to 23 mar 1999 **/ +/** # Version 3.4 : from : 20 mar 2000 **/ +/** to 20 mar 2000 **/ +/** # Version 4.0 : from : 24 nov 2001 **/ +/** to 03 mar 2006 **/ +/** # Version 5.0 : from : 03 mar 2006 **/ +/** to 01 jun 2008 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 04 nov 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 09 aug 2014 **/ +/** **/ +/************************************************************/ + +#define GRAPH_H + +/* +** The defines. +*/ + +/*+ Graph option flags. +*/ + +#define GRAPHNONE 0x0000 /* No options set */ + +#define GRAPHFREEEDGE 0x0001 /* Free edgetab array */ +#define GRAPHFREEVERT 0x0002 /* Free verttab array */ +#define GRAPHFREEVNUM 0x0004 /* Free vnumtab array */ +#define GRAPHFREEOTHR 0x0008 /* Free all other arrays */ +#define GRAPHFREETABS 0x000F /* Free all graph arrays */ +#define GRAPHVERTGROUP 0x0010 /* All vertex arrays grouped */ +#define GRAPHEDGEGROUP 0x0020 /* All edge arrays grouped */ + +#define GRAPHBITSUSED 0x003F /* Significant bits for plain graph routines */ +#define GRAPHBITSNOTUSED 0x0040 /* Value above which bits not used by plain graph routines */ + +#define GRAPHIONOLOADVERT 1 /* Remove vertex loads on loading */ +#define GRAPHIONOLOADEDGE 2 /* Remove edge loads on loading */ + +/* +** The type and structure definitions. +*/ + +#ifndef GNUMMAX /* If dgraph.h not included */ +typedef INT Gnum; /* Vertex and edge numbers */ +typedef UINT Gunum; /* Unsigned type of same width */ +#define GNUMMAX (INTVALMAX) /* Maximum signed Gnum value */ +#define GNUMSTRING INTSTRING /* String to printf a Gnum */ +#endif /* GNUMMAX */ + +/*+ The vertex part type, in compressed form. +*/ + +typedef byte GraphPart; + +/*+ The vertex list structure. Since a vertex list + always refers to a given graph, vertex indices + contained in the vertex list array are based with + respect to the base value of the associated graph. + However, the array itself is not based. +*/ + +typedef struct VertList_ { + Gnum vnumnbr; /*+ Number of vertices in list +*/ + Gnum * vnumtab; /*+ Pointer to vertex array +*/ +} VertList; + +/*+ The graph flag type. +*/ + +typedef int GraphFlag; /*+ Graph property flags +*/ + +/*+ The graph parallel context structure. +*/ + +typedef struct GraphProc_ { +#ifdef SCOTCH_PTSCOTCH + MPI_Comm proccomm; /*+ Communicator used for parallel algorithm +*/ + int procglbnbr; /*+ Number of processes in communicator +*/ + int proclocnum; /*+ Rank of process in current communicator +*/ +#endif /* SCOTCH_PTSCOTCH */ +} GraphProc; + +/*+ The graph structure. +*/ + +typedef struct Graph_ { + GraphFlag flagval; /*+ Graph properties +*/ + Gnum baseval; /*+ Base index for edge/vertex arrays +*/ + Gnum vertnbr; /*+ Number of vertices in graph +*/ + Gnum vertnnd; /*+ Number of vertices in graph, plus baseval +*/ + Gnum * verttax; /*+ Vertex array [based] +*/ + Gnum * vendtax; /*+ End vertex array [based] +*/ + Gnum * velotax; /*+ Vertex load array (if present) +*/ + Gnum velosum; /*+ Overall graph vertex load +*/ + Gnum * vnumtax; /*+ Vertex number in ancestor graph +*/ + Gnum * vlbltax; /*+ Vertex label (from file) +*/ + Gnum edgenbr; /*+ Number of edges (arcs) in graph +*/ + Gnum * edgetax; /*+ Edge array [based] +*/ + Gnum * edlotax; /*+ Edge load array (if present) +*/ + Gnum edlosum; /*+ Sum of edge (in fact arc) loads +*/ + Gnum degrmax; /*+ Maximum degree +*/ + GraphProc * procptr; /*+ Pointer to parallel context (if any) +*/ +} Graph; + +/* +** The function prototypes. +*/ + +#ifndef GRAPH +#define static +#endif + +int listInit (VertList *); +void listExit (VertList *); +int listAlloc (VertList *, Gnum); +int listFree (VertList *); +int listLoad (VertList *, FILE *); +int listSave (VertList *, FILE *); +void listSort (VertList *); +int listCopy (VertList *, VertList *); + +int graphInit (Graph * const); +void graphExit (Graph * const); +void graphFree (Graph * const); +Gnum graphBase (Graph * const, const Gnum); +int graphBand (const Graph * restrict const, const Gnum, Gnum * restrict const, const Gnum, Gnum * restrict * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, const Gnum * restrict const, Gnum * restrict const); +int graphCheck (const Graph *); +int graphInduceList (const Graph * const, const VertList * const, Graph * const); +int graphInducePart (const Graph * const, const GraphPart *, const Gnum, const GraphPart, Graph * const); +int graphLoad (Graph * const, FILE * const, const Gnum, const GraphFlag); +int graphLoad2 (const Gnum, const Gnum, const Gnum * const, const Gnum * const, Gnum * restrict const, const Gnum, const Gnum * const); +int graphSave (const Graph * const, FILE * const); + +#ifdef GEOM_H +int graphGeomLoadChac (Graph * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); +int graphGeomSaveChac (const Graph * restrict const, const Geom * restrict const, FILE * const, FILE * const, const char * const); +int graphGeomLoadHabo (Graph * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); +int graphGeomLoadMmkt (Graph * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); +int graphGeomSaveMmkt (const Graph * restrict const, const Geom * restrict const, FILE * const, FILE * const, const char * const); +int graphGeomLoadScot (Graph * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); +int graphGeomSaveScot (const Graph * restrict const, const Geom * restrict const, FILE * const, FILE * const, const char * const); +#endif /* GEOM_H */ + +#undef static diff --git a/scotch_6.0.3/src/libscotch/graph_band.c b/scotch_6.0.3/src/libscotch/graph_band.c new file mode 100644 index 00000000..b8b07242 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_band.c @@ -0,0 +1,166 @@ +/* Copyright 2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_band.c **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a band graph **/ +/** from the given frontier array. **/ +/** **/ +/** DATES : # Version 6.0 : from : 05 jan 2010 **/ +/** to : 22 sep 2011 **/ +/** **/ +/** NOTES : # This code derives from the code of **/ +/** dgraph_band.c in version 5.1. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_BAND + +#include "module.h" +#include "common.h" +#include "graph.h" + +/**********************************/ +/* */ +/* Distance computation routines. */ +/* */ +/**********************************/ + +/* This routine computes an index array +** of given width around the current separator. +** It returns: +** - 0 : if the index array could be computed. +** - !0 : on error. +*/ + +int +graphBand ( +const Graph * restrict const grafptr, /*+ Graph +*/ +const Gnum queunbr, /*+ Number of frontier vertices, start size for vertex queue +*/ +Gnum * restrict const queutab, /*+ Array of frontier vertices, re-used as queue array +*/ +const Gnum distmax, /*+ Maximum distance from separator vertices +*/ +Gnum * restrict * restrict const vnumptr, /*+ Pointer to vnumtax +*/ +Gnum * restrict const bandvertlvlptr, /*+ Pointer to based start index of last level +*/ +Gnum * restrict const bandvertptr, /*+ Pointer to bandvertnbr +*/ +Gnum * restrict const bandedgeptr, /*+ Pointer to bandedgenbr +*/ +const Gnum * restrict const pfixtax, /*+ Fixed partition array +*/ +Gnum * restrict const bandvfixptr) /*+ Pointer to bandvfixnbr +*/ +{ + Gnum queunum; + Gnum * restrict vnumtax; /* Index array for vertices kept in band graph */ + Gnum queuheadidx; /* Index of head of queue */ + Gnum queutailidx; /* Index of tail of queue */ + Gnum bandvertlvlnum; + Gnum bandvertnum; + Gnum bandedgenbr; + Gnum distval; + Gnum bandvfixnbr; /* Number of band fixed vertices */ + + const Gnum * restrict const verttax = grafptr->verttax; + const Gnum * restrict const vendtax = grafptr->vendtax; + const Gnum * restrict const edgetax = grafptr->edgetax; + + if ((vnumtax = memAlloc (grafptr->vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("graphBand: out of memory (1)"); + return (1); + } + + bandvertlvlnum = /* Start index of last level is start index */ + bandvertnum = grafptr->baseval; /* Reset number of band vertices */ + bandedgenbr = + bandvfixnbr = 0; + memSet (vnumtax, ~0, grafptr->vertnbr * sizeof (Gnum)); /* Reset part array */ + vnumtax -= grafptr->baseval; + + for (queunum = 0; queunum < queunbr; queunum ++) { /* All frontier vertices will be first vertices of band graph */ + Gnum vertnum; + + vertnum = queutab[queunum]; + if ((pfixtax != NULL) && (pfixtax[vertnum] != -1)) { /* It is a fixed vertex */ + vnumtax[vertnum] = -2; /* Set vertex as fixed */ + bandvfixnbr ++; + } + else + vnumtax[vertnum] = bandvertnum ++; /* Keep frontier vertex in band */ + bandedgenbr += vendtax[vertnum] - verttax[vertnum]; /* Account for its edges */ + } + queuheadidx = 0; /* No queued vertex read yet */ + queutailidx = queunbr; /* All frontier vertices are already in queue */ + + for (distval = 0; ++ distval <= distmax; ) { + Gnum queunextidx; /* Tail index for enqueuing vertices of next band */ + + bandvertlvlnum = bandvertnum; + *bandvertlvlptr = bandvertlvlnum; /* Save start index of current level, based */ + + for (queunextidx = queutailidx; queuheadidx < queutailidx; ) { /* For all vertices in queue */ + Gnum vertnum; + Gnum edgenum; + + vertnum = queutab[queuheadidx ++]; /* Dequeue vertex */ + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = edgetax[edgenum]; + if (vnumtax[vertend] != ~0) /* If end vertex has already been processed */ + continue; /* Skip to next vertex */ + + if ((pfixtax != NULL) && (pfixtax[vertend] != -1)) { /* If fixed vertex */ + vnumtax[vertend] = -2; /* Set vertex as fixed */ + bandvfixnbr ++; + } + else + vnumtax[vertend] = bandvertnum ++; /* Enqueue vertex label */ + + bandedgenbr += vendtax[vertend] - verttax[vertend]; /* Account for its edges */ + queutab[queunextidx ++] = vertend; /* Enqueue vertex for next pass */ + } + } + + queutailidx = queunextidx; /* Prepare queue for next sweep */ + } + + *vnumptr = vnumtax; + *bandvfixptr = bandvfixnbr; + *bandvertptr = bandvertnum - grafptr->baseval; + *bandedgeptr = bandedgenbr; + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/graph_base.c b/scotch_6.0.3/src/libscotch/graph_base.c new file mode 100644 index 00000000..3793eb5b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_base.c @@ -0,0 +1,130 @@ +/* Copyright 2004,2007,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_base.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the graph base **/ +/** changing routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 31 oct 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 08 jun 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 15 sep 1998 **/ +/** # Version 3.3 : from : 22 sep 1998 **/ +/** to 31 dec 1998 **/ +/** # Version 4.0 : from : 24 nov 2001 **/ +/** to 22 apr 2004 **/ +/** # Version 6.0 : from : 05 aug 2014 **/ +/** to 05 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" + +/****************************************/ +/* */ +/* These routines handle source graphs. */ +/* */ +/****************************************/ + +/* This routine sets the base of the given +** graph to the given base value, and returns +** the old base value. +** It returns: +** - old base value : in all cases. +*/ + +Gnum +graphBase ( +Graph * const grafptr, +const Gnum baseval) +{ + Gnum baseold; /* Old base value */ + Gnum baseadj; /* Base adjustment */ + Gnum vertnum; + Gnum edgenum; + + if (grafptr->baseval == baseval) /* If nothing to do */ + return (baseval); + + baseold = grafptr->baseval; /* Record old base value */ + baseadj = baseval - baseold; /* Compute adjustment */ + + for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { + for (edgenum = grafptr->verttax[vertnum]; edgenum < grafptr->vendtax[vertnum]; edgenum ++) + grafptr->edgetax[edgenum] += baseadj; + grafptr->verttax[vertnum] += baseadj; + } + if (grafptr->vendtax != grafptr->verttax + 1) { /* If distinct vertex end array */ + for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) + grafptr->vendtax[vertnum] += baseadj; + } + else /* If same vertex end array (of size +1) */ + grafptr->verttax[grafptr->vertnnd] += baseadj; /* Adjust last entry of verttax */ + + grafptr->verttax -= baseadj; /* Adjust array accesses */ + grafptr->vendtax -= baseadj; + grafptr->edgetax -= baseadj; + + if (grafptr->velotax != NULL) + grafptr->velotax -= baseadj; + if (grafptr->vnumtax != NULL) + grafptr->vnumtax -= baseadj; + if (grafptr->vlbltax != NULL) + grafptr->vlbltax -= baseadj; + if (grafptr->edlotax != NULL) + grafptr->edlotax -= baseadj; + + grafptr->baseval = baseval; /* Set new base value */ + grafptr->vertnnd += baseadj; + + return (baseold); /* Return old base value */ +} diff --git a/scotch_6.0.3/src/libscotch/graph_check.c b/scotch_6.0.3/src/libscotch/graph_check.c new file mode 100644 index 00000000..230e8abc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_check.c @@ -0,0 +1,191 @@ +/* Copyright 2004,2007,2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the source graph **/ +/** checking function. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 31 oct 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 08 jun 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 15 sep 1998 **/ +/** # Version 3.3 : from : 22 sep 1998 **/ +/** to 31 dec 1998 **/ +/** # Version 4.0 : from : 24 nov 2001 **/ +/** to 22 apr 2004 **/ +/** # Version 5.0 : from : 13 dec 2006 **/ +/** to 02 oct 2007 **/ +/** # Version 6.0 : from : 27 jun 2011 **/ +/** to 14 feb 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" + +/****************************************/ +/* */ +/* These routines handle source graphs. */ +/* */ +/****************************************/ + +/* This routine checks the consistency +** of the given graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +graphCheck ( +const Graph * const grafptr) +{ + Gnum vertnum; /* Number of current vertex */ + Gnum velosum; /* Sum of vertex loads */ + Gnum edlosum; /* Sum of edge loads */ + Gnum edgenbr; /* Number of edges (arcs) */ + Gnum edgenum; /* Number of current edge */ + Gnum degrmax; /* Maximum degree */ + + if (grafptr->vertnbr != (grafptr->vertnnd - grafptr->baseval)) { + errorPrint ("graphCheck: invalid vertex numbers"); + return (1); + } + + degrmax = + edgenbr = 0; + velosum = (grafptr->velotax == NULL) ? grafptr->vertnbr : 0; + edlosum = (grafptr->edlotax == NULL) ? grafptr->edgenbr : 0; + for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { + if ((grafptr->verttax[vertnum] < grafptr->baseval) || + (grafptr->vendtax[vertnum] < grafptr->verttax[vertnum])) { + errorPrint ("graphCheck: invalid vertex arrays"); + return (1); + } + + if ((grafptr->vendtax[vertnum] - grafptr->verttax[vertnum]) > degrmax) + degrmax = grafptr->vendtax[vertnum] - grafptr->verttax[vertnum]; + + edgenbr += grafptr->vendtax[vertnum] - grafptr->verttax[vertnum]; + for (edgenum = grafptr->verttax[vertnum]; edgenum < grafptr->vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* Number of end vertex */ + Gnum edgeend; /* Number of end vertex edge */ + + vertend = grafptr->edgetax[edgenum]; + if (grafptr->edlotax != NULL) { + Gnum edlotmp; + + edlotmp = edlosum + grafptr->edlotax[edgenum]; + if (edlotmp < edlosum) { /* If overflow */ + errorPrint ("graphCheck: edge load sum overflow"); + return (1); + } + edlosum = edlotmp; + } + + if ((vertend < grafptr->baseval) || (vertend >= grafptr->vertnnd)) { /* If invalid edge end */ + errorPrint ("graphCheck: invalid edge array"); + return (1); + } + if (vertend == vertnum) { /* Loops not allowed */ + errorPrint ("graphCheck: loops not allowed"); + return (1); + } + for (edgeend = grafptr->verttax[vertend]; /* Search for matching arc */ + (edgeend < grafptr->vendtax[vertend]) && (grafptr->edgetax[edgeend] != vertnum); + edgeend ++) ; + if ((edgeend >= grafptr->vendtax[vertend]) || + ((grafptr->edlotax != NULL) && (grafptr->edlotax[edgenum] != grafptr->edlotax[edgeend]))) { + errorPrint ("graphCheck: arc data do not match"); + return (1); + } + for (edgeend ++; /* Search for duplicate arcs */ + (edgeend < grafptr->vendtax[vertend]) && (grafptr->edgetax[edgeend] != vertnum); + edgeend ++) ; + if (edgeend < grafptr->vendtax[vertend]) { + errorPrint ("graphCheck: duplicate arc"); + return (1); + } + } + if (grafptr->velotax != NULL) { + Gnum velotmp; + + if (grafptr->velotax[vertnum] < 0) { /* If non positive loads */ + errorPrint ("graphCheck: invalid vertex load array"); + return (1); + } + velotmp = velosum + grafptr->velotax[vertnum]; + if (velotmp < velosum) { /* If overflow */ + errorPrint ("graphCheck: vertex load sum overflow"); + return (1); + } + velosum = velotmp; + } + } + if (grafptr->edgenbr != edgenbr) { + errorPrint ("graphCheck: invalid number of edges"); + return (1); + } + if (grafptr->velosum != velosum) { + errorPrint ("graphCheck: invalid vertex load sum"); + return (1); + } + if (grafptr->edlosum != edlosum) { + errorPrint ("graphCheck: invalid edge load sum"); + return (1); + } + if (grafptr->degrmax < degrmax) { + errorPrint ("graphCheck: invalid maximum degree"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/graph_coarsen.c b/scotch_6.0.3/src/libscotch/graph_coarsen.c new file mode 100644 index 00000000..0de29dca --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_coarsen.c @@ -0,0 +1,508 @@ +/* Copyright 2004,2007,2009,2011-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_coarsen.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the source graph **/ +/** coarsening functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 31 oct 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 08 jun 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 17 sep 1998 **/ +/** # Version 4.0 : from : 13 dec 2001 **/ +/** to 31 aug 2005 **/ +/** # Version 5.0 : from : 13 dec 2006 **/ +/** to 24 mar 2008 **/ +/** # Version 5.1 : from : 30 oct 2009 **/ +/** to 30 oct 2009 **/ +/** # Version 6.0 : from : 09 mar 2011 **/ +/** to 26 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_COARSEN + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "graph.h" +#include "graph_coarsen.h" +#include "graph_match.h" + +/***************************/ +/* */ +/* The coarsening routine. */ +/* */ +/***************************/ + +#ifdef GRAPHCOARSENTHREAD + +/* This routine aggregates a sum and max +** reduction of partial coarse graph +** parameters computed by multiple +** threads. +*/ + +static +void +graphCoarsenReduce ( +GraphCoarsenThread * restrict const tlocptr, /* Pointer to local thread */ +void * restrict const vlocptr, /* Pointer to local value */ +void * restrict const vremptr) /* Pointer to remote value */ +{ + GraphCoarsenThread * restrict const tremptr = (GraphCoarsenThread *) vremptr; + + tlocptr->coaredloadj += tremptr->coaredloadj; /* Sum edge load sum adjustments */ + if (tremptr->coardegrmax > tlocptr->coardegrmax) /* Take maximum of degrees */ + tlocptr->coardegrmax = tremptr->coardegrmax; +} + +/* This routine performs a perfix scan +** sum operation on a single Gnum value. +*/ + +static +void +graphCoarsenScan ( +GraphCoarsenThread * restrict const tlocptr, /* Pointer to local thread */ +Gnum * restrict const vlocptr, /* Pointer to local value */ +Gnum * restrict const vremptr, /* Pointer to remote value */ +const int phasval) /* Phase index */ +{ + vlocptr[1 - phasval] = vlocptr[phasval] + ((vremptr == NULL) ? 0 : vremptr[phasval]); +} + +#endif /* GRAPHCOARSENTHREAD */ + +/* This routine coarsens the given "finegraph" into +** "coargraph", as long as the coarsening ratio remains +** below some threshold value and the coarsened graph +** is not too small. +** It returns: +** - 0 : if the graph has been coarsened. +** - 1 : if the graph could not be coarsened. +** - 2 : on error. +*/ + +static +int +graphCoarsen2 ( +void * dataptr) +{ + Gnum baseval; + Gnum finevertbas; + Gnum finevertnnd; + Gnum finevertnbr; + Gnum finevertnum; + Gnum coarvertnbr; + Gnum coarvertnum; + Gnum coarhashnbr; /* Size of neighbor vertex hash table */ + GraphCoarsenMulti * restrict coarmulttax; +#ifdef GRAPHCOARSENTHREAD + int thrdnbr; + int thrdnum; +#endif /* GRAPHCOARSENTHREAD */ + + GraphCoarsenThread * restrict const thrdptr = (GraphCoarsenThread *) dataptr; + volatile GraphCoarsenData * restrict const coarptr = (GraphCoarsenData *) (thrdptr->thrddat.grouptr); + const Graph * restrict const finegrafptr = coarptr->finegrafptr; + volatile Gnum * restrict const finecoartax = coarptr->finematetax; + volatile Graph * restrict const coargrafptr = coarptr->coargrafptr; + + graphMatch (thrdptr); /* Perform (threaded) matching */ + + coarvertnbr = coarptr->coarvertnbr; /* Get number of vertices actually created */ + if (coarvertnbr >= coarptr->coarvertmax) /* If matching failed or if coarsened graph too large */ + return (1); /* Do not proceed any further */ + + baseval = finegrafptr->baseval; +#ifdef GRAPHCOARSENTHREAD + thrdnbr = coarptr->thrddat.thrdnbr; + thrdnum = thrdptr->thrddat.thrdnum; + + if (thrdnum == 0) /* Thread 0 populates the graph data structure */ +#endif /* GRAPHCOARSENTHREAD */ + { + memSet (coargrafptr, 0, sizeof (Graph)); /* Initialize coarse graph on thread 0 */ + coargrafptr->flagval = GRAPHFREEVERT | GRAPHVERTGROUP | GRAPHEDGEGROUP; + coargrafptr->baseval = baseval; + coargrafptr->vertnbr = coarvertnbr; + coargrafptr->vertnnd = coarvertnbr + baseval; + coargrafptr->velosum = finegrafptr->velosum; /* Keep load of finer graph */ + if (memAllocGroup ((void **) (void *) + &coargrafptr->verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), + &coargrafptr->velotax, (size_t) (coarvertnbr * sizeof (Gnum)), + &coarmulttax, (size_t) (coarvertnbr * sizeof (GraphCoarsenMulti)), + &coargrafptr->edgetax, (size_t) (finegrafptr->edgenbr * sizeof (Gnum)), /* Pre-allocate space for edge arrays */ + &coargrafptr->edlotax, (size_t) (finegrafptr->edgenbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("graphCoarsen2: out of memory (1)"); /* Allocate coarser graph structure */ + return (2); + } + coargrafptr->verttax -= baseval; /* Base coarse graph arrays */ + coargrafptr->velotax -= baseval; + coargrafptr->edgetax -= baseval; + coargrafptr->edlotax -= baseval; + coarmulttax -= baseval; + coarptr->coarmulttax = coarmulttax; /* Only thread 0 knows coarptr->coarmulttax */ + } + + finevertnnd = thrdptr->finevertnnd; /* Will be used by many loops */ +#ifdef GRAPHCOARSENTHREAD + if (thrdnbr > 1) { /* If more than one thread */ + Gnum coarvertnnd; + + for (finevertnum = thrdptr->finevertbas, coarvertnum = 0; + finevertnum < finevertnnd; finevertnum ++) { + Gnum finematenum; /* Number of current mate vertex */ + + finematenum = finecoartax[finevertnum]; /* Get mate number */ + if (finematenum >= finevertnum) /* If mate has larger number */ + coarvertnum ++; /* One more local multinode created */ + } + + thrdptr->coarvertbas = (thrdnum == 0) ? (coarvertnum + baseval) : coarvertnum; + threadScan (thrdptr, &thrdptr->coarvertbas, (ThreadScanFunc) graphCoarsenScan); /* Compute start indices for multinodes; barrier for coarptr->coarmulttax */ + coarvertnum = thrdptr->coarvertbas - coarvertnum; + coarmulttax = coarptr->coarmulttax; /* All threads know coarptr->coarmulttax */ + + for (finevertnum = thrdptr->finevertbas; + finevertnum < finevertnnd; finevertnum ++) { + Gnum finematenum; /* Number of current mate vertex */ + + finematenum = finecoartax[finevertnum]; /* Get mate number */ + if (finematenum >= finevertnum) { /* If mate has larger number */ + coarmulttax[coarvertnum].vertnum[0] = finevertnum; /* Build new multinode */ + coarmulttax[coarvertnum].vertnum[1] = finematenum; /* Second index always biggest */ + coarvertnum ++; /* One more local multinode created */ + } + } + + thrdptr->coarvertbas = DATASCAN (coargrafptr->vertnbr, thrdnbr, thrdnum) + baseval; /* Set bounds for coarse vertex processing */ + thrdptr->coarvertnnd = DATASIZE (coargrafptr->vertnbr, thrdnbr, thrdnum) + thrdptr->coarvertbas; + + threadBarrier (thrdptr); /* Ensure all of coarmulttax has been written */ + + for (coarvertnum = thrdptr->coarvertbas, coarvertnnd = thrdptr->coarvertnnd; + coarvertnum < coarvertnnd; coarvertnum ++) { + finecoartax[coarmulttax[coarvertnum].vertnum[0]] = /* Build fine-to-coarse array */ + finecoartax[coarmulttax[coarvertnum].vertnum[1]] = coarvertnum; + } + } + else +#endif /* GRAPHCOARSENTHREAD */ + { + for (finevertnum = thrdptr->finevertbas, coarvertnum = baseval; /* Finalize finecoartab array */ + finevertnum < finevertnnd; finevertnum ++) { + Gnum finematenum; /* Number of current mate vertex */ + + finematenum = finecoartax[finevertnum]; /* Get mate number */ + if (finematenum >= finevertnum) { /* If mate has larger number */ + coarmulttax[coarvertnum].vertnum[0] = finevertnum; /* Build new multinode */ + coarmulttax[coarvertnum].vertnum[1] = finematenum; /* Second index always biggest */ + finecoartax[finematenum] = /* Point to coarse vertex */ + finecoartax[finevertnum] = coarvertnum; /* Always valid since coarvertnum <= finevertnum */ + coarvertnum ++; /* One more multinode created */ + } + } + + thrdptr->coarvertbas = baseval; /* Set bounds for coarse vertex processing */ + thrdptr->coarvertnnd = coarvertnbr + baseval; + } + + coarhashnbr = coarptr->coarhashmsk + 1; + if ((thrdptr->coarhashtab = memAlloc (coarhashnbr * sizeof (GraphCoarsenHash))) == NULL) { /* Allocate local thread memory */ + errorPrint ("graphCoarsen2: out of memory (2)"); + return (2); + } + memSet (thrdptr->coarhashtab, ~0, coarhashnbr * sizeof (GraphCoarsenHash)); /* Initialize (local) hash table */ + +#ifdef GRAPHCOARSENTHREAD + if (thrdnbr > 1) { /* If more than one thread */ + Gnum coaredgenbr; + + threadBarrier (thrdptr); /* Ensure all of finecoartax has been written */ + + thrdptr->coaredgebas = 0; /* No coarse edges accounted for yet */ + graphCoarsenEdgeCt (thrdptr); /* Count number of coarse edges for each thread */ + + coaredgenbr = thrdptr->coaredgebas; /* Save number of local coarse edges */ + if (thrdnum == 0) /* Prepare start index for edge index scan */ + thrdptr->coaredgebas = coaredgenbr + baseval; + threadScan (thrdptr, &thrdptr->coaredgebas, (ThreadScanFunc) graphCoarsenScan); /* Compute scan on coarse edge indices */ + thrdptr->coaredgebas -= coaredgenbr; /* Adjust value to have real edge start index */ + + memSet (thrdptr->coarhashtab, ~0, coarhashnbr * sizeof (GraphCoarsenHash)); /* Re-initialize (local) hash table */ + } + else +#endif /* GRAPHCOARSENTHREAD */ + thrdptr->coaredgebas = baseval; /* We start from the beginning */ + + ((finegrafptr->edlotax != NULL) ? graphCoarsenEdgeLl : graphCoarsenEdgeLu) (thrdptr); /* Build coarse graph edge array */ + + memFree (thrdptr->coarhashtab); /* Free used (local) hash table */ + +#ifdef GRAPHCOARSENTHREAD + if (thrdnbr > 1) + threadReduce (thrdptr, thrdptr, (ThreadReduceFunc) graphCoarsenReduce, 0); /* Sum edloadj and get maximum of degrmax */ + if (thrdnum == 0) +#endif /* GRAPHCOARSENTHREAD */ + { + coargrafptr->edlosum = thrdptr->coaredloadj + finegrafptr->edlosum; + coargrafptr->degrmax = thrdptr->coardegrmax; + } +#ifdef GRAPHCOARSENTHREAD + if (thrdnum == (thrdnbr - 1)) +#endif /* GRAPHCOARSENTHREAD */ + coargrafptr->verttax[coargrafptr->vertnnd] = thrdptr->coaredgebas; /* Mark end of edge array */ + + return (0); /* Joining all treads will serve as synchronization for coarse graph data */ +} + +/* This routine coarsens the given "finegraph" into +** "coargraph", as long as the coarsening ratio remains +** below some threshold value and the coarsened graph +** is not too small. +** It returns: +** - 0 : if the graph has been coarsened. +** - 1 : if the graph could not be coarsened. +** - 2 : on error. +*/ + +int +graphCoarsen ( +const Graph * restrict const finegrafptr, /*+ Graph to coarsen +*/ +Graph * restrict const coargrafptr, /*+ Coarse graph to build +*/ +GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ +const Gnum coarnbr, /*+ Minimum number of coarse vertices +*/ +const double coarval, /*+ Maximum contraction ratio +*/ +const Anum * restrict const fineparotax, +const Anum * restrict const finepfixtax, +const Gnum finevfixnbr, +Gnum * restrict const coarvfixptr) +{ + Gnum baseval; + GraphCoarsenData coardat; /* Graph coarsening global data */ + Gnum coarvertnbr; /* Number of coarse vertices */ + Gnum coarvertnum; /* Number of current multinode vertex */ + Gnum coarvfixnbr; /* Coarse number of fixed vertices */ + GraphCoarsenMulti * restrict coarmulttax; /* Multinode array */ + Gnum * finecoartab; /* Fine vertex mating / indexing array */ + Gnum finevertnbr; /* Number of fine vertices */ + Gnum finevertnum; /* Number of currently selected fine vertex */ + Gnum coarhashmsk; /* Mask for access to hash table */ + size_t coarmultoftval; + size_t coarvelooftval; + size_t coaredgeoftval; + size_t coaredlooftval; +#ifdef GRAPHCOARSENTHREAD + int thrdnbr; +#endif /* GRAPHCOARSENTHREAD */ + int o; + +#ifdef SCOTCH_DEBUG_GRAPH1 + if (coarval < 0.5L) /* If impossible coarsening ratio wanted */ + return (1); /* We will never succeed */ +#endif /* SCOTCH_DEBUG_GRAPH1 */ + + coardat.coarvertmax = (Gnum) ((double) (finegrafptr->vertnbr - finevfixnbr) * coarval) + finevfixnbr; /* Maximum number of coarse vertices */ + if (coardat.coarvertmax < coarnbr) /* If there will be too few vertices in graph */ + return (1); /* It is useless to go any further */ + + coardat.finegrafptr = finegrafptr; /* Fill caller part of matching data structure */ + coardat.fineparotax = fineparotax; + coardat.finepfixtax = finepfixtax; + coardat.finevfixnbr = finevfixnbr; + coardat.coargrafptr = coargrafptr; +#ifdef GRAPHCOARSENTHREAD + coardat.thrddat.thrdnbr = thrdnbr = SCOTCH_PTHREAD_NUMBER; /* Needed for graphMatchInit */ +#endif /* GRAPHCOARSENTHREAD */ + + if (graphMatchInit (&coardat) != 0) /* Initialize global data needed for matching */ + return (1); + + for (coarhashmsk = 31; coarhashmsk < finegrafptr->degrmax; coarhashmsk = coarhashmsk * 2 + 1) ; /* Compute size of hash table */ + coardat.coarhashmsk = coarhashmsk * 4 + 3; /* Record it for (local) hash table allocation */ + + baseval = finegrafptr->baseval; + finevertnbr = finegrafptr->vertnbr; + if ((finecoartab = (Gnum *) memAlloc (finevertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("graphCoarsen: out of memory (1)"); /* Allocate coarse graph mating and indexing array */ + return (2); + } + coardat.finematetax = finecoartab - baseval; /* Set based access to finematetab / finecoartab */ + +#ifdef GRAPHCOARSENTHREAD + if (thrdnbr > 1) { + GraphCoarsenThread * restrict thrdtab; + int thrdnum; + Gnum finevertbas; + + if ((thrdtab = memAlloc (thrdnbr * sizeof (GraphCoarsenThread))) == NULL) { + errorPrint ("graphCoarsen: out of memory (2)"); + memFree (finecoartab); + return (2); + } + + for (thrdnum = 0, finevertbas = baseval; + thrdnum < thrdnbr; thrdnum ++) { + thrdtab[thrdnum].randval = intRandVal (INT_MAX); + thrdtab[thrdnum].finevertbas = finevertbas; + thrdtab[thrdnum].finevertnnd = finevertbas += DATASIZE (finevertnbr, thrdnbr, thrdnum); + thrdtab[thrdnum].coarvertnbr = 0; /* No coarse vertices yet */ + } + + o = threadLaunch (&coardat, thrdtab, sizeof (GraphCoarsenThread), (ThreadLaunchStartFunc) graphCoarsen2, (ThreadLaunchJoinFunc) NULL, + thrdnbr, THREADCANBARRIER | THREADCANREDUCE); + + memFree (thrdtab); /* Free group leader */ + } + else +#endif /* GRAPHCOARSENTHREAD */ + { + GraphCoarsenThread thrddat; + +#ifdef GRAPHCOARSENTHREAD + coardat.thrddat.thrdnbr = 1; /* Thread 0 of 1 */ + thrddat.thrddat.thrdnum = 0; +#endif /* GRAPHCOARSENTHREAD */ + thrddat.thrddat.grouptr = (void *) &coardat; + thrddat.randval = intRandVal (INT_MAX); + thrddat.finevertbas = baseval; + thrddat.finevertnnd = baseval + finevertnbr; + + o = graphCoarsen2 (&thrddat); + } + + memFree (finecoartab); + + if (o != 0) /* If coarsened graph is too small, abort here */ + return (1); + + coargrafptr->edgenbr = coargrafptr->verttax[coargrafptr->vertnnd] - baseval; /* Set exact number of edges */ + + coarmulttax = coardat.coarmulttax; + coarvertnbr = coargrafptr->vertnbr; + coarvelooftval = coargrafptr->velotax - coargrafptr->verttax; + coarmultoftval = (Gnum *) coarmulttax - coargrafptr->verttax; + coaredgeoftval = coargrafptr->edgetax - coargrafptr->verttax; + coaredlooftval = coargrafptr->edlotax - coargrafptr->verttax; + if (memReallocGroup ((void *) (coargrafptr->verttax + baseval), /* Re-allocate data, wiping temporary arrays */ + &coargrafptr->verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), + &coargrafptr->velotax, (size_t) (coarvertnbr * sizeof (Gnum)), + &coarmulttax, (size_t) (coarvertnbr * sizeof (GraphCoarsenMulti)), + &coargrafptr->edgetax, (size_t) (finegrafptr->edgenbr * sizeof (Gnum)), + &coargrafptr->edlotax, (size_t) (coargrafptr->edgenbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("graphCoarsen: cannot reallocate memory"); /* Allocate coarser graph structure */ + return (2); + } + coargrafptr->verttax -= baseval; + coargrafptr->vendtax = coargrafptr->verttax + 1; /* Use compact representation of arrays */ + coargrafptr->velotax = coargrafptr->verttax + coarvelooftval; + coargrafptr->edgetax = coargrafptr->verttax + coaredgeoftval; + coargrafptr->edlotax = coargrafptr->verttax + coaredlooftval; + coarmulttax = (GraphCoarsenMulti *) (coargrafptr->verttax + coarmultoftval); + *coarmultptr = coarmulttax; /* Return pointer to multinode array */ + if (coarvfixptr != NULL) + *coarvfixptr = coarvfixnbr = finevfixnbr; /* TODO : compute real number ! */ + +#ifdef SCOTCH_DEBUG_GRAPH2 + if (graphCheck (coargrafptr) != 0) { /* Check graph consistency */ + errorPrint ("graphCoarsen: inconsistent graph data"); + graphFree (coargrafptr); + return (2); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + return (0); +} + +/****************************************/ +/* */ +/* The edge array building subroutines. */ +/* */ +/****************************************/ + +#define GRAPHCOARSENEDGENAME graphCoarsenEdgeLl +#define GRAPHCOARSENEDGEINIT const Gnum * restrict const fineedlotax = finegrafptr->edlotax +#define GRAPHCOARSENEDGEEDLOINIT coaredlotax[coaredgenum] = fineedlotax[fineedgenum] +#define GRAPHCOARSENEDGEEDLOADD coaredlotax[coarhashtab[h].edgenum] += fineedlotax[fineedgenum] +#define GRAPHCOARSENEDGEEDLOSUB coaredloadj -= fineedlotax[fineedgenum] +#include "graph_coarsen_edge.c" +#undef GRAPHCOARSENEDGENAME +#undef GRAPHCOARSENEDGEINIT +#undef GRAPHCOARSENEDGEEDLOINIT +#undef GRAPHCOARSENEDGEEDLOADD +#undef GRAPHCOARSENEDGEEDLOSUB + +#define GRAPHCOARSENEDGENAME graphCoarsenEdgeLu +#define GRAPHCOARSENEDGEINIT +#define GRAPHCOARSENEDGEEDLOINIT coaredlotax[coaredgenum] = 1 +#define GRAPHCOARSENEDGEEDLOADD coaredlotax[coarhashtab[h].edgenum] ++ +#define GRAPHCOARSENEDGEEDLOSUB coaredloadj -- +#include "graph_coarsen_edge.c" +#undef GRAPHCOARSENEDGENAME +#undef GRAPHCOARSENEDGEINIT +#undef GRAPHCOARSENEDGEEDLOINIT +#undef GRAPHCOARSENEDGEEDLOADD +#undef GRAPHCOARSENEDGEEDLOSUB + +#ifdef GRAPHCOARSENTHREAD +#define GRAPHCOARSENEDGECOUNT /* Local coarse edge count routine */ +#define GRAPHCOARSENEDGENAME graphCoarsenEdgeCt +#define GRAPHCOARSENEDGEINIT +#define GRAPHCOARSENEDGEEDLOINIT +#define GRAPHCOARSENEDGEEDLOADD +#define GRAPHCOARSENEDGEEDLOSUB +#include "graph_coarsen_edge.c" +#undef GRAPHCOARSENEDGENAME +#undef GRAPHCOARSENEDGEINIT +#undef GRAPHCOARSENEDGEEDLOINIT +#undef GRAPHCOARSENEDGEEDLOADD +#undef GRAPHCOARSENEDGEEDLOSUB +#undef GRAPHCOARSENEDGECOUNT +#endif /* GRAPHCOARSENTHREAD */ diff --git a/scotch_6.0.3/src/libscotch/graph_coarsen.h b/scotch_6.0.3/src/libscotch/graph_coarsen.h new file mode 100644 index 00000000..12d98f1f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_coarsen.h @@ -0,0 +1,167 @@ +/* Copyright 2004,2007,2011-2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_coarsen.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source graph coarsening **/ +/** functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 02 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 18 aug 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 28 nov 1995 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 17 sep 1998 **/ +/** # Version 4.0 : from : 13 dec 2001 **/ +/** to 05 dec 2004 **/ +/** # Version 6.0 : from : 09 mar 2011 **/ +/** to 02 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#ifdef SCOTCH_PTHREAD +#define GRAPHCOARSENTHREAD +#endif /* SCOTCH_PTHREAD */ + +/** Prime number for hashing vertex numbers. **/ + +#define GRAPHCOARSENHASHPRIME 1049 /* Prime number */ + +/* +** The type and structure definitions. +*/ + +/*+ Here are the edge matching function types for coarsening. +*/ + +typedef enum GraphCoarsenType_ { + GRAPHCOARHEM, /*+ Heavy-edge matching +*/ + GRAPHCOARSCN, /*+ Scanning (first) matching +*/ + GRAPHCOARNBR /*+ Number of matching types +*/ +} GraphCoarsenType; + +/*+ The multinode table element, which contains + pairs of based indices of collapsed vertices. + Both values are equal for uncollapsed vertices. + As the base values of the fine and coarse graphs + may be different, the values of the collapsed + vertices are set with respect to the base value + of the fine graph. +*/ + +typedef struct GraphCoarsenMulti_ { + Gnum vertnum[2]; /*+ Numbers of the collapsed vertices of a multinode +*/ +} GraphCoarsenMulti; + +/*+ A table made of such elements is used during + coarsening to build the edge array of the new + graph, after the labeling of the vertices. +*/ + +typedef struct GraphCoarsenHash_ { + Gnum vertorgnum; /*+ Origin vertex (i.e. pass) number +*/ + Gnum vertendnum; /*+ Other end vertex number +*/ + Gnum edgenum; /*+ Number of corresponding edge +*/ +} GraphCoarsenHash; + +/*+ The matching and coarsening routine + parameter structure. It contains the + thread-independent data. +*/ + +typedef struct GraphCoarsenData_ { + ThreadGroupHeader thrddat; /*+ Thread handling data +*/ + const Graph * finegrafptr; /*+ Fine graph to perform matching on +*/ + const Anum * fineparotax; /*+ Old part array +*/ + const Anum * finepfixtax; /*+ Array of fixed vertices +*/ + Gnum finevfixnbr; /*+ Number of fine fixed vertices +*/ + Gnum * finematetax; /*+ Fine mate array / fine-to-coarse array +*/ + Graph * coargrafptr; /*+ Coarse graph to build +*/ + Gnum coarvertmax; /*+ Maximum number of vertices to get +*/ + Gnum coarvertnbr; /*+ Global number of coarse vertices after matching +*/ + GraphCoarsenMulti * coarmulttax; /*+ Multinode array +*/ + Gnum coarhashmsk; /*+ Hash table mask +*/ +#ifdef SCOTCH_PTHREAD + int * restrict finelocktax; /*+ Matching lock array (if any) +*/ + Gnum * restrict finequeutab; /*+ Matching queue array (if any) +*/ + void (* fendptr) (void *); /*+ Pointer to final / sequential match routine +*/ + void (* fmidptr) (void *); /*+ Pointer to intermediate match routine (if any) +*/ +#endif /* SCOTCH_PTHREAD */ + void (* fbegptr) (void *); /*+ Pointer to beginning match routine (if any) +*/ +} GraphCoarsenData; + +/*+ The thread-specific data block. +*/ + +typedef struct GraphCoarsenThread_ { + ThreadHeader thrddat; /*+ Thread management data +*/ + Gunum randval; /*+ Per-thread unsigned random value +*/ + GraphCoarsenHash * coarhashtab; /*+ End vertex hash table (may be local) +*/ + Gnum coarvertnnd; /*+ After-last coarse vertex number +*/ + Gnum coarvertbas; /*+ Minimum coarse vertex number; for prefix scan +*/ + Gnum coarvertnbr; /*+ Number of coarse vertices to date; TRICK: scan dummy area +*/ + Gnum coaredloadj; /*+ (Local) coarse edge load sum adjust +*/ + Gnum coardegrmax; /*+ (Local) maximum degree +*/ + Gnum coaredgebas; /*+ Minimum coarse edge number; for prefix scan +*/ + Gnum finevertbas; /*+ Start of fine vertex range; TRICK: scan dummy area +*/ + Gnum finevertnnd; /*+ End of fine vertex range +*/ + Gnum finequeubas; /*+ Minimum perturbation or queue index for matching +*/ + Gnum finequeunnd; /*+ After-last perturbation or queue index for matching +*/ +} GraphCoarsenThread; + +/* +** The function prototypes. +*/ + +#ifndef GRAPH_COARSEN +#define static +#endif + +int graphCoarsen (const Graph * restrict const, Graph * restrict const, GraphCoarsenMulti * restrict * const, const Gnum, const double, const Anum * restrict const, const Anum * restrict const, const Gnum, Gnum * restrict const); + +#ifdef GRAPHCOARSENTHREAD +static void graphCoarsenEdgeCt (GraphCoarsenThread *); +#endif /* GRAPHCOARSENTHREAD */ +static void graphCoarsenEdgeLl (GraphCoarsenThread *); +static void graphCoarsenEdgeLu (GraphCoarsenThread *); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/graph_coarsen_edge.c b/scotch_6.0.3/src/libscotch/graph_coarsen_edge.c new file mode 100644 index 00000000..c98244b0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_coarsen_edge.c @@ -0,0 +1,158 @@ +/* Copyright 2004,2007,2009,2012 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_coarsen_edge.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This commodity file contains the edge **/ +/** arrays building subroutine which is **/ +/** duplicated, with minor modifications, **/ +/** into graph_coarsen.c. **/ +/** **/ +/** DATES : # Version 4.0 : from : 17 dec 2001 **/ +/** to 25 feb 2004 **/ +/** # Version 5.0 : from : 13 dec 2006 **/ +/** to 14 dec 2006 **/ +/** # Version 5.1 : from : 30 oct 2009 **/ +/** to 30 oct 2009 **/ +/** # Version 6.0 : from : 28 oct 2012 **/ +/** to 30 oct 2012 **/ +/** **/ +/************************************************************/ + +static +void +GRAPHCOARSENEDGENAME ( +GraphCoarsenThread * thrdptr) +{ + Gnum coarvertnum; + Gnum coarvertnnd; + Gnum coaredgenum; + Gnum coardegrmax; + Gnum coaredloadj; /* Edge load sum adjust with respect to fine graph edge load sum */ + + GraphCoarsenData * restrict coarptr = (GraphCoarsenData *) (thrdptr->thrddat.grouptr); + const Graph * restrict const finegrafptr = coarptr->finegrafptr; + const Gnum * restrict const fineverttax = finegrafptr->verttax; + const Gnum * restrict const finevendtax = finegrafptr->vendtax; + const Gnum * restrict const finevelotax = finegrafptr->velotax; + const Gnum * restrict const fineedgetax = finegrafptr->edgetax; + Gnum * restrict const finecoartax = coarptr->finematetax; + const Graph * restrict const coargrafptr = coarptr->coargrafptr; +#ifndef GRAPHCOARSENEDGECOUNT + Gnum * restrict const coarverttax = coargrafptr->verttax; + Gnum * restrict const coarvelotax = coargrafptr->velotax; + Gnum * restrict const coaredgetax = coargrafptr->edgetax; + Gnum * restrict const coaredlotax = coargrafptr->edlotax; +#endif /* GRAPHCOARSENEDGECOUNT */ + GraphCoarsenHash * restrict const coarhashtab = thrdptr->coarhashtab; /* Hash table is thread-dependent for memory locality */ + const Gnum coarhashmsk = coarptr->coarhashmsk; + const GraphCoarsenMulti * restrict const coarmulttax = coarptr->coarmulttax; + + + GRAPHCOARSENEDGEINIT; + + coaredloadj = 0; + for (coarvertnum = thrdptr->coarvertbas, coardegrmax = 0, /* For all local coarse vertices */ + coarvertnnd = thrdptr->coarvertnnd, coaredgenum = thrdptr->coaredgebas; + coarvertnum < coarvertnnd; coarvertnum ++) { + Gnum finevertnum; + int i; + +#ifndef GRAPHCOARSENEDGECOUNT /* If we do not only want to count */ + Gnum coarveloval; /* Load of coarse vertex */ + Gnum coaredgetmp; /* Current index in edge array */ + + coarverttax[coarvertnum] = /* Set vertex edge index */ + coaredgetmp = coaredgenum; + coarveloval = 0; +#endif /* GRAPHCOARSENEDGECOUNT */ + i = 0; + do { /* For all fine edges of multinode vertices */ + Gnum fineedgenum; + + finevertnum = coarmulttax[coarvertnum].vertnum[i]; +#ifndef GRAPHCOARSENEDGECOUNT /* If we do not only want to count */ + coarveloval += (finevelotax != NULL) ? finevelotax[finevertnum] : 1; +#endif /* GRAPHCOARSENEDGECOUNT */ + + for (fineedgenum = fineverttax[finevertnum]; + fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { + Gnum coarvertend; /* Number of coarse vertex which is end of fine edge */ + Gnum h; + + coarvertend = finecoartax[fineedgetax[fineedgenum]]; + if (coarvertend != coarvertnum) { /* If not end of collapsed edge */ + for (h = (coarvertend * GRAPHCOARSENHASHPRIME) & coarhashmsk; ; h = (h + 1) & coarhashmsk) { + if (coarhashtab[h].vertorgnum != coarvertnum) { /* If old slot */ + coarhashtab[h].vertorgnum = coarvertnum; /* Mark it in reference array */ + coarhashtab[h].vertendnum = coarvertend; + coarhashtab[h].edgenum = coaredgenum; +#ifndef GRAPHCOARSENEDGECOUNT /* If we do not only want to count */ + coaredgetax[coaredgenum] = coarvertend; /* One more edge created */ + GRAPHCOARSENEDGEEDLOINIT; /* Initialize edge load entry */ +#endif /* GRAPHCOARSENEDGECOUNT */ + coaredgenum ++; + break; /* Give up hashing */ + } + if (coarhashtab[h].vertendnum == coarvertend) { /* If coarse edge already exists */ +#ifndef GRAPHCOARSENEDGECOUNT + GRAPHCOARSENEDGEEDLOADD; /* Accumulate edge load */ +#endif /* GRAPHCOARSENEDGECOUNT */ + break; /* Give up hashing */ + } + } + } +#ifndef GRAPHCOARSENEDGECOUNT + else { + GRAPHCOARSENEDGEEDLOSUB; + } +#endif /* GRAPHCOARSENEDGECOUNT */ + } + } while (i ++, finevertnum != coarmulttax[coarvertnum].vertnum[1]); /* Skip to next matched vertex if both vertices not equal */ + +#ifndef GRAPHCOARSENEDGECOUNT /* If we do not only want to count */ + coarvelotax[coarvertnum] = coarveloval; /* Create coarse vertex load array */ + coaredgetmp = coaredgenum - coaredgetmp; /* Compute degree of current vertex */ + if (coardegrmax < coaredgetmp) + coardegrmax = coaredgetmp; +#endif /* GRAPHCOARSENEDGECOUNT */ + } /* End of (local) edge array not marked since will be done by next or main thread */ + + thrdptr->coaredgebas = coaredgenum; /* Record counted number of edges */ +#ifndef GRAPHCOARSENEDGECOUNT + thrdptr->coaredloadj = coaredloadj; + thrdptr->coardegrmax = coardegrmax; +#endif /* GRAPHCOARSENEDGECOUNT */ +} diff --git a/scotch_6.0.3/src/libscotch/graph_induce.c b/scotch_6.0.3/src/libscotch/graph_induce.c new file mode 100644 index 00000000..2cbde24d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_induce.c @@ -0,0 +1,381 @@ +/* Copyright 2004,2007-2009,2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_induce.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles the source graph **/ +/** subgraph-making functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 31 oct 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 08 jun 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 17 sep 1998 **/ +/** # Version 4.0 : from : 28 nov 2001 **/ +/** to 17 apr 2006 **/ +/** # Version 5.0 : from : 14 dec 2006 **/ +/** to 11 jun 2008 **/ +/** # Version 5.1 : from : 01 jan 2009 **/ +/** to 01 jan 2009 **/ +/** # Version 6.0 : from : 29 mar 2011 **/ +/** to 01 aug 2014 **/ +/** **/ +/** NOTES : # Several algorithms, such as the **/ +/** active graph building routine of **/ +/** bgraphInit2, assume that, for every **/ +/** vertex, remaining edges will be kept **/ +/** in the same order as in the original **/ +/** graph. This must be enforced. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH +#define GRAPH_INDUCE + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "graph_induce.h" + +/****************************************/ +/* */ +/* These routines handle source graphs. */ +/* */ +/****************************************/ + +/* This routine builds the graph induced +** by the original graph and the list of +** selected vertices. +** The induced vnumtab array is the list +** array if the original graph does not have +** a vnumtab, or the proper subset of the +** original vnumtab else. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphInduceList ( +const Graph * restrict const orggrafptr, +const VertList * restrict const indlistptr, +Graph * restrict const indgrafptr) +{ + Gnum * restrict orgindxtax; /* Based access to vertex translation array */ + Gnum indvertnbr; /* Number of vertices in induced graph */ + Gnum indvertnum; /* Number of current vertex in induced graph */ + Gnum * restrict indedgetab; /* Pointer to pre-allocated edge array */ + Gnum indedgenbr; /* (Approximate) number of edges in induced graph */ + + indvertnbr = indlistptr->vnumnbr; + + memSet (indgrafptr, 0, sizeof (Graph)); /* Initialize graph fields */ + indgrafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; + indgrafptr->baseval = orggrafptr->baseval; + + if (orggrafptr->velotax != NULL) { + if (memAllocGroup ((void **) (void *) + &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), + &indgrafptr->vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), + &indgrafptr->velotax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("graphInduceList: out of memory (1)"); + return (1); /* Nothing to free because group allocation failed */ + } + indgrafptr->velotax -= indgrafptr->baseval; + } + else { + if (memAllocGroup ((void **) (void *) + &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), + &indgrafptr->vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("graphInduceList: out of memory (2)"); + return (1); + } + } + indgrafptr->verttax -= indgrafptr->baseval; /* Adjust base of arrays */ + indgrafptr->vnumtax -= indgrafptr->baseval; + indgrafptr->vertnbr = indvertnbr; + indgrafptr->vertnnd = indvertnbr + indgrafptr->baseval; + + indedgenbr = orggrafptr->edgenbr; /* Choose best upper bound on number of edges (avoid multiply overflow) */ + if ((orggrafptr->degrmax > 0) && (indvertnbr < (indedgenbr / orggrafptr->degrmax))) + indedgenbr = indvertnbr * orggrafptr->degrmax; + if (orggrafptr->edlotax != NULL) /* If graph has edge weights */ + indedgenbr *= 2; /* Account for edge weights */ + + if (memAllocGroup ((void *) + &indedgetab, (size_t) (indedgenbr * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab) */ + &orgindxtax, (size_t) (orggrafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxtab is at the end of the heap */ + errorPrint ("graphInduceList: out of memory (3)"); + graphExit (indgrafptr); + return (1); + } + orgindxtax -= orggrafptr->baseval; + + memCpy (indgrafptr->vnumtax + indgrafptr->baseval, /* Copy vertex number array from list */ + indlistptr->vnumtab, indvertnbr * sizeof (Gnum)); + + memSet (orgindxtax + orggrafptr->baseval, ~0, orggrafptr->vertnbr * sizeof (Gnum)); /* Preset index array */ + + for (indvertnum = indgrafptr->baseval, indedgenbr = 0; /* Fill index array */ + indvertnum < indgrafptr->baseval + indvertnbr; indvertnum ++) { + Gnum orgvertnum; + + orgvertnum = indgrafptr->vnumtax[indvertnum]; + + orgindxtax[orgvertnum] = indvertnum; /* Mark selected vertices */ + indedgenbr += orggrafptr->vendtax[orgvertnum] - orggrafptr->verttax[orgvertnum]; + } + + return (graphInduce2 (orggrafptr, indgrafptr, indvertnbr, indedgenbr, indedgetab, orgindxtax)); +} + +/* This routine builds the graph induced +** by the original graph and the vector +** of selected vertices. +** The induced vnumtab array is the list of +** selected vertices if the original graph +** does not have a vnumtab, or the proper +** subset of the original vnumtab else. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphInducePart ( +const Graph * restrict const orggrafptr, /* Pointer to original graph */ +const GraphPart * const orgparttax, /* Based array of vertex partition flags */ +const Gnum indvertnbr, /* Number of vertices in selected part */ +const GraphPart indpartval, /* Partition value of vertices to keep */ +Graph * restrict const indgrafptr) /* Pointer to induced subgraph */ +{ + Gnum * restrict orgindxtax; /* Based access to vertex translation array */ + Gnum indvertnum; /* Number of current vertex in induced graph */ + Gnum * restrict indedgetab; /* Pointer to pre-allocated edge array */ + Gnum indedgenbr; /* (Approximate) number of edges in induced graph */ + Gnum orgvertnum; + + memSet (indgrafptr, 0, sizeof (Graph)); /* Initialize graph fields */ + indgrafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; + indgrafptr->baseval = orggrafptr->baseval; + + if (orggrafptr->velotax != NULL) { + if (memAllocGroup ((void **) (void *) + &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), + &indgrafptr->vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), + &indgrafptr->velotax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("graphInducePart: out of memory (1)"); + return (1); /* Nothing to free because group allocation failed */ + } + indgrafptr->velotax -= indgrafptr->baseval; + } + else { + if (memAllocGroup ((void **) (void *) + &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), + &indgrafptr->vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("graphInducePart: out of memory (2)"); + return (1); + } + } + indgrafptr->verttax -= indgrafptr->baseval; /* Adjust base of arrays */ + indgrafptr->vnumtax -= indgrafptr->baseval; + indgrafptr->vertnbr = indvertnbr; + indgrafptr->vertnnd = indvertnbr + indgrafptr->baseval; + + indedgenbr = orggrafptr->edgenbr; /* Choose best upper bound on number of edges (avoid multiply overflow) */ + if ((orggrafptr->degrmax > 0) && (indvertnbr < (indedgenbr / orggrafptr->degrmax))) + indedgenbr = indvertnbr * orggrafptr->degrmax; + if (orggrafptr->edlotax != NULL) /* If graph has edge weights */ + indedgenbr *= 2; /* Account for edge weights */ + + if (memAllocGroup ((void *) + &indedgetab, (size_t) (indedgenbr * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab) */ + &orgindxtax, (size_t) (orggrafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxtab is at the end of the heap */ + errorPrint ("graphInducePart: out of memory (3)"); + graphExit (indgrafptr); + return (1); + } + orgindxtax -= orggrafptr->baseval; + + for (indvertnum = indgrafptr->baseval, indedgenbr = 0, orgvertnum = orggrafptr->baseval; /* Fill index array */ + orgvertnum < orggrafptr->vertnnd; orgvertnum ++) { + if (orgparttax[orgvertnum] == indpartval) { /* If vertex should be kept */ + orgindxtax[orgvertnum] = indvertnum; /* Mark selected vertex */ + indgrafptr->vnumtax[indvertnum] = orgvertnum; + indedgenbr += orggrafptr->vendtax[orgvertnum] - orggrafptr->verttax[orgvertnum]; + indvertnum ++; /* One more induced vertex created */ + } + else + orgindxtax[orgvertnum] = ~0; + } +#ifdef SCOTCH_DEBUG_GRAPH2 + if ((indvertnum - indgrafptr->baseval) != indvertnbr) { + errorPrint ("graphInducePart: inconsistent data"); + memFree (indedgetab); + graphExit (indgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + return (graphInduce2 (orggrafptr, indgrafptr, indvertnbr, indedgenbr, indedgetab, orgindxtax)); +} + +/* This routine finalizes the building +** of the induced subgraph. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +int +graphInduce2 ( +const Graph * restrict const orggrafptr, /* Pointer to original graph */ +Graph * restrict const indgrafptr, /* Pointer to induced graph */ +const Gnum indvertnbr, /* Number of vertices in induced graph */ +const Gnum indedgenbr, /* (Upper bound of) number of edges in induced graph */ +Gnum * const indedgetab, /* Pointer to pre-allocated edge and edge load arrays */ +const Gnum * restrict const orgindxtax) /* Array of numbers of selected vertices */ +{ + Gnum indvertnum; /* Current induced vertex number */ + Gnum indvelosum; /* Overall induced vertex load */ + Gnum indedlosum; /* Overall induced edge load */ + Gnum indedgenum; /* Number of current induced edge */ + Gnum orgvertnum; /* Number of current vertex in original graph */ + Gnum orgedgenum; /* Number of current edge in original graph */ + + const Gnum * restrict const orgverttax = orggrafptr->verttax; + const Gnum * restrict const orgvendtax = orggrafptr->vendtax; + const Gnum * restrict const orgvelotax = orggrafptr->velotax; + const Gnum * restrict const orgvnumtax = orggrafptr->vnumtax; + const Gnum * restrict const orgedgetax = orggrafptr->edgetax; + const Gnum * restrict const orgedlotax = orggrafptr->edlotax; + Gnum * restrict const indverttax = indgrafptr->verttax; + Gnum * restrict const indvelotax = indgrafptr->velotax; + Gnum * restrict const indvnumtax = indgrafptr->vnumtax; + Gnum * restrict indedgetax; + Gnum * restrict indedlotax; + + if (orgedlotax != NULL) { + memOffset ((void *) indedgetab, + &indedgetax, (size_t) (indedgenbr * sizeof (Gnum)), + &indedlotax, (size_t) (indedgenbr * sizeof (Gnum)), NULL); + indedgetax -= indgrafptr->baseval; + indedlotax -= indgrafptr->baseval; + } + else { + indedgetax = indedgetab - indgrafptr->baseval; + indedlotax = NULL; + } + + indvelosum = (indvelotax == NULL) ? indgrafptr->vertnbr : 0; + indedlosum = 0; + for (indvertnum = indedgenum = indgrafptr->baseval; + indvertnum < indgrafptr->vertnnd; indvertnum ++) { + orgvertnum = indvnumtax[indvertnum]; + indverttax[indvertnum] = indedgenum; + if (indvelotax != NULL) { /* If graph has vertex weights */ + indvelosum += /* Accumulate vertex loads */ + indvelotax[indvertnum] = orgvelotax[orgvertnum]; + } + + if (indedlotax != NULL) { /* If graph has edge weights */ + for (orgedgenum = orgverttax[orgvertnum]; + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { + if (orgindxtax[orgedgetax[orgedgenum]] != ~0) { /* If edge should be kept */ + indedlosum += + indedlotax[indedgenum] = orgedlotax[orgedgenum]; + indedgetax[indedgenum] = orgindxtax[orgedgetax[orgedgenum]]; + indedgenum ++; + } + } + } + else { + for (orgedgenum = orgverttax[orgvertnum]; + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { + if (orgindxtax[orgedgetax[orgedgenum]] != ~0) { /* If edge should be kept */ + indedgetax[indedgenum] = orgindxtax[orgedgetax[orgedgenum]]; + indedgenum ++; + } + } + } + } + indverttax[indvertnum] = indedgenum; /* Mark end of edge array */ + + indgrafptr->vendtax = indgrafptr->verttax + 1; /* Use compact representation of vertex arrays */ + indgrafptr->vertnbr = indvertnum - indgrafptr->baseval; + indgrafptr->vertnnd = indvertnum; + indgrafptr->velosum = indvelosum; + indgrafptr->edgenbr = indedgenum - indgrafptr->baseval; /* Set actual number of edges */ + indgrafptr->edlosum = (indedlotax != NULL) ? indedlosum : indgrafptr->edgenbr; + indgrafptr->degrmax = orggrafptr->degrmax; /* Induced maximum degree is likely to be the one of the original graph */ + + if (orggrafptr->vnumtax != NULL) { /* Adjust vnumtax */ + for (indvertnum = indgrafptr->baseval; indvertnum < indgrafptr->vertnnd; indvertnum ++) + indvnumtax[indvertnum] = orgvnumtax[indvnumtax[indvertnum]]; + } + + if (indedlotax != NULL) { /* Re-allocate arrays and delete orgindxtab */ + size_t indedlooftval; /* Offset of edge load array with respect to edge array */ + + indedlooftval = indedlotax - indedgetax; + indgrafptr->edgetax = (Gnum *) memRealloc (indedgetab, (indedlooftval + indgrafptr->edgenbr) * sizeof (Gnum)) - indgrafptr->baseval; + indgrafptr->edlotax = indgrafptr->edgetax + indedlooftval; /* Use old index into old array as new index */ + } + else + indgrafptr->edgetax = (Gnum *) memRealloc (indedgetab, indgrafptr->edgenbr * sizeof (Gnum)) - indgrafptr->baseval; + +#ifdef SCOTCH_DEBUG_GRAPH2 + if (graphCheck (indgrafptr) != 0) { /* Check graph consistency */ + errorPrint ("graphInduce2: inconsistent graph data"); + graphExit (indgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/graph_induce.h b/scotch_6.0.3/src/libscotch/graph_induce.h new file mode 100644 index 00000000..eee65371 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_induce.h @@ -0,0 +1,69 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_induce.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source graph sub-graph making **/ +/** functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 02 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 18 aug 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 28 nov 1995 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 17 sep 1998 **/ +/** # Version 4.0 : from : 28 nov 2001 **/ +/** to 28 nov 2001 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef GRAPH_INDUCE +#define static +#endif + +static int graphInduce2 (const Graph * const, Graph * const, const Gnum, const Gnum, Gnum * const, const Gnum * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/graph_io.c b/scotch_6.0.3/src/libscotch/graph_io.c new file mode 100644 index 00000000..8eaf7b7e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io.c @@ -0,0 +1,380 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the source graph **/ +/** input/output functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 31 oct 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 08 jun 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 15 mar 1999 **/ +/** # Version 4.0 : from : 25 nov 2001 **/ +/** to 21 jan 2004 **/ +/** # Version 5.0 : from : 13 dec 2006 **/ +/** to 10 sep 2007 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_IO + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "graph_io.h" + +/*******************************************/ +/* */ +/* These routines handle source graph I/O. */ +/* */ +/*******************************************/ + +/* This routine loads a source graph from +** the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphLoad ( +Graph * restrict const grafptr, /* Graph structure to fill */ +FILE * const stream, /* Stream from which to read graph data */ +const Gnum baseval, /* Base value (-1 means keep file base) */ +const GraphFlag flagval) /* Graph loading flags */ +{ + Gnum edgenum; /* Number of edges really allocated */ + Gnum edgennd; + Gnum vlblnbr; /* = vertnbr if vertex labels */ + Gnum vlblmax; /* Maximum vertex label number */ + Gnum velonbr; /* = vertnbr if vertex loads wanted */ + Gnum velosum; /* Sum of vertex loads */ + Gnum edlonbr; /* = edgenbr if edge loads wanted */ + Gnum edlosum; /* Sum of edge loads */ + Gnum edgeval; /* Value where to read edge end */ + Gnum baseadj; + Gnum versval; + Gnum degrmax; + Gnum propval; + char proptab[4]; + Gnum vertnum; + + memSet (grafptr, 0, sizeof (Graph)); + + if (intLoad (stream, &versval) != 1) { /* Read version number */ + errorPrint ("graphLoad: bad input (1)"); + return (1); + } + if (versval != 0) { /* If version not zero */ + errorPrint ("graphLoad: old-style graph format no longer supported"); + return (1); + } + + if ((intLoad (stream, &grafptr->vertnbr) != 1) || /* Read rest of header */ + (intLoad (stream, &grafptr->edgenbr) != 1) || + (intLoad (stream, &baseadj) != 1) || + (intLoad (stream, &propval) != 1) || + (propval < 0) || + (propval > 111)) { + errorPrint ("graphLoad: bad input (2)"); + return (1); + } + sprintf (proptab, "%3.3d", (int) propval); /* Compute file properties */ + proptab[0] -= '0'; /* Vertex labels flag */ + proptab[1] -= '0'; /* Edge weights flag */ + proptab[2] -= '0'; /* Vertex loads flag */ + + grafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; + if (baseval == -1) { /* If keep file graph base */ + grafptr->baseval = baseadj; /* Set graph base as file base */ + baseadj = 0; /* No base adjustment needed */ + } + else { /* If set graph base */ + grafptr->baseval = baseval; /* Set wanted graph base */ + baseadj = baseval - baseadj; /* Update base adjust */ + } + if (proptab[0] != 0) /* If vertex labels, no base adjust */ + baseadj = 0; + + velonbr = ((proptab[2] != 0) && ((flagval & GRAPHIONOLOADVERT) == 0)) ? grafptr->vertnbr : 0; + vlblnbr = (proptab[0] != 0) ? grafptr->vertnbr : 0; + edlonbr = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? grafptr->edgenbr : 0; + + if ((memAllocGroup ((void **) (void *) + &grafptr->verttax, (size_t) ((grafptr->vertnbr + 1) * sizeof (Gnum)), + &grafptr->velotax, (size_t) (velonbr * sizeof (Gnum)), + &grafptr->vlbltax, (size_t) (vlblnbr * sizeof (Gnum)), NULL) == NULL) || + (memAllocGroup ((void **) (void *) + &grafptr->edgetax, (size_t) (grafptr->edgenbr * sizeof (Gnum)), + &grafptr->edlotax, (size_t) (edlonbr * sizeof (Gnum)), NULL) == NULL)) { + if (grafptr->verttax != NULL) + memFree (grafptr->verttax); + errorPrint ("graphLoad: out of memory"); + graphFree (grafptr); + return (1); + } + grafptr->vertnnd = grafptr->vertnbr + grafptr->baseval; + grafptr->verttax -= grafptr->baseval; + grafptr->vendtax = grafptr->verttax + 1; /* Use compact vertex array */ + grafptr->velotax = (velonbr != 0) ? (grafptr->velotax - grafptr->baseval) : NULL; + grafptr->vlbltax = (vlblnbr != 0) ? (grafptr->vlbltax - grafptr->baseval) : NULL; + grafptr->edgetax -= grafptr->baseval; + grafptr->edlotax = (edlonbr != 0) ? (grafptr->edlotax - grafptr->baseval) : NULL; + + vlblmax = grafptr->vertnnd - 1; /* No vertex labels known */ + velosum = (grafptr->velotax == NULL) ? grafptr->vertnbr : 0; + edlosum = (grafptr->edlotax == NULL) ? grafptr->edgenbr : 0; + edgennd = grafptr->edgenbr + grafptr->baseval; + degrmax = 0; /* No maximum degree yet */ + + for (vertnum = edgenum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { + Gnum degrval; + + if (grafptr->vlbltax != NULL) { /* If must read label */ + Gnum vlblval; /* Value where to read vertex label */ + + if (intLoad (stream, &vlblval) != 1) { /* Read label data */ + errorPrint ("graphLoad: bad input (3)"); + graphFree (grafptr); + return (1); + } + grafptr->vlbltax[vertnum] = vlblval; + if (grafptr->vlbltax[vertnum] > vlblmax) /* Get maximum vertex label */ + vlblmax = grafptr->vlbltax[vertnum]; + } + if (proptab[2] != 0) { /* If must read vertex load */ + Gnum veloval; /* Value where to read vertex load */ + + if (intLoad (stream, &veloval) != 1) { /* Read vertex load data */ + errorPrint ("graphLoad: bad input (4)"); + graphFree (grafptr); + return (1); + } + if (grafptr->velotax != NULL) + velosum += + grafptr->velotax[vertnum] = veloval; + } + if (intLoad (stream, °rval) != 1) { /* Read vertex degree */ + errorPrint ("graphLoad: bad input (5)"); + graphFree (grafptr); + return (1); + } + if (degrmax < degrval) /* Set maximum degree */ + degrmax = degrval; + + grafptr->verttax[vertnum] = edgenum; /* Set index in edge array */ + degrval += edgenum; + if (degrval > edgennd) { /* Check if edge array overflows */ + errorPrint ("graphLoad: invalid arc count (1)"); + graphFree (grafptr); + return (1); + } + + for ( ; edgenum < degrval; edgenum ++) { + if (proptab[1] != 0) { /* If must read edge load */ + Gnum edloval; /* Value where to read edge load */ + + if (intLoad (stream, &edloval) != 1) { /* Read edge load data */ + errorPrint ("graphLoad: bad input (6)"); + graphFree (grafptr); + return (1); + } + if (grafptr->edlotax != NULL) + edlosum += + grafptr->edlotax[edgenum] = (Gnum) edloval; + } + if (intLoad (stream, &edgeval) != 1) { /* Read edge data */ + errorPrint ("graphLoad: bad input (7)"); + graphFree (grafptr); + return (1); + } + grafptr->edgetax[edgenum] = edgeval + baseadj; + } + } + grafptr->verttax[vertnum] = edgenum; /* Set end of edge array */ + if (edgenum != edgennd) { /* Check if number of edges is valid */ + errorPrint ("graphLoad: invalid arc count (2)"); + graphFree (grafptr); + return (1); + } + grafptr->velosum = velosum; + grafptr->edlosum = edlosum; + grafptr->degrmax = degrmax; + + if (grafptr->vlbltax != NULL) { /* If vertex label renaming necessary */ + if (graphLoad2 (grafptr->baseval, grafptr->vertnnd, grafptr->verttax, /* Rename edge ends */ + grafptr->vendtax, grafptr->edgetax, vlblmax, grafptr->vlbltax) != 0) { + errorPrint ("graphLoad: cannot relabel vertices"); + graphFree (grafptr); + return (1); + } + } + +#ifdef SCOTCH_DEBUG_GRAPH2 + if (graphCheck (grafptr) != 0) { /* Check graph consistency */ + errorPrint ("graphLoad: inconsistent graph data"); + graphFree (grafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + return (0); +} + +int +graphLoad2 ( +const Gnum baseval, +const Gnum vertnnd, +const Gnum * const verttax, +const Gnum * const vendtax, +Gnum * restrict const edgetax, +const Gnum vlblmax, +const Gnum * const vlbltax) +{ + Gnum vertnum; /* Number of current vertex */ + Gnum * restrict indxtab; /* Vertex label/number index table */ + + if ((indxtab = (Gnum *) memAlloc ((vlblmax + 1) * sizeof (Gnum))) == NULL) { + errorPrint ("graphLoad2: out of memory"); + return (1); + } + + memSet (indxtab, ~0, (vlblmax + 1) * sizeof (Gnum)); /* Assume labels not used */ + for (vertnum = baseval; vertnum < vertnnd; vertnum ++) { + if (indxtab[vlbltax[vertnum]] != ~0) { /* If vertex label already used */ + errorPrint ("graphLoad2: duplicate vertex label"); + memFree (indxtab); + return (1); + } + indxtab[vlbltax[vertnum]] = vertnum; /* Set vertex number index */ + } + for (vertnum = baseval; vertnum < vertnnd; vertnum ++) { + Gnum edgenum; /* Number of current edge */ + + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + if (edgetax[edgenum] > vlblmax) { /* If invalid edge end number */ + errorPrint ("graphLoad2: invalid arc end number (1)"); + memFree (indxtab); + return (1); + } + if (indxtab[edgetax[edgenum]] == ~0) { /* If unused edge end number */ + errorPrint ("graphLoad2: invalid arc end number (2)"); + memFree (indxtab); + return (1); + } + edgetax[edgenum] = indxtab[edgetax[edgenum]]; /* Replace label by number */ + } + } + + memFree (indxtab); /* Free index array */ + + return (0); +} + +/* This routine saves a source graph to +** the given stream, in the new-style +** graph format. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphSave ( +const Graph * const grafptr, +FILE * const stream) +{ + Gnum vertnum; + char propstr[4]; /* Property string */ + int o; + + propstr[0] = (grafptr->vlbltax != NULL) ? '1' : '0'; /* Set property string */ + propstr[1] = (grafptr->edlotax != NULL) ? '1' : '0'; + propstr[2] = (grafptr->velotax != NULL) ? '1' : '0'; + propstr[3] = '\0'; + + if (fprintf (stream, "0\n" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t%3s\n", /* Write file header */ + (Gnum) grafptr->vertnbr, + (Gnum) grafptr->edgenbr, + (Gnum) grafptr->baseval, + propstr) == EOF) { + errorPrint ("graphSave: bad output (1)"); + return (1); + } + + for (vertnum = grafptr->baseval, o = 0; + (vertnum < grafptr->vertnnd) && (o == 0); vertnum ++) { + Gnum edgenum; + + if (grafptr->vlbltax != NULL) /* Write vertex label if necessary */ + o = (fprintf (stream, GNUMSTRING "\t", (Gnum) grafptr->vlbltax[vertnum]) == EOF); + if (grafptr->velotax != NULL) /* Write vertex load if necessary */ + o |= (fprintf (stream, GNUMSTRING "\t", (Gnum) grafptr->velotax[vertnum]) == EOF); + + o |= (fprintf (stream, GNUMSTRING, (Gnum) (grafptr->vendtax[vertnum] - grafptr->verttax[vertnum])) == EOF); /* Write vertex degree */ + + for (edgenum = grafptr->verttax[vertnum]; + (edgenum < grafptr->vendtax[vertnum]) && (o == 0); edgenum ++) { + Gnum vertend; + + o |= (putc ('\t', stream) == EOF); + if (grafptr->edlotax != NULL) /* Write edge load if necessary */ + o |= (fprintf (stream, GNUMSTRING "\t", (Gnum) grafptr->edlotax[edgenum]) == EOF); + vertend = grafptr->edgetax[edgenum]; + o |= (fprintf (stream, GNUMSTRING, (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertend] : vertend)) == EOF); /* Write edge end */ + } + o |= (putc ('\n', stream) == EOF); + } + + if (o != 0) + errorPrint ("graphSave: bad output (2)"); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/graph_io.h b/scotch_6.0.3/src/libscotch/graph_io.h new file mode 100644 index 00000000..3dd89e6b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io.h @@ -0,0 +1,69 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source graph input/output **/ +/** functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 02 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 18 aug 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 28 nov 1995 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 15 may 1999 **/ +/** # Version 4.0 : from : 25 nov 2001 **/ +/** to 25 nov 2001 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef GRAPH_IO +#define static +#endif + +int graphLoad2 (const Gnum, const Gnum, const Gnum * const, const Gnum * const, Gnum * const, const Gnum, const Gnum * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/graph_io_chac.c b/scotch_6.0.3/src/libscotch/graph_io_chac.c new file mode 100644 index 00000000..b12d671b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io_chac.c @@ -0,0 +1,329 @@ +/* Copyright 2004,2007,2008,2010,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io_chac.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the I/O routines **/ +/** for handling the Chaco graph format. **/ +/** **/ +/** DATES : # Version 3.2 : from : 06 nov 1997 **/ +/** to 26 may 1998 **/ +/** # Version 3.3 : from : 13 dec 1998 **/ +/** to 24 dec 1998 **/ +/** # Version 3.4 : from : 05 oct 1999 **/ +/** to : 04 feb 2000 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 19 jan 2004 **/ +/** # Version 5.0 : from : 04 feb 2007 **/ +/** to 21 may 2008 **/ +/** # Version 5.1 : from : 02 dec 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 10 oct 2013 **/ +/** to 10 oct 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_IO_CHAC + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" + +/* This routine loads the geometrical graph +** in the Chaco graph format, and allocates +** the proper structures. +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphGeomLoadChac ( +Graph * restrict const grafptr, /* Graph to load */ +Geom * restrict const geomptr, /* Geometry to load */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* No use */ +{ + char chalinetab[80]; /* Header line */ + long chavertnbr; /* Number of vertices */ + Gnum chavertnum; /* Number of vertex read */ + long chaedgenbr; /* Number of edges */ + long chaflagval; /* Flag on numeric form */ + char chaflagstr[4]; /* Flag for optional data */ + int chabuffcar; /* Buffer for line processing */ + Gnum edgenum; + Gnum edlosum; + Gnum vertnum; + Gnum velosum; + Gnum vlblmax; + Gnum degrmax; + + do { /* Skip comment lines */ + chabuffcar = getc (filesrcptr); /* Read first character */ + if (chabuffcar == '%') { /* If comment line */ + fscanf (filesrcptr, "%*[^\n]"); /* Purge line */ + getc (filesrcptr); /* Purge newline */ + } + } while (chabuffcar == '%'); + ungetc (chabuffcar, filesrcptr); + + chaflagval = 0; + if ((fscanf (filesrcptr, "%79[^\n]%*[^\n]", chalinetab) != 1) || /* Read graph header */ + (sscanf (chalinetab, "%ld%ld%ld", + &chavertnbr, + &chaedgenbr, + &chaflagval) < 2)) { + errorPrint ("graphGeomLoadChac: bad input (1)"); + return (1); + } + getc (filesrcptr); /* Purge newline (cannot be merged with above fscanf) */ + + chaflagstr[0] = /* Pre-set flag array */ + chaflagstr[1] = + chaflagstr[2] = + chaflagstr[3] = '\0'; + chaflagstr[0] = '0' + ((chaflagval / 100) % 10); /* Set the flags */ + chaflagstr[1] = '0' + ((chaflagval / 10) % 10); + chaflagstr[2] = '0' + ((chaflagval) % 10); + + grafptr->flagval = GRAPHFREETABS; + grafptr->baseval = 1; /* Chaco graphs are based */ + grafptr->vertnbr = chavertnbr; + grafptr->vertnnd = chavertnbr + 1; + grafptr->edgenbr = chaedgenbr * 2; /* We are counting arcs */ + if (((grafptr->verttax = (Gnum *) memAlloc (grafptr->vertnnd * sizeof (Gnum))) == NULL) || + ((grafptr->edgetax = (Gnum *) memAlloc (grafptr->edgenbr * sizeof (Gnum))) == NULL)) { + errorPrint ("graphGeomLoadChac: out of memory (1)"); + if (grafptr->verttax != NULL) + memFree (grafptr->verttax); + return (1); + } + grafptr->edgetax -= grafptr->baseval; + grafptr->verttax -= grafptr->baseval; + grafptr->vendtax = grafptr->verttax + 1; + + if (chaflagstr[0] != '0') { + if ((grafptr->vlbltax = (Gnum *) memAlloc (chavertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("graphGeomLoadChac: out of memory (2)"); + memFree (grafptr); + return (1); + } + grafptr->vlbltax -= grafptr->baseval; + } + + velosum = grafptr->vertnbr; /* Assume no vertex loads */ + if (chaflagstr[1] != '0') { + if ((grafptr->velotax = (Gnum *) memAlloc (chavertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("graphGeomLoadChac: out of memory (3)"); + memFree (grafptr); + return (1); + } + grafptr->velotax -= grafptr->baseval; + velosum = 0; + } + + edlosum = grafptr->edgenbr; + if (chaflagstr[2] != '0') { + if ((grafptr->edlotax = (Gnum *) memAlloc (grafptr->edgenbr * sizeof (Gnum))) == NULL) { + errorPrint ("graphGeomLoadChac: out of memory (4)"); + memFree (grafptr); + return (1); + } + grafptr->edlotax -= grafptr->baseval; + edlosum = 0; + } + + for (vertnum = edgenum = grafptr->baseval, degrmax = vlblmax = 0; + vertnum < grafptr->vertnnd; vertnum ++) { + do { /* Skip comment lines */ + chabuffcar = getc (filesrcptr); /* Read first character */ + if (chabuffcar == '%') { /* If comment line */ + fscanf (filesrcptr, "%*[^\n]"); /* Purge line */ + getc (filesrcptr); /* Purge newline */ + } + } while (chabuffcar == '%'); + ungetc (chabuffcar, filesrcptr); /* Put character back to filesrcptr */ + + if (grafptr->vlbltax != NULL) { + if ((intLoad (filesrcptr, &grafptr->vlbltax[vertnum]) != 1) || + (grafptr->vlbltax[vertnum] < 1) || + (grafptr->vlbltax[vertnum] > chavertnbr)) { + errorPrint ("graphGeomLoadChac: bad input (2)"); + graphFree (grafptr); + return (1); + } + if (grafptr->vlbltax[vertnum] > vlblmax) + vlblmax = grafptr->vlbltax[vertnum]; + } + if (grafptr->velotax != NULL) { + if ((intLoad (filesrcptr, &grafptr->velotax[vertnum]) != 1) || + (grafptr->velotax[vertnum] < 1)) { + errorPrint ("graphGeomLoadChac: bad input (3)"); + graphFree (grafptr); + return (1); + } + velosum += grafptr->velotax[vertnum]; + } + grafptr->verttax[vertnum] = edgenum; /* Set based edge array index */ + + while (1) { /* Read graph edges */ + fscanf (filesrcptr, "%*[ \t\r]"); /* Skip white spaces except '\n' */ + chabuffcar = getc (filesrcptr); /* Read next char */ + if (chabuffcar == EOF) /* If end of file reached */ + chabuffcar = '\n'; /* Indicate line as complete */ + if (chabuffcar == '\n') /* Exit loop if line is complete */ + break; + + ungetc (chabuffcar, filesrcptr); /* Else put character back to stream */ + + if ((intLoad (filesrcptr, &chavertnum) != 1) || + (chavertnum < 1) || + (chavertnum > chavertnbr) || + ((grafptr->edlotax != NULL) && + ((intLoad (filesrcptr, &grafptr->edlotax[edgenum]) != 1) || + (edlosum += grafptr->edlotax[edgenum], grafptr->edlotax[edgenum] < 1)))) { + errorPrint ("graphGeomLoadChac: bad input (4)"); + graphFree (grafptr); + return (1); + } + if (edgenum > (grafptr->edgenbr + grafptr-> baseval)) { /* Test edge array overflow */ + errorPrint ("graphGeomLoadChac: bad input (5)"); + graphFree (grafptr); + return (1); + } + grafptr->edgetax[edgenum ++] = chavertnum; + } + + if ((edgenum - grafptr->verttax[vertnum]) > degrmax) + degrmax = edgenum - grafptr->verttax[vertnum]; + } + grafptr->verttax[vertnum] = edgenum; /* Set end of based vertex array */ + grafptr->velosum = velosum; + grafptr->edlosum = edlosum; + grafptr->degrmax = degrmax; + + if (grafptr->vlbltax != NULL) { /* If graph has labels */ + if (graphLoad2 (grafptr->baseval, grafptr->vertnnd, /* Un-label graph data */ + grafptr->verttax, grafptr->vendtax, + grafptr->edgetax, vlblmax, grafptr->vlbltax) != 0) { + errorPrint ("graphGeomLoadChac: cannot relabel graph"); + graphFree (grafptr); + return (1); + } + } + +#ifdef SCOTCH_DEBUG_GRAPH2 + if (graphCheck (grafptr) != 0) { /* Check graph consistency */ + errorPrint ("graphGeomLoadChac: internal error"); + graphFree (grafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + return (0); +} + +/* This routine saves the geometrical graph +** in the Chaco graph format. +** It returns: +** - 0 : on succes +** - !0 : on error. +*/ + +int +graphGeomSaveChac ( +const Graph * restrict const grafptr, /* Graph to save */ +const Geom * restrict const geomptr, /* Geometry to save */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* No use */ +{ + Gnum baseadj; /* Base adjustment */ + Gnum vertnum; /* Current vertex */ + Gnum edgenum; /* Current edge */ + char * sepaptr; /* Separator string */ + int o; + + baseadj = 1 - grafptr->baseval; /* Output base is always 1 */ + + o = (fprintf (filesrcptr, GNUMSTRING "\t" GNUMSTRING "\t%c%c%c\n", /* Write graph header */ + (Gnum) grafptr->vertnbr, + (Gnum) (grafptr->edgenbr / 2), + ((grafptr->vlbltax != NULL) ? '1' : '0'), + ((grafptr->velotax != NULL) ? '1' : '0'), + ((grafptr->edlotax != NULL) ? '1' : '0')) < 0); + + for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) { + sepaptr = ""; /* Start lines as is */ + + if (grafptr->vlbltax != NULL) { + o |= (fprintf (filesrcptr, GNUMSTRING, (Gnum) (grafptr->vlbltax[vertnum] + baseadj)) < 0); + sepaptr = "\t"; + } + if (grafptr->velotax != NULL) { + o |= (fprintf (filesrcptr, "%s" GNUMSTRING, + sepaptr, + (Gnum) grafptr->velotax[vertnum]) < 0); + sepaptr = "\t"; + } + + for (edgenum = grafptr->verttax[vertnum]; + (o == 0) && (edgenum < grafptr->vendtax[vertnum]); edgenum ++) { + if (grafptr->vlbltax != NULL) + o |= (fprintf (filesrcptr, "%s" GNUMSTRING, + sepaptr, + (Gnum) (grafptr->vlbltax[grafptr->edgetax[edgenum]] + baseadj)) < 0); + else + o |= (fprintf (filesrcptr, "%s" GNUMSTRING, + sepaptr, + (Gnum) (grafptr->edgetax[edgenum] + baseadj)) < 0); + + if (grafptr->edlotax != NULL) + o |= (fprintf (filesrcptr, " " GNUMSTRING, (Gnum) grafptr->edlotax[edgenum]) < 0); + + sepaptr = "\t"; + } + o |= (fprintf (filesrcptr, "\n") < 0); + } + if (o != 0) + errorPrint ("graphGeomSaveChac: bad output"); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/graph_io_habo.c b/scotch_6.0.3/src/libscotch/graph_io_habo.c new file mode 100644 index 00000000..121f6d3c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io_habo.c @@ -0,0 +1,424 @@ +/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io_habo.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the I/O routines **/ +/** for handling the Harwell-Boeing matrix **/ +/** format. **/ +/** **/ +/** DATES : # Version 3.2 : from : 06 nov 1997 **/ +/** to 26 may 1998 **/ +/** # Version 3.3 : from : 13 dec 1998 **/ +/** to 24 dec 1998 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 21 mar 2005 **/ +/** # Version 5.0 : from : 06 jun 2007 **/ +/** to 31 aug 2007 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to 27 apr 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_IO_HABO + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "graph_io_habo.h" + +/* This routine loads the geometrical graph +** in the Harwell-Boeing matrix format, and +** allocates the proper structures. +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphGeomLoadHabo ( +Graph * restrict const grafptr, /* Graph to load */ +Geom * restrict const geomptr, /* Geometry to load */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* Tag value */ +{ + Gnum habmattag; /* Matrix tag number in file */ + Gnum habmatnum; /* Current matrix number */ + char habmatbuf[4][84]; /* Matrix header line buffers */ + char habmattype[3]; /* Matrix type */ + Gnum habcrdnbr; /* Total number of data lines */ + Gnum habrhsnbr; /* Number of right hand side lines */ + Gnum habrownbr; /* Number of rows */ + GraphGeomHaboLine habcolfmt; /* Format of column line */ + int habvalnum; /* Number of value in line */ + Gnum habcolnbr; /* Number of columns */ + Gnum habcolnum; /* Number of current column index */ + Gnum * restrict habcoltab; /* Index array */ + GraphGeomHaboLine habnzrfmt; /* Format of non-zero type */ + Gnum habnzrnbr; /* Number of non-zero indices */ + Gnum habnzrnum; /* Number of current row data */ + Gnum * restrict habnzrtab; /* Row data array */ + GraphGeomHaboHash * restrict hashtab; /* Neighbor hash table */ + Gnum hashmsk; /* Mask for access to hash table */ + Gnum vertnum; /* Number of current vertex */ + Gnum edgenum; /* Number of current edge (arc) */ + Gnum edgeold; /* Number of non-purged edge */ + Gnum edgetmp; /* Temporary edge number */ + Gnum degrmax; /* Maximum degree */ + int c; + + if ((dataptr != NULL) && /* If tag value provided */ + (dataptr[0] != '\0') && + ((habmattag = (Gnum) atol (dataptr)) == 0) && /* Get tag value */ + (dataptr[0] != '0')) { + errorPrint ("graphGeomLoadHabo: invalid parameter"); + return (1); + } + + habmattype[0] = + habmattype[1] = + habmattype[2] = '\0'; + for (habmatnum = 0; habmatnum <= habmattag; habmatnum ++) { /* Read headers and skip if necessary */ + memSet (habmatbuf[0], ' ', &habmatbuf[3][83] - &habmatbuf[0][0]); /* Initialize header buffers */ + if ((fgets (habmatbuf[0], 83, filesrcptr) == NULL) || /* Read graph header */ + (fgets (habmatbuf[1], 83, filesrcptr) == NULL) || + (fgets (habmatbuf[2], 83, filesrcptr) == NULL) || + (fgets (habmatbuf[3], 83, filesrcptr) == NULL)) { + errorPrint ("graphGeomLoadHabo: bad input (1)"); + return (1); + } + habmatbuf[1][70] = '\0'; /* Extract header values */ + habrhsnbr = (Gnum) atol (&habmatbuf[1][56]); + habmatbuf[1][14] = '\0'; + habcrdnbr = (Gnum) atol (&habmatbuf[1][00]); + habmattype[0] = toupper (habmatbuf[2][0]); + habmattype[1] = toupper (habmatbuf[2][1]); + habmattype[2] = toupper (habmatbuf[2][2]); + habmatbuf[2][56] = '\0'; + habnzrnbr = (Gnum) atol (&habmatbuf[2][43]); + habmatbuf[2][42] = '\0'; + habcolnbr = (Gnum) atol (&habmatbuf[2][29]); + habmatbuf[2][28] = '\0'; + habrownbr = (Gnum) atol (&habmatbuf[2][14]); + + habmatbuf[3][32] = '\0'; + if (graphGeomLoadHaboFormat (&habnzrfmt, &habmatbuf[3][16]) != 0) { + errorPrint ("graphGeomLoadHabo: bad input (2)"); + return (1); + } + habmatbuf[3][16] = '\0'; + if (graphGeomLoadHaboFormat (&habcolfmt, &habmatbuf[3][0]) != 0) { + errorPrint ("graphGeomLoadHabo: bad input (3)"); + return (1); + } + + if (habrhsnbr != 0) { + while ((c = getc (filesrcptr)) != '\n'){ /* Skip RHS format line */ + if (c == EOF) { + errorPrint ("graphGeomLoadHabo: bad input (4)"); + return (1); + } + } + } + + if (habmatnum < habmattag) { /* If we have to skip file */ + while (habcrdnbr -- > 0) { /* Skip all of file lines */ + while ((c = getc (filesrcptr)) != '\n') { /* Skip line */ + if (c == EOF) { + errorPrint ("graphGeomLoadHabo: bad input (5)"); + return (1); + } + } + } + } + } + + if (habmattype[2] != 'A') { + errorPrint ("graphGeomLoadHabo: only assembled matrices supported; for unassembled matrices, use the mesh version of the tools"); + return (1); + } + if (habmattype[1] == 'R') { + errorPrint ("graphGeomLoadHabo: rectangular matrices not supported"); + return (1); + } + + if (((grafptr->verttax = (Gnum *) memAlloc ((habcolnbr + 1) * sizeof (Gnum))) == NULL) || + ((grafptr->edgetax = (Gnum *) memAllocGroup ((void **) (void *) + &grafptr->edgetax, (size_t) (habnzrnbr * 2 * sizeof (Gnum)), + &habcoltab, (size_t) ((habcolnbr + 1) * sizeof (Gnum)), + &habnzrtab, (size_t) (habnzrnbr * sizeof (Gnum)), NULL)) == NULL)) { + errorPrint ("graphGeomLoadHabo: out of memory (1)"); + if (grafptr->verttax != NULL) { + memFree (grafptr->verttax); + grafptr->verttax = NULL; + } + return (1); + } + grafptr->flagval = GRAPHFREETABS; /* Totally new graph structure */ + grafptr->baseval = 1; /* Harwell-Boeing graphs have base 1 */ + grafptr->vertnbr = (Gnum) habcolnbr; + grafptr->vertnnd = grafptr->vertnbr + 1; + grafptr->velosum = grafptr->vertnbr; + grafptr->vendtax = grafptr->verttax; /* Use compact representation for array based at 1 */ + grafptr->verttax --; /* Base verttab array at 1, with vendtab = verttab + 1 */ + grafptr->edgetax --; + + ungetc ('\n', filesrcptr); /* Create fake previous line */ + for (habcolnum = 0, habvalnum = habcolfmt.datanbr; /* Eat up fake previous line */ + habcolnum <= habcolnbr; habcolnum ++) { /* Read column indices */ + Gnum habcolval; /* Current column value */ + int habcolidx; /* Current index in column value */ + + c = getc (filesrcptr); + if (habvalnum ++ >= habcolfmt.datanbr) { /* If all useful data read from line */ + habvalnum = 1; /* Start at beginning of new line */ + + while ((c != '\n') && (c != '\r')) /* Eat up all remaining spaces */ + c = getc (filesrcptr); + while (((c = getc (filesrcptr)) == '\n') || (c == '\r')) ; /* Read till end of line */ + + for (habcolidx = 0; habcolidx < habcolfmt.strtnbr; habcolidx ++) /* Get start of line */ + c = getc (filesrcptr); + } + + habcolval = (c == ' ') ? 0 : (c - '0'); + for (habcolidx = 1; habcolidx < habcolfmt.datalen; habcolidx ++) { + if ((c = getc (filesrcptr)) != ' ') + habcolval = habcolval * 10 + c - '0'; + } + if (c == EOF) { + errorPrint ("graphGeomLoadHabo: bad input (6)"); + graphFree (grafptr); + return (1); + } + habcoltab[habcolnum] = habcolval; + } + if (habcoltab[habcolnbr] != (Gnum) habnzrnbr + 1) { + errorPrint ("graphGeomLoadHabo: bad input (7)"); + graphFree (grafptr); + return (1); + } + + memSet (grafptr->vendtax, 0, habcolnbr * sizeof (Gnum)); /* Here, vendtax = verttab */ + + for (vertnum = 1, habnzrnum = 0, habvalnum = habnzrfmt.datanbr; /* Start by eating end of previous line */ + vertnum < grafptr->vertnnd; vertnum ++) { /* Read matrix pattern */ + for ( ; habnzrnum < (habcoltab[vertnum] - 1); habnzrnum ++) { /* All right since vertnum is based at 1 */ + Gnum habnzrval; /* Current non-zero value */ + int habnzridx; /* Current index in non-zero value */ + + c = getc (filesrcptr); + if (habvalnum ++ >= habnzrfmt.datanbr) { /* If all useful data read from line */ + habvalnum = 1; /* Start at beginning of new line */ + + while ((c != '\n') && (c != '\r')) /* Eat up all remaining spaces */ + c = getc (filesrcptr); + while (((c = getc (filesrcptr)) == '\n') || (c == '\r')) ; /* Read till end of line */ + + for (habnzridx = 0; habnzridx < habnzrfmt.strtnbr; habnzridx ++) /* Get start of line */ + c = getc (filesrcptr); + } + habnzrval = (c == ' ') ? 0 : (c - '0'); + for (habnzridx = 1; habnzridx < habnzrfmt.datalen; habnzridx ++) { + if ((c = getc (filesrcptr)) != ' ') + habnzrval = habnzrval * 10 + c - '0'; + } + if (c == EOF) { + errorPrint ("graphGeomLoadHabo: bad input (8)"); + graphFree (grafptr); + return (1); + } + habnzrtab[habnzrnum] = habnzrval; + if (habnzrval != vertnum) { /* If not loop edge */ + grafptr->verttax[vertnum] ++; /* Account for arc */ + grafptr->verttax[habnzrval] ++; /* Add arc to symmetrize */ + } + } + } + + degrmax = 1; + for (vertnum = edgenum = 1; vertnum < grafptr->vertnnd; vertnum ++) { /* Build (superset of) vertex array */ + Gnum edgetmp; + + edgetmp = grafptr->verttax[vertnum]; + grafptr->verttax[vertnum] = edgenum; + edgenum += edgetmp; + if (edgetmp > degrmax) /* Update bound on maximum degree */ + degrmax = edgetmp; + } + grafptr->verttax[vertnum] = edgenum; /* Set end of vertex array */ + + for (vertnum = 1, habnzrnum = 0; vertnum < grafptr->vertnnd; vertnum ++) { /* Build (superset of) edge array */ + for ( ; habnzrnum < (habcoltab[vertnum] - 1); habnzrnum ++) { + Gnum vertend; /* Number of end vertex */ + + vertend = habnzrtab[habnzrnum]; + if (vertend != vertnum) { /* If not loop edge */ + grafptr->edgetax[grafptr->verttax[vertnum] ++] = vertend; /* Build arc */ + grafptr->edgetax[grafptr->verttax[vertend] ++] = vertnum; /* Symmetrize */ + } + } + } + + for (hashmsk = 31; hashmsk < degrmax; hashmsk = hashmsk * 2 + 1) ; /* Set neighbor hash table size */ + hashmsk = hashmsk * 4 + 3; + + if ((hashtab = (GraphGeomHaboHash *) memAlloc ((hashmsk + 1) * sizeof (GraphGeomHaboHash))) == NULL) { + errorPrint ("graphGeomLoadHabo: out of memory (2)"); + graphFree (grafptr); + return (1); + } + memSet (hashtab, ~0, (hashmsk + 1) * sizeof (GraphGeomHaboHash)); /* Pre-set hash table */ + + degrmax = 1; + for (vertnum = edgetmp = edgenum = 1; vertnum < grafptr->vertnnd; vertnum ++) { /* Remove duplicates from edge array */ + for (edgeold = edgetmp, edgetmp = grafptr->verttax[vertnum], grafptr->verttax[vertnum] = edgenum; + edgeold < edgetmp; edgeold ++) { + Gnum vertend; /* Number of end vertex */ + Gnum hashnum; /* Current hash index */ + + vertend = grafptr->edgetax[edgeold]; + for (hashnum = (vertend * GRAPHGEOMHABOHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + if (hashtab[hashnum].vertnum != vertnum) { /* If edge not found */ + hashtab[hashnum].vertnum = vertnum; + hashtab[hashnum].vertend = vertend; + grafptr->edgetax[edgenum ++] = vertend; + break; + } + if (hashtab[hashnum].vertend == vertend) /* Do not add duplicate edges */ + break; + } + } + if ((edgenum - grafptr->verttax[vertnum]) > degrmax) /* Set real maximum degree */ + degrmax = edgenum - grafptr->verttax[vertnum]; + } + grafptr->verttax[vertnum] = edgenum; /* Set end of vertex array */ + + grafptr->edgenbr = edgenum - 1; + grafptr->edlosum = grafptr->edgenbr; + grafptr->degrmax = degrmax; + + memFree (hashtab); + + grafptr->edgetax = ((Gnum *) memRealloc (grafptr->edgetax + 1, grafptr->edgenbr * sizeof (Gnum))) - 1; + +#ifdef SCOTCH_DEBUG_GRAPH2 + if (graphCheck (grafptr) != 0) { /* Check graph consistency */ + errorPrint ("graphGeomLoadHabo: internal error"); + graphFree (grafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + return (0); +} + +/* This routine reads a Fortran format structure +** and returns the size of the integers to read. +*/ + +static +int +graphGeomLoadHaboFormat ( +GraphGeomHaboLine * restrict const lineptr, /* Line format to fill */ +const char * const dataptr) /* Format string */ +{ + const char * restrict charptr; + int number; /* Number to read */ + + lineptr->strtnbr = + lineptr->datanbr = + lineptr->datalen = 0; + for (charptr = dataptr; ; charptr ++) { /* Skip to first '(' */ + if (*charptr == '(') + break; + if (*charptr == '\0') /* Error if end of string */ + return (1); + } + + number = 0; /* Read number */ + for (charptr ++ ; ; charptr ++) { + if (*charptr == '\0') /* Error if end of string */ + return (1); + if (! isdigit ((int) (unsigned char) *charptr)) + break; + number = number * 10 + *charptr - '0'; + } + + if ((*charptr == 'x') || (*charptr == 'X')) { /* If dummy characters at beginning of line */ + lineptr->strtnbr = number; + for (charptr ++; ; charptr ++) { /* Skip to first ',' */ + if (*charptr == '\0') /* Error if end of string */ + return (1); + if (*charptr == ',') + break; + } + + number = 0; /* Read number */ + for (charptr ++; *charptr != '\0'; charptr ++) { + if (*charptr == '\0') /* Error if end of string */ + return (1); + if (! isdigit (*charptr < '0')) + break; + number = number * 10 + *charptr - '0'; + } + } + + if ((*charptr != 'I') && (*charptr != 'i')) /* If not integer specification */ + return (1); + + lineptr->datanbr = number; + + number = 0; /* Read size of integer */ + for (charptr ++; ; charptr ++) { + if (*charptr == '\0') /* Error if end of string */ + return (1); + if (! isdigit ((int) (unsigned char) *charptr)) + break; + number = number * 10 + *charptr - '0'; + } + + if (number == 0) + return (1); + + lineptr->datalen = number; + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/graph_io_habo.h b/scotch_6.0.3/src/libscotch/graph_io_habo.h new file mode 100644 index 00000000..f259936b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io_habo.h @@ -0,0 +1,92 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io_habo.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the Harwell-Boeing matrix **/ +/** format I/O module. **/ +/** **/ +/** DATES : # Version 3.2 : from : 06 nov 1997 **/ +/** to 06 nov 1997 **/ +/** # Version 3.3 : from : 13 dec 1998 **/ +/** to 15 dec 1998 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 19 jan 2004 **/ +/** # Version 5.0 : from : 06 jun 2007 **/ +/** to 06 jun 2007 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to 09 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Prime number for hashing vertex numbers. +*/ + +#define GRAPHGEOMHABOHASHPRIME 7 /*+ Prime number +*/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds neighbor vertex hashing data. +*/ + +typedef struct GraphGeomHaboHash_ { + Gnum vertnum; /*+ Origin vertex (i.e. pass) number +*/ + Gnum vertend; /*+ Adjacent end vertex number +*/ +} GraphGeomHaboHash; + +/*+ This structure holds line formats for reading input data +*/ + +typedef struct GraphGeomHaboLine_ { + int strtnbr; /*+ Number of starting blank characters +*/ + int datanbr; /*+ Number of integers par line +*/ + int datalen; /*+ Number of characters per integer +*/ +} GraphGeomHaboLine; + +/* +** The function prototypes. +*/ + +#ifndef GRAPH_IO_HABO +#define static +#endif + +static int graphGeomLoadHaboFormat (GraphGeomHaboLine * restrict const, const char * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/graph_io_mmkt.c b/scotch_6.0.3/src/libscotch/graph_io_mmkt.c new file mode 100644 index 00000000..9fe27708 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io_mmkt.c @@ -0,0 +1,311 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io_mmkt.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : This module contains the input/output **/ +/** routines for handling the Matrix Market **/ +/** format. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 jan 2008 **/ +/** to : 21 mar 2008 **/ +/** # Version 5.1 : from : 27 apr 2010 **/ +/** to : 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_IO_MMKT + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "graph_io_mmkt.h" + +/********************************************************/ +/* */ +/* These routines handle source Matrix Market matrices. */ +/* */ +/********************************************************/ + +/* This routine loads a source graph from +** the given stream, corresponding to a MatrixMarket file. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphGeomLoadMmkt ( +Graph * restrict const grafptr, /* Graph to load */ +Geom * restrict const geomptr, /* Geometry to load */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* Fake base value */ +{ + Gnum baseval; + Gnum mrownbr; + Gnum mcolnbr; + Gnum linenbr; + Gnum linenum; + Gnum vertnum; + Gnum verttmp; + GraphGeomMmktEdge * sorttab; + Gnum sortnbr; + Gnum sortnum; + Gnum * edgetax; + Gnum edgenum; + Gnum edgetmp; + Gnum degrmax; + char linetab[1025]; + char * lineptr; + char c; + + baseval = 1; /* Regular MatrixMarket indices start from 1 */ + + if ((dataptr != NULL) && /* If base value provided */ + (dataptr[0] != '\0') && + ((baseval = (Gnum) atol (dataptr)) == 0) && /* Get base value */ + (dataptr[0] != '0')) { + errorPrint ("graphGeomLoadMmkt: invalid parameter"); + return (1); + } + + if (fgets (linetab, 1025, filesrcptr) == NULL) { /* Read header lines */ + errorPrint ("graphGeomLoadMmkt: bad input (1)"); + return (1); + } + if (strncmp (linetab, "%%MatrixMarket", 14) != 0) { + errorPrint ("graphGeomLoadMmkt: invalid header"); + return (1); + } + + for (lineptr = linetab + 14; *lineptr != '\0'; lineptr ++) + *lineptr = tolower (*lineptr); + + if (strstr (linetab + 14, "matrix") == NULL) { + errorPrint ("graphGeomLoadMmkt: only matrix types supported"); + return (1); + } + + while ((c = fgetc (filesrcptr)) == '%') { /* Skip additional comment lines */ + if (fgets (linetab, 1025, filesrcptr) == NULL) { + errorPrint ("graphGeomLoadMmkt: bad input (2)"); + return (1); + } + } + ungetc (c, filesrcptr); + + if ((intLoad (filesrcptr, &mrownbr) != 1) || /* Read number of rows */ + (intLoad (filesrcptr, &mcolnbr) != 1) || /* Read number of columns */ + (intLoad (filesrcptr, &linenbr) != 1)) { /* Read number of lines */ + errorPrint ("graphGeomLoadMmkt: bad input (3)"); + return (1); + } + if (mrownbr != mcolnbr) { /* If not a square matrix */ + errorPrint ("graphGeomLoadMmkt: not a square matrix"); + return (1); + } + + memSet (grafptr, 0, sizeof (Graph)); + + grafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; + grafptr->baseval = baseval; + grafptr->vertnbr = mrownbr; + grafptr->vertnnd = grafptr->vertnbr + baseval; + + if ((grafptr->verttax = memAlloc ((grafptr->vertnbr + 1) * sizeof (Gnum))) == NULL) { + errorPrint ("graphGeomLoadMmkt: out of memory (1)"); + graphExit (grafptr); + return (1); + } + grafptr->verttax -= baseval; + grafptr->vendtax = grafptr->verttax + 1; + grafptr->velosum = grafptr->vertnbr; + + if ((sorttab = (GraphGeomMmktEdge *) memAlloc (2 * linenbr * sizeof (GraphGeomMmktEdge))) == NULL) { /* Twice the space for symmetric edges */ + errorPrint ("graphGeomLoadMmkt: out of memory (2)"); + graphExit (grafptr); + return (1); + } + grafptr->edgetax = ((Gnum *) sorttab) - baseval; /* TRICK: will be freed if graph is freed */ + + for (linenum = sortnbr = 0; linenum < linenbr; linenum ++) { + if ((intLoad (filesrcptr, &sorttab[sortnbr].vertnum[0]) != 1) || /* Read edge ends */ + (intLoad (filesrcptr, &sorttab[sortnbr].vertnum[1]) != 1) || + (fgets (linetab, 1025, filesrcptr) == NULL)) { /* Skip end of line */ + errorPrint ("graphGeomLoadMmkt: bad input (4)"); + graphExit (grafptr); + return (1); + } + + if ((sorttab[sortnbr].vertnum[0] < baseval) || (sorttab[sortnbr].vertnum[0] >= (mrownbr + baseval)) || + (sorttab[sortnbr].vertnum[1] < baseval) || (sorttab[sortnbr].vertnum[1] >= (mrownbr + baseval))) { + errorPrint ("graphGeomLoadMmkt: bad input (5)"); + graphExit (grafptr); + return (1); + } + + if (sorttab[sortnbr].vertnum[0] != sorttab[sortnbr].vertnum[1]) { /* If not loop edge */ + sorttab[sortnbr + 1].vertnum[0] = sorttab[sortnbr].vertnum[1]; /* Add symmetric edge */ + sorttab[sortnbr + 1].vertnum[1] = sorttab[sortnbr].vertnum[0]; + sortnbr += 2; + } + } + + intSort2asc2 (sorttab, sortnbr); /* Sort edges by increasing indices */ + + edgetax = grafptr->edgetax; /* TRICK: point to beginning of sorted edge array for re-use */ + for (sortnum = degrmax = 0, vertnum = baseval - 1, edgetmp = edgenum = baseval; + sortnum < sortnbr; sortnum ++) { + Gnum vertend; + + if (vertnum < sorttab[sortnum].vertnum[0]) { /* If change of vertex index, that is, first edge end */ + edgetmp = edgenum - edgetmp; /* Compute degree and see if it is maximum degree */ + if (edgetmp > degrmax) + degrmax = edgetmp; + edgetmp = edgenum; + + grafptr->verttax[++ vertnum] = edgenum; /* Set beginning of new edge sub-array */ + + while (vertnum < sorttab[sortnum].vertnum[0]) /* Fill gaps with isolated vertices */ + grafptr->verttax[++ vertnum] = edgenum; + + verttmp = baseval - 1; /* Make sure next edge will be considered as never seen before */ + } + + vertend = sorttab[sortnum].vertnum[1]; /* Get end of current edge */ + if (vertend != verttmp) /* If edge differs from previous one */ + edgetax[edgenum ++] = verttmp = vertend; /* Add it to array and prevent duplicates */ + } + edgetmp = edgenum - edgetmp; /* Compute degree and see if it is maximum degree */ + if (edgetmp > degrmax) + degrmax = edgetmp; + while (vertnum < mrownbr) /* Fill gaps with isolated vertices and mark beginning of new one */ + grafptr->verttax[++ vertnum] = edgenum; + grafptr->verttax[++ vertnum] = edgenum; /* Mark end of array */ + +#ifdef SCOTCH_DEBUG_GRAPH2 + if (vertnum != grafptr->vertnnd) { + errorPrint ("graphGeomLoadMmkt: internal error (1)"); + graphExit (grafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + grafptr->edgenbr = edgenum - baseval; + grafptr->edgetax = ((Gnum *) memRealloc (edgetax + baseval, grafptr->edgenbr * sizeof (Gnum))) - baseval; /* TRICK: keep only useful space in re-used array */ + grafptr->edlotax = NULL; + grafptr->edlosum = grafptr->edgenbr; + grafptr->degrmax = degrmax; + +#ifdef SCOTCH_DEBUG_GRAPH2 + if (graphCheck (grafptr) != 0) { /* Check graph consistency */ + errorPrint ("graphGeomLoadMmkt: internal error (2)"); + graphExit (grafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + return (0); +} + +/* This routine saves the geometrical graph +** in the Matrix Market symmetric graph format. +** It returns: +** - 0 : on succes +** - !0 : on error. +*/ + +int +graphGeomSaveMmkt ( +const Graph * restrict const grafptr, /* Graph to save */ +const Geom * restrict const geomptr, /* Geometry to save */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* No use */ +{ + Gnum baseadj; /* Base adjustment */ + Gnum vertnum; /* Current vertex */ + Gnum edgenum; /* Current edge */ + int o; + + baseadj = 1 - grafptr->baseval; /* Output base is always 1 */ + + o = (fprintf (filesrcptr, "%%%%MatrixMarket matrix coordinate pattern symmetric\n%% Produced by Scotch graphGeomSaveMmkt\n" GNUMSTRING " " GNUMSTRING " " GNUMSTRING "\n", /* Write graph header */ + (Gnum) grafptr->vertnbr, + (Gnum) grafptr->vertnbr, + (Gnum) ((grafptr->edgenbr / 2) + grafptr->vertnbr)) == EOF); + + for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) { + Gnum vlblnum; /* Vertex label to output */ + + vlblnum = ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum) + baseadj; + + if (fprintf (filesrcptr, GNUMSTRING " " GNUMSTRING "\n", /* Write diagonal term */ + (Gnum) vlblnum, + (Gnum) vlblnum) < 0) { + o = 1; + break; + } + + for (edgenum = grafptr->verttax[vertnum]; edgenum < grafptr->vendtax[vertnum]; edgenum ++) { + Gnum vlblend; /* End vertex label to output */ + + vlblend = grafptr->edgetax[edgenum]; + if (grafptr->vlbltax != NULL) + vlblend = grafptr->vlbltax[vlblend]; + vlblend += baseadj; + + if (vlblend < vlblnum) { + if (fprintf (filesrcptr, GNUMSTRING " " GNUMSTRING "\n", + (Gnum) vlblnum, + (Gnum) vlblend) < 0) { + o = 1; + break; + } + } + } + } + if (o != 0) + errorPrint ("graphGeomSaveMmkt: bad output"); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/graph_io_mmkt.h b/scotch_6.0.3/src/libscotch/graph_io_mmkt.h new file mode 100644 index 00000000..2479bbcc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io_mmkt.h @@ -0,0 +1,55 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io_mmkt.h **/ +/** **/ +/** AUTHORS : Cedric CHEVALIER (v5.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the Input routines **/ +/** for handling the Matrix Market format. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 jan 2008 **/ +/** to : 14 mar 2008 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/* Structure representing edges to symmetrize. */ + +typedef struct GraphGeomMmktEdge_ { + Gnum vertnum[2]; +} GraphGeomMmktEdge; diff --git a/scotch_6.0.3/src/libscotch/graph_io_scot.c b/scotch_6.0.3/src/libscotch/graph_io_scot.c new file mode 100644 index 00000000..2f05b92e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io_scot.c @@ -0,0 +1,272 @@ +/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io_scot.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the I/O routines **/ +/** for handling the Scotch graph format. **/ +/** **/ +/** DATES : # Version 3.2 : from : 06 nov 1997 **/ +/** to 26 may 1998 **/ +/** # Version 3.3 : from : 13 dec 1998 **/ +/** to 21 dec 1998 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 22 dec 2005 **/ +/** # Version 5.0 : from : 13 sep 2006 **/ +/** to 27 feb 2008 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_IO_SCOT + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "graph_io_scot.h" + +/* This routine loads the geometrical graph +** in the Scotch graph format, and allocates +** the proper structures. +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphGeomLoadScot ( +Graph * restrict const grafptr, /* Graph to load */ +Geom * restrict const geomptr, /* Geometry to load */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* No use */ +{ + void * coorfileptr; /* Temporary pointer to comply with C99 rules */ + double * restrict coorfiletab; /* Pointer to geometric data read from file */ + GraphGeomScotSort * restrict coorsorttab; /* Pointer to geometric data sorting array */ + int coorsortflag; /* Flag set if geometric data sorted by label */ + Gnum coornbr; /* Number of geometric coordinates in file */ + Gnum coornum; /* Number of current coordinate */ + GraphGeomScotSort * restrict vertsorttab; /* Pointer to graph sorting array */ + int vertsortflag; /* Flag set if graph data sorted by label */ + Gnum vertnum; /* Current graph vertex */ + Gnum dimnnbr; /* Dimension of geometry file */ + int o; + + if (filesrcptr != NULL) { + if (graphLoad (grafptr, filesrcptr, -1, 0) != 0) + return (1); + } + + if (filegeoptr == NULL) + return (0); + + if ((intLoad (filegeoptr, &dimnnbr) != 1) || /* Read type and number of geometry items */ + (intLoad (filegeoptr, &coornbr) != 1) || + (dimnnbr < 1) || + (dimnnbr > 3)) { + errorPrint ("graphGeomLoadScot: bad input (1)"); + return (1); + } + if ((filesrcptr != NULL) && (grafptr->vertnbr != coornbr)) { + errorPrint ("graphGeomLoadScot: inconsistent number of vertices"); + return (1); + } + + if (grafptr->vertnbr == 0) + return (0); + + if ((geomptr->geomtab == NULL) && /* Allocate geometry if necessary */ + ((geomptr->geomtab = (double *) memAlloc (grafptr->vertnbr * dimnnbr * sizeof (double))) == NULL)) { + errorPrint ("graphGeomLoadScot: out of memory (1)"); + return (1); + } + + if (memAllocGroup ((void **) + &coorfileptr, (size_t) (coornbr * dimnnbr * sizeof (double)), + &coorsorttab, (size_t) (coornbr * sizeof (GraphGeomScotSort)), + &vertsorttab, (size_t) (grafptr->vertnbr * sizeof (GraphGeomScotSort)), NULL) == NULL) { + errorPrint ("graphGeomLoadScot: out of memory (2)"); + return (1); + } + coorfiletab = coorfileptr; + + o = 0; + coorsortflag = 1; /* Assume geometry data sorted */ + for (coornum = 0; (o == 0) && (coornum < coornbr); coornum ++) { + Gnum vlblnum; + + o = 1 - intLoad (filegeoptr, &vlblnum); + coorsorttab[coornum].labl = vlblnum; + coorsorttab[coornum].num = coornum; + if ((coornum > 0) && /* Check if geometry data sorted */ + (coorsorttab[coornum].labl < coorsorttab[coornum - 1].labl)) + coorsortflag = 0; /* Geometry data not sorted */ + + o |= 1 - fscanf (filegeoptr, "%lf", /* Read X coordinate */ + &coorfiletab[coornum * dimnnbr]); + if (dimnnbr > 1) { + o |= 1 - fscanf (filegeoptr, "%lf", /* Read Y coordinate */ + &coorfiletab[(coornum * dimnnbr) + 1]); + if (dimnnbr > 2) + o |= 1 - fscanf (filegeoptr, "%lf", /* Read Z coordinate */ + &coorfiletab[(coornum * dimnnbr) + 2]); + } + } + if (o != 0) { + errorPrint ("graphGeomLoadScot: bad input (2)"); + memFree (coorfiletab); /* Free group leader */ + return (1); + } + + if (coorsortflag != 1) /* If geometry data not sorted */ + intSort2asc1 (coorsorttab, coornbr); /* Sort sort area by ascending labels */ + + for (coornum = 1; coornum < coornbr; coornum ++) { /* Check geometric data integrity */ + if (coorsorttab[coornum].labl == coorsorttab[coornum - 1].labl) { + errorPrint ("graphGeomLoadScot: duplicate vertex label"); + memFree (coorfiletab); /* Free group leader */ + return (1); + } + } + + if (grafptr->vlbltax != NULL) { /* If graph has vertex labels */ + vertsortflag = 1; /* Assume graph data sorted */ + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { + vertsorttab[vertnum].labl = grafptr->vlbltax[vertnum + grafptr->baseval]; + vertsorttab[vertnum].num = vertnum; + if ((vertnum > 0) && /* Check if graph data sorted */ + (vertsorttab[vertnum].labl < vertsorttab[vertnum - 1].labl)) + vertsortflag = 0; /* Graph data not sorted */ + } + if (vertsortflag != 1) /* If graph data not sorted */ + intSort2asc1 (vertsorttab, grafptr->vertnbr); /* Sort sort area by ascending labels */ + } + else { /* Graph does not have vertex labels */ + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) + vertsorttab[vertnum].labl = + vertsorttab[vertnum].num = vertnum; + } + + for (coornum = vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { /* For all vertices in graph */ + while ((coornum < coornbr) && (coorsorttab[coornum].labl < vertsorttab[vertnum].labl)) + coornum ++; /* Search geometry vertex with same label */ + if ((coornum >= coornbr) || (coorsorttab[coornum].labl > vertsorttab[vertnum].labl)) { /* If label does not exist */ + errorPrint ("graphGeomLoadScot: vertex geometry data not found (%d)", + vertsorttab[vertnum].labl); + memFree (coorfiletab); /* Free group leader */ + return (1); + } + memCpy (&geomptr->geomtab[vertsorttab[vertnum].num * dimnnbr], &coorfiletab[coorsorttab[coornum ++].num * dimnnbr], dimnnbr * sizeof (double)); + } + + memFree (coorfiletab); /* Free group leader */ + + return (0); +} + +/* This routine saves the source process graph +** in the Scotch source and geometry formats. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +graphGeomSaveScot ( +const Graph * restrict const grafptr, /* Graph to save */ +const Geom * restrict const geomptr, /* Geometry to save */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* No use */ +{ + Gnum vertnum; + int dimnnbr; + int o; + + if (filesrcptr != NULL) { + if (graphSave (grafptr, filesrcptr) != 0) /* Save graph structural data */ + return (1); + } + + dimnnbr = geomptr->dimnnbr; + + o = 0; + if (geomptr->geomtab != NULL) { /* If geometrical data present */ + o = (fprintf (filegeoptr, GNUMSTRING "\n" GNUMSTRING "\n", /* Output file header */ + (Gnum) geomptr->dimnnbr, + (Gnum) grafptr->vertnbr) == EOF); + + switch (dimnnbr) { /* Output geometry data */ + case 1 : + for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) + o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\n", + (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum), + (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr]) == EOF); + break; + case 2 : + for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) + o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\n", + (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum), + (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr], + (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 1]) == EOF); + break; + case 3 : + for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) + o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\t%lf\n", + (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum), + (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr], + (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 1], + (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 2]) == EOF); + break; +#ifdef SCOTCH_DEBUG_GRAPH2 + default : + errorPrint ("graphGeomSaveScot: invalid geometry type"); + return (1); +#endif /* SCOTCH_DEBUG_GRAPH2 */ + } + + if (o != 0) { + errorPrint ("graphGeomSaveScot: bad output"); + } + } + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/graph_io_scot.h b/scotch_6.0.3/src/libscotch/graph_io_scot.h new file mode 100644 index 00000000..a62a1187 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_io_scot.h @@ -0,0 +1,63 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_io_scot.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the Scotch graph format **/ +/** module. **/ +/** **/ +/** DATES : # Version 3.2 : from : 06 nov 1997 **/ +/** to 06 nov 1997 **/ +/** # Version 3.3 : from : 13 dec 1998 **/ +/** to 21 dec 1998 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 19 jan 2004 **/ +/** # Version 5.0 : from : 13 sep 2006 **/ +/** to 13 sep 2006 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ The sort structure, used to sort graph vertices by label. + Field labl is first because of intSort2asc1. +*/ + +typedef struct GraphGeomScotSort_ { + Gnum labl; /*+ Vertex label: FIRST +*/ + Gnum num; /*+ Vertex number +*/ +} GraphGeomScotSort; diff --git a/scotch_6.0.3/src/libscotch/graph_list.c b/scotch_6.0.3/src/libscotch/graph_list.c new file mode 100644 index 00000000..f948b69b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_list.c @@ -0,0 +1,263 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_list.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the source graph **/ +/** vertex lists functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 01 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 31 oct 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 08 jun 1996 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 15 sep 1998 **/ +/** # Version 4.0 : from : 10 dec 2001 **/ +/** to 10 dec 2001 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_LIST + +#include "module.h" +#include "common.h" +#include "graph.h" + +/********************************/ +/* */ +/* These routines handle vertex */ +/* number lists. */ +/* */ +/********************************/ + +/* This routine creates a vertex number list. +** It returns: +** - 0 : in all cases. +*/ + +int +listInit ( +VertList * listptr) +{ + listptr->vnumnbr = 0; /* Initialize list fields */ + listptr->vnumtab = NULL; + + return (0); +} + +/* This routine deletes the given vertex number list. +** It returns: +** - VOID : in all cases. +*/ + +void +listExit ( +VertList * listptr) +{ + if (listptr->vnumtab != NULL) + memFree (listptr->vnumtab); /* Free vertex list array */ + +#ifdef SCOTCH_DEBUG_GRAPH2 + memSet (listptr, 0, sizeof (VertList)); /* Purge list fields */ +#endif /* SCOTCH_DEBUG_GRAPH2 */ +} + +/* This routine allocates a vertex +** number list array. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +listAlloc ( +VertList * listptr, +Gnum vnumnbr) +{ + if (vnumnbr == listptr->vnumnbr) /* If array is already dimensioned */ + return (0); /* Keep it as it is */ + + listFree (listptr); /* Free vertex array */ + if (vnumnbr > 0) { /* Reallocate vertex space */ + if ((listptr->vnumtab = (Gnum *) memAlloc (vnumnbr * sizeof (Gnum))) == NULL) { + errorPrint ("listAlloc: out of memory"); + return (1); + } + listptr->vnumnbr = vnumnbr; + } + + return (0); +} + +/* This routine frees a vertex +** number list array. +** It returns: +** - 0 : in all cases. +*/ + +int +listFree ( +VertList * listptr) +{ + if (listptr->vnumtab != NULL) /* Free vertex list array */ + memFree (listptr->vnumtab); + + listptr->vnumnbr = 0; /* Reset list values */ + listptr->vnumtab = NULL; + + return (0); +} + +/* These routines load a vertex number list +** from the given stream. Because of the search +** for duplicates, the list read is always +** sorted by ascending order. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +listLoad ( +VertList * listptr, +FILE * stream) +{ + Gnum vnumnbr; + Gnum vnumnum; + + if (intLoad (stream, &vnumnbr) != 1) { /* Read number of vertices */ + errorPrint ("listLoad: bad input (1)"); + return (1); + } + + if (listAlloc (listptr, vnumnbr) != 0) { /* Allocate vertex space */ + errorPrint ("listLoad: out of memory"); + return (1); + } + + for (vnumnum = 0; vnumnum < vnumnbr; vnumnum ++) { /* Read vertex list contents */ + if (intLoad (stream, &listptr->vnumtab[vnumnum]) != 1) { + errorPrint ("listLoad: bad input (2)"); + return (1); + } + } + + listSort (listptr); /* Sort vertex list by ascending order */ + for (vnumnum = 1; vnumnum < vnumnbr; vnumnum ++) { /* Search list for duplicates */ + if (listptr->vnumtab[vnumnum] == listptr->vnumtab[vnumnum - 1]) { + errorPrint ("listLoad: duplicate vertex numbers"); + return (1); + } + } + + return (0); +} + +/* This routine sorts a vertex list +** by ascending order. +** It returns: +** - VOID : in all cases. +*/ + +void +listSort ( +VertList * listptr) +{ + intSort1asc1 (listptr->vnumtab, listptr->vnumnbr); +} + +/* This routine saves a vertex number list +** to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +listSave ( +VertList * listptr, +FILE * stream) +{ + Gnum vnumnum; + int o; + + o = (intSave (stream, listptr->vnumnbr) == 0); /* Write number of vertices */ + for (vnumnum = 0; (o == 0) && (vnumnum < listptr->vnumnbr); vnumnum ++) { + o = (fprintf (stream, "%c" GNUMSTRING, + ((vnumnum % 8) == 0) ? '\n' : '\t', + (Gnum) listptr->vnumtab[vnumnum]) == EOF); + } + o |= (fprintf (stream, "\n") == EOF); + + if (o != 0) + errorPrint ("listSave: bad output"); + + return (o); +} + +/* This routine copies the contents +** of a vertex list into another. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +listCopy ( +VertList * dstlistptr, /* Destination list */ +VertList * srclistptr) /* Source list */ +{ + if (listAlloc (dstlistptr, dstlistptr->vnumnbr) != 0) { /* Allocate vertex space */ + errorPrint ("listCopy: out of memory"); + return (1); + } + memCpy (dstlistptr->vnumtab, /* Copy list data */ + srclistptr->vnumtab, + srclistptr->vnumnbr * sizeof (Gnum)); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/graph_list.h b/scotch_6.0.3/src/libscotch/graph_list.h new file mode 100644 index 00000000..c5b4eee8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_list.h @@ -0,0 +1,98 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_list.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source graph functions. **/ +/** **/ +/** DATES : # Version 0.0 : from : 02 dec 1992 **/ +/** to 18 may 1993 **/ +/** # Version 1.3 : from : 30 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 18 aug 1994 **/ +/** # Version 3.0 : from : 07 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 28 nov 1995 **/ +/** to 28 nov 1995 **/ +/** # Version 3.2 : from : 07 sep 1996 **/ +/** to 15 sep 1998 **/ +/** # Version 3.3 : from : 28 sep 1998 **/ +/** to 23 mar 1999 **/ +/** # Version 3.4 : from : 20 mar 2000 **/ +/** to 20 mar 2000 **/ +/** # Version 4.0 : from : 24 nov 2001 **/ +/** to 27 sep 2002 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +#define GRAPH_LIST_H + +/* +** The type and structure definitions. +*/ + +/*+ The vertex list structure. Since a vertex list + always refers to a given graph, vertex indices + contained in the vertex list array are based with + respect to the base value of the associated graph. + However, the array itself is not based. +*/ + +typedef struct VertList_ { + Gnum vnumnbr; /*+ Number of vertices in list +*/ + Gnum * vnumtab; /*+ Pointer to vertex array +*/ +} VertList; + +/* +** The function prototypes. +*/ + +#ifndef GRAPH_LIST +#define static +#endif + +int listInit (VertList *); +void listExit (VertList *); +int listAlloc (VertList *, Gnum); +int listFree (VertList *); +int listLoad (VertList *, FILE *); +int listSave (VertList *, FILE *); +void listSort (VertList *); +int listCopy (VertList *, VertList *); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/graph_match.c b/scotch_6.0.3/src/libscotch/graph_match.c new file mode 100644 index 00000000..a888937b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_match.c @@ -0,0 +1,478 @@ +/* Copyright 2004,2007,2009,2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_match.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the source graph **/ +/** matching functions, generated from the **/ +/** generic pattern. **/ +/** **/ +/** DATES : # Version 6.0 : from : 05 oct 2012 **/ +/** to 21 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GRAPH_MATCH + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "graph.h" +#include "graph_coarsen.h" +#include "graph_match.h" + +/* +** The static variables. +*/ + +static void (* graphmatchfuncseqtab[]) (GraphCoarsenThread *) = { /* Array of sequential matching routines */ + GRAPHMATCHFUNCBLOCK (Seq) + }; + +#ifdef GRAPHMATCHTHREAD + +static void (* graphmatchfuncthrbegtab[]) (GraphCoarsenThread *) = { /* Array of threaded matching start routines */ + GRAPHMATCHFUNCBLOCK (ThrBeg) + }; + +static void (* graphmatchfuncthrmidtab[]) (GraphCoarsenThread *) = { /* Array of threaded matching intermediate routines */ + GRAPHMATCHFUNCBLOCK (ThrMid) + }; + +static void (* graphmatchfuncthrendtab[]) (GraphCoarsenThread *) = { /* Array of threaded matching end routines */ + GRAPHMATCHFUNCBLOCK (ThrEnd) + }; + +#endif /* GRAPHMATCHTHREAD */ + +/***************************/ +/* */ +/* The sequential matching */ +/* subroutines. */ +/* */ +/***************************/ + +#define GRAPHMATCHSCANP1INPERT /* Perturbation scan for first pass */ +#define GRAPHMATCHSCANP2INPERT /* Perturbation scan for second pass */ + +#define GRAPHMATCHSCANNAME graphMatchSeqNfNvNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANEDLOTAB +#define GRAPHMATCHSCANNAME graphMatchSeqNfNvEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANVELOTAB +#define GRAPHMATCHSCANNAME graphMatchSeqNfVlEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANEDLOTAB + +#define GRAPHMATCHSCANNAME graphMatchSeqNfVlNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANVELOTAB + +#define GRAPHMATCHSCANPFIXTAB +#define GRAPHMATCHSCANNAME graphMatchSeqFxNvNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANEDLOTAB +#define GRAPHMATCHSCANNAME graphMatchSeqFxNvEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANVELOTAB +#define GRAPHMATCHSCANNAME graphMatchSeqFxVlEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANEDLOTAB + +#define GRAPHMATCHSCANNAME graphMatchSeqFxVlNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANVELOTAB +#undef GRAPHMATCHSCANPFIXTAB + +#undef GRAPHMATCHSCANP1INPERT +#undef GRAPHMATCHSCANP2INPERT + +/*************************/ +/* */ +/* The threaded matching */ +/* start subroutines. */ +/* */ +/*************************/ + +#ifdef GRAPHMATCHTHREAD + +/* Start subroutines +*/ + +#define GRAPHMATCHSCANP1INPERT /* Perturbation scan for first pass */ +#define GRAPHMATCHSCANP2INPERT /* Perturbation scan for second pass */ +#define GRAPHMATCHSCANP2OUTQUEUE /* Queue storage for second pass */ + +#define GRAPHMATCHSCANNAME graphMatchThrBegNfNvNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANEDLOTAB +#define GRAPHMATCHSCANNAME graphMatchThrBegNfNvEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANVELOTAB +#define GRAPHMATCHSCANNAME graphMatchThrBegNfVlEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANEDLOTAB + +#define GRAPHMATCHSCANNAME graphMatchThrBegNfVlNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANVELOTAB + +#define GRAPHMATCHSCANPFIXTAB +#define GRAPHMATCHSCANNAME graphMatchThrBegFxNvNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANEDLOTAB +#define GRAPHMATCHSCANNAME graphMatchThrBegFxNvEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANVELOTAB +#define GRAPHMATCHSCANNAME graphMatchThrBegFxVlEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANEDLOTAB + +#define GRAPHMATCHSCANNAME graphMatchThrBegFxVlNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANVELOTAB +#undef GRAPHMATCHSCANPFIXTAB + +#undef GRAPHMATCHSCANP1INPERT +#undef GRAPHMATCHSCANP2INPERT +#undef GRAPHMATCHSCANP2OUTQUEUE + +/* Intermediate subroutines +*/ + +#define GRAPHMATCHSCANP2INQUEUE /* Read queue for second (only) pass */ +#define GRAPHMATCHSCANP2OUTQUEUE /* Queue storage for second pass */ + +#define GRAPHMATCHSCANNAME graphMatchThrMidNfNvNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANEDLOTAB +#define GRAPHMATCHSCANNAME graphMatchThrMidNfNvEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANVELOTAB +#define GRAPHMATCHSCANNAME graphMatchThrMidNfVlEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANEDLOTAB + +#define GRAPHMATCHSCANNAME graphMatchThrMidNfVlNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANVELOTAB + +#define GRAPHMATCHSCANPFIXTAB +#define GRAPHMATCHSCANNAME graphMatchThrMidFxNvNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANEDLOTAB +#define GRAPHMATCHSCANNAME graphMatchThrMidFxNvEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANVELOTAB +#define GRAPHMATCHSCANNAME graphMatchThrMidFxVlEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANEDLOTAB + +#define GRAPHMATCHSCANNAME graphMatchThrMidFxVlNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANVELOTAB +#undef GRAPHMATCHSCANPFIXTAB + +#undef GRAPHMATCHSCANP2INQUEUE +#undef GRAPHMATCHSCANP2OUTQUEUE + +/* End subroutines +*/ + +#define GRAPHMATCHSCANP2INQUEUE /* Read queue for second (only) pass */ + +#define GRAPHMATCHSCANNAME graphMatchThrEndNfNvNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANEDLOTAB +#define GRAPHMATCHSCANNAME graphMatchThrEndNfNvEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANVELOTAB +#define GRAPHMATCHSCANNAME graphMatchThrEndNfVlEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANEDLOTAB + +#define GRAPHMATCHSCANNAME graphMatchThrEndNfVlNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANVELOTAB + +#define GRAPHMATCHSCANPFIXTAB +#define GRAPHMATCHSCANNAME graphMatchThrEndFxNvNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANEDLOTAB +#define GRAPHMATCHSCANNAME graphMatchThrEndFxNvEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME + +#define GRAPHMATCHSCANVELOTAB +#define GRAPHMATCHSCANNAME graphMatchThrEndFxVlEl +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANEDLOTAB + +#define GRAPHMATCHSCANNAME graphMatchThrEndFxVlNe +#include "graph_match_scan.c" +#undef GRAPHMATCHSCANNAME +#undef GRAPHMATCHSCANVELOTAB +#undef GRAPHMATCHSCANPFIXTAB + +#undef GRAPHMATCHSCANP2INQUEUE + +#endif /* GRAPHMATCHTHREAD */ + +/*************************/ +/* */ +/* The matching routine. */ +/* */ +/*************************/ + +/* This routine performs the sequential +** initialization of the global mating +** data structures, before the threads +** are launched. +** It returns: +** - 0 : if initialization could be performed. +** - 1 : on error. +*/ + +int +graphMatchInit ( +GraphCoarsenData * restrict coarptr) +{ + int flagval; + + const Graph * restrict const finegrafptr = coarptr->finegrafptr; +#if ((defined GRAPHMATCHTHREAD) && ! (defined SCOTCH_DETERMINISTIC)) + const Gnum finevertnbr = finegrafptr->vertnbr; + const Gnum baseval = finegrafptr->baseval; + const int thrdnbr = coarptr->thrddat.thrdnbr; +#endif /* ((defined GRAPHMATCHTHREAD) && ! (defined SCOTCH_DETERMINISTIC)) */ + + flagval = (finegrafptr->edlotax != NULL) ? 1 : 0; + if (finegrafptr->velotax != NULL) + flagval |= 2; + if ((coarptr->finevfixnbr > 0) || (coarptr->fineparotax != NULL)) + flagval |= 4; + +#if ((defined GRAPHMATCHTHREAD) && ! (defined SCOTCH_DETERMINISTIC)) + if (thrdnbr > 1) { + if (memAllocGroup ((void **) (void *) + &coarptr->finequeutab, (size_t) (finevertnbr * sizeof (Gnum)), + &coarptr->finelocktax, (size_t) (finevertnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("graphMatchInit: out of memory"); + return (1); + } + coarptr->finelocktax -= baseval; + + coarptr->fbegptr = (void (*) (void *)) graphmatchfuncthrbegtab[flagval]; + coarptr->fmidptr = (void (*) (void *)) graphmatchfuncthrmidtab[flagval]; + coarptr->fendptr = (void (*) (void *)) graphmatchfuncthrendtab[flagval]; + } + else { + coarptr->finequeutab = NULL; + coarptr->finelocktax = NULL; /* If deterministic behavior wanted, no threaded mating */ + coarptr->fbegptr = (void (*) (void *)) graphmatchfuncseqtab[flagval]; +#ifdef SCOTCH_DEBUG_GRAPH2 + coarptr->fmidptr = (void (*) (void *)) NULL; + coarptr->fendptr = (void (*) (void *)) NULL; +#endif /* SCOTCH_DEBUG_GRAPH2 */ + } +#else /* ((defined GRAPHMATCHTHREAD) && ! (defined SCOTCH_DETERMINISTIC)) */ + coarptr->fbegptr = (void (*) (void *)) graphmatchfuncseqtab[flagval]; +#endif /* ((defined GRAPHMATCHTHREAD) && ! (defined SCOTCH_DETERMINISTIC)) */ + + return (0); +} + +/* This routine merges the results of two mating +** threads and re-launches a mating operations +** if necessary. +*/ + +#ifdef GRAPHMATCHTHREAD +static +void +graphMatchReduce ( +GraphCoarsenThread * restrict const tlocptr, /* Pointer to local thread */ +void * restrict const vlocptr, /* Pointer to local value */ +void * restrict const vremptr) /* Pointer to remote value */ +{ + GraphCoarsenData * restrict const coarptr = (GraphCoarsenData *) (tlocptr->thrddat.grouptr); + GraphCoarsenThread * restrict const tremptr = (GraphCoarsenThread *) vremptr; + const int thrdnbr = coarptr->thrddat.thrdnbr; + const int thrdnum = tlocptr->thrddat.thrdnum; + Gnum qremnbr; + + qremnbr = tremptr->finequeunnd - tremptr->finequeubas; /* Number of enqueued fine vertices in second thread */ + + memMov (coarptr->finequeutab + tlocptr->finequeunnd, /* Merge queues */ + coarptr->finequeutab + tremptr->finequeubas, + qremnbr * sizeof (Gnum)); + tlocptr->finequeunnd += qremnbr; + tlocptr->coarvertnbr += tremptr->coarvertnbr; + + if ((thrdnum == 0) && (((tremptr - tlocptr) << 1) >= thrdnbr)) /* If last join */ + coarptr->fendptr (tlocptr); /* Call end match routine */ + else + coarptr->fmidptr (tlocptr); /* Call intermediate match routine */ +} +#endif /* GRAPHMATCHTHREAD */ + +/* This routine matches the vertices of the given +** graph, according to various constraints. The +** matching can be either single-threaded or +** multi-threaded. +** It returns: +** - 0 : if matching could be performed. +** - 1 : on error. +*/ + +void +graphMatch ( +GraphCoarsenThread * restrict thrdptr) /*+ Pointer to incomplete match data array +*/ +{ + Gnum finevertsiz; +#ifdef SCOTCH_DEBUG_GRAPH2 + Gnum finevertnum; +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + GraphCoarsenData * restrict const coarptr = (GraphCoarsenData *) (thrdptr->thrddat.grouptr); + const Graph * restrict const finegrafptr = coarptr->finegrafptr; + const Gnum finevertbas = thrdptr->finevertbas; /* Get fine vertex range */ + const Gnum finevertnnd = thrdptr->finevertnnd; + Gnum * restrict const finematetax = coarptr->finematetax; + const Gnum baseval = finegrafptr->baseval; + + thrdptr->finequeubas = finevertbas; /* Assume matching range is fine vertex processing range */ + thrdptr->finequeunnd = finevertnnd; + thrdptr->coarvertnbr = 0; /* No coarse vertices created yet */ + + finevertsiz = finevertnnd - finevertbas; /* Compute fine vertex range */ + memSet (finematetax + finevertbas, ~0, finevertsiz * sizeof (Gnum)); +#if ((defined GRAPHMATCHTHREAD) && ! (defined SCOTCH_DETERMINISTIC)) + if (coarptr->thrddat.thrdnbr > 1) { + memSet (coarptr->finelocktax + finevertbas, 0, finevertsiz * sizeof (int)); /* Initialize local part of lock array for concurrent accesses */ + threadBarrier (thrdptr); /* finematetax and finelocktax must have been globally initialized before we can go on */ + + coarptr->fbegptr (thrdptr); /* Perform bulk on local part */ + threadReduce (thrdptr, thrdptr, (ThreadReduceFunc) graphMatchReduce, 0); /* Reduce work on remaining vertices */ + + if (thrdptr->thrddat.thrdnum == 0) { + coarptr->coarvertnbr = thrdptr->coarvertnbr; /* Global number of coarse vertices is reduced number */ + memFree (coarptr->finequeutab); /* Free group leader of matching data */ + } + + threadBarrier (thrdptr); /* coarptr->coarvertnbr must be known to all */ + } + else +#else /* (defined GRAPHMATCHTHREAD) && ! (defined SCOTCH_DETERMINISTIC) */ +#ifdef GRAPHCOARSENTHREAD /* If matching was called from a threaded environment */ + if (coarptr->thrddat.thrdnbr > 1) { + threadBarrier (thrdptr); /* finematetax must have been fully initialized before we go on */ + + thrdptr->finequeubas = finegrafptr->baseval; /* Thread 0 will handle all of fine graph vertices */ + thrdptr->finequeunnd = finegrafptr->vertnnd; + if (thrdptr->thrddat.thrdnum == 0) { /* Only thread 0 will do the job sequentially */ + coarptr->fbegptr (thrdptr); /* Call sequential mating routine */ + coarptr->coarvertnbr = thrdptr->coarvertnbr; /* Global number of coarse vertices is that computed by (sequential) thread 0 */ + } + + threadBarrier (thrdptr); /* coarptr->coarvertnbr must be known to all */ + } + else +#endif /* GRAPHCOARSENTHREAD */ +#endif /* (defined GRAPHMATCHTHREAD) && ! (defined SCOTCH_DETERMINISTIC) */ + { + coarptr->fbegptr (thrdptr); /* Call sequential mating routine */ + coarptr->coarvertnbr = thrdptr->coarvertnbr; /* Global number of coarse vertices is that computed by (sequential) thread 0 */ + } + +#ifdef SCOTCH_DEBUG_GRAPH2 + for (finevertnum = finevertbas; finevertnum < finevertnnd; finevertnum ++) { + if (finematetax[finevertnum] == ~0) { /* If matching not aborted, this should not happen */ + errorPrint ("graphMatch: internal error"); + coarptr->coarvertnbr = coarptr->coarvertmax; + } + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ +} diff --git a/scotch_6.0.3/src/libscotch/graph_match.h b/scotch_6.0.3/src/libscotch/graph_match.h new file mode 100644 index 00000000..a32bb088 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_match.h @@ -0,0 +1,98 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_match.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the centralized source graph **/ +/** matching routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 02 oct 2012 **/ +/** to 01 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#if (defined SCOTCH_PTHREAD) && (defined GRAPHCOARSENTHREAD) +#define GRAPHMATCHTHREAD +#endif /* (defined SCOTCH_PTHREAD) && (defined GRAPHCOARSENTHREAD) */ + +/** Prime number for cache-friendly perturbations. **/ + +#define GRAPHMATCHSCANPERTPRIME 179 /* Prime number */ + +/** Function block building macro. **/ + +#define GRAPHMATCHFUNCBLOCK(t) graphMatch##t##NfNvNe, \ + graphMatch##t##NfNvEl, \ + graphMatch##t##NfVlNe, \ + graphMatch##t##NfVlEl, \ + graphMatch##t##FxNvNe, \ + graphMatch##t##FxNvEl, \ + graphMatch##t##FxVlNe, \ + graphMatch##t##FxVlEl + +#define GRAPHMATCHFUNCDECL(t) static void graphMatch##t##NfNvNe (GraphCoarsenThread *); \ + static void graphMatch##t##NfNvEl (GraphCoarsenThread *); \ + static void graphMatch##t##NfVlNe (GraphCoarsenThread *); \ + static void graphMatch##t##NfVlEl (GraphCoarsenThread *); \ + static void graphMatch##t##FxNvNe (GraphCoarsenThread *); \ + static void graphMatch##t##FxNvEl (GraphCoarsenThread *); \ + static void graphMatch##t##FxVlNe (GraphCoarsenThread *); \ + static void graphMatch##t##FxVlEl (GraphCoarsenThread *); + +/* +** The function prototypes. +*/ + +int graphMatchInit (GraphCoarsenData *); +void graphMatch (GraphCoarsenThread * restrict const); + +#ifndef GRAPH_MATCH +#define static +#endif + +GRAPHMATCHFUNCDECL (Seq); + +GRAPHMATCHFUNCDECL (ThrBeg); + +GRAPHMATCHFUNCDECL (ThrMid); + +GRAPHMATCHFUNCDECL (ThrEnd); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/graph_match_scan.c b/scotch_6.0.3/src/libscotch/graph_match_scan.c new file mode 100644 index 00000000..992720b9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/graph_match_scan.c @@ -0,0 +1,345 @@ +/* Copyright 2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : graph_match_scan.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the stub of the **/ +/** threaded and un-threaded centralized **/ +/** graph matching functions. **/ +/** **/ +/** DATES : # Version 6.0 : from : 01 oct 2012 **/ +/** to 04 jun 2014 **/ +/** **/ +/** NOTES : # This code partly derives from the **/ +/** code of graph_match.c partly updated **/ +/** in the early stages of release 6.0 **/ +/** so as to account for fixed vertices **/ +/** and an old partition. **/ +/** **/ +/************************************************************/ + +/***************************/ +/* */ +/* The matching subroutine */ +/* pattern. */ +/* */ +/***************************/ + +/* This routine matches the vertices of the given +** centralized graph according to various constraints. +** It returns: +** - void : in all cases +*/ + +static +void +GRAPHMATCHSCANNAME ( +GraphCoarsenThread * restrict thrdptr) /* Thread-dependent data */ +{ + GraphCoarsenData * restrict const coarptr = (GraphCoarsenData *) (thrdptr->thrddat.grouptr); + const Graph * restrict const finegrafptr = coarptr->finegrafptr; + Gnum finevertnum; /* Current vertex index */ + Gnum finevertnnd; /* Current end of vertex array */ +#ifdef GRAPHMATCHSCANVELOTAB + Gnum finevelomin = (1 * finegrafptr->velosum) / (4 * finegrafptr->vertnbr); /* Minimum load of neighbor */ + Gnum coarvelomax = (4 * finegrafptr->velosum) / (1 * (coarptr->coarvertmax - coarptr->finevfixnbr)) + 1; +#endif /* GRAPHMATCHSCANVELOTAB */ + Gnum coarvertnbr = thrdptr->coarvertnbr; /* Current number of multinode vertices */ +#if ((defined GRAPHMATCHSCANP1INPERT) || defined (GRAPHMATCHSCANP2INPERT)) + const Gnum degrmax = finegrafptr->degrmax; + Gnum pertbas; + Gnum pertnnd; + Gnum pertnbr; + Gunum randval = thrdptr->randval; /* Unsigned to avoid negative random numbers */ +#endif /* ((defined GRAPHMATCHSCANP1INPERT) || defined (GRAPHMATCHSCANP2INPERT)) */ +#if ((defined GRAPHMATCHSCANP1INQUEUE) || defined (GRAPHMATCHSCANP2INQUEUE) || defined (GRAPHMATCHSCANP2OUTQUEUE)) + Gnum * const queutab = coarptr->finequeutab; + volatile int * const locktax = coarptr->finelocktax; +#endif /* ((defined GRAPHMATCHSCANP1INQUEUE) || defined (GRAPHMATCHSCANP2INQUEUE) || defined (GRAPHMATCHSCANP2OUTQUEUE)) */ +#if ((defined GRAPHMATCHSCANP1INQUEUE) || defined (GRAPHMATCHSCANP2INQUEUE)) + Gnum queunnd; + Gnum queunum; +#endif /* ((defined GRAPHMATCHSCANP1INQUEUE) || defined (GRAPHMATCHSCANP2INQUEUE)) */ +#if ((defined GRAPHMATCHSCANP1OUTQUEUE) || defined (GRAPHMATCHSCANP2OUTQUEUE)) + Gnum queunew; +#endif /* ((defined GRAPHMATCHSCANP1OUTQUEUE) || defined (GRAPHMATCHSCANP2OUTQUEUE)) */ + + const Gnum * restrict const fineverttax = finegrafptr->verttax; + const Gnum * restrict const finevendtax = finegrafptr->vendtax; +#ifdef GRAPHMATCHSCANVELOTAB + const Gnum * restrict const finevelotax = finegrafptr->velotax; +#endif /* GRAPHMATCHSCANVELOTAB */ + const Gnum * restrict const fineedgetax = finegrafptr->edgetax; +#ifdef GRAPHMATCHSCANEDLOTAB + const Gnum * restrict const fineedlotax = finegrafptr->edlotax; +#endif /* GRAPHMATCHSCANEDLOTAB */ + volatile Gnum * restrict const finematetax = coarptr->finematetax; +#ifdef GRAPHMATCHSCANPFIXTAB + const Gnum * restrict const fineparotax = coarptr->fineparotax; + const Gnum * restrict const finepfixtax = coarptr->finepfixtax; +#endif /* GRAPHMATCHSCANPFIXTAB */ + +#ifdef GRAPHMATCHSCANP1INPERT /* First pass is only for start or sequential routines */ +#ifdef GRAPHMATCHSCANVELOTAB +#ifdef GRAPHMATCHSCANP1OUTQUEUE + queunew = thrdptr->queubas; +#endif /* GRAPHMATCHSCANP1OUTQUEUE */ +#ifdef GRAPHMATCHSCANP1INQUEUE + for (queunum = thrdptr->queubas, queunnd = thrdptr->queunnd; + queunum < queunnd; queunum ++) { + finevertnum = queutab[queunum]; +#endif /* GRAPHMATCHSCANP1INQUEUE */ +#ifdef GRAPHMATCHSCANP1INPERT + for (pertbas = thrdptr->finequeubas, pertnnd = thrdptr->finequeunnd; + pertbas < pertnnd; pertbas += pertnbr) { /* Run cache-friendly perturbation */ + Gnum pertval; /* Current index in perturbation area */ + + pertnbr = degrmax * 2 + randval % (degrmax + 1) + 1; /* Compute perturbation area size (avoid DIV0 in random) */ + if (pertnbr >= GRAPHMATCHSCANPERTPRIME) + pertnbr = 32 + randval % (GRAPHMATCHSCANPERTPRIME - 34); + if (pertbas + pertnbr > pertnnd) + pertnbr = pertnnd - pertbas; + + pertval = 0; /* Start from first perturbation vertex */ + do { /* Loop on perturbation vertices */ + finevertnum = pertbas + pertval; /* Compute corresponding vertex number */ +#endif /* GRAPHMATCHSCANP1INPERT */ + { + Gnum fineedgenum; + Gnum finevertbst; +#ifdef GRAPHMATCHSCANEDLOTAB + Gnum fineedlobst = -1; /* Edge load of current best neighbor */ +#endif /* GRAPHMATCHSCANEDLOTAB */ + + if (finematetax[finevertnum] >= 0) /* If vertex already mated, skip it without remembering it */ + goto loop1; + + finevertbst = finevertnum; /* Assume we match with ourselves */ + + if ((finevelotax[finevertnum] >= finevelomin) || /* If vertex is not too light, skip it and record it */ + (fineverttax[finevertnum] == finevendtax[finevertnum])) /* Same for isolated vertex: process later */ +#ifdef GRAPHMATCHSCANP1OUTQUEUE + goto record1; +#else /* GRAPHMATCHSCANP1OUTQUEUE */ + goto loop1; +#endif /* GRAPHMATCHSCANP1OUTQUEUE */ + + for (fineedgenum = fineverttax[finevertnum]; + fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { + Gnum finevertend; + + finevertend = fineedgetax[fineedgenum]; + + if ((finematetax[finevertend] < 0) /* If unmatched vertex */ +#ifdef GRAPHMATCHSCANPFIXTAB + && ((finepfixtax == NULL) || (finepfixtax[finevertend] == finepfixtax[finevertnum])) /* We can only mate if potential mate has same value */ + && ((fineparotax == NULL) || (fineparotax[finevertend] == fineparotax[finevertnum])) /* And is in the same old part */ +#endif /* GRAPHMATCHSCANPFIXTAB */ +#ifdef GRAPHMATCHSCANEDLOTAB + && (fineedlotax[fineedgenum] > fineedlobst) /* And is better candidate */ +#endif /* GRAPHMATCHSCANEDLOTAB */ + ) { + finevertbst = finevertend; +#ifdef GRAPHMATCHSCANEDLOTAB + fineedlobst = fineedlotax[fineedgenum]; +#else /* GRAPHMATCHSCANEDLOTAB */ + break; +#endif /* GRAPHMATCHSCANEDLOTAB */ + } + } + +#ifdef GRAPHMATCHSCANP2OUTQUEUE + if (__sync_lock_test_and_set (&locktax[finevertnum], 1)) /* If could not acquire local vertex */ + goto loop1; /* Do not remember it as some other vertex has already acquired both */ + + if (finevertbst != finevertnum) { /* If we mated with another vertex */ + if (__sync_lock_test_and_set (&locktax[finevertbst], 1)) { /* If could not acquire mate vertex */ + __sync_lock_release (&locktax[finevertnum]); /* Release lock on local vertex */ +#ifdef GRAPHMATCHSCANP1OUTQUEUE +record1: + queutab[queunew ++] = finevertnum; /* Postpone processing to next pass */ +#endif /* GRAPHMATCHSCANP1OUTQUEUE */ + goto loop1; + } + finematetax[finevertbst] = finevertnum; + } +#else /* GRAPHMATCHSCANP2OUTQUEUE */ + finematetax[finevertbst] = finevertnum; /* If last (sequential) pass, always record */ +#endif /* GRAPHMATCHSCANP2OUTQUEUE */ + finematetax[finevertnum] = finevertbst; /* At this point or if last pass, record */ + coarvertnbr ++; /* One more coarse vertex created */ +loop1: ; + } +#ifdef GRAPHMATCHSCANP1INPERT + pertval = (pertval + GRAPHMATCHSCANPERTPRIME) % pertnbr; /* Compute next perturbation index */ + } while (pertval != 0); + randval += finevertnum; /* Perturbation for thread-dependent pseudo-random number */ + } +#endif /* GRAPHMATCHSCANP1INPERT */ +#ifdef GRAPHMATCHSCANP1INQUEUE + } +#endif /* GRAPHMATCHSCANP1INQUEUE */ +#ifdef GRAPHMATCHSCANP1OUTQUEUE + thrdptr->queunnd = queunew; /* Record queue index for next pass */ +#endif /* GRAPHMATCHSCANP1OUTQUEUE */ +#endif /* GRAPHMATCHSCANVELOTAB */ +#endif /* GRAPHMATCHSCANP1INPERT */ + +#ifdef GRAPHMATCHSCANP2OUTQUEUE + queunew = thrdptr->finequeubas; +#endif /* GRAPHMATCHSCANP2OUTQUEUE */ +#ifdef GRAPHMATCHSCANP2INQUEUE + for (queunum = thrdptr->finequeubas, queunnd = thrdptr->finequeunnd; + queunum < queunnd; queunum ++) { + finevertnum = queutab[queunum]; +#endif /* GRAPHMATCHSCANP2INQUEUE */ +#ifdef GRAPHMATCHSCANP2INPERT + for (pertbas = thrdptr->finequeubas, pertnnd = thrdptr->finequeunnd; + pertbas < pertnnd; pertbas += pertnbr) { /* Run cache-friendly perturbation */ + Gnum pertval; /* Current index in perturbation area */ + + pertnbr = degrmax * 2 + randval % (degrmax + 1) + 1; /* Compute perturbation area size (avoid DIV0 in random) */ + if (pertnbr >= GRAPHMATCHSCANPERTPRIME) + pertnbr = 32 + randval % (GRAPHMATCHSCANPERTPRIME - 34); + if (pertbas + pertnbr > pertnnd) + pertnbr = pertnnd - pertbas; + + pertval = 0; /* Start from first perturbation vertex */ + do { /* Loop on perturbation vertices */ + finevertnum = pertbas + pertval; /* Compute corresponding vertex number */ +#endif /* GRAPHMATCHSCANP2INPERT */ + { + Gnum fineedgenum; + Gnum finevertbst; + + if (finematetax[finevertnum] >= 0) /* If vertex already mated, skip it without remembering it */ + goto loop2; + + if (fineverttax[finevertnum] == finevendtax[finevertnum]) { /* If isolated vertex */ +#ifdef GRAPHMATCHSCANP2INPERT + Gnum perttmp = pertnnd; + do + finevertbst = -- perttmp; +#endif /* GRAPHMATCHSCANP2INPERT */ +#ifdef GRAPHMATCHSCANP2INQUEUE + Gnum queutmp = queunnd; + do + finevertbst = queutab[-- queutmp]; +#endif /* GRAPHMATCHSCANP2INQUEUE */ + while ((finematetax[finevertbst] >= 0) /* No test for overflow; we will always mate ourselves as we are isolated */ +#ifdef GRAPHMATCHSCANPFIXTAB + || ((finepfixtax != NULL) && (finepfixtax[finevertbst] != fineparotax[finevertnum])) + || ((fineparotax != NULL) && (fineparotax[finevertbst] != fineparotax[finevertnum]))); +#else /* GRAPHMATCHSCANPFIXTAB */ + ); +#ifdef GRAPHMATCHSCANP2INPERT + pertnnd = perttmp; /* If no extra conditions on mating, no longer consider traversed array */ +#endif /* GRAPHMATCHSCANP2INPERT */ +#ifdef GRAPHMATCHSCANP2INQUEUE + queunnd = queutmp; +#endif /* GRAPHMATCHSCANP2INQUEUE */ +#endif /* GRAPHMATCHSCANPFIXTAB */ + } + else { + Gnum fineedgenum; +#ifdef GRAPHMATCHSCANVELOTAB + Gnum finevelodlt = coarvelomax - finevelotax[finevertnum]; +#endif /* GRAPHMATCHSCANVELOTAB */ +#ifdef GRAPHMATCHSCANEDLOTAB + Gnum fineedlobst = -1; +#endif /* GRAPHMATCHSCANEDLOTAB */ + + finevertbst = finevertnum; /* No matching neighbor found yet */ + for (fineedgenum = fineverttax[finevertnum]; /* For all adjacent vertices */ + fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { + Gnum finevertend; + + finevertend = fineedgetax[fineedgenum]; + if ((finematetax[finevertend] < 0) /* If unmatched vertex */ +#ifdef GRAPHMATCHSCANPFIXTAB + && ((finepfixtax == NULL) || (finepfixtax[finevertend] == finepfixtax[finevertnum])) /* And is in the same part */ + && ((fineparotax == NULL) || (fineparotax[finevertend] == fineparotax[finevertnum])) +#endif /* GRAPHMATCHSCANPFIXTAB */ +#ifdef GRAPHMATCHSCANVELOTAB + && (finevelodlt >= finevelotax[finevertend]) /* And does not create overloads */ +#endif /* GRAPHMATCHSCANVELOTAB */ +#ifdef GRAPHMATCHSCANEDLOTAB + && (fineedlotax[fineedgenum] > fineedlobst) +#endif /* GRAPHMATCHSCANEDLOTAB */ + ) { /* And is better candidate */ + finevertbst = finevertend; +#ifdef GRAPHMATCHSCANEDLOTAB + fineedlobst = fineedlotax[fineedgenum]; +#else /* GRAPHMATCHSCANEDLOTAB */ + break; /* First match will do if no edge loads */ +#endif /* GRAPHMATCHSCANEDLOTAB */ + } + } + } + +#ifdef GRAPHMATCHSCANP2OUTQUEUE + if (__sync_lock_test_and_set (&locktax[finevertnum], 1)) /* If could not acquire local vertex */ + goto loop2; /* Do not remember it as some other vertex has already acquired both */ + + if (finevertbst != finevertnum) { /* If we mated with another vertex */ + if (__sync_lock_test_and_set (&locktax[finevertbst], 1)) { /* If could not acquire mate vertex */ + __sync_lock_release (&locktax[finevertnum]); /* Release lock on local vertex */ + queutab[queunew ++] = finevertnum; /* Postpone processing to next pass */ + goto loop2; + } + finematetax[finevertbst] = finevertnum; + } +#else /* GRAPHMATCHSCANP2OUTQUEUE */ + finematetax[finevertbst] = finevertnum; /* If last (sequential) pass, always record */ +#endif /* GRAPHMATCHSCANP2OUTQUEUE */ + finematetax[finevertnum] = finevertbst; /* At this point or if last pass, record */ + coarvertnbr ++; /* One more coarse vertex created */ +loop2: ; /* We may do something before looping */ + } +#ifdef GRAPHMATCHSCANP2INPERT + pertval = (pertval + GRAPHMATCHSCANPERTPRIME) % pertnbr; /* Compute next perturbation index */ + } while (pertval != 0); + randval += finevertnum; /* Perturbation for thread-dependent pseudo-random number */ + } +#endif /* GRAPHMATCHSCANP2INPERT */ +#ifdef GRAPHMATCHSCANP2INQUEUE + } +#endif /* GRAPHMATCHSCANP2INQUEUE */ +#ifdef GRAPHMATCHSCANP2OUTQUEUE + thrdptr->finequeunnd = queunew; /* Record queue index for next pass */ +#endif /* GRAPHMATCHSCANP2OUTQUEUE */ + thrdptr->coarvertnbr = coarvertnbr; /* Record subsequent number of multinode vertices */ +} diff --git a/scotch_6.0.3/src/libscotch/hall_order_hd.c b/scotch_6.0.3/src/libscotch/hall_order_hd.c new file mode 100644 index 00000000..e678c0b5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hall_order_hd.c @@ -0,0 +1,903 @@ +/* Copyright 2004,2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hall_order_hd.c **/ +/** **/ +/** AUTHOR : Patrick AMESTOY **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a halo graph or mesh **/ +/** structure using the block-oriented Halo **/ +/** Approximate (Multiple) Minimum Degree **/ +/** algorithm, with super-variable **/ +/** accounting (HaloAMD v2.0). **/ +/** **/ +/** DATES : # Version 3.2 : from : 09 aug 1998 **/ +/** to 18 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 05 jan 1999 **/ +/** # Version 4.0 : from : 14 jan 2003 **/ +/** to : 29 aug 2007 **/ +/** # Version 6.0 : from : 08 mar 2012 **/ +/** to : 08 mar 2012 **/ +/** **/ +/** NOTES : # This module contains pieces of code **/ +/** that belong to other people; see **/ +/** below. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HALL_ORDER_HD + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "hall_order_hd.h" + +/* -- translated by f2c (version 19970219). */ + +/** -------------------------------------------------------------------- **/ +/** December 8th 2003 **/ +/** Unique version for both graph of variables and graphs of elements **/ +/** Let us refer to as **/ +/** Gv a graph with only variables **/ +/** Ge a graph with both variables and elements **/ +/** **/ +/** Notations used: **/ +/** **/ +/** Let V be the set of nodes **/ +/** V = Ve + V0 + V1 **/ +/** V0 = Set of variable nodes (not in halo) **/ +/** V1 = Set of variable nodes (in halo) **/ +/** Ve = Set of element nodes **/ +/** **/ +/** All 3 sets are disjoint, Ve and V1 can be empty **/ +/** **/ +/** Modifications w.r.t. previous version : **/ +/** **/ +/** New Input: **/ +/** --------- **/ +/** nbelts : integer holding size of Ve **/ +/** =0 if Gv (graph of variables) **/ +/** >0 if Ge **/ +/** **/ +/** Extension of the meaning of input entry len for nodes in Ve **/ +/** --------- **/ +/** len(i) = | Adj(i) | if i \in V0 U Ve **/ +/** ( Note that in the case of a GE graph **/ +/** if v\in V0 then len(v) = nb of elements adjacent to v ) **/ +/** len(i) = - | Adj(i) | if i \in V1 **/ +/** or -N -1 if | Adj(i) | = 0 and i \in V1 **/ +/** **/ +/** Modified the meaning of input entry elen **/ +/** --------- **/ +/** if e \in Ve then elen (e) = -N-1 **/ +/** if v \in V0 then elen (v) = External degree of v **/ +/** Gv : elen (v) = len(v) **/ +/** Ge : elen (v) **/ +/** should be computed in SCOTCH **/ +/** if v \in V1 then elen (v) = 0 **/ +/** **/ +/** **/ +/** Output is unchanged **/ +/** --------- **/ +/** **/ +/** **/ +/** End remarks done on December 8th 2003 **/ +/** ---------------------------------------------------------------------**/ + +void +hallOrderHdHalmd ( +const Gnum n, /* Matrix order */ +const Gnum nbelts, /* Number of elements */ +const Gnum iwlen, /* Length of array iw */ +Gnum * restrict pe, /* Array of indexes in iw of start of row i */ +Gnum pfree, /* Useful size in iw */ +Gnum * restrict len, /* Array of lengths of adjacency lists */ +Gnum * restrict iw, /* Adjacency list array */ +Gnum * restrict nv, /* Array of element degrees */ +Gnum * restrict elen, /* Array that holds the inverse permutation */ +Gnum * restrict last, /* Array that holds the permutation */ +Gnum * restrict ncmpa, /* Number of times array iw was compressed */ +Gnum * restrict degree, /* Array that holds degree data */ +Gnum * restrict head, /* Linked list structure */ +Gnum * restrict next, /* Linked list structure */ +Gnum * restrict w) /* Flag array */ +{ + Gnum deg, degme, dext, dmax, e, elenme, eln, hash, hmod, i, + ilast, inext, j, jlast, jnext, k, knt1, knt2, knt3, + lenj, ln, me = 0, mem, mindeg, nel, newmem, + nleft, nvi, nvj, nvpiv, slenme, we, wflg, wnvi, x, + nbflag, nreal, lastd, nelme; + Gnum p, p1, p2, p3, pdst, pend, pj, pme, pme1, pme2, pn, psrc; + +/** -------------------------------------------------------------------- **/ +/** HALOAMD_V6: (January 1999, P. Amestoy) **/ +/** *********** **/ +/** 1/ ERROR 2 detection followed by stop statement suppressed. **/ +/** 2/ Pb 1 identified in V5 was not correctly solved. **/ +/** **/ +/** HALOAMD_V5: (December 1998, P. Amestoy) **/ +/** *********** **/ +/** 1/ Solved problem with matrix psmigr 1, because upper bound degree **/ +/** DEG>N was considered as a node of V1. **/ +/** **/ +/** HALOAMD_V4: (October 1998, P. Amestoy) **/ +/** *********** **/ +/** Only MA41 interface (ok for both scotch and MA41) is included in **/ +/** this file. **/ +/** **/ +/** HALOAMD_V3: (August 1998, P. Amestoy) **/ +/** ********** **/ +/** Solved problem in version 2: variables of V1 with len(i)=0 were not **/ +/** well processed. See modification of the input to characterize those **/ +/** variables. **/ +/** Problem detected by Jacko Koster while experimenting with C version **/ +/** 2 of haloAMD in the context of multiple front method based on **/ +/** MA27: "if for an interface variable i, row i in the matrix has only **/ +/** a nonzero entry on the diagonal, we first remove this entry and **/ +/** len(i) is set to zero on input to HALOAMD. However, this means that **/ +/** HALOAMD will treat variable i as an interior variable (in V0) **/ +/** instead as an interface variable (in V1). It is indeed a bit **/ +/** strange to have such interface variables but we encountered some **/ +/** in our debugging experiments with some random partitionings. **/ +/** Solution: **/ +/** IF on input i \in V1 and len(i)=0 (that is adjlist(i)={}) THEN **/ +/** len(i) must be set on input to -N-1. **/ +/** ENDIF **/ +/** Therefore, all variables i / len(i) < 0 and only those are in V1. **/ +/** Variables with len(i) = -N-1 are then processed differently at the **/ +/** beginning of the code. **/ +/** **/ +/** HALOAMD_V2: (April 1998) **/ +/** ********** **/ +/** The end of the tree (including links to block of flagged indices **/ +/** is built) . The list of flagged indices is considered as a dense **/ +/** amalgamated node. **/ +/** Tested on rosanna: ~amestoy/MA41_NEW/SUN_RISC_dbl/SOFT **/ +/** **/ +/** Comments on the OUTPUT: **/ +/** ---------------------- **/ +/** **/ +/** Let V= V0 U V1 the nodes of the initial graph (|V|=n). **/ +/** The assembly tree corresponds to the tree of the supernodes (or **/ +/** supervariables). Each node of the assembly tree is then composed of **/ +/** one principal variable and a list of secondary variables. The list **/ +/** of variable of a node (principal + secondary variables) then **/ +/** describes the structure of the diagonal bloc of the supernode. **/ +/** The elimination tree denotes the tree of all the variables(=nodes) **/ +/** and is therefore of order n. The arrays NV(N) and PE(N) give a **/ +/** description of the assembly tree. **/ +/** **/ +/** 1/ Description of array nv(N) (on OUPUT) **/ +/** nv(i)=0 i is a secondary variable. **/ +/** N+1> nv(i) >0 i is a principal variable, nv(i) holds the number **/ +/** of elements in column i of L (true degree of i) **/ +/** nv(i) = N+1 then i is a flagged variable (belonging to V1) **/ +/** **/ +/** 2/ Description of array PE(N) (on OUPUT) **/ +/** pe(i) = -(father of variable/node i) in the elimination tree. **/ +/** If nv (i) .gt. 0, then i represents a node in the assembly tree, **/ +/** and the parent of i is -pe (i), or zero if i is a root. **/ +/** If nv (i) = 0, then (i,-pe (i)) represents an edge in a **/ +/** subtree, the root of which is a node in the assembly tree. **/ +/** **/ +/** 3/ Example: **/ +/** Let If be a root node father of Is in the assembly tree. **/ +/** If is the principal variable of the node If and let If1, If2, If3 **/ +/** be the secondary variables of node If. Is is the principal **/ +/** variable of the node Is and let Is1, Is2 be the secondary **/ +/** variables of node Is. **/ +/** Then: **/ +/** NV(If1)=NV(If2)=NV(If3) = 0 (secondary variables) **/ +/** NV(Is1)=NV(Is2) = 0 (secondary variables) **/ +/** NV(If) > 0 (principal variable) **/ +/** NV(Is) > 0 (principal variable) **/ +/** PE(If) = 0 (root node) **/ +/** PE(Is) = -If (If is the father of Is in the assembly tree) **/ +/** PE(If1)=PE(If2)=PE(If3)= -If (If is the principal variable) **/ +/** PE(Is1)=PE(Is2)= -Is (Is is the principal variable) **/ +/** **/ +/** HALOAMD_V1: (September 1997) **/ +/** ********** **/ +/** Initial version designed to experiment the numerical (fill-in) **/ +/** impact of taking into account the halo. This code should be able to **/ +/** experiment no-halo, partial halo, complete halo. **/ +/** -------------------------------------------------------------------- **/ +/** HALOAMD is designed to process a graph composed of two types **/ +/** of nodes, V0 and V1, extracted from a larger gragh. **/ +/** V0^V1 = {}, **/ +/** We used Min. degree heuristic to order only **/ +/** nodes in V0, but the adjacency to nodes **/ +/** in V1 is taken into account during ordering. **/ +/** Nodes in V1 are odered at last. **/ +/** Adjacency between nodes of V1 need not be provided, **/ +/** however |len(i)| must always corresponds to the number of **/ +/** edges effectively provided in the adjacency list of i. **/ +/** On input : **/ +/** ******** **/ +/** Nodes INODE in V1 are flagged with len(INODE) = -degree **/ +/** Update version HALO V3 (August 1998): **/ +/** if len(i)=0 and i \in V1 then len(i) must be set **/ +/** on input to -N-1. **/ +/** ERROR return : **/ +/** ************ **/ +/** Negative value in ncmpa indicates an error detected **/ +/** by HALOAMD. **/ +/** **/ +/** The graph provided MUST follow the rule: **/ +/** if (i,j) is an edge in the gragh then **/ +/** j must be in the adjacency list of i AND **/ +/** i must be in the adjacency list of j. **/ +/** **/ +/** REMARKS : **/ +/** ------- **/ +/** 1/ Providing edges between nodes of V1 should not **/ +/** affect the final ordering, only the amount of edges **/ +/** of the halo should effectively affect the solution. **/ +/** This code should work in the following cases: **/ +/** 1/ halo not provided **/ +/** 2/ halo partially provided **/ +/** 3/ complete halo **/ +/** 4/ complete halo+interconnection between nodes of V1. **/ +/** **/ +/** 1/ should run and provide identical results (w.r.t to **/ +/** current implementation of AMD in SCOTCH). **/ +/** 3/ and 4/ should provide identical results. **/ +/** **/ +/** 2/ All modifications of the MC47 initial code are indicated **/ +/** with begin HALO .. end HALO **/ +/** **/ +/** Ordering of nodes in V0 is based on Approximate Minimum Degree **/ +/** ordering algorithm, with aggressive absorption: **/ +/** Given a representation of the nonzero pattern of a symmetric matrix, **/ +/** A, (excluding the diagonal) perform an approximate minimum **/ +/** (UMFPACK/MA38-style) degree ordering to compute a pivot order **/ +/** such that fill-in in the Cholesky **/ +/** factors A = LL^T is kept low. At each step, the pivot **/ +/** selected is the one with the minimum UMFPACK/MA38-style **/ +/** upper-bound on the external degree. Aggresive absorption is **/ +/** used to tighten the bound on the degree. This can result an **/ +/** significant improvement in the quality of the ordering for **/ +/** some matrices. **/ +/** The approximate degree algorithm implemented here is the **/ +/** symmetric analogue of the degree update algorithm in MA38, by **/ +/** Davis and Duff, also in the Harwell Subroutine Library. **/ +/** **/ +/** **** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ***** **/ +/** ** If you want error checking, a more versatile input format, and ** **/ +/** ** a simpler user interface, then use MC47A/AD in the Harwell ** **/ +/** ** Subroutine Library, which checks for errors, transforms the ** **/ +/** ** input, and calls MC47B/BD. ** **/ +/** ******************************************************************** **/ +/** References: (UF Tech Reports are available via anonymous ftp **/ +/** to ftp.cis.ufl.edu:cis/tech-reports). **/ +/** [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern **/ +/** multifrontal method for sparse LU factorization", **/ +/** SIAM J. Matrix Analysis and Applications, to appear. **/ +/** also Univ. of Florida Technical Report TR-94-038. **/ +/** Discuss UMFPACK / MA38. **/ +/** [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, **/ +/** "An approximate minimum degree ordering algorithm," **/ +/** SIAM J. Matrix Analysis and Applications (to appear), **/ +/** also Univ. of Florida Technical Report TR-94-039. **/ +/** Discusses this routine. **/ +/** [3] Alan George and Joseph Liu, "The evolution of the **/ +/** minimum degree ordering algorithm," SIAM Review, vol. **/ +/** 31, no. 1, pp. 1-19, March 1989. We list below the **/ +/** features mentioned in that paper that this code **/ +/** includes: **/ +/** mass elimination: **/ +/** Yes. MA27 relied on supervariable detection for mass **/ +/** elimination. **/ +/** indistinguishable nodes: **/ +/** Yes (we call these "supervariables"). This was also **/ +/** in the MA27 code - although we modified the method of **/ +/** detecting them (the previous hash was the true degree, **/ +/** which we no longer keep track of). A supervariable is **/ +/** a set of rows with identical nonzero pattern. All **/ +/** variables in a supervariable are eliminated together. **/ +/** Each supervariable has as its numerical name that of **/ +/** one of its variables (its principal variable). **/ +/** quotient graph representation: **/ +/** Yes. We use the term "element" for the cliques formed **/ +/** during elimination. This was also in the MA27 code. **/ +/** The algorithm can operate in place, but it will work **/ +/** more efficiently if given some "elbow room." **/ +/** element absorption: **/ +/** Yes. This was also in the MA27 code. **/ +/** external degree: **/ +/** Yes. The MA27 code was based on the true degree. **/ +/** incomplete degree update and multiple elimination: **/ +/** No. This was not in MA27, either. Our method of **/ +/** degree update within MC47B/BD is element-based, not **/ +/** variable-based. It is thus not well-suited for use **/ +/** with incomplete degree update or multiple elimination. **/ +/** -------------------------------------------------------------------- **/ +/** Authors, and Copyright (C) 1995 by: **/ +/** Timothy A. Davis, Patrick Amestoy, Iain S. Duff, & **/ +/** John K. Reid. **/ +/** Modified (V1) by P.R. Amestoy ENSEEIHT (1997) **/ +/** Modified (V2) by P.R. Amestoy ENSEEIHT (1998) **/ +/** Modified (V3) by P.R. Amestoy ENSEEIHT (1998) **/ +/** Modified (V4) by P.R. Amestoy ENSEEIHT (1998) **/ +/** Modified (V5) by P.R. Amestoy ENSEEIHT (1998) **/ +/** Modified (V6) by P.R. Amestoy ENSEEIHT (1999) **/ +/** **/ +/** Dates: September, 1995 **/ +/** September, 1997 (halo AMD V1) **/ +/** April, 1998 (halo AMD V2) **/ +/** August, 1998 (halo AMD V3) **/ + + -- w; /* Parameter adjustments */ + -- next; + -- head; + -- degree; + -- last; + -- elen; + -- nv; + -- len; + -- pe; + -- iw; + + wflg = 2; + mindeg = 1; + *ncmpa = 0; + nel = 0; + hmod = MAX (1, (n - 1)); + dmax = 0; + mem = pfree - 1; + nbflag = 0; + lastd = 0; + + memSet (last + 1, 0, n * sizeof (Gnum)); + memSet (head + 1, 0, n * sizeof (Gnum)); + + if (nbelts == 0) { /* Patch 8/12/03 */ + memSet (elen + 1, 0, n * sizeof (Gnum)); + for (i = 1; i <= n; i ++) { + nv[i] = 1; + w[i] = 1; + if (len[i] < 0) { + degree[i] = n + 1; + nbflag ++; + if (len[i] == - (n + 1)) { /* Patch 09/08/98 */ + len[i] = 0; + pe[i] = 0; /* Patch 12/12/03 : Because of compress, we force skipping those entries (which are anyway empty) */ + } + else + len[i] = - len[i]; + } + else + degree[i] = len[i]; + } + } + else { /* Patch 08/12/03 : Duplicate part of previous loop to avoid sytematic testing for elements */ + for (i = 1; i <= n; i ++) { + nv[i] = 1; + w[i] = 1; + if (len[i] < 0) { /* i \in V1 */ + degree[i] = n + 1; + nbflag ++; + if (len[i] == - (n + 1)) { /* Patch 09/08/98 */ + len[i] = 0; + pe[i] = 0; /* Patch 12/12/03 : because of compress, we force skipping those entries (which are anyway empty) */ + elen[i] = 0; /* Patch 16/12/03 */ + } + else { + len[i] = - len[i]; + elen[i] = len[i]; /* Patch 16/12/03 : only elements are adjacent to a variable */ + } + } + else { /* i \in Ve or V0 */ + if (elen[i] < 0) { /* i \in Ve */ + nel ++; + degree[i] = len[i]; + elen[i] = - nel; + dmax = MAX (dmax, degree[i]); /* Patch 11/03/04 */ + } + else { + degree[i] = elen[i]; + elen[i] = len[i]; /* Patch 16/12/03 : only elements are adjacent to a variable */ + } + } + } + } + +#ifdef SCOTCH_DEBUG_ORDER2 + if (nbelts != nel) /* Temporary Patch 8/12/03 */ + printf ("error 8Dec2003\n"); +#endif /* SCOTCH_DEBUG_ORDER2 */ + + nreal = n - nbflag; + + for (i = 1; i <= n; i ++) { + if (elen[i] < 0 ) /* Patch 16/12/03 : Skip elements */ + continue; + + deg = degree[i]; + if (deg == (n + 1)) { + deg = n; + if (lastd == 0) { + lastd = i; + head[deg] = i; + next[i] = 0; + last[i] = 0; + } + else { + next[lastd] = i; + last[i] = lastd; + lastd = i; + next[i] = 0; + } + } + else if (deg > 0) { + inext = head[deg]; + if (inext != 0) + last[inext] = i; + next[i] = inext; + head[deg] = i; + } + else { + nel ++; + elen[i] = - nel; + pe[i] = 0; + w[i] = 0; + } + } /* L20: */ + + nleft = n - nel; /* Patch v5 12/12/98 */ + + while (nel < nreal) { /* WHILE (selecting pivots) DO */ + for (deg = mindeg; deg <= n; deg ++) { /* Patch 17/11/97 */ + me = head[deg]; + if (me > 0) + break; /* GO to 50 */ + } /* L40: */ + mindeg = deg; + if (me <= 0) { /* Error 1 */ + *ncmpa = -n; + return; + } + + inext = next[me]; + if (inext != 0) + last[inext] = 0; + head[deg] = inext; + + elenme = elen[me]; + elen[me] = - (nel + 1); + nvpiv = nv[me]; + nel += nvpiv; + + nv[me] = - nvpiv; + degme = 0; + if (elenme == 0) { + pme1 = pe[me]; + pme2 = pme1 - 1; + + for (p = pme1; p <= pme1 + len[me] - 1; p ++) { + i = iw[p]; + nvi = nv[i]; + if (nvi > 0) { + degme += nvi; + nv[i] = - nvi; + pme2 ++; + iw[pme2] = i; + + if (degree[i] <= n) { + ilast = last[i]; + inext = next[i]; + if (inext != 0) + last[inext] = ilast; + if (ilast != 0) + next[ilast] = inext; + else + head[degree[i]] = inext; + } + } + } /* L60: */ + + newmem = 0; + } + else { + p = pe[me]; + pme1 = pfree; + slenme = len[me] - elenme; + for (knt1 = 1; knt1 <= elenme + 1; knt1 ++) { + if (knt1 > elenme) { + e = me; + pj = p; + ln = slenme; + } + else { + e = iw[p ++]; + pj = pe[e]; + ln = len[e]; + } + + for (knt2 = 1; knt2 <= ln; knt2 ++) { + i = iw[pj ++]; + nvi = nv[i]; + if (nvi > 0) { + if (pfree > iwlen) { + pe[me] = p; + len[me] -= knt1; + if (len[me] == 0) + pe[me] = 0; + pe[e] = pj; + len[e] = ln - knt2; + if (len[e] == 0) + pe[e] = 0; + (*ncmpa) ++; + + for (j = 1; j <= n; j ++) { + pn = pe[j]; + if (pn > 0) { + pe[j] = iw[pn]; + iw[pn] = - j; + } + } /* L70: */ + + pdst = 1; + psrc = 1; + pend = pme1 - 1; + + while (psrc <= pend) { /* L80: */ + j = - iw[psrc ++]; + if (j > 0) { + iw[pdst] = pe[j]; + pe[j] = pdst ++; + lenj = len[j]; + for (knt3 = 0; knt3 <= lenj - 2; knt3 ++) + iw[pdst + knt3] = iw[psrc + knt3]; + pdst = pdst + (lenj - 1); + psrc = psrc + (lenj - 1); + } + } + + p1 = pdst; + for (psrc = pme1; psrc <= pfree - 1; psrc ++, pdst ++) /* L100: */ + iw[pdst] = iw[psrc]; + pme1 = p1; + pfree = pdst; + pj = pe[e]; + p = pe[me]; + } + + degme += nvi; + nv[i] = - nvi; + iw[pfree] = i; + pfree ++; + + if (degree[i] <= n) { + ilast = last[i]; + inext = next[i]; + if (inext != 0) + last[inext] = ilast; + if (ilast != 0) + next[ilast] = inext; + else + head[degree[i]] = inext; + } + } + } /* L110: */ + + if (e != me) { + pe[e] = -me; + w[e] = 0; + } + } /* L120: */ + pme2 = pfree - 1; + + newmem = pfree - pme1; + mem += newmem; + } + + degree[me] = degme; + pe[me] = pme1; + len[me] = pme2 - pme1 + 1; + + if (wflg + n <= wflg) { + for (x = 1; x <= n; x ++) { + if (w[x] != 0) + w[x] = 1; + } /* L130: */ + wflg = 2; + } + + for (pme = pme1; pme <= pme2; pme ++) { + i = iw[pme]; + eln = elen[i]; + if (eln > 0) { + nvi = - nv[i]; + wnvi = wflg - nvi; + for (p = pe[i]; p < pe[i] + eln; p ++) { + e = iw[p]; + we = w[e]; + if (we >= wflg) + we -= nvi; + else if (we != 0) + we = degree[e] + wnvi; + w[e] = we; + } /* L140: */ + } + } /* L150: */ + + for (pme = pme1; pme <= pme2; pme ++) { + i = iw[pme]; + p1 = pe[i]; + p2 = p1 + elen[i] - 1; + pn = p1; + hash = 0; + deg = 0; + + for (p = p1; p <= p2; p ++) { + e = iw[p]; + dext = w[e] - wflg; + if (dext > 0) { + deg += dext; + iw[pn ++] = e; + hash += e; + } + else if (dext == 0) { + pe[e] = -me; + w[e] = 0; + } + } /* L160: */ + elen[i] = pn - p1 + 1; + + p3 = pn; + for (p = p2 + 1; p < p1 + len[i]; p ++) { + j = iw[p]; + nvj = nv[j]; + if (nvj > 0) { + deg += nvj; + iw[pn ++] = j; + hash += j; + } + } /* L170: */ + + if (degree[i] == (n + 1)) + deg = n + 1; + if (deg == 0) { + pe[i] = - me; + nvi = - nv[i]; + degme -= nvi; + nvpiv += nvi; + nel += nvi; + nv[i] = 0; + elen[i] = 0; + } + else { + if (degree[i] != (n + 1)) { /* Patch v6 05/01/99 */ + deg = MIN (nleft, deg); /* Patch v5 12/12/98 */ + degree[i] = MIN (degree[i], deg); + } + + iw[pn] = iw[p3]; + iw[p3] = iw[p1]; + iw[p1] = me; + len[i] = pn - p1 + 1; + + if (deg <= n) { + hash = (hash % hmod) + 1; + j = head[hash]; + if (j <= 0) { + next[i] = - j; + head[hash] = - i; + } + else { + next[i] = last[j]; + last[j] = i; + } + last[i] = hash; + } + } + } /* L180: */ + degree[me] = degme; + + dmax = MAX (dmax, degme); + wflg += dmax; + + if (wflg + n <= wflg) { + for (x = 1; x <= n; x ++) { + if (w[x] != 0) + w[x] = 1; + } + wflg = 2; + } + + for (pme = pme1; pme <= pme2; pme ++) { + i = iw[pme]; + if ((nv[i] < 0) && (degree[i] <= n)) { + hash = last[i]; + j = head[hash]; + if (j == 0) + continue; + if (j < 0) { + i = - j; + head[hash] = 0; + } + else { + i = last[j]; + last[j] = 0; + } + if (i == 0) + continue; + +L200: /* WHILE LOOP: */ + if (next[i] != 0) { + ln = len[i]; + eln = elen[i]; + for (p = pe[i] + 1; p < pe[i] + ln; p ++) + w[iw[p]] = wflg; + + jlast = i; + j = next[i]; + +L220: /* WHILE LOOP: */ + if (j != 0) { + if (len[j] != ln) + goto L240; + if (elen[j] != eln) + goto L240; + + for (p = pe[j] + 1; p < pe[j] + ln; p ++) { + if (w[iw[p]] != wflg) + goto L240; + } /* L230: */ + + pe[j] = -i; + nv[i] += nv[j]; + nv[j] = 0; + elen[j] = 0; + + j = next[j]; + next[jlast] = j; + goto L220; + +L240: + jlast = j; + j = next[j]; + goto L220; + } + + wflg ++; + i = next[i]; + if (i != 0) + goto L200; + } + } + } + + p = pme1; + nleft = n - nel; + for (pme = pme1; pme <= pme2; pme ++) { + i = iw[pme]; + nvi = - nv[i]; + if (nvi > 0) { + nv[i] = nvi; + if (degree[i] <= n) { + deg = MIN (degree[i] + degme, nleft) - nvi; + + inext = head[deg]; + if (inext != 0) + last[inext] = i; + next[i] = inext; + last[i] = 0; + head[deg] = i; + + mindeg = MIN (mindeg, deg); + degree[i] = deg; + } + + iw[p ++] = i; + } + } /* L260: */ + + nv[me] = nvpiv + degme; + len[me] = p - pme1; + if (len[me] == 0) { + pe[me] = 0; + w[me] = 0; + } + if (newmem != 0) { + pfree = p; + mem = mem - newmem + len[me]; + } + } /* END WHILE (selecting pivots) */ + + if (nel < n) { /* Patch 12/12/98 (old: nreal < n) */ + for (deg = mindeg; deg <= n; deg ++) { + me = head[deg]; + if (me > 0) + break; + } + + mindeg = deg; + nelme = - (nel + 1); + for (x = 1; x <= n; x ++) { + if ((pe[x] > 0) && (elen[x] < 0)) + pe[x] = - me; + else if (degree[x] == (n + 1)) { + nel += nv[x]; + pe[x] = - me; + elen[x] = 0; + nv[x] = 0; /* Patch 12/12/98 (old: n + 1) */ + } + } + + elen[me] = nelme; + nv[me] = n - nreal; /* Patch 12/12/98 (old: n + 1) */ + pe[me] = 0; + if (nel != n) { /* Error 2 */ + *ncmpa = - (n + 1); + return; + } + } + + for (i = 1; i <= n; i ++) { + if (elen[i] == 0) { + j = - pe[i]; + + while (elen[j] >= 0) /* L270: */ + j = - pe[j]; + e = j; + + k = - elen[e]; + j = i; + + while (elen[j] >= 0) { /* L280: */ + jnext = - pe[j]; + pe[j] = - e; + if (elen[j] == 0) + elen[j] = k ++; + j = jnext; + } + elen[e] = - k; + } + } /* L290: */ + +#ifdef DEAD_CODE /* No need for permutations */ + for (i = 1; i <= n; i ++) { /* Patch 19/10/98 */ + k = abs (elen[i]); + last[k] = i; + elen[i] = k; + } /* L300: */ +#endif /* DEAD_CODE */ +} diff --git a/scotch_6.0.3/src/libscotch/hall_order_hd.h b/scotch_6.0.3/src/libscotch/hall_order_hd.h new file mode 100644 index 00000000..988f0fb7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hall_order_hd.h @@ -0,0 +1,62 @@ +/* Copyright 2004,2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hall_order_hd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the block-oriented Halo **/ +/** Approximate (Multiple) Minimum Degree **/ +/** ordering routine. **/ +/** **/ +/** DATES : # Version 3.4 : from : 15 may 2001 **/ +/** to : 15 may 2001 **/ +/** # Version 4.0 : from : 10 jan 2003 **/ +/** to : 10 dec 2003 **/ +/** # Version 6.0 : from : 08 mar 2012 **/ +/** to : 08 mar 2012 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef HALL_ORDER_HD +#define static +#endif + +void hallOrderHdHalmd (const Gnum n, const Gnum nbelts, const Gnum iwlen, Gnum pe[], Gnum pfree, Gnum len[], Gnum iw[], Gnum nv[], Gnum elen[], Gnum last[], Gnum * ncmpa, Gnum degree[], Gnum head[], Gnum next[], Gnum w[]); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hall_order_hf.c b/scotch_6.0.3/src/libscotch/hall_order_hf.c new file mode 100644 index 00000000..7ca80e4c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hall_order_hf.c @@ -0,0 +1,1024 @@ +/* Copyright 2004,2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hall_order_hf.c **/ +/** **/ +/** AUTHOR : Patrick AMESTOY **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a halo graph or mesh **/ +/** structure using the block-oriented Halo **/ +/** Approximate (Multiple) Minimum Fill **/ +/** algorithm, with super-variable **/ +/** accounting R2HAMDf4 (v2.0). **/ +/** **/ +/** DATES : # Version 3.4 : from : 15 may 2001 **/ +/** to : 23 nov 2001 **/ +/** # Version 4.0 : from : 10 jan 2003 **/ +/** to : 29 aug 2007 **/ +/** # Version 5.1 : from : 08 dec 2010 **/ +/** to : 08 dec 2010 **/ +/** # Version 6.0 : from : 08 mar 2012 **/ +/** to : 08 mar 2012 **/ +/** **/ +/** NOTES : # This module contains pieces of code **/ +/** that belong to other people; see **/ +/** below. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HALL_ORDER_HF + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "hall_order_hf.h" + +/* -- translated by f2c (version 19970219). */ + +/** -------------------------------------------------------------------- **/ +/** December 8th 2003 **/ +/** Unique version for both graph of variables and graphs of elements **/ +/** Let us refer to as **/ +/** Gv a graph with only variables **/ +/** Ge a graph with both variables and elements **/ +/** **/ +/** Notations used: **/ +/** **/ +/** Let V be the set of nodes **/ +/** V = Ve + V0 + V1 **/ +/** V0 = Set of variable nodes (not in halo) **/ +/** V1 = Set of variable nodes (in halo) **/ +/** Ve = Set of element nodes **/ +/** **/ +/** All 3 sets are disjoint, Ve and V1 can be empty **/ +/** **/ +/** Modifications w.r.t. previous version : **/ +/** **/ +/** New Input: **/ +/** --------- **/ +/** nbelts : integer holding size of Ve **/ +/** =0 if Gv (graph of variables) **/ +/** >0 if Ge **/ +/** **/ +/** Extension of the meaning of input entry len for nodes in Ve **/ +/** --------- **/ +/** len(i) = | Adj(i) | if i \in V0 U Ve **/ +/** ( Note that in the case of a GE graph **/ +/** if v\in V0 then len(v) = nb of elements adjacent to v ) **/ +/** len(i) = - | Adj(i) | if i \in V1 **/ +/** or -N -1 if | Adj(i) | = 0 and i \in V1 **/ +/** **/ +/** Modified the meaning of input entry elen **/ +/** --------- **/ +/** if e \in Ve then elen (e) = -N-1 **/ +/** if v \in V0 then elen (v) = External degree of v **/ +/** Gv : elen (v) = len(v) **/ +/** Ge : elen (v) **/ +/** should be computed in SCOTCH **/ +/** if v \in V1 then elen (v) = 0 **/ +/** **/ +/** **/ +/** Output is unchanged **/ +/** --------- **/ +/** **/ +/** **/ +/** End remarks done on December 8th 2003 **/ +/** ---------------------------------------------------------------------**/ +/** **/ +/** **/ +/** AMF4 (version used on newton for uns tests) **/ +/** given to Francois on Nov 31 2000 **/ +/** Approximation of level4 of the minimum fill heuristic **/ +/** (best approx of Min fill currently available based on collaborative **/ +/** work between P. Amestoy, T. Davis and I. Duff) **/ +/** **/ +/** Remarks: **/ +/** ------- **/ +/** 1/ !!!!!!!! WARNING !!!!!!!!!! **/ +/** TWO additionnal parameters w.r.t HALOAMD **/ +/** -------------------------- **/ +/** NBBUCK : integer greater than 1 (advised value is 2*N) **/ +/** HEAD : HEAD(0:NBBUCK+1) integer array of size NBBUCK+2 **/ +/** NOTE that it starts at index 0 !! **/ +/** **/ +/** 2/ Interface for MA41 or SCOTCH **/ +/** **/ +/** 3/ Nodes of V1 are amalgamated in one root supervariable **/ +/** the complete tree (of V0+V1) is correct in the sense of **/ +/** MC47B output interface (NV for V1 nodes is ok). **/ +/** Output data (PE,NV) can then be exploited by MA41LD. **/ +/** Variable in V1 cannot be characterized on output. **/ +/** -------------------------------------------------------------------- **/ + +void +hallOrderHfR2hamdf4 ( +const Gnum n, /* Matrix order */ +const Gnum nbelts, /* Number of elements */ +const Gnum nbbuck, /* Number of buckets */ +const Gnum iwlen, /* Length of array iw */ +Gnum * restrict pe /* [] */, /* Array of indexes in iw of start of row i */ +Gnum pfree, /* Useful size in iw */ +Gnum * restrict len /* [] */, /* Array of lengths of adjacency lists */ +Gnum * restrict iw /* [] */, /* Adjacency list array */ +Gnum * restrict nv /* [] */, /* Array of element degrees */ +Gnum * restrict elen /* [] */, /* Array that holds the inverse permutation */ +Gnum * restrict last /* [] */, /* Array that holds the permutation */ +Gnum * restrict ncmpaptr, /* Number of times array iw was compressed */ +Gnum * restrict degree /* [] */, /* Array that holds degree data */ +Gnum * restrict wf /* [] */, /* Flag array */ +Gnum * restrict next /* [] */, /* Linked list structure */ +Gnum * restrict w /* [] */, /* Flag array */ +Gnum * restrict head /* [] */) /* Linked list structure */ +{ + Gnum hash, pend, hmod, lenj, dmax, wflg, dext, psrc, pdst, + wnvi, e, i, j, k, p, degme, x, nelme, nreal, lastd, nleft, + ilast, jlast, inext, jnext, n2, p1, nvpiv, p2, p3, me = 0, nbflag, ln, + we, pj, pn, mindeg, elenme, slenme, maxmem, newmem, wf3, wf4, + deg, eln, mem, nel, pme, pas, nvi, nvj, pme1, pme2, knt1, knt2, knt3; + Gnum ncmpa; + float rmf, rmf1; + +/** Min fill approximation one extra array of size NBBUCK+2 is needed **/ +/** INTEGER HEAD(0:NBBUCK+1) **/ +/** -------------------------------------------------------------------- **/ +/** HALOAMD_V6: (January 1999, P. Amestoy) **/ +/** *********** **/ +/** 1/ ERROR 2 detection followed by stop statement suppressed. **/ +/** 2/ Pb 1 identified in V5 was not correctly solved. **/ +/** **/ +/** HALOAMD_V5: (December 1998, P. Amestoy) **/ +/** *********** **/ +/** 1/ Solved problem with matrix psmigr 1, because upper bound degree **/ +/** DEG>N was considered as a node of V1. **/ +/** **/ +/** HALOAMD_V4: (October 1998, P. Amestoy) **/ +/** *********** **/ +/** Only MA41 interface (ok for both scotch and MA41) is included in **/ +/** this file. **/ +/** **/ +/** HALOAMD_V3: (August 1998, P. Amestoy) **/ +/** ********** **/ +/** Solved problem in version 2: variables of V1 with len(i)=0 were not **/ +/** well processed. See modification of the input to characterize those **/ +/** variables. **/ +/** Problem detected by Jacko Koster while experimenting with C version **/ +/** 2 of haloAMD in the context of multiple front method based on **/ +/** MA27: "if for an interface variable i, row i in the matrix has only **/ +/** a nonzero entry on the diagonal, we first remove this entry and **/ +/** len(i) is set to zero on input to HALOAMD. However, this means that **/ +/** HALOAMD will treat variable i as an interior variable (in V0) **/ +/** instead as an interface variable (in V1). It is indeed a bit **/ +/** strange to have such interface variables but we encountered some **/ +/** in our debugging experiments with some random partitionings. **/ +/** Solution: **/ +/** IF on input i \in V1 and len(i)=0 (that is adjlist(i)={}) THEN **/ +/** len(i) must be set on input to -N-1. **/ +/** ENDIF **/ +/** Therefore, all variables i / len(i) < 0 and only those are in V1. **/ +/** Variables with len(i) = -N-1 are then processed differently at the **/ +/** beginning of the code. **/ +/** **/ +/** HALOAMD_V2: (April 1998) **/ +/** ********** **/ +/** The end of the tree (including links to block of flagged indices **/ +/** is built) . The list of flagged indices is considered as a dense **/ +/** amalgamated node. **/ +/** Tested on rosanna: ~amestoy/MA41_NEW/SUN_RISC_dbl/SOFT **/ +/** **/ +/** Comments on the OUTPUT: **/ +/** ---------------------- **/ +/** **/ +/** Let V= V0 U V1 the nodes of the initial graph (|V|=n). **/ +/** The assembly tree corresponds to the tree of the supernodes (or **/ +/** supervariables). Each node of the assembly tree is then composed of **/ +/** one principal variable and a list of secondary variables. The list **/ +/** of variable of a node (principal + secondary variables) then **/ +/** describes the structure of the diagonal bloc of the supernode. **/ +/** The elimination tree denotes the tree of all the variables(=nodes) **/ +/** and is therefore of order n. The arrays NV(N) and PE(N) give a **/ +/** description of the assembly tree. **/ +/** **/ +/** 1/ Description of array nv(N) (on OUPUT) **/ +/** nv(i)=0 i is a secondary variable. **/ +/** N+1> nv(i) >0 i is a principal variable, nv(i) holds the number **/ +/** of elements in column i of L (true degree of i) **/ +/** nv(i) = N+1 then i is a flagged variable (belonging to V1) **/ +/** **/ +/** 2/ Description of array PE(N) (on OUPUT) **/ +/** pe(i) = -(father of variable/node i) in the elimination tree. **/ +/** If nv (i) .gt. 0, then i represents a node in the assembly tree, **/ +/** and the parent of i is -pe (i), or zero if i is a root. **/ +/** If nv (i) = 0, then (i,-pe (i)) represents an edge in a **/ +/** subtree, the root of which is a node in the assembly tree. **/ +/** **/ +/** 3/ Example: **/ +/** Let If be a root node father of Is in the assembly tree. **/ +/** If is the principal variable of the node If and let If1, If2, If3 **/ +/** be the secondary variables of node If. Is is the principal **/ +/** variable of the node Is and let Is1, Is2 be the secondary **/ +/** variables of node Is. **/ +/** Then: **/ +/** NV(If1)=NV(If2)=NV(If3) = 0 (secondary variables) **/ +/** NV(Is1)=NV(Is2) = 0 (secondary variables) **/ +/** NV(If) > 0 (principal variable) **/ +/** NV(Is) > 0 (principal variable) **/ +/** PE(If) = 0 (root node) **/ +/** PE(Is) = -If (If is the father of Is in the assembly tree) **/ +/** PE(If1)=PE(If2)=PE(If3)= -If (If is the principal variable) **/ +/** PE(Is1)=PE(Is2)= -Is (Is is the principal variable) **/ +/** **/ +/** HALOAMD_V1: (September 1997) **/ +/** ********** **/ +/** Initial version designed to experiment the numerical (fill-in) **/ +/** impact of taking into account the halo. This code should be able to **/ +/** experiment no-halo, partial halo, complete halo. **/ +/** -------------------------------------------------------------------- **/ +/** HALOAMD is designed to process a graph composed of two types **/ +/** of nodes, V0 and V1, extracted from a larger gragh. **/ +/** V0^V1 = {}, **/ +/** We used Min. degree heuristic to order only **/ +/** nodes in V0, but the adjacency to nodes **/ +/** in V1 is taken into account during ordering. **/ +/** Nodes in V1 are odered at last. **/ +/** Adjacency between nodes of V1 need not be provided, **/ +/** however |len(i)| must always corresponds to the number of **/ +/** edges effectively provided in the adjacency list of i. **/ +/** On input : **/ +/** ******** **/ +/** Nodes INODE in V1 are flagged with len(INODE) = -degree **/ +/** Update version HALO V3 (August 1998): **/ +/** if len(i)=0 and i \in V1 then len(i) must be set **/ +/** on input to -N-1. **/ +/** ERROR return : **/ +/** ************ **/ +/** Negative value in ncmpa indicates an error detected **/ +/** by HALOAMD. **/ +/** **/ +/** The graph provided MUST follow the rule: **/ +/** if (i,j) is an edge in the gragh then **/ +/** j must be in the adjacency list of i AND **/ +/** i must be in the adjacency list of j. **/ +/** **/ +/** REMARKS : **/ +/** ------- **/ +/** 1/ Providing edges between nodes of V1 should not **/ +/** affect the final ordering, only the amount of edges **/ +/** of the halo should effectively affect the solution. **/ +/** This code should work in the following cases: **/ +/** 1/ halo not provided **/ +/** 2/ halo partially provided **/ +/** 3/ complete halo **/ +/** 4/ complete halo+interconnection between nodes of V1. **/ +/** **/ +/** 1/ should run and provide identical results (w.r.t to **/ +/** current implementation of AMD in SCOTCH). **/ +/** 3/ and 4/ should provide identical results. **/ +/** **/ +/** 2/ All modifications of the MC47 initial code are indicated **/ +/** with begin HALO .. end HALO **/ +/** **/ +/** Ordering of nodes in V0 is based on Approximate Minimum Degree **/ +/** ordering algorithm, with aggressive absorption: **/ +/** Given a representation of the nonzero pattern of a symmetric matrix, **/ +/** A, (excluding the diagonal) perform an approximate minimum **/ +/** (UMFPACK/MA38-style) degree ordering to compute a pivot order **/ +/** such that fill-in in the Cholesky **/ +/** factors A = LL^T is kept low. At each step, the pivot **/ +/** selected is the one with the minimum UMFPACK/MA38-style **/ +/** upper-bound on the external degree. Aggresive absorption is **/ +/** used to tighten the bound on the degree. This can result an **/ +/** significant improvement in the quality of the ordering for **/ +/** some matrices. **/ +/** The approximate degree algorithm implemented here is the **/ +/** symmetric analogue of the degree update algorithm in MA38, by **/ +/** Davis and Duff, also in the Harwell Subroutine Library. **/ +/** **/ +/** **** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ***** **/ +/** ** If you want error checking, a more versatile input format, and ** **/ +/** ** a simpler user interface, then use MC47A/AD in the Harwell ** **/ +/** ** Subroutine Library, which checks for errors, transforms the ** **/ +/** ** input, and calls MC47B/BD. ** **/ +/** ******************************************************************** **/ +/** References: (UF Tech Reports are available via anonymous ftp **/ +/** to ftp.cis.ufl.edu:cis/tech-reports). **/ +/** [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern **/ +/** multifrontal method for sparse LU factorization", **/ +/** SIAM J. Matrix Analysis and Applications, to appear. **/ +/** also Univ. of Florida Technical Report TR-94-038. **/ +/** Discuss UMFPACK / MA38. **/ +/** [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, **/ +/** "An approximate minimum degree ordering algorithm," **/ +/** SIAM J. Matrix Analysis and Applications (to appear), **/ +/** also Univ. of Florida Technical Report TR-94-039. **/ +/** Discusses this routine. **/ +/** [3] Alan George and Joseph Liu, "The evolution of the **/ +/** minimum degree ordering algorithm," SIAM Review, vol. **/ +/** 31, no. 1, pp. 1-19, March 1989. We list below the **/ +/** features mentioned in that paper that this code **/ +/** includes: **/ +/** mass elimination: **/ +/** Yes. MA27 relied on supervariable detection for mass **/ +/** elimination. **/ +/** indistinguishable nodes: **/ +/** Yes (we call these "supervariables"). This was also **/ +/** in the MA27 code - although we modified the method of **/ +/** detecting them (the previous hash was the true degree, **/ +/** which we no longer keep track of). A supervariable is **/ +/** a set of rows with identical nonzero pattern. All **/ +/** variables in a supervariable are eliminated together. **/ +/** Each supervariable has as its numerical name that of **/ +/** one of its variables (its principal variable). **/ +/** quotient graph representation: **/ +/** Yes. We use the term "element" for the cliques formed **/ +/** during elimination. This was also in the MA27 code. **/ +/** The algorithm can operate in place, but it will work **/ +/** more efficiently if given some "elbow room." **/ +/** element absorption: **/ +/** Yes. This was also in the MA27 code. **/ +/** external degree: **/ +/** Yes. The MA27 code was based on the true degree. **/ +/** incomplete degree update and multiple elimination: **/ +/** No. This was not in MA27, either. Our method of **/ +/** degree update within MC47B/BD is element-based, not **/ +/** variable-based. It is thus not well-suited for use **/ +/** with incomplete degree update or multiple elimination. **/ +/** -------------------------------------------------------------------- **/ +/** Authors, and Copyright (C) 1995 by: **/ +/** Timothy A. Davis, Patrick Amestoy, Iain S. Duff, & **/ +/** John K. Reid. **/ +/** Modified (V1) by P.R. Amestoy ENSEEIHT (1997) **/ +/** Modified (V2) by P.R. Amestoy ENSEEIHT (1998) **/ +/** Modified (V3) by P.R. Amestoy ENSEEIHT (1998) **/ +/** Modified (V4) by P.R. Amestoy ENSEEIHT (1998) **/ +/** Modified (V5) by P.R. Amestoy ENSEEIHT (1998) **/ +/** Modified (V6) by P.R. Amestoy ENSEEIHT (1999) **/ +/** **/ +/** Dates: September, 1995 **/ +/** September, 1997 (halo AMD V1) **/ +/** April, 1998 (halo AMD V2) **/ +/** August, 1998 (halo AMD V3) **/ + + -- w; /* Parameter adjustments */ + -- next; + -- wf; + -- degree; + -- last; + -- elen; + -- nv; + -- len; + -- pe; + -- iw; +/* -- head; Array head not updated since starts from 0 */ + + n2 = - (nbbuck + 1); +/* pas = n / 8; [Update F.P. 20020715 selon hamf_20020220] Distance betweeen elements of the N, ..., NBBUCK entries of HEAD */ + pas = MAX ((n / 8), 1); /* Distance betweeen elements of the N, ..., NBBUCK entries of HEAD */ + wflg = 2; + ncmpa = 0; + nel = 0; + hmod = MAX (1, nbbuck - 1); + dmax = 0; + mem = pfree - 1; + maxmem = mem; + mindeg = 0; + rmf = (float) (n) * (float) (n - 1); /* Average sparsity of matrix; diagonal entry is not in mem */ + nbflag = 0; + lastd = 0; + + memSet (head, 0, (nbbuck + 2) * sizeof (Gnum)); + memSet (last + 1, 0, n * sizeof (Gnum)); + + if (nbelts == 0) { /* Patch 8/12/03 */ + memSet (elen + 1, 0, n * sizeof (Gnum)); + for (i = 1; i <= n; i ++) { + nv[i] = 1; + w[i] = 1; + if (len[i] < 0) { + degree[i] = n2; + nbflag ++; + if (len[i] == - (n + 1)) { /* Patch 09/08/98 */ + len[i] = 0; + pe[i] = 0; /* Patch 12/12/03 : Because of compress, we force skipping those entries (which are anyway empty) */ + } + else + len[i] = - len[i]; + } + else + degree[i] = len[i]; + } + } + else { /* Patch 08/12/03 : Duplicate part of previous loop to avoid sytematic testing for elements */ + for (i = 1; i <= n; i ++) { + nv[i] = 1; + w[i] = 1; + if (len[i] < 0) { /* i \in V1 */ + degree[i] = n2; + nbflag ++; + if (len[i] == - (n + 1)) { /* Patch 09/08/98 */ + len[i] = 0; + pe[i] = 0; /* Patch 12/12/03 : because of compress, we force skipping those entries (which are anyway empty) */ + elen[i] = 0; /* Patch 16/12/03 */ + } + else { + len[i] = - len[i]; + elen[i] = len[i]; /* Patch 16/12/03 : only elements are adjacent to a variable */ + } + } + else { /* i \in Ve or V0 */ + if (elen[i] < 0) { /* i \in Ve */ + nel ++; + degree[i] = len[i]; + elen[i] = - nel; + dmax = MAX (dmax, degree[i]); /* Patch 11/03/04 */ + } + else { + degree[i] = elen[i]; + elen[i] = len[i]; /* Patch 16/12/03 : only elements are adjacent to a variable */ + } + } + } + } + +#ifdef SCOTCH_DEBUG_ORDER2 + if (nbelts != nel) /* Temporary Patch 8/12/03 */ + printf ("error 8Dec2003\n"); +#endif /* SCOTCH_DEBUG_ORDER2 */ + + nreal = n - nbflag; + + for (i = 1; i <= n; i ++) { + if (elen[i] < 0 ) /* Patch 16/12/03 : Skip elements */ + continue; + + deg = degree[i]; + if (deg == n2) { + deg = nbbuck + 1; + if (lastd == 0) { + lastd = i; + head[deg] = i; + next[i] = 0; + last[i] = 0; + } + else { + next[lastd] = i; + last[i] = lastd; + lastd = i; + next[i] = 0; + } + } + else if (deg > 0) { + if (nbelts != 0) { /* Patch 04/01/04 */ + Gnum l; /* Size of largest adjacent element */ + Gnum m; /* Current edge being visited */ + + for (m = pe[i], l = 0; m < pe[i] + elen[i]; m ++) { + Gnum o; /* Current element being visited */ + + o = iw[m]; + if (len[o] > l) + l = len[o]; + } + deg = (Gnum) ((float) deg * (float) (deg - 1) - (float) l * (float) (l - 1)) / 2; + if (deg < 0) /* Patch 04/01/04 */ + deg = 0; + } + wf[i] = deg; /* Patch 14/01/04 */ + if (deg > n) + deg = MIN ((deg - n) / pas + n, nbbuck); + inext = head[deg]; + if (inext != 0) + last[inext] = i; + next[i] = inext; + head[deg] = i; + } + else { + nel ++; + elen[i] = - nel; + pe[i] = 0; + w[i] = 0; + } + } /* L20: */ + + nleft = n - nel; /* Patch v5 12/12/98 */ + + while (nel < nreal) { /* WHILE (selecting pivots) DO */ + for (deg = mindeg; deg <= nbbuck; deg ++) { + me = head[deg]; + if (me > 0) + break; /* GO to 50 */ + } /* L40: */ + mindeg = deg; + if (me <= 0) { /* Error 1 */ + *ncmpaptr = -n; + return; + } + + if (deg > n) { + j = next[me]; + k = wf[me]; + while (j > 0) { + if (wf[j] < k) { + me = j; + k = wf[me]; + } + j = next[j]; + } + ilast = last[me]; + inext = next[me]; + if (inext != 0) + last[inext] = ilast; + if (ilast != 0) + next[ilast] = inext; + else + head[deg] = inext; /* me is at the head of the degree list */ + } + else { + inext = next[me]; + if (inext != 0) + last[inext] = 0; + head[deg] = inext; + } + + elenme = elen[me]; + elen[me] = - (nel + 1); + nvpiv = nv[me]; + nel += nvpiv; + + nv[me] = - nvpiv; + degme = 0; + if (elenme == 0) { + pme1 = pe[me]; + pme2 = pme1 - 1; + + for (p = pme1; p <= pme1 + len[me] - 1; p ++) { + i = iw[p]; + nvi = nv[i]; + if (nvi > 0) { + degme += nvi; + nv[i] = - nvi; + pme2 ++; + iw[pme2] = i; + + if (degree[i] != n2) { + ilast = last[i]; + inext = next[i]; + if (inext != 0) + last[inext] = ilast; + if (ilast != 0) + next[ilast] = inext; + else { + if (wf[i] > n) + deg = MIN ((wf[i] - n) / pas + n, nbbuck); + else + deg = wf[i]; + head[deg] = inext; + } + } + } + } /* L60: */ + + newmem = 0; + } + else { + p = pe[me]; + pme1 = pfree; + slenme = len[me] - elenme; + for (knt1 = 1; knt1 <= elenme + 1; knt1 ++) { + if (knt1 > elenme) { + e = me; + pj = p; + ln = slenme; + } + else { + e = iw[p ++]; + pj = pe[e]; + ln = len[e]; + } + + for (knt2 = 1; knt2 <= ln; knt2 ++) { + i = iw[pj ++]; + nvi = nv[i]; + if (nvi > 0) { + if (pfree > iwlen) { + pe[me] = p; + len[me] -= knt1; + if (len[me] == 0) + pe[me] = 0; + pe[e] = pj; + len[e] = ln - knt2; + if (len[e] == 0) + pe[e] = 0; + ncmpa ++; + + for (j = 1; j <= n; j ++) { + pn = pe[j]; + if (pn > 0) { + pe[j] = iw[pn]; + iw[pn] = - j; + } + } /* L70: */ + + pdst = 1; + psrc = 1; + pend = pme1 - 1; + + while (psrc <= pend) { /* L80: */ + j = - iw[psrc ++]; + if (j > 0) { + iw[pdst] = pe[j]; + pe[j] = pdst ++; + lenj = len[j]; + for (knt3 = 0; knt3 <= lenj - 2; knt3 ++) + iw[pdst + knt3] = iw[psrc + knt3]; + pdst = pdst + (lenj - 1); + psrc = psrc + (lenj - 1); + } + } + + p1 = pdst; + for (psrc = pme1; psrc <= pfree - 1; psrc ++, pdst ++) /* L100: */ + iw[pdst] = iw[psrc]; + pme1 = p1; + pfree = pdst; + pj = pe[e]; + p = pe[me]; + } + + degme += nvi; + nv[i] = - nvi; + iw[pfree] = i; + pfree ++; + + if (degree[i] != n2) { + ilast = last[i]; + inext = next[i]; + if (inext != 0) + last[inext] = ilast; + if (ilast != 0) + next[ilast] = inext; + else { + if (wf[i] > n) + deg = MIN ((wf[i] - n) / pas + n, nbbuck); + else + deg = wf[i]; + head[deg] = inext; + } + } + } + } /* L110: */ + + if (e != me) { + pe[e] = -me; + w[e] = 0; + } + } /* L120: */ + pme2 = pfree - 1; + + newmem = pfree - pme1; + mem += newmem; + maxmem = MAX (maxmem, mem); + } + + degree[me] = degme; + pe[me] = pme1; + len[me] = pme2 - pme1 + 1; + + if (wflg + n <= wflg) { + for (x = 1; x <= n; x ++) { + if (w[x] != 0) + w[x] = 1; + } /* L130: */ + wflg = 2; + } + + for (pme = pme1; pme <= pme2; pme ++) { + i = iw[pme]; + eln = elen[i]; + if (eln > 0) { + nvi = - nv[i]; + wnvi = wflg - nvi; + for (p = pe[i]; p < pe[i] + eln; p ++) { + e = iw[p]; + we = w[e]; + if (we >= wflg) + we -= nvi; + else if (we != 0) { + we = degree[e] + wnvi; + wf[e] = 0; + } + w[e] = we; + } /* L140: */ + } + } /* L150: */ + + for (pme = pme1; pme <= pme2; pme ++) { + i = iw[pme]; + p1 = pe[i]; + p2 = p1 + elen[i] - 1; + pn = p1; + hash = 0; + deg = 0; + wf3 = 0; + wf4 = 0; + nvi = - nv[i]; + + for (p = p1; p <= p2; p ++) { + e = iw[p]; + dext = w[e] - wflg; + if (dext > 0) { + if (wf[e] == 0) + wf[e] = dext * ((2 * degree[e]) - dext - 1); + wf4 += wf[e]; + deg += dext; + iw[pn ++] = e; + hash += e; + } + else if (dext == 0) { + pe[e] = -me; + w[e] = 0; + } + } /* L160: */ + elen[i] = pn - p1 + 1; + + p3 = pn; + for (p = p2 + 1; p < p1 + len[i]; p ++) { + j = iw[p]; + nvj = nv[j]; + if (nvj > 0) { + deg += nvj; + wf3 += nvj; + iw[pn ++] = j; + hash += j; + } + } /* L170: */ + + if (degree[i] == n2) + deg = n2; + if (deg == 0) { + pe[i] = - me; + nvi = - nv[i]; + degme -= nvi; + nvpiv += nvi; + nel += nvi; + nv[i] = 0; + elen[i] = 0; + } + else { + if (degree[i] != n2) { + if (degree[i] < deg) { + wf4 = 0; + wf3 = 0; + } + else + degree[i] = deg; + } + wf[i] = wf4 + 2 * nvi * wf3; + iw[pn] = iw[p3]; + iw[p3] = iw[p1]; + iw[p1] = me; + len[i] = pn - p1 + 1; + + if (deg != n2) { + hash = (hash % hmod) + 1; + j = head[hash]; + if (j <= 0) { + next[i] = - j; + head[hash] = - i; + } + else { + next[i] = last[j]; + last[j] = i; + } + last[i] = hash; + } + } + } /* L180: */ + degree[me] = degme; + + dmax = MAX (dmax, degme); + wflg += dmax; + + if (wflg + n <= wflg) { + for (x = 1; x <= n; x ++) { + if (w[x] != 0) + w[x] = 1; + } + wflg = 2; + } + + for (pme = pme1; pme <= pme2; pme ++) { + i = iw[pme]; + if ((nv[i] < 0) && (degree[i] != n2)) { + hash = last[i]; + j = head[hash]; + if (j == 0) + continue; + if (j < 0) { + i = - j; + head[hash] = 0; + } + else { + i = last[j]; + last[j] = 0; + } + if (i == 0) + continue; + +L200: /* WHILE LOOP: */ + if (next[i] != 0) { + ln = len[i]; + eln = elen[i]; + for (p = pe[i] + 1; p < pe[i] + ln; p ++) + w[iw[p]] = wflg; + + jlast = i; + j = next[i]; + +L220: /* WHILE LOOP: */ + if (j != 0) { + if (len[j] != ln) + goto L240; + if (elen[j] != eln) + goto L240; + + for (p = pe[j] + 1; p < pe[j] + ln; p ++) { + if (w[iw[p]] != wflg) + goto L240; + } /* L230: */ + + pe[j] = -i; + if (wf[j] > wf[i]) + wf[i] = wf[j]; + nv[i] += nv[j]; + nv[j] = 0; + elen[j] = 0; + + j = next[j]; + next[jlast] = j; + goto L220; + +L240: + jlast = j; + j = next[j]; + goto L220; + } + + wflg ++; + i = next[i]; + if (i != 0) + goto L200; + } + } + } + + p = pme1; + nleft = n - nel; + for (pme = pme1; pme <= pme2; pme ++) { + i = iw[pme]; + nvi = - nv[i]; + if (nvi > 0) { + nv[i] = nvi; + if (degree[i] != n2) { + deg = MIN (degree[i] + degme, nleft) - nvi; + if (degree[i] + degme > nleft) { + deg = degree[i]; + rmf1 = (float) deg * (float) (deg - 1 + (2 * degme)) - (float) wf[i]; + degree[i] = nleft - nvi; + deg = degree[i]; + rmf = (float) deg * (float) (deg - 1) - (float) (degme - nvi) * (float) (degme - nvi - 1); + rmf = MIN (rmf, rmf1); + } + else { + deg = degree[i]; + degree[i] = degree[i] + degme - nvi; + rmf = (float) deg * (float) (deg - 1 + (2 * degme)) - (float) wf[i]; + } + + wf[i] = (Gnum) (rmf / (float) (nvi + 1) + 0.5F); /* Patch 08/12/2010 */ + wf[i] = MAX (0, wf[i]); + deg = wf[i]; + if (deg > n) + deg = MIN ((deg - n) / pas + n, nbbuck); + inext = head[deg]; + if (inext != 0) + last[inext] = i; + next[i] = inext; + last[i] = 0; + head[deg] = i; + + mindeg = MIN (mindeg, deg); + } + + iw[p ++] = i; + } + } /* L260: */ + + nv[me] = nvpiv + degme; + len[me] = p - pme1; + if (len[me] == 0) { + pe[me] = 0; + w[me] = 0; + } + if (newmem != 0) { + pfree = p; + mem = mem - newmem + len[me]; + } + } /* END WHILE (selecting pivots) */ + + if (nel < n) { /* Patch 12/12/98 (old: nreal < n) */ + for (deg = mindeg; deg <= (nbbuck + 1); deg ++) { + me = head[deg]; + if (me > 0) + break; + } + + mindeg = deg; + nelme = - (nel + 1); + for (x = 1; x <= n; x ++) { + if ((pe[x] > 0) && (elen[x] < 0)) + pe[x] = - me; + else if (degree[x] == n2) { + nel += nv[x]; + pe[x] = - me; + elen[x] = 0; + nv[x] = 0; /* Patch 12/12/98 (old: n + 1) */ + } + } + + elen[me] = nelme; + nv[me] = n - nreal; /* Patch 12/12/98 (old: n + 1) */ + pe[me] = 0; + if (nel != n) { /* Error 2 */ + *ncmpaptr = - (n + 1); + return; + } + } + + for (i = 1; i <= n; i ++) { + if (elen[i] == 0) { + j = - pe[i]; + + while (elen[j] >= 0) /* L270: */ + j = - pe[j]; + e = j; + + k = - elen[e]; + j = i; + + while (elen[j] >= 0) { /* L280: */ + jnext = - pe[j]; + pe[j] = - e; + if (elen[j] == 0) + elen[j] = k ++; + j = jnext; + } + elen[e] = - k; + } + } /* L290: */ + +#ifdef DEAD_CODE + for (i = 1; i <= n; i ++) { /* Patch 19/10/98 */ + k = abs (elen[i]); + last[k] = i; + elen[i] = k; + } /* L300: */ +#endif /* DEAD_CODE */ + +/* pfree = maxmem; Patch 08/03/12 No need to update pfree */ + *ncmpaptr = ncmpa; +} diff --git a/scotch_6.0.3/src/libscotch/hall_order_hf.h b/scotch_6.0.3/src/libscotch/hall_order_hf.h new file mode 100644 index 00000000..75f1eae9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hall_order_hf.h @@ -0,0 +1,60 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hall_order_hf.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the block-oriented Halo **/ +/** Approximate (Multiple) Minimum Fill **/ +/** ordering routine. **/ +/** **/ +/** DATES : # Version 3.4 : from : 15 may 2001 **/ +/** to : 15 may 2001 **/ +/** # Version 4.0 : from : 10 jan 2003 **/ +/** to : 08 dec 2003 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef HALL_ORDER_HF +#define static +#endif + +void hallOrderHfR2hamdf4 (const Gnum n, const Gnum nbelts, const Gnum nbbuck, const Gnum iwlen, Gnum pe[], Gnum pfree, Gnum len[], Gnum iw[], Gnum nv[], Gnum elen[], Gnum last[], Gnum * ncmpa, Gnum degree[], Gnum wf[], Gnum next[], Gnum w[], Gnum head[]); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hall_order_hx.c b/scotch_6.0.3/src/libscotch/hall_order_hx.c new file mode 100644 index 00000000..e3a6de18 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hall_order_hx.c @@ -0,0 +1,342 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hall_order_hx.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains service routines **/ +/** for interfacing the halo ordering **/ +/** routines provided by Patrick Amestoy **/ +/** with the ones of libScotch. **/ +/** **/ +/** DATES : # Version 4.0 : from : 13 jan 2003 **/ +/** to : 28 dec 2004 **/ +/** # Version 5.0 : from : 25 jul 2007 **/ +/** to : 29 may 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HALL_ORDER_HX + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hall_order_hx.h" + +/*********************/ +/* */ +/* Service routines. */ +/* */ +/*********************/ + +/* This routine post-processes the elimination tree +** produced by Amestoy's halo ordering routines. +** On input, the elimination tree is described by +** nvtab and petab. +** On output, we build an un-based elimination tree +** (that is, based to 0), structured as follows: +** - cblknbr : number of column blocks (that is, +** principal variables). +** - sizetab : sizetab[i] holds the total number of +** variables (principal and secondary) if i is +** a principal variable, or ~0 if i is a secondary +** variable or in halo. (sizetab = lentab) +** - petab : petab[i] holds the father of principal +** variable i, or ~0 if i is a root. +** - frsttab : when i is a principal variable, +** frsttab[i] holds the number of the first principal +** son variable of principal variable i, or ~0 if none. +** If i is a secondary variable or in halo, frsttab[i] +** holds ~0 too. +** - nexttab : linked list of principal son variables. +** When i is a principal variable, j=frsttab[i] is +** its first son (if any), and k=nexttab[j] is the +** second son, and l=nexttab[k] is its third son, and +** so on, or ~0 if none. +** - secntab : linked list of secondary variables. +** When i is a principal variable, secntab[i] holds +** the number of the first secondary variable of +** principal variable i, or ~0 if none. When i is +** a secondary variable, secntab[i] holds the next +** secondary variable in linked list, or ~0 if none. +** It returns: +** - 0 : if data structures have been initialized. +** - !0 : on error. +*/ + +int +hallOrderHxBuild ( +const Gnum baseval, /*+ Base value of graph and permutation +*/ +const Gnum vertnbr, /*+ Number of vertices in considered graph +*/ +const Gnum vnohnbr, /*+ Number of non-halo vertices in considered graph +*/ +const Gnum * restrict const vnumtax, /*+ Vertex number array of subgraph, if subgraph +*/ +Order * restrict const ordeptr, /*+ Ordering to update +*/ +OrderCblk * restrict const cblkptr, /*+ Multiple column-block of ordering +*/ +Gnum * restrict const nvartax, +Gnum * restrict const sizetax, +Gnum * restrict const fathtax, /*+ Was petab +*/ +Gnum * restrict const frsttax, +Gnum * restrict const nexttax, +Gnum * restrict const secntax, +Gnum * restrict const desctax, /*+ Was iwtab +*/ +Gnum * restrict const permtax, /*+ Based direct permutation array +*/ +Gnum * restrict const peritab, /*+ Un-based inverse permutation array +*/ +Gnum * restrict const leaftab, /*+ Un-based array for storage of leaves +*/ +const Gnum colmin, +const Gnum colmax, +const float fillrat) +{ + Gnum vnohnnd; + Gnum cblknbr; + Gnum cblknum; + Gnum leafnbr; + Gnum leafnum; + Gnum rootnum; + Gnum ordetmp; + Gnum i, j, k; + + memSet (desctax + baseval, 0, vertnbr * sizeof (Gnum)); + memSet (sizetax + baseval, 0, vertnbr * sizeof (Gnum)); + memSet (frsttax + baseval, ~0, vertnbr * sizeof (Gnum)); + memSet (secntax + baseval, ~0, vertnbr * sizeof (Gnum)); + + vnohnnd = vnohnbr + baseval; + +#ifdef SCOTCH_DEBUG_ORDER2 + for (i = baseval; i < vnohnnd; i ++) { + if ((fathtax[i] > 0) || (fathtax[i] < - vertnbr)) { + errorPrint ("hallOrderHxBuild: elimination tree out of bounds"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + for (i = baseval, cblknbr = 0, rootnum = ~0; /* Assume no root found yet */ + i < vnohnnd; i ++) { + if (nvartax[i] != 0) { /* If principal variable */ + cblknbr ++; /* One more column block */ + sizetax[i] ++; /* One more column */ + if ((fathtax[i] < 0) && /* If not root of tree */ + (fathtax[i] > - (vnohnbr + 1))) { /* And father not in halo */ + fathtax[i] = baseval - (fathtax[i] + 1); /* Re-base father number */ + nexttax[i] = frsttax[fathtax[i]]; /* Link vertex to tree */ + frsttax[fathtax[i]] = i; /* Variable is first son */ + desctax[fathtax[i]] ++; /* Father has one more son */ + } + else { + fathtax[i] = ~0; /* Father is (pseudo-)root */ + rootnum = i; /* Record (last) root */ + } + } + else { /* If secondary variable */ + fathtax[i] = baseval - (fathtax[i] + 1); /* Re-base father number */ + if (fathtax[i] >= vnohnnd) { /* If father in halo */ + if (frsttax[fathtax[i]] == ~0) { /* If first such vertex */ + cblknbr ++; /* One more column block */ + sizetax[i] = 1; /* One more column */ + nvartax[i] = 1; /* Make it principal */ + frsttax[fathtax[i]] = i; /* Record it as root */ + fathtax[i] = ~0; /* Make it (pseudo-)root */ + rootnum = i; /* Record (last) root */ + continue; /* Skip to next vertex */ + } + else { + fathtax[i] = frsttax[fathtax[i]]; /* Get first such vertex as root */ + nvartax[fathtax[i]] ++; /* Record us as secondary variable */ + } + } + sizetax[fathtax[i]] ++; /* One more column */ + secntax[i] = secntax[fathtax[i]]; /* Link secondary variable */ + secntax[fathtax[i]] = i; + } + } + + for (i = baseval, leafnbr = 0; /* Build leaf list for amalgamation */ + i < vnohnnd; i ++) { + if ((fathtax[i] != ~0) && /* If node has a father */ + (nvartax[i] != 0) && /* And is a principal variable */ + (frsttax[i] == ~0)) /* And is a leaf */ + leaftab[leafnbr ++] = i; /* Add it to leaf list */ + } + + for (leafnum = 0; leafnum < leafnbr; leafnum ++) { /* As long as candidate leaves exist */ + i = leaftab[leafnum]; + j = fathtax[i]; + + if ((sizetax[i] + sizetax[j]) <= colmax) { /* If will not be too large */ + if ((sizetax[i] < colmin) || /* If column block too small */ + (((float) (2 * sizetax[i]) * (float) (nvartax[j] - nvartax[i] + sizetax[i])) < + (float) nvartax[j] * (float) nvartax[j] * fillrat)) { + nvartax[j] += sizetax[i]; + sizetax[j] += sizetax[i]; + nvartax[i] = 0; + if (secntax[i] == ~0) /* If node had no secondary variables */ + secntax[i] = secntax[j]; /* Make it take the ones of its father */ + else if (secntax[j] != ~0) { /* Else if there is something to append */ + for (k = secntax[i]; secntax[k] != ~0; k = secntax[k]) ; /* Find last node */ + secntax[k] = secntax[j]; /* Append father list to node list */ + } + secntax[j] = i; /* Now he is a secondary variable of it */ + if (frsttax[j] == i) { /* If node is first son of father */ + if (frsttax[i] == ~0) /* If node has no sons */ + frsttax[j] = nexttax[i]; /* First son is now next node */ + else { + frsttax[j] = frsttax[i]; + for (k = frsttax[i]; nexttax[k] != ~0; k = nexttax[k]) + fathtax[k] = j; + fathtax[k] = j; + nexttax[k] = nexttax[i]; + } + } + else { /* Else unlink node from son chain */ + for (k = frsttax[j]; nexttax[k] != i; k = nexttax[k]) ; + if (frsttax[i] == ~0) /* If node has no sons */ + nexttax[k] = nexttax[i]; + else { + nexttax[k] = frsttax[i]; + for (k = frsttax[i]; nexttax[k] != ~0; k = nexttax[k]) + fathtax[k] = j; + fathtax[k] = j; + nexttax[k] = nexttax[i]; + } + } + cblknbr --; /* One less column block */ + } + } + if (((-- desctax[j]) <= 0) && /* If all descendents processed */ + (fathtax[j] != ~0)) /* And node has a father */ + leaftab[leafnbr ++] = j; /* Enqueue father */ + } + +#ifdef SCOTCH_DEBUG_ORDER2 + memSet (peritab, ~0, vnohnbr * sizeof (Gnum)); +#endif /* SCOTCH_DEBUG_ORDER2 */ + ordetmp = hallOrderHxTree (frsttax, nexttax, secntax, peritab, 0, rootnum); + if (ordetmp < vnohnbr) { /* If not all nodes ordered */ + for (i = baseval; i < rootnum; i ++) { /* For all potential remaining roots */ + if (fathtax[i] == ~0) /* If node is a pseudo-root */ + ordetmp = hallOrderHxTree (frsttax, nexttax, secntax, peritab, ordetmp, i); + } + } +#ifdef SCOTCH_DEBUG_ORDER2 + if (ordetmp != vnohnbr) { + errorPrint ("hallOrderHxBuild: incomplete elimination tree"); + return (1); + } + + memSet (permtax + baseval, ~0, vnohnbr * sizeof (Gnum)); + + for (i = 0; i < vnohnbr; i ++) { + if ((peritab[i] < baseval) || (peritab[i] >= vnohnnd)) { + errorPrint ("hallOrderHxBuild: permutation out of bounds"); + return (1); + } + if (permtax[peritab[i]] != ~0) { + errorPrint ("hallOrderHxBuild: duplicate permutation index"); + return (1); + } + permtax[peritab[i]] = i; + } + for (i = baseval; i < vnohnnd; i ++) { + if (permtax[i] == ~0) { + errorPrint ("hallOrderHxBuild: unused permutation index"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + if (cblknbr != 1) { /* If more than one column block in the end, create subtree */ + if ((cblkptr->cblktab = (OrderCblk *) memAlloc (cblknbr * sizeof (OrderCblk))) == NULL) { + errorPrint ("hallOrderHxBuild: out of memory"); + return (1); + } + cblkptr->cblknbr = cblknbr; + ordeptr->cblknbr += cblknbr - 1; /* These more column blocks created */ + ordeptr->treenbr += cblknbr; /* These more tree nodes created */ + + for (i = 0, cblknum = 0; i < vnohnbr; i ++) { + if (nvartax[peritab[i]] == 0) /* If secondary variable */ + continue; /* Skip to next vertex */ + cblkptr->cblktab[cblknum].typeval = ORDERCBLKOTHR; /* Build column blocks */ + cblkptr->cblktab[cblknum].vnodnbr = sizetax[peritab[i]]; + cblkptr->cblktab[cblknum].cblknbr = 0; + cblkptr->cblktab[cblknum].cblktab = NULL; + cblknum ++; /* One more column block created */ + } + } + + if (vnumtax != NULL) { /* If graph is not original graph */ + for (i = 0; i < vnohnbr; i ++) /* Finalize inverse permutation */ + peritab[i] = vnumtax[peritab[i]]; + } + + return (0); +} + +/*+ This routine computes the inverse +*** permutation according to the +*** elimination tree. +*** It returns: +*** - >0 : next index to be used to order, in all cases. ++*/ + +Gnum +hallOrderHxTree ( +const Gnum * restrict const frsttax, +const Gnum * restrict const nexttax, +const Gnum * restrict const secntax, +Gnum * restrict const peritab, +const Gnum ordenum, +const Gnum nodenum) +{ + Gnum ordetmp; + Gnum nodetmp; + + ordetmp = ordenum; + for (nodetmp = frsttax[nodenum]; nodetmp != ~0; nodetmp = nexttax[nodetmp]) + ordetmp = hallOrderHxTree (frsttax, nexttax, secntax, peritab, ordetmp, nodetmp); + + peritab[ordetmp ++] = nodenum; /* Order principal variable */ + for (nodetmp = secntax[nodenum]; nodetmp != ~0; nodetmp = secntax[nodetmp]) { + peritab[ordetmp ++] = nodetmp; /* Order secondary variables */ + } + + return (ordetmp); +} diff --git a/scotch_6.0.3/src/libscotch/hall_order_hx.h b/scotch_6.0.3/src/libscotch/hall_order_hx.h new file mode 100644 index 00000000..1374c280 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hall_order_hx.h @@ -0,0 +1,58 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hall_order_hx.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the halo ordering service **/ +/** routines. **/ +/** **/ +/** DATES : # Version 4.0 : from : 14 jan 2003 **/ +/** to : 08 dec 2003 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef HALL_ORDER_HX +#define static +#endif + +int hallOrderHxBuild (const Gnum, const Gnum, const Gnum, const Gnum * restrict const, Order * restrict const, OrderCblk * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, const Gnum, const Gnum, const float); +Gnum hallOrderHxTree (const Gnum * restrict const, const Gnum * restrict const, const Gnum * restrict const, Gnum * restrict const, const Gnum, const Gnum); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hdgraph.c b/scotch_6.0.3/src/libscotch/hdgraph.c new file mode 100644 index 00000000..6bc23594 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph.c @@ -0,0 +1,87 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed graph general **/ +/** purpose routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 21 apr 2006 **/ +/** to : 21 apr 2006 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "hdgraph.h" + +/******************************/ +/* */ +/* These routines handle halo */ +/* distributed source graphs. */ +/* */ +/******************************/ + +/* This routine destroys a distributed halo graph +** structure. It is not a collective routine, as no +** communication is needed to perform the freeing of +** memory structures. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +void +hdgraphExit ( +Hdgraph * restrict const grafptr) +{ + if ((grafptr->vhndloctax != grafptr->s.vertloctax + 1) && /* If graph has a halo, with a separate end vertex array */ + ((grafptr->s.flagval & HDGRAPHFREEVHND) != 0)) + memFree (grafptr->vhndloctax); + + dgraphExit (&grafptr->s); /* Free distributed graph data (flagval may be corrupted afterwards) */ + +#ifdef SCOTCH_DEBUG_HDGRAPH1 + memSet (grafptr, 0, sizeof (Hdgraph)); +#endif /* SCOTCH_DEBUG_HDGRAPH1 */ +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph.h b/scotch_6.0.3/src/libscotch/hdgraph.h new file mode 100644 index 00000000..c888fd87 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph.h @@ -0,0 +1,111 @@ +/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source halo distributed graph **/ +/** structure. **/ +/** **/ +/** DATES : # Version 5.0 : from : 15 apr 2006 **/ +/** to 16 jun 2007 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +#define HDGRAPH_H + +/* +** The defines. +*/ + +/*+ Graph option flags. +*/ + +#define HDGRAPHFREEVHND 0x0400 /* Free vnhdtab array */ +#define HDGRAPHFREETABS (DGRAPHFREETABS | HGRAPHFREEVHND) + +/* +** The type and structure definitions. +*/ + +/*+ Halo distributed graph structure. In order to + keep efficiency, distributed halo graphs are not + considered as regular graphs as sequential halo + graphs were. Halo distributed graphs have a compact + vertex array, with halo edges added at the end of + each vertex sub-array. They are not visible when + considering the vertlocnbr, vertloctax (which is in + fact most often of size vhallocnbr + 1 when the graph + is compact, as in this case we have vnhdloctax = + vertloctax + 1) and vendloctax (which is of size + vertlocnbr) of the embedded distributed graph, but + can be accessed through vendloctax and vnhdloctax. + Halo vertex ends are stored only in edgeloctax, not + in edgegsttax, except when graph has only an edgegsttax + and no edgeloctax. Since halo vertices have no real + existence in distributed graphs, they are simply + numbered from baseval. They are converted into real + vertices when a distributed halo graph is turned into + a sequential halo graph. */ + +typedef struct Hdgraph_ { + Dgraph s; /*+ Source distributed graph +*/ + Gnum vhallocnbr; /*+ Local number of halo end vertices +*/ + Gnum * vhndloctax; /*+ End vertex array including halo vertex indices +*/ + Gnum ehallocnbr; /*+ Local number of halo edges +*/ + Gnum levlnum; /*+ Nested dissection level +*/ +} Hdgraph; + +/* +** The function prototypes. +*/ + +#ifndef HDGRAPH +#define static +#endif + +int hdgraphInit (Hdgraph * const); +void hdgraphExit (Hdgraph * const); +void hdgraphFree (Hdgraph * const); +int hdgraphFold (const Hdgraph *, const int, Hdgraph * const); +int hdgraphFold2 (const Hdgraph *, const int, Hdgraph * const, MPI_Comm); +int hdgraphCheck (const Hdgraph *); +#ifdef HGRAPH_H +int hdgraphGather (Hdgraph *, Hgraph *); +#endif /* HGRAPH_H */ +int hdgraphInduceList (Hdgraph * restrict const, const Gnum, const Gnum * restrict const, Hdgraph * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hdgraph_check.c b/scotch_6.0.3/src/libscotch/hdgraph_check.c new file mode 100644 index 00000000..099c9dfc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_check.c @@ -0,0 +1,164 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_check.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel static mapper. **/ +/** This module contains the distributed **/ +/** graph consistency checking routine. **/ +/** **/ +/** # Version 5.0 : from : 21 apr 2006 **/ +/** to : 29 apr 2006 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH_CHECK + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "hdgraph.h" + +/******************************/ +/* */ +/* These routines handle halo */ +/* distributed source graphs. */ +/* */ +/******************************/ + +/* This function checks the consistency +** of the given halo distributed graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +hdgraphCheck ( +const Hdgraph * restrict const grafptr) +{ + Gnum vertlocnum; + int * restrict vhalloctax; /* Flag array for halo vertices */ + Gnum vhallocnnd; + Gnum vhallocnum; + Gnum ehallocnbr; + int cheklocval; /* Local consistency flag */ + int chekglbval; /* Global consistency flag */ + + cheklocval = 0; + for (vertlocnum = grafptr->s.baseval, ehallocnbr = 0; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { + if ((grafptr->vhndloctax[vertlocnum] < grafptr->s.vendloctax[vertlocnum]) || + (grafptr->vhndloctax[vertlocnum] > (grafptr->s.edgelocsiz + grafptr->s.baseval))) { + errorPrint ("hdgraphCheck: inconsistent local vertex arrays"); + cheklocval = 1; + } + ehallocnbr += grafptr->vhndloctax[vertlocnum] - grafptr->s.vendloctax[vertlocnum]; + } + if (ehallocnbr != grafptr->ehallocnbr) { + errorPrint ("hdgraphCheck: invalid local number of halo edges"); + cheklocval = 1; + } + + if ((grafptr->vhallocnbr < 0) || (grafptr->vhallocnbr > grafptr->s.edgelocsiz)) { + errorPrint ("hdgraphCheck: invalid local number of halo vertices"); + cheklocval = 1; + } + + vhalloctax = NULL; + if ((cheklocval == 0) && + ((vhalloctax = (int *) memAlloc (grafptr->vhallocnbr * sizeof (int))) == NULL)) { + errorPrint ("hdgraphCheck: out of memory"); + cheklocval = 1; + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphCheck: communication error (1)"); + return (1); + } + if (chekglbval != 0) { + if (vhalloctax != NULL) + memFree (vhalloctax); + return (1); + } + + memSet (vhalloctax, ~0, grafptr->vhallocnbr * sizeof (int)); + vhalloctax -= grafptr->s.baseval; + vhallocnnd = grafptr->vhallocnbr + grafptr->s.baseval; + for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + + for (edgelocnum = grafptr->s.vendloctax[vertlocnum]; + edgelocnum < grafptr->vhndloctax[vertlocnum]; edgelocnum ++) { + Gnum vhallocend; + + vhallocend = grafptr->s.edgeloctax[edgelocnum]; + if ((vhallocend < grafptr->s.baseval) || (vhallocend >= vhallocnnd)) { + errorPrint ("hdgraphCheck: invalid halo vertex number"); + vertlocnum = grafptr->s.vertlocnnd; /* Avoid unwanted cascaded error messages */ + cheklocval = 1; + break; + } + vhalloctax[vhallocend] = 0; /* Flag halo vertex as used */ + } + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphCheck: communication error (2)"); + return (1); + } + if (chekglbval != 0) { + memFree (vhalloctax + grafptr->s.baseval); + return (1); + } + + for (vhallocnum = grafptr->s.baseval; vhallocnum < vhallocnnd; vhallocnum ++) { + if (vhalloctax[vhallocnum] != 0) { /* If halo vertex index not used in graph */ + errorPrint ("hdgraphCheck: unused halo vertex number"); + cheklocval = 1; + break; + } + } + memFree (vhalloctax + grafptr->s.baseval); + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphCheck: communication error (3)"); + return (1); + } + if (chekglbval != 0) + return (1); + + return (dgraphCheck (&grafptr->s)); +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph_fold.c b/scotch_6.0.3/src/libscotch/hdgraph_fold.c new file mode 100644 index 00000000..ccd0123a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_fold.c @@ -0,0 +1,883 @@ +/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_fold.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the halo distribu- **/ +/** ted graph folding function. **/ +/** **/ +/** DATES : # Version 5.0 : from : 23 apr 2006 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 27 jun 2008 **/ +/** to : 04 jan 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_fold_comm.h" +#include "hdgraph.h" +#include "hdgraph_fold.h" + +/******************************/ +/* */ +/* These routines handle halo */ +/* distributed source graphs. */ +/* */ +/******************************/ + +/* This routine builds a folded graph by +** merging graph data to the processes of +** the first half or to the second half +** of the communicator. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +hdgraphFold ( +const Hdgraph * restrict const orggrafptr, +const int partval, /* 0 for first half, 1 for second half */ +Hdgraph * restrict const fldgrafptr) +{ + int fldprocglbnbr; + int fldproclocnum; /* Index of local process in folded communicator */ + int fldproccol; /* Color of receiver or not wanted in communicator */ + MPI_Comm fldproccomm; /* Communicator of folded part */ + + fldprocglbnbr = (orggrafptr->s.procglbnbr + 1) / 2; + if (partval == 1) { + fldproclocnum = orggrafptr->s.proclocnum - fldprocglbnbr; + fldprocglbnbr = orggrafptr->s.procglbnbr - fldprocglbnbr; + } + else + fldproclocnum = orggrafptr->s.proclocnum; + + fldproccol = ((fldproclocnum >= 0) && (fldproclocnum < fldprocglbnbr)) ? 0 : MPI_UNDEFINED; + + if (MPI_Comm_split (orggrafptr->s.proccomm, fldproccol, fldproclocnum, &fldproccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphFold: communication error"); + return (1); + } + + return (hdgraphFold2 (orggrafptr, partval, fldgrafptr, fldproccomm)); +} + +int +hdgraphFold2 ( +const Hdgraph * restrict const orggrafptr, +const int partval, /* 0 for first half, 1 for second half */ +Hdgraph * restrict const fldgrafptr, +MPI_Comm fldproccomm) /* Pre-computed communicator */ +{ + int fldcommtypval; /* Type of communication for this process */ + DgraphFoldCommData * restrict fldcommdattab; /* Array of two communication data */ + Gnum * restrict fldcommvrttab; /* Starting global send indices of communications */ + Gnum * restrict fldvertidxtab; /* Start indices of vertex arrays */ + Gnum * restrict fldvendidxtab; /* Adjustment value for end vertex arrays */ + Gnum * restrict fldedgeidxtab; /* Start indices of edge arrays */ + Gnum * restrict fldedgecnttab; /* Number of edges exchanged during each communication */ + Gnum fldvertlocnbr; /* Number of vertices in local folded part */ + Gnum fldedgelocsiz; /* (Upper bound of) number of edges in folded graph */ + int fldprocglbnbr; + int fldproclocnum; /* Index of local process in folded communicator */ + int fldvertadjnbr; + Gnum * restrict fldvertadjtab; /* Array of index adjustments for original vertices */ + Gnum * restrict fldvertdlttab; /* Array of index adjustments for original vertices */ + Gnum * restrict fldvhalloctax; /* Index array for remote halo vertex renumbering */ + int cheklocval; + int chekglbval; + int commmax; + int commnbr; + int requnbr; + MPI_Request * restrict requtab; + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (orggrafptr->vhndloctax != (orggrafptr->s.vertloctax + 1)) { + errorPrint ("hdgraphFold2: halo graph must be compact"); + return (1); + } + if (orggrafptr->s.vendloctax < (orggrafptr->s.vertloctax + orggrafptr->s.vertlocnbr)) { /* MPI_Isend calls should not overlap */ + errorPrint ("hdgraphFold2: halo graph must have distinct arrays"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + fldprocglbnbr = (orggrafptr->s.procglbnbr + 1) / 2; + if (partval == 1) { + fldproclocnum = orggrafptr->s.proclocnum - fldprocglbnbr; + fldprocglbnbr = orggrafptr->s.procglbnbr - fldprocglbnbr; + } + else + fldproclocnum = orggrafptr->s.proclocnum; + + fldcommtypval = ((fldproclocnum >= 0) && (fldproclocnum < fldprocglbnbr)) ? DGRAPHFOLDCOMMRECV : DGRAPHFOLDCOMMSEND; + + cheklocval = 0; + fldvertidxtab = NULL; + fldcommdattab = NULL; + if (fldcommtypval == DGRAPHFOLDCOMMRECV) { /* If we are going to receive */ +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (fldgrafptr == NULL) { + errorPrint ("hdgraphFold2: invalid parameters (1)"); + return (1); + } + if (fldproccomm == MPI_COMM_NULL) { + errorPrint ("hdgraphFold2: invalid parameters (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + memSet (fldgrafptr, 0, sizeof (Hdgraph)); /* Pre-initialize graph fields */ + + fldgrafptr->s.proccomm = fldproccomm; + fldgrafptr->s.procglbnbr = fldprocglbnbr; + fldgrafptr->s.proclocnum = fldproclocnum; + fldgrafptr->s.flagval = DGRAPHFREEALL | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* For premature freeing on error; do not free vhndloctab as it is grouped with vertloctab */ + + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ + &fldgrafptr->s.procdsptab, (size_t) ((fldprocglbnbr + 1) * sizeof (Gnum)), + &fldgrafptr->s.proccnttab, (size_t) (fldprocglbnbr * sizeof (Gnum)), + &fldgrafptr->s.procngbtab, (size_t) (fldprocglbnbr * sizeof (int)), + &fldgrafptr->s.procrcvtab, (size_t) (fldprocglbnbr * sizeof (int)), + &fldgrafptr->s.procsndtab, (size_t) (fldprocglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("hdgraphFold2: out of memory (1)"); + cheklocval = 1; + } + else if (dgraphFoldComm (&orggrafptr->s, partval, &commmax, &fldcommtypval, &fldcommdattab, &fldcommvrttab, /* Process can become a sender receiver */ + fldgrafptr->s.proccnttab, &fldvertadjnbr, &fldvertadjtab, &fldvertdlttab) != 0) { + errorPrint ("hdgraphFold2: cannot compute folding communications (1)"); + cheklocval = 1; + } + else { + Gnum fldvelolocnbr; + + if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver */ + int i; + + for (i = 0, fldvertlocnbr = orggrafptr->s.vertlocnbr; (i < commmax) && (fldcommdattab[i].procnum != -1); i ++) + fldvertlocnbr += fldcommdattab[i].vertnbr; + commnbr = i; + + fldedgelocsiz = orggrafptr->s.edgelocsiz + orggrafptr->s.edgeglbsmx * i; /* Upper bound on local edges (degree useless since only for non-halo vertices) */ + } + else { /* Process is a sender receiver */ + fldvertlocnbr = fldcommvrttab[0] - orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]; /* Communications will remove vertices */ + fldedgelocsiz = orggrafptr->s.vertloctax[fldvertlocnbr + orggrafptr->s.baseval] - orggrafptr->s.baseval; /* Exact number of edges */ + + fldgrafptr->s.edgelocsiz = fldedgelocsiz; + } + fldvelolocnbr = (orggrafptr->s.veloloctax != NULL) ? fldvertlocnbr : 0; + + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ + &fldgrafptr->s.vertloctax, (size_t) ((fldvertlocnbr + 1) * sizeof (Gnum)), + &fldgrafptr->s.vendloctax, (size_t) ( fldvertlocnbr * sizeof (Gnum)), /* Vertex end array for non-halo vertices */ + &fldgrafptr->s.vnumloctax, (size_t) ( fldvertlocnbr * sizeof (Gnum)), + &fldgrafptr->s.veloloctax, (size_t) ( fldvelolocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hdgraphFold2: out of memory (2)"); + cheklocval = 1; + } + else if (fldgrafptr->s.vertloctax -= orggrafptr->s.baseval, + fldgrafptr->s.vendloctax -= orggrafptr->s.baseval, + fldgrafptr->s.vnumloctax -= orggrafptr->s.baseval, + fldgrafptr->s.veloloctax = ((orggrafptr->s.veloloctax != NULL) ? fldgrafptr->s.veloloctax - orggrafptr->s.baseval : NULL), + memAllocGroup ((void **) (void *) + &fldgrafptr->s.edgeloctax, (size_t) (fldedgelocsiz * sizeof (Gnum)), + &fldvhalloctax, (size_t) (orggrafptr->s.edgeglbsmx * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hdgraphFold2: out of memory (3)"); + cheklocval = 1; + } + else { + fldgrafptr->s.edgeloctax -= orggrafptr->s.baseval; + fldvhalloctax -= orggrafptr->s.baseval; + } + } + } + else { /* Process is a sender */ +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (fldproccomm != MPI_COMM_NULL) { + errorPrint ("hdgraphFold2: invalid parameters (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + if (dgraphFoldComm (&orggrafptr->s, partval, &commmax, &fldcommtypval, &fldcommdattab, &fldcommvrttab, NULL, NULL, NULL, NULL) != 0) { + errorPrint ("hdgraphFold2: cannot compute folding communications (2)"); + cheklocval = 1; + } + } + + if ((cheklocval == 0) && + (memAllocGroup ((void **) (void *) /* Allocate folding data */ + &fldvertidxtab, (size_t) (commmax * sizeof (Gnum)), + &fldvendidxtab, (size_t) (commmax * sizeof (Gnum)), + &fldedgeidxtab, (size_t) (commmax * sizeof (Gnum)), + &fldedgecnttab, (size_t) (commmax * sizeof (Gnum)), + &requtab, (size_t) (commmax * HDGRAPHFOLDTAGNBR * sizeof (MPI_Request)), NULL) == NULL)) { + errorPrint ("hdgraphFold2: out of memory (4)"); + cheklocval = 1; + } + +#ifdef SCOTCH_DEBUG_HDGRAPH1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, orggrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (1)"); + chekglbval = 1; + } +#else /* SCOTCH_DEBUG_HDGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_HDGRAPH1 */ + if (chekglbval != 0) { + if ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) { + hdgraphExit (fldgrafptr); + if (fldvertidxtab != NULL) + memFree (fldvertidxtab); /* Free group leaders */ + if (fldcommdattab != NULL) + memFree (fldcommdattab); + } + return (1); + } + + requnbr = 0; /* Communications without further processing are placed at beginning of array */ + + if ((fldcommtypval & DGRAPHFOLDCOMMSEND) != 0) { /* If process is (also) a sender */ + Gnum vertsndbas; + Gnum vertsndnbr; + int i; + + vertsndnbr = ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) ? (fldcommvrttab[0] - orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]) : 0; /* If process is also a receiver, start sending after kept vertices */ + + for (i = 0, requnbr = 0, vertsndbas = orggrafptr->s.baseval; /* For all send communications to perform */ + (i < commmax) && (fldcommdattab[i].procnum != -1); i ++) { + Gnum edgelocsiz; + + vertsndbas += vertsndnbr; + vertsndnbr = fldcommdattab[i].vertnbr; + edgelocsiz = orggrafptr->s.vertloctax[vertsndbas + vertsndnbr] - orggrafptr->s.vertloctax[vertsndbas]; /* Graph is compact */ + + fldvertidxtab[i] = vertsndbas; + fldedgeidxtab[i] = orggrafptr->s.vertloctax[vertsndbas]; + fldedgecnttab[i] = edgelocsiz; + if (MPI_Isend (&edgelocsiz, 1, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVLBLLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (2)"); + cheklocval = 1; + } + } + commnbr = i; + + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Isend (orggrafptr->s.vertloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVERTLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (3)"); + cheklocval = 1; + } + } + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Isend (orggrafptr->s.vendloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVENDLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (4)"); + cheklocval = 1; + } + } + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Isend (orggrafptr->s.edgeloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGEDGELOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (5)"); + cheklocval = 1; + } + } + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + Gnum vertsndbas; + int vertsndnbr; + int procsndnum; /* Rank of process to send to */ + + vertsndbas = fldvertidxtab[i]; + vertsndnbr = (int) fldcommdattab[i].vertnbr; + procsndnum = (int) fldcommdattab[i].procnum; + if ((orggrafptr->s.veloloctax != NULL) && + (MPI_Isend (orggrafptr->s.veloloctax + vertsndbas, vertsndnbr, GNUM_MPI, procsndnum, + TAGFOLD + TAGVELOLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { + errorPrint ("hdgraphFold2: communication error (6)"); + cheklocval = 1; + } + else if ((orggrafptr->s.vnumloctax != NULL) && + (MPI_Isend (orggrafptr->s.vnumloctax + vertsndbas, vertsndnbr, GNUM_MPI, procsndnum, + TAGFOLD + TAGVNUMLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { + errorPrint ("hdgraphFold2: communication error (7)"); + cheklocval = 1; + } + } /* Communications of sender-receivers will be completed in the receiving phase */ + } + + if ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) { /* If process is (also) a receiver */ + Gnum orgvertlocnbr; + Gnum orgvertlocnnd; + Gnum fldvertlocadj; + Gnum fldvelolocsum; + Gnum fldedgelocnum; + Gnum fldvhallocnum; + Gnum fldehallocnbr; + int fldprocnum; + int i; + + const Gnum * restrict const orgvertloctax = orggrafptr->s.vertloctax; + const Gnum * restrict const orgvendloctax = orggrafptr->s.vendloctax; + const Gnum * restrict const orgedgeloctax = orggrafptr->s.edgeloctax; + + fldgrafptr->s.procvrttab = fldgrafptr->s.procdsptab; /* Graph does not have holes */ + fldgrafptr->s.procdsptab[0] = orggrafptr->s.baseval; /* Build private data of folded graph and array */ + for (fldprocnum = 0; fldprocnum < fldprocglbnbr; fldprocnum ++) /* New subdomain indices start from baseval */ + fldgrafptr->s.procdsptab[fldprocnum + 1] = fldgrafptr->s.procdsptab[fldprocnum] + fldgrafptr->s.proccnttab[fldprocnum]; + + if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver */ + Gnum orgvertlocmin; + Gnum orgvertlocmax; + Gnum fldvertlocnum; + Gnum fldedgelocbas; + Gnum fldvertrcvbas; + Gnum fldvertrcvnbr; + int procngbmin; + int procngbmax; + + Gnum * restrict const fldedgeloctax = fldgrafptr->s.edgeloctax; + + for (i = 0, fldvertrcvbas = orggrafptr->s.vertlocnnd, fldvertrcvnbr = 0; /* For all receive communications to perform */ + (i < commnbr) && (cheklocval == 0); i ++) { + fldvertrcvbas += fldvertrcvnbr; + fldvertrcvnbr = fldcommdattab[i].vertnbr; + + fldvertidxtab[i] = fldvertrcvbas; + if (MPI_Irecv (&fldedgecnttab[i], 1, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVLBLLOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGENBR * commmax + i]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (8)"); + cheklocval = 1; + } + } + + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { /* Let these communications progress while we process the edge size messages */ + if (MPI_Irecv (fldgrafptr->s.vertloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVERTLOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGVERT * commmax + i]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (9)"); + cheklocval = 1; + } + } + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Irecv (fldgrafptr->s.vendloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVENDLOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGVEND * commmax + i]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (10)"); + cheklocval = 1; + } + } + + MPI_Waitall (commnbr, &requtab[HDGRAPHFOLDTAGENBR * commmax], MPI_STATUSES_IGNORE); + + for (i = 0, fldedgelocbas = orggrafptr->s.vertloctax[orggrafptr->s.vertlocnnd]; (i < commnbr) && (cheklocval == 0); i ++) { + fldedgeidxtab[i] = fldedgelocbas; + fldedgelocbas += fldedgecnttab[i]; + + if (MPI_Irecv (fldedgeloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGEDGELOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGEDGE * commmax + i]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (11)"); + cheklocval = 1; + } + } + fldgrafptr->s.edgelocsiz = fldedgelocbas - orggrafptr->s.baseval; /* Get number of local and halo edges */ + + if (orggrafptr->s.veloloctax != NULL) { + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Irecv (fldgrafptr->s.veloloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVELOLOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGVELO * commmax + i]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (12)"); + cheklocval = 1; + } + } + } + if (orggrafptr->s.vnumloctax != NULL) { + for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { + if (MPI_Irecv (fldgrafptr->s.vnumloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, + TAGFOLD + TAGVNUMLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (13)"); + cheklocval = 1; + } + } + } + + orgvertlocnbr = orggrafptr->s.vertlocnbr; /* Process all local vertices */ + orgvertlocnnd = orggrafptr->s.vertlocnnd; + + if (orggrafptr->s.vnumloctax == NULL) { /* If original graph does not have vertex numbers, create remote parts of vertex number array */ + Gnum fldvertlocnum; + Gnum fldvertlocadj; + int i; + + Gnum * restrict const fldvnumloctax = fldgrafptr->s.vnumloctax; + + for (i = 0, fldvertlocnum = orgvertlocnnd; i < commnbr; i ++) { + Gnum fldvertlocnnd; + + for (fldvertlocnnd = fldvertlocnum + fldcommdattab[i].vertnbr, fldvertlocadj = fldcommvrttab[i]; + fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) + fldvnumloctax[fldvertlocnum] = fldvertlocadj ++; + } + } + + for (procngbmin = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ + procngbmax - procngbmin > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbmin) / 2; + if (fldvertadjtab[procngbmed] <= orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]) + procngbmin = procngbmed; + else + procngbmax = procngbmed; + } + orgvertlocmin = fldvertadjtab[procngbmin]; + orgvertlocmax = fldvertadjtab[procngbmax]; + fldvertlocadj = fldvertdlttab[procngbmin]; + for (fldvertlocnum = fldedgelocnum = orggrafptr->s.baseval; /* Adjust local part of edge array */ + fldvertlocnum < orgvertlocnnd; ) { + for ( ; fldedgelocnum < orgvendloctax[fldvertlocnum]; fldedgelocnum ++) { /* Reorder end vertices */ + Gnum orgvertlocend; + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval)) { + errorPrint ("hdgraphFold2: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + orgvertlocend = orgedgeloctax[fldedgelocnum]; + + if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ + (orgvertlocend < orgvertlocmax)) + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; + else { /* End vertex is not local */ + int procngbmin; + int procngbmax; + + for (procngbmin = 0, procngbmax = fldvertadjnbr; + procngbmax - procngbmin > 1; ) { + int procngbnum; + + procngbnum = (procngbmax + procngbmin) / 2; + if (fldvertadjtab[procngbnum] <= orgvertlocend) + procngbmin = procngbnum; + else + procngbmax = procngbnum; + } + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbmin]; + } + } + fldvertlocnum ++; + for ( ; fldedgelocnum < orgvertloctax[fldvertlocnum]; fldedgelocnum ++) { /* Copy halo part as is */ +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if ((orgedgeloctax[fldedgelocnum] < orggrafptr->s.baseval) || + (orgedgeloctax[fldedgelocnum] >= (orggrafptr->vhallocnbr + orggrafptr->s.baseval))) { + errorPrint ("hdgraphFold2: internal error (2)"); + return (1); + } + if (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval)) { + errorPrint ("hdgraphFold2: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + fldedgeloctax[fldedgelocnum] = orgedgeloctax[fldedgelocnum]; + } + } + + fldvelolocsum = orggrafptr->s.velolocsum; /* In case there are vertex loads, we keep all of existing load */ + fldehallocnbr = orggrafptr->ehallocnbr; /* Normal receivers have at least all of their local halo vertices */ + fldvhallocnum = orggrafptr->vhallocnbr + orggrafptr->s.baseval; /* Index of next halo vertex number to assign */ + } + else { /* Receiver process is also a sender */ + Gnum orgvertlocmin; + Gnum orgvertlocmax; + Gnum fldvertlocnum; + Gnum fldvertlocadj; + Gnum fldvhallocmax; /* Maximum current size of halo vertex array */ + int procngbmin; + int procngbmax; + + Gnum * restrict const fldedgeloctax = fldgrafptr->s.edgeloctax; + + orgvertlocnbr = fldvertlocnbr; /* Process only remaining local vertices */ + orgvertlocnnd = fldvertlocnbr + orggrafptr->s.baseval; + + for (procngbmin = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ + procngbmax - procngbmin > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbmin) / 2; + if (fldvertadjtab[procngbmed] <= orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]) + procngbmin = procngbmed; + else + procngbmax = procngbmed; + } + orgvertlocmin = fldvertadjtab[procngbmin]; + orgvertlocmax = fldvertadjtab[procngbmax]; + fldvertlocadj = fldvertdlttab[procngbmin]; + fldvhallocmax = orggrafptr->s.baseval - 1; /* Reset halo vertex array for local part as halo vertices may have disappeared */ + fldehallocnbr = 0; /* Recount all remaining halo vertices and edges */ + fldvhallocnum = orggrafptr->s.baseval; + for (fldvertlocnum = fldedgelocnum = orggrafptr->s.baseval; /* Copy remaining local part of edge array */ + fldvertlocnum < orgvertlocnnd; ) { + for ( ; fldedgelocnum < orgvendloctax[fldvertlocnum]; fldedgelocnum ++) { /* Reorder end vertices */ + Gnum orgvertlocend; + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval)) { + errorPrint ("hdgraphFold2: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + orgvertlocend = orgedgeloctax[fldedgelocnum]; + + if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ + (orgvertlocend < orgvertlocmax)) + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; + else { /* End vertex is not local */ + int procngbnum; + int procngbmax; + + for (procngbnum = 0, procngbmax = fldvertadjnbr; + procngbmax - procngbnum > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (fldvertadjtab[procngbmed] <= orgvertlocend) + procngbnum = procngbmed; + else + procngbmax = procngbmed; + } + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbnum]; + } + } + fldvertlocnum ++; + fldehallocnbr += orgvertloctax[fldvertlocnum] - fldedgelocnum; + for ( ; fldedgelocnum < orgvertloctax[fldvertlocnum]; fldedgelocnum ++) { /* Renumber halo part */ + Gnum orgverthalend; + Gnum fldvhallocend; + + orgverthalend = orgedgeloctax[fldedgelocnum]; +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if ((orgverthalend < orggrafptr->s.baseval) || + (orgverthalend >= (orggrafptr->vhallocnbr + orggrafptr->s.baseval)) || + (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval))) { + errorPrint ("hdgraphFold2: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + while (fldvhallocmax < orgverthalend) /* Expand halo vertex index array whenever necessary */ + fldvhalloctax[++ fldvhallocmax] = ~0; + fldvhallocend = fldvhalloctax[orgverthalend]; /* Get renumbered halo vertex */ + if (fldvhallocend < 0) { /* If new halo vertex not yet given */ + fldvhallocend = /* Allocate it */ + fldvhalloctax[orgverthalend] = fldvhallocnum ++; + } + fldedgeloctax[fldedgelocnum] = fldvhallocend; + } + } + + if (orggrafptr->s.veloloctax != NULL) { /* If original graph has vertex loads */ + Gnum fldvertlocnum; + + for (fldvertlocnum = orggrafptr->s.baseval, fldvelolocsum = 0; /* Accumulate load sum of remaining part */ + fldvertlocnum < orgvertlocnnd; fldvertlocnum ++) + fldvelolocsum += orggrafptr->s.veloloctax[fldvertlocnum]; + } + + commnbr = 0; /* Turn sender-receiver into normal receiver without any communications to perform */ + } + + if (orggrafptr->s.veloloctax != NULL) /* If original graph has vertex loads */ + memCpy (fldgrafptr->s.veloloctax + orggrafptr->s.baseval, /* Copy local part of vertex load array */ + orggrafptr->s.veloloctax + orggrafptr->s.baseval, orgvertlocnbr * sizeof (Gnum)); + + if (orggrafptr->s.vnumloctax != NULL) /* If original graph has vertex numbers */ + memCpy (fldgrafptr->s.vnumloctax + orggrafptr->s.baseval, /* Copy local part of vertex number array */ + orggrafptr->s.vnumloctax + orggrafptr->s.baseval, orgvertlocnbr * sizeof (Gnum)); + else { /* Build local part of vertex number array */ + Gnum fldvertlocnum; + Gnum fldvertlocadj; + + for (fldvertlocnum = orggrafptr->s.baseval, + fldvertlocadj = orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]; + fldvertlocnum < orgvertlocnnd; fldvertlocnum ++) + fldgrafptr->s.vnumloctax[fldvertlocnum] = fldvertlocadj ++; + } + + memCpy (fldgrafptr->s.vertloctax + orggrafptr->s.baseval, /* Copy local part of vertex arrays, since they are compact */ + orggrafptr->s.vertloctax + orggrafptr->s.baseval, orgvertlocnbr * sizeof (Gnum)); /* Last value not copied */ + fldgrafptr->s.vertloctax[fldvertlocnbr + orggrafptr->s.baseval] = fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval; + memCpy (fldgrafptr->s.vendloctax + orggrafptr->s.baseval, + orggrafptr->s.vendloctax + orggrafptr->s.baseval, orgvertlocnbr * sizeof (Gnum)); + + for (i = 0; i < commnbr; i ++) { + int j; + + if (MPI_Waitany (commnbr, &requtab[HDGRAPHFOLDTAGVERT * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (14)"); + cheklocval = 1; + } + else { /* Adjust first remote part of vertex array */ + Gnum fldvertlocnum; + Gnum fldvertlocnnd; + Gnum fldvertlocadj; + + Gnum * restrict const fldvertloctax = fldgrafptr->s.vertloctax; + + fldvertlocnum = fldvertidxtab[j]; + fldvertlocadj = fldedgeidxtab[j] - fldgrafptr->s.vertloctax[fldvertlocnum]; + fldvendidxtab[j] = fldvertlocadj; /* Record updated adjust value for vendloctab pass */ + + for (fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) + fldvertloctax[fldvertlocnum] += fldvertlocadj; + } + } + + for (i = 0; i < commnbr; i ++) { + int j; + + if (MPI_Waitany (commnbr, &requtab[HDGRAPHFOLDTAGVEND * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (15)"); + cheklocval = 1; + } + else { /* Adjust first remote part of vertex array */ + Gnum fldvendlocnum; + Gnum fldvendlocnnd; + Gnum fldvendlocadj; + + Gnum * restrict const fldvendloctax = fldgrafptr->s.vendloctax; + + fldvendlocnum = fldvertidxtab[j]; + fldvendlocadj = fldvendidxtab[j]; /* Get updated adjust from above vertloctab pass */ + + for (fldvendlocnnd = fldvendlocnum + fldcommdattab[j].vertnbr; fldvendlocnum < fldvendlocnnd; fldvendlocnum ++) + fldvendloctax[fldvendlocnum] += fldvendlocadj; + } + } + + for (i = 0; i < commnbr; i ++) { + MPI_Status statdat; + int j; + + if (MPI_Waitany (commnbr, &requtab[HDGRAPHFOLDTAGEDGE * commmax], &j, &statdat) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (16)"); + cheklocval = 1; + } + else if (cheklocval == 0) { /* Adjust remote part(s) of edge array */ + Gnum orgvertlocmin; + Gnum orgvertlocmax; + Gnum fldvertlocnum; + Gnum fldvertlocnnd; + Gnum fldvertlocadj; + Gnum fldvhallocmax; /* Maximum current size of halo vertex array */ + int procngbmin; + int procngbmax; + + Gnum * restrict const fldvertloctax = fldgrafptr->s.vertloctax; + Gnum * restrict const fldvendloctax = fldgrafptr->s.vendloctax; + Gnum * restrict const fldedgeloctax = fldgrafptr->s.edgeloctax; + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + int fldedgercvnbr; + + MPI_Get_count (&statdat, GNUM_MPI, &fldedgercvnbr); + if (fldedgercvnbr != fldedgecnttab[j]) { + errorPrint ("hdgraphFold2: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + for (procngbmin = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ + procngbmax - procngbmin > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbmin) / 2; + if (fldvertadjtab[procngbmed] <= fldcommvrttab[j]) + procngbmin = procngbmed; + else + procngbmax = procngbmed; + } + orgvertlocmin = fldvertadjtab[procngbmin]; + orgvertlocmax = fldvertadjtab[procngbmax]; + fldvertlocadj = fldvertdlttab[procngbmin]; + fldvhallocmax = orggrafptr->s.baseval - 1; /* Reset halo vertex array for each remote part */ + for (fldvertlocnum = fldvertidxtab[j], fldedgelocnum = fldedgeidxtab[j], /* Update received part of edge array */ + fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; + fldvertlocnum < fldvertlocnnd; ) { + for ( ; fldedgelocnum < fldvendloctax[fldvertlocnum]; fldedgelocnum ++) { /* Reorder end vertices */ + Gnum orgvertlocend; + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval)) { + errorPrint ("hdgraphFold2: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + orgvertlocend = fldedgeloctax[fldedgelocnum]; + + if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ + (orgvertlocend < orgvertlocmax)) + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; + else { + int procngbnum; + int procngbmax; + + for (procngbnum = 0, procngbmax = fldvertadjnbr; + procngbmax - procngbnum > 1; ) { + int procngbmed; + + procngbmed = (procngbmax + procngbnum) / 2; + if (fldvertadjtab[procngbmed] <= orgvertlocend) + procngbnum = procngbmed; + else + procngbmax = procngbmed; + } + fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbnum]; + } + } + fldvertlocnum ++; + fldehallocnbr += fldvertloctax[fldvertlocnum] - fldedgelocnum; + for ( ; fldedgelocnum < fldvertloctax[fldvertlocnum]; fldedgelocnum ++) { /* Renumber halo part */ + Gnum orgverthalend; + Gnum fldvhallocend; + + orgverthalend = fldedgeloctax[fldedgelocnum]; +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if ((orgverthalend < orggrafptr->s.baseval) || + (orgverthalend >= (orggrafptr->s.edgeglbsmx + orggrafptr->s.baseval)) || + (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval))) { + errorPrint ("hdgraphFold2: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + while (fldvhallocmax < orgverthalend) /* Expand halo vertex index array whenever necessary */ + fldvhalloctax[++ fldvhallocmax] = ~0; + fldvhallocend = fldvhalloctax[orgverthalend]; /* Get renumbered halo vertex */ + if (fldvhallocend < 0) { /* If new halo vertex not yet given */ + fldvhallocend = /* Allocate it */ + fldvhalloctax[orgverthalend] = fldvhallocnum ++; + } + fldedgeloctax[fldedgelocnum] = fldvhallocend; + } + } + } + } + + if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver, edge arrays may have been oversized */ + fldgrafptr->s.edgeloctax = memRealloc (fldgrafptr->s.edgeloctax + orggrafptr->s.baseval, fldgrafptr->s.edgelocsiz * sizeof (Gnum)); + fldgrafptr->s.edgeloctax -= orggrafptr->s.baseval; + } + + fldgrafptr->vhallocnbr = fldvhallocnum - orggrafptr->s.baseval; + fldgrafptr->vhndloctax = fldgrafptr->s.vertloctax + 1; /* Compact edge array with halo vertices */ + fldgrafptr->ehallocnbr = fldehallocnbr; + fldgrafptr->levlnum = orggrafptr->levlnum; /* Folded graph is of same level */ + + if (orggrafptr->s.veloloctax == NULL) /* If no vertex loads, reset graph vertex load to number of vertices */ + fldvelolocsum = fldvertlocnbr; + else { /* Graph has vertex loads and load of local part has already been computed */ + for (i = 0; i < commnbr; i ++) { + int j; + + if (MPI_Waitany (commnbr, &requtab[HDGRAPHFOLDTAGVELO * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (17)"); + cheklocval = 1; + } + else if (cheklocval == 0) { /* Accumulate vertex loads for received vertex load array */ + Gnum fldvertlocnum; + Gnum fldvertlocnnd; + + for (fldvertlocnum = fldvertidxtab[j], fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; + fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) + fldvelolocsum += fldgrafptr->s.veloloctax[fldvertlocnum]; + } + } + } + + fldgrafptr->s.baseval = orggrafptr->s.baseval; + fldgrafptr->s.vertlocnbr = fldvertlocnbr; + fldgrafptr->s.vertlocnnd = fldvertlocnbr + orggrafptr->s.baseval; + fldgrafptr->s.velolocsum = fldvelolocsum; + fldgrafptr->s.edgelocnbr = fldgrafptr->s.edgelocsiz - fldehallocnbr; + fldgrafptr->s.degrglbmax = orggrafptr->s.degrglbmax; + if (dgraphBuild4 (&fldgrafptr->s) != 0) { + errorPrint ("hdgraphFold2: cannot build folded graph"); + hdgraphExit (fldgrafptr); + return (1); + } + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (hdgraphCheck (fldgrafptr) != 0) { /* Check graph consistency; vnumloctab is not checked so no need to wait for it */ + errorPrint ("hdgraphFold2: internal error (9)"); + hdgraphExit (fldgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + } + + memFree (fldcommdattab); /* Free group leader */ + + if (MPI_Waitall (requnbr, requtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for all graph data to arrive because graph could be freed afterwards */ + errorPrint ("hdgraphFold2: communication error (18)"); + cheklocval = 1; + } + + memFree (fldvertidxtab); /* Free group leader including request array */ + +#ifdef SCOTCH_DEBUG_HDGRAPH1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, orggrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphFold2: communication error (19)"); + chekglbval = 1; + } +#else /* SCOTCH_DEBUG_HDGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_HDGRAPH1 */ + + return (chekglbval); +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph_fold.h b/scotch_6.0.3/src/libscotch/hdgraph_fold.h new file mode 100644 index 00000000..1eff1189 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_fold.h @@ -0,0 +1,66 @@ +/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_fold.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the distributed source graph **/ +/** folding routines. **/ +/** **/ +/** # Version 5.0 : from : 06 sep 2006 **/ +/** to 06 sep 2006 **/ +/** # Version 5.1 : from : 03 jan 2009 **/ +/** to 03 jan 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/* Slot indices used for point-to-point folding + communications. First indices are used for + communications without further processing. + At the moment, there is one anonymous slot: + vnumloctab. */ + +typedef enum HdgraphFoldTag_ { + HDGRAPHFOLDTAGENBR = 1, /*+ Edge size message +*/ + HDGRAPHFOLDTAGVERT, /*+ vertloctab message +*/ + HDGRAPHFOLDTAGVEND, /*+ vendloctab message +*/ + HDGRAPHFOLDTAGVELO, /*+ veloloctab message +*/ + HDGRAPHFOLDTAGEDGE, /*+ edgeloctab message +*/ + HDGRAPHFOLDTAGNBR /*+ Number of tags +*/ +} HdgraphFoldTag; diff --git a/scotch_6.0.3/src/libscotch/hdgraph_gather.c b/scotch_6.0.3/src/libscotch/hdgraph_gather.c new file mode 100644 index 00000000..87d332bb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_gather.c @@ -0,0 +1,451 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_gather.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the routine which **/ +/** builds a centralized halo graph by **/ +/** gathering the pieces of a distributed **/ +/** halo graph. **/ +/** **/ +/** DATES : # Version 5.0 : from : 19 apr 2006 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 30 jul 2010 **/ +/** to : 30 jul 2010 **/ +/** # Version 6.0 : from : 27 nov 2012 **/ +/** to 27 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH_GATHER + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "graph.h" +#include "hgraph.h" +#include "dgraph.h" +#include "hdgraph.h" + +/******************************/ +/* */ +/* These routines handle halo */ +/* distributed source graphs. */ +/* */ +/******************************/ + +/* This function gathers the pieces of +** a distributed halo graph to build a +** centralized halo graph. +** There is no gathered vnumtab array if +** the original graph did not have one, as +** vertices are gathered in global order, or +** else the original vnumloctab is gathered. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +hdgraphGather ( +Hdgraph * restrict const dgrfptr, /* Distributed halo graph */ +Hgraph * restrict const cgrfptr) /* Centralized halo graph */ +{ + Gnum vertlocnum; + Gnum vertlocadj; /* Local vertex array adjust */ + Gnum vhallocnnd; + int vhallocnbr; /* Local copy for sending as a MPI_INT */ + Gnum * restrict verthaltax; + Gnum * restrict edgehaltax; + Gnum edgehalnum; + int ehallocnbr; /* Local copy for sending as a MPI_INT */ + int rootnum; /* Index of root process */ + Gnum reduloctab[4]; /* Arrays for reductions */ + Gnum reduglbtab[4]; + int * restrict recvcnttab; /* Arrays for parametrizing gather operations */ + int * restrict recvdsptab; + int cheklocval; + int chekglbval; + Gnum degrmax; + + if (cgrfptr != NULL) { /* If centralized graph provided */ + reduloctab[0] = 1; /* This process is the root */ + reduloctab[1] = (Gnum) dgrfptr->s.proclocnum; /* Get its rank */ + } + else { + reduloctab[0] = /* This process is not the root */ + reduloctab[1] = 0; + } + reduloctab[2] = dgrfptr->vhallocnbr; + reduloctab[3] = dgrfptr->ehallocnbr; + if (MPI_Allreduce (reduloctab, reduglbtab, 4, GNUM_MPI, MPI_SUM, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (1)"); + return (1); + } + if (reduglbtab[0] != 1) { + errorPrint ("hdgraphGather: should have only one root"); + return (1); + } + rootnum = (int) reduglbtab[1]; /* Get rank of root process */ + degrmax = dgrfptr->s.degrglbmax; /* Distributed degree does not account for halo edges */ + + cheklocval = 0; + if (cgrfptr != NULL) { /* If process is root */ + Gnum vnohnbr; + Gnum vertnbr; + Gnum velonbr; + Gnum vnumnbr; + Gnum * restrict velotax; + Gnum * restrict vnumtax; + Gnum edgenbr; + + vnohnbr = dgrfptr->s.vertglbnbr; + vertnbr = vnohnbr + reduglbtab[2]; + velonbr = (dgrfptr->s.veloloctax != NULL) ? vertnbr : 0; + vnumnbr = (dgrfptr->s.vnumloctax != NULL) ? vnohnbr : 0; /* Vertex numbers only serve for non-halo vertices */ + edgenbr = dgrfptr->s.edgeglbnbr + 2 * reduglbtab[3]; /* Twice since halo vertices will be created for real */ + + cgrfptr->s.flagval = GRAPHFREEEDGE | GRAPHEDGEGROUP | GRAPHFREEVERT | GRAPHVERTGROUP; /* In case of premature freeing on error */ + recvcnttab = NULL; + if (memAllocGroup ((void **) (void *) + &cgrfptr->s.verttax, (size_t) ((vertnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ + &velotax, (size_t) (velonbr * sizeof (Gnum)), + &vnumtax, (size_t) (vnumnbr * sizeof (Gnum)), + &cgrfptr->vnhdtax, (size_t) (vnohnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hdgraphGather: out of memory (1)"); + cheklocval = 1; + } + else if (cgrfptr->s.verttax -= dgrfptr->s.baseval, + cgrfptr->s.velotax = (dgrfptr->s.veloloctax != NULL) ? velotax - dgrfptr->s.baseval : NULL, + cgrfptr->s.vnumtax = (dgrfptr->s.vnumloctax != NULL) ? vnumtax - dgrfptr->s.baseval : NULL, + cgrfptr->vnhdtax -= dgrfptr->s.baseval, + ((cgrfptr->s.edgetax = (Gnum *) memAlloc (edgenbr * sizeof (Gnum))) == NULL)) { + errorPrint ("hdgraphGather: out of memory (2)"); + cheklocval = 1; + } + else if (cgrfptr->s.edgetax -= dgrfptr->s.baseval, + memAllocGroup ((void **) (void *) + &recvcnttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), + &recvdsptab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("hdgraphGather: out of memory (3)"); + cheklocval = 1; + } + else { + cgrfptr->s.baseval = dgrfptr->s.baseval; + cgrfptr->s.vertnbr = vertnbr; + cgrfptr->s.vertnnd = vertnbr + dgrfptr->s.baseval; + cgrfptr->s.vendtax = cgrfptr->s.verttax + 1; /* Compact edge array */ + cgrfptr->s.velosum = dgrfptr->s.veloglbsum + reduglbtab[2]; /* Halo vertices have unity vertex loads */ + cgrfptr->s.vlbltax = NULL; + cgrfptr->s.edgenbr = edgenbr; + cgrfptr->s.edlotax = NULL; + cgrfptr->s.edlosum = edgenbr; + cgrfptr->s.procptr = NULL; /* Not a multi-sequential gather: no communication possible */ + cgrfptr->vnohnbr = vnohnbr; + cgrfptr->vnohnnd = vnohnbr + dgrfptr->s.baseval; + cgrfptr->vnlosum = dgrfptr->s.veloglbsum; + cgrfptr->enohnbr = + cgrfptr->enohsum = dgrfptr->s.edgeglbnbr; + cgrfptr->levlnum = dgrfptr->levlnum; + } + } + if ((cheklocval == 0) && + (memAllocGroup ((void **) (void *) + &verthaltax, (size_t) (dgrfptr->vhallocnbr * sizeof (Gnum)), + &edgehaltax, (size_t) (dgrfptr->ehallocnbr * sizeof (Gnum)), NULL) == NULL)) { + errorPrint ("hdgraphGather: out of memory (4)"); + cheklocval = 1; + } + else { + verthaltax -= dgrfptr->s.baseval; + edgehaltax -= dgrfptr->s.baseval; + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (2)"); + return (1); + } + if (chekglbval != 0) { + if (verthaltax != NULL) + memFree (verthaltax + dgrfptr->s.baseval); + if (cgrfptr != NULL) { /* If data were previously allocated */ + if (recvcnttab != NULL) + memFree (recvcnttab); + hgraphExit (cgrfptr); + } + return (1); + } + + if (dgrfptr->vhndloctax == dgrfptr->s.vertloctax + 1) { /* If distributed halo graph is compact */ + Gnum procglbnum; + Gnum edgenum; + + if (cgrfptr != NULL) { + Gnum vertnum; + + cgrfptr->s.verttax[dgrfptr->s.baseval] = dgrfptr->s.baseval; + if (commGatherv (dgrfptr->s.vertloctax + 1 + dgrfptr->s.baseval, /* Do not send first index, it is always equal to baseval */ + dgrfptr->s.vertlocnbr, GNUM_MPI, + cgrfptr->s.verttax + 1, /* First index will always be equal to baseval too, and procdsptab holds based values */ + dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (3)"); + return (1); + } + if (commGatherv (dgrfptr->s.vendloctax + dgrfptr->s.baseval, + dgrfptr->s.vertlocnbr, GNUM_MPI, cgrfptr->vnhdtax, /* procdsptab holds based values */ + dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (4)"); + return (1); + } + + for (procglbnum = 1, vertnum = dgrfptr->s.procdsptab[1] + 1; /* Adjust index sub-arrays for all processors except the first one */ + procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { + Gnum vertnnd; + Gnum edgeadj; + + for (vertnnd = dgrfptr->s.procdsptab[procglbnum + 1] + 1, + edgeadj = cgrfptr->s.verttax[vertnum - 1] - dgrfptr->s.baseval; + vertnum < vertnnd; vertnum ++) { + cgrfptr->s.verttax[vertnum] += edgeadj; + cgrfptr->vnhdtax[vertnum - 1] += edgeadj; + } + } + + for (procglbnum = 0, edgenum = dgrfptr->s.baseval; /* Build arrays for MPI_Gatherv on edge arrays */ + procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { + recvcnttab[procglbnum] = cgrfptr->s.verttax[dgrfptr->s.procdsptab[procglbnum + 1]] - + cgrfptr->s.verttax[dgrfptr->s.procdsptab[procglbnum]]; /* verttax used twice since centralized graph is compact */ + recvdsptab[procglbnum] = edgenum; + edgenum += recvcnttab[procglbnum]; + } + if (MPI_Gatherv (dgrfptr->s.edgeloctax + dgrfptr->s.baseval, /* Gather edge arrays with global vertex indices */ + (int) (dgrfptr->s.edgelocnbr + dgrfptr->ehallocnbr), GNUM_MPI, cgrfptr->s.edgetax, + recvcnttab, recvdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (5)"); + return (1); + } + } + else { + if (MPI_Gatherv (dgrfptr->s.vertloctax + 1 + dgrfptr->s.baseval, /* Do not send first index, it is always equal to baseval */ + (int) dgrfptr->s.vertlocnbr, GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (6)"); + return (1); + } + if (MPI_Gatherv (dgrfptr->s.vendloctax + dgrfptr->s.baseval, + (int) dgrfptr->s.vertlocnbr, GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (7)"); + return (1); + } + if (MPI_Gatherv (dgrfptr->s.edgeloctax + dgrfptr->s.baseval, /* Gather edge arrays with global vertex indices */ + (int) (dgrfptr->s.edgelocnbr + dgrfptr->ehallocnbr), GNUM_MPI, + NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (8)"); + return (1); + } + } + } + else { + errorPrint ("hdgraphGather: Not implemented"); /* Not really necessary as all Hdgraph structures created by Scotch itself are compact */ + return (1); + } + + memSet (verthaltax + dgrfptr->s.baseval, 0, dgrfptr->vhallocnbr * sizeof (Gnum)); /* Initialize halo end vertex count array */ + for (vertlocnum = dgrfptr->s.baseval; vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + + for (edgelocnum = dgrfptr->s.vendloctax[vertlocnum]; edgelocnum < dgrfptr->vhndloctax[vertlocnum]; edgelocnum ++) + verthaltax[dgrfptr->s.edgeloctax[edgelocnum]] ++; /* One more edge to this halo vertex */ + } + vhallocnbr = (int) dgrfptr->vhallocnbr; + if (MPI_Gather (&vhallocnbr, 1, MPI_INT, recvcnttab, 1, MPI_INT, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (9)"); + return (1); + } + if (cgrfptr != NULL) { /* Build gather parameter array to receive halo edge counts */ + Gnum procglbnum; + Gnum vertnum; + + for (procglbnum = 0, vertnum = 0; procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { /* Displacements start from zero because adjusted later */ + recvdsptab[procglbnum] = vertnum; + vertnum += recvcnttab[procglbnum]; + } + if (MPI_Gatherv (verthaltax + dgrfptr->s.baseval, (int) dgrfptr->vhallocnbr, GNUM_MPI, /* Gather count arrays of halo vertices */ + cgrfptr->s.verttax + cgrfptr->vnohnnd + 1, recvcnttab, recvdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (10)"); + return (1); + } + + for (procglbnum = 0, vertnum = dgrfptr->s.baseval; /* Adjust end vertex indices for halo edges */ + procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { + Gnum vertnnd; + Gnum vertadj; + + for (vertnnd = dgrfptr->s.procdsptab[procglbnum + 1], vertadj = cgrfptr->vnohnbr + recvdsptab[procglbnum]; + vertnum < vertnnd; vertnum ++) { + Gnum edgenum; + + if (degrmax < (cgrfptr->s.vendtax[vertnum] - cgrfptr->s.verttax[vertnum])) /* Account for halo edges in maximum degree */ + degrmax = (cgrfptr->s.vendtax[vertnum] - cgrfptr->s.verttax[vertnum]); + for (edgenum = cgrfptr->vnhdtax[vertnum]; edgenum < cgrfptr->s.vendtax[vertnum]; edgenum ++) + cgrfptr->s.edgetax[edgenum] += vertadj; + } + } + } + else { + if (MPI_Gatherv (verthaltax + dgrfptr->s.baseval, (int) dgrfptr->vhallocnbr, GNUM_MPI, /* Gather count arrays of halo vertices */ + NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (11)"); + return (1); + } + } + for (vertlocnum = edgehalnum = dgrfptr->s.baseval, vhallocnnd = dgrfptr->vhallocnbr + dgrfptr->s.baseval; + vertlocnum < vhallocnnd; vertlocnum ++) { /* Prepare index array for edge collection */ + Gnum degrlocval; + + degrlocval = verthaltax[vertlocnum]; + verthaltax[vertlocnum] = edgehalnum; + edgehalnum += degrlocval; + } + vertlocadj = dgrfptr->s.procdsptab[dgrfptr->s.proclocnum] - dgrfptr->s.baseval; + for (vertlocnum = dgrfptr->s.baseval; vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { /* Collect halo edge ends */ + Gnum edgelocnum; + + for (edgelocnum = dgrfptr->s.vendloctax[vertlocnum]; edgelocnum < dgrfptr->vhndloctax[vertlocnum]; edgelocnum ++) + edgehaltax[verthaltax[dgrfptr->s.edgeloctax[edgelocnum]] ++] = vertlocnum + vertlocadj; + } + ehallocnbr = (int) dgrfptr->ehallocnbr; + if (MPI_Gather (&ehallocnbr, 1, MPI_INT, recvcnttab, 1, MPI_INT, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { /* Gather halo edge counts */ + errorPrint ("hdgraphGather: communication error (12)"); + return (1); + } + if (cgrfptr != NULL) { /* Compute receive arrays for edge sub-arrays of halo vertices */ + Gnum procglbnum; + Gnum edgeadj; + + for (procglbnum = 0, edgeadj = 0; procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { + recvdsptab[procglbnum] = edgeadj; + edgeadj += recvcnttab[procglbnum]; + } + if (MPI_Gatherv (edgehaltax + dgrfptr->s.baseval, (int) dgrfptr->ehallocnbr, GNUM_MPI, /* Gather edge arrays of halo vertices */ + cgrfptr->s.edgetax + cgrfptr->enohnbr + reduglbtab[3] + dgrfptr->s.baseval, recvcnttab, recvdsptab, GNUM_MPI, + rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (13)"); + return (1); + } + } + else { + if (MPI_Gatherv (edgehaltax + dgrfptr->s.baseval, (int) dgrfptr->ehallocnbr, GNUM_MPI, /* Gather edge arrays of halo vertices */ + NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (14)"); + return (1); + } + } + + memFree (verthaltax + dgrfptr->s.baseval); /* Free group leader */ + + if (cgrfptr != NULL) { /* Finalize vertex and edge arrays of centralized graph */ + Gnum vertnum; + Gnum edgeadj; + + if (dgrfptr->s.veloloctax != NULL) { /* Get vertex loads if any */ + if (commGatherv (dgrfptr->s.veloloctax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GNUM_MPI, + cgrfptr->s.velotax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, + rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (15)"); + return (1); + } + + for (vertnum = cgrfptr->vnohnnd; vertnum < cgrfptr->s.vertnnd; vertnum ++) /* complete filling of vertex load array */ + cgrfptr->s.velotax[vertnum] = 1; + } + if (dgrfptr->s.vnumloctax != NULL) { /* Get vertex numbers if any */ + if (commGatherv (dgrfptr->s.vnumloctax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GNUM_MPI, + cgrfptr->s.vnumtax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, + rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (16)"); + return (1); + } + } + + memFree (recvcnttab); /* Free group leader */ + + for (vertnum = cgrfptr->vnohnnd + 1, edgeadj = cgrfptr->s.verttax[cgrfptr->vnohnnd]; /* Adjust vertex array for halo vertices */ + vertnum <= cgrfptr->s.vertnnd; vertnum ++) { + Gnum degrval; + + degrval = cgrfptr->s.verttax[vertnum]; + if (degrmax < degrval) /* Account for halo edges in maximum degree */ + degrmax = degrval; + edgeadj += degrval; + cgrfptr->s.verttax[vertnum] = edgeadj; + } + cgrfptr->s.degrmax = degrmax; + } + else { + if (dgrfptr->s.veloloctax != NULL) { /* Get vertex loads if any */ + if (MPI_Gatherv (dgrfptr->s.veloloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI, + NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (17)"); + return (1); + } + } + if (dgrfptr->s.vnumloctax != NULL) { /* Get vertex numbers if any */ + if (MPI_Gatherv (dgrfptr->s.vnumloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI, + NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (18)"); + return (1); + } + } + } + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + cheklocval = (cgrfptr != NULL) ? hgraphCheck (cgrfptr) : 0; + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphGather: communication error (19)"); + return (1); + } + if (chekglbval != 0) { + errorPrint ("hdgraphGather: internal error"); + if (cgrfptr != NULL) + hgraphExit (cgrfptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph_induce.c b/scotch_6.0.3/src/libscotch/hdgraph_induce.c new file mode 100644 index 00000000..1cc6f31d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_induce.c @@ -0,0 +1,358 @@ +/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_induce.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the halo source **/ +/** graph subgraph-making functions. **/ +/** **/ +/** DATES : # Version 5.0 : from : 19 apr 2006 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 27 jun 2008 **/ +/** to : 22 oct 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "hdgraph.h" + +/******************************/ +/* */ +/* These routines handle halo */ +/* distributed source graphs. */ +/* */ +/******************************/ + +/* This routine builds the graph induced +** by the original graph and the list of +** selected vertices. +** The induced vnumtab array is the global +** translation of the list array if the +** original graph does not have a vnumtab, +** or the proper subset of the original +** vnumtab else. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +hdgraphInduceList ( +Hdgraph * restrict const orggrafptr, +const Gnum indlistnbr, +const Gnum * restrict const indlisttab, /* Local list of kept vertices */ +Hdgraph * restrict const indgrafptr) +{ + const Gnum * restrict orgvertloctax; + const Gnum * restrict orgvendloctax; + const Gnum * restrict orgveloloctax; + const Gnum * restrict orgedgegsttax; + const Gnum * restrict orgedgeloctax; + Gnum * restrict orgindxgsttax; /* Based access to vertex translation array */ + Gnum * restrict orgindxhaltax; /* Based access to halo vertex translation array */ + Gnum * restrict indvertloctax; + Gnum * restrict indveloloctax; + Gnum indvertlocnnd; /* Based index of end of local vertex array */ + Gnum indvertlocnum; /* Number of current vertex in induced graph */ + Gnum indvertglbnum; /* Number of current vertex in global ordering */ + Gnum * restrict indvendloctax; + Gnum indvelolocnbr; /* Size of local vertex load array */ + Gnum indvelolocsum; /* Sum of vertex loads */ + Gnum indvhallocnum; /* Number of halo vertex to be declared */ + Gnum * restrict indedgeloctax; + Gnum indedgelocmax; /* (Approximate) number of edges in induced graph */ + Gnum indedgelocsiz; /* Real size of edge array, including halo */ + Gnum indedgelocnbr; /* Real number of edges in induced graph */ + Gnum indedgelocnum; + Gnum inddegrlocmax; /* Local maximum degree over non-halo vertices */ + const Gnum * restrict indlisttax; /* Based access to list of kept vertices */ + int cheklocval; + int chekglbval; + + if (dgraphGhst (&orggrafptr->s) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("hdgraphInduceList: cannot compute ghost edge array"); + return (1); + } + + memSet (indgrafptr, 0, sizeof (Hdgraph)); /* Pre-initialize graph fields */ + + indgrafptr->s.proccomm = orggrafptr->s.proccomm; + indgrafptr->s.procglbnbr = orggrafptr->s.procglbnbr; + indgrafptr->s.proclocnum = orggrafptr->s.proclocnum; + indgrafptr->s.flagval = (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* For premature freeing on error; do not free vhndloctab as it is grouped with vertloctab */ + + if (orggrafptr->s.veloloctax != NULL) { + indvelolocnbr = indlistnbr; + indvelolocsum = 0; + } + else { + indvelolocnbr = 0; + indvelolocsum = indlistnbr; + } + indedgelocmax = orggrafptr->s.edgelocnbr; /* Choose best upper bound on number of edges (avoid multiply overflow) */ + if ((orggrafptr->s.degrglbmax > 0) && (indlistnbr < (indedgelocmax / orggrafptr->s.degrglbmax))) + indedgelocmax = indlistnbr * orggrafptr->s.degrglbmax; + indedgelocmax += orggrafptr->ehallocnbr; + + cheklocval = + chekglbval = 0; + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ + &indgrafptr->s.procdsptab, (size_t) ((orggrafptr->s.procglbnbr + 1) * sizeof (Gnum)), + &indgrafptr->s.proccnttab, (size_t) (orggrafptr->s.procglbnbr * sizeof (Gnum)), + &indgrafptr->s.procngbtab, (size_t) (orggrafptr->s.procglbnbr * sizeof (int)), + &indgrafptr->s.procrcvtab, (size_t) (orggrafptr->s.procglbnbr * sizeof (int)), + &indgrafptr->s.procsndtab, (size_t) (orggrafptr->s.procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("hdgraphInduceList: out of memory (1)"); + cheklocval = 1; + } + else if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ + &indgrafptr->s.vertloctax, (size_t) ((indlistnbr + 1) * sizeof (Gnum)), /* Compact vertex arrays */ + &indgrafptr->s.vendloctax, (size_t) (indlistnbr * sizeof (Gnum)), /* Vertex end array for non-halo vertices */ + &indgrafptr->s.vnumloctax, (size_t) (indlistnbr * sizeof (Gnum)), + &indgrafptr->s.veloloctax, (size_t) (indvelolocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hdgraphInduceList: out of memory (2)"); + cheklocval = 1; + } + else if (indgrafptr->s.vertloctax -= orggrafptr->s.baseval, + indgrafptr->s.vendloctax -= orggrafptr->s.baseval, + indgrafptr->s.vnumloctax -= orggrafptr->s.baseval, + indgrafptr->s.veloloctax = ((orggrafptr->s.veloloctax != NULL) ? indgrafptr->s.veloloctax - orggrafptr->s.baseval : NULL), + memAllocGroup ((void **) (void *) + &indgrafptr->s.edgeloctax, (size_t) (indedgelocmax * sizeof (Gnum)), /* Pre-allocate space for edgeloctab */ + &orgindxgsttax, (size_t) (orggrafptr->s.vertgstnbr * sizeof (Gnum)), /* orgindxgsttab and orgindxhaltab are at the end */ + &orgindxhaltax, (size_t) (orggrafptr->vhallocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hdgraphInduceList: out of memory (3)"); + cheklocval = 1; + } + else + indgrafptr->s.edgeloctax -= orggrafptr->s.baseval; + + if (cheklocval != 0) { /* In case of memory error */ + Gnum procngbnum; + int dummyval; + + dummyval = -1; + chekglbval = 1; + if (MPI_Allgather (&dummyval, 1, GNUM_MPI, /* Use proccnttab of orggraf as dummy receive array (will be regenerated) */ + orggrafptr->s.proccnttab, 1, GNUM_MPI, indgrafptr->s.proccomm) != MPI_SUCCESS) + errorPrint ("hdgraphInduceList: communication error (1)"); + + for (procngbnum = 1; procngbnum <= orggrafptr->s.procglbnbr; procngbnum ++) /* Rebuild proccnttab of orggraf */ + orggrafptr->s.proccnttab[procngbnum - 1] = orggrafptr->s.procdsptab[procngbnum] - orggrafptr->s.procdsptab[procngbnum - 1]; + } + else { + indgrafptr->s.procvrttab = indgrafptr->s.procdsptab; /* Graph does not have holes */ + indgrafptr->s.procdsptab[0] = indlistnbr; + if (MPI_Allgather (&indgrafptr->s.procdsptab[0], 1, GNUM_MPI, + &indgrafptr->s.proccnttab[0], 1, GNUM_MPI, indgrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphInduceList: communication error (2)"); + chekglbval = 1; + } + else { + Gnum procngbnum; + + indgrafptr->s.procdsptab[0] = orggrafptr->s.baseval; /* Build vertex-to-process array */ + for (procngbnum = 0; procngbnum < indgrafptr->s.procglbnbr; procngbnum ++) { /* Process potential error flags from other processes */ + if (indgrafptr->s.proccnttab[procngbnum] < 0) { /* If error notified by another process */ + chekglbval = 1; + break; + } + indgrafptr->s.procdsptab[procngbnum + 1] = indgrafptr->s.procdsptab[procngbnum] + indgrafptr->s.proccnttab[procngbnum]; + } + } + } + if (chekglbval != 0) { /* If something went wrong in all of the above */ + hdgraphExit (indgrafptr); + return (1); + } + + memSet (orgindxgsttax, ~0, orggrafptr->s.vertgstnbr * sizeof (Gnum)); /* Preset index arrays */ + orgindxgsttax -= orggrafptr->s.baseval; + memSet (orgindxhaltax, ~0, orggrafptr->vhallocnbr * sizeof (Gnum)); + orgindxhaltax -= orggrafptr->s.baseval; + + indlisttax = indlisttab - orggrafptr->s.baseval; + indvertlocnnd = indlistnbr + orggrafptr->s.baseval; + for (indvertlocnum = orggrafptr->s.baseval, indvertglbnum = indgrafptr->s.procdsptab[indgrafptr->s.proclocnum]; /* Set adjustment for global ordering */ + indvertlocnum < indvertlocnnd; indvertlocnum ++, indvertglbnum ++) + orgindxgsttax[indlisttax[indvertlocnum]] = indvertglbnum; /* Mark selected vertices */ + + if (dgraphHaloSync (&orggrafptr->s, (byte *) (orgindxgsttax + orggrafptr->s.baseval), GNUM_MPI) != 0) { /* Share global indexing of subgraph vertices */ + errorPrint ("hdgraphInduceList: cannot perform halo exchange"); + hdgraphExit (indgrafptr); + return (1); + } + + orgvertloctax = orggrafptr->s.vertloctax; + orgvendloctax = orggrafptr->s.vendloctax; + orgveloloctax = orggrafptr->s.veloloctax; + orgedgegsttax = orggrafptr->s.edgegsttax; + orgedgeloctax = orggrafptr->s.edgeloctax; + indvertloctax = indgrafptr->s.vertloctax; + indvendloctax = indgrafptr->s.vendloctax; + indveloloctax = indgrafptr->s.veloloctax; + indedgeloctax = indgrafptr->s.edgeloctax; + inddegrlocmax = 0; + for (indvertlocnum = indedgelocnum = indvhallocnum = orggrafptr->s.baseval, indedgelocnbr = 0; + indvertlocnum < indvertlocnnd; indvertlocnum ++) { + Gnum orgvertlocnum; + Gnum orgedgelocnum; + Gnum orgdegrlocval; + Gnum inddegrlocval; + Gnum indedgelocnnd; + + orgvertlocnum = indlisttax[indvertlocnum]; + orgdegrlocval = orgvendloctax[orgvertlocnum] - orgvertloctax[orgvertlocnum]; + + indvertloctax[indvertlocnum] = indedgelocnum; + if (orgveloloctax != NULL) { /* If graph has vertex weights */ + indvelolocsum += /* Accumulate vertex loads */ + indveloloctax[indvertlocnum] = orgveloloctax[orgvertlocnum]; + } + indedgelocnnd = indedgelocnum + orgdegrlocval; +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (indedgelocnnd > (indedgelocmax + orggrafptr->s.baseval)) { + errorPrint ("hdgraphInduceList: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + for (orgedgelocnum = orgvertloctax[orgvertlocnum]; /* Process local and ghost non-halo vertices */ + orgedgelocnum < orgvendloctax[orgvertlocnum]; orgedgelocnum ++) { + Gnum orgvertlocend; + Gnum indvertgstend; + + orgvertlocend = orgedgegsttax[orgedgelocnum]; +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if ((orgvertlocend < orggrafptr->s.baseval) || (orgvertlocend > orggrafptr->s.vertgstnnd)) { + errorPrint ("hdgraphInduceList: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + indvertgstend = orgindxgsttax[orgvertlocend]; + if (indvertgstend >= 0) /* If edge is local or halo */ + indedgeloctax[indedgelocnum ++] = indvertgstend; /* Keep it as regular edge */ + else { /* If edge is halo edge */ + if (indvertgstend == ~0) /* If halo vertex not assigned yet */ + orgindxgsttax[orgvertlocend] = indvertgstend = -2 - indvhallocnum ++; /* Set new halo number */ + indedgeloctax[-- indedgelocnnd] = -2 - indvertgstend; + } + } +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (indedgelocnnd != indedgelocnum) { + errorPrint ("hdgraphInduceList: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + indvendloctax[indvertlocnum] = indedgelocnum; + inddegrlocval = indedgelocnum - indvertloctax[indvertlocnum]; + indedgelocnbr += inddegrlocval; + if (inddegrlocmax < inddegrlocval) + inddegrlocmax = inddegrlocval; + + for (indedgelocnum = indvertloctax[indvertlocnum] + orgdegrlocval; /* Process local halo vertices */ + orgedgelocnum < orggrafptr->vhndloctax[orgvertlocnum]; orgedgelocnum ++) { + Gnum orgvhallocend; + Gnum indvhallocend; + + orgvhallocend = orgedgeloctax[orgedgelocnum]; /* Halo vertices only exist in the edgeloctab array */ +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if ((orgvhallocend < orggrafptr->s.baseval) || (orgvhallocend >= (orggrafptr->vhallocnbr + orggrafptr->s.baseval))) { + errorPrint ("hdgraphInduceList: inconsistent halo vertex numbers"); + hdgraphExit (indgrafptr); + return (1); + } + if (indedgelocnum >= (indedgelocmax + orggrafptr->s.baseval)) { + errorPrint ("hdgraphInduceList: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + indvhallocend = orgindxhaltax[orgvhallocend]; + if (indvhallocend == ~0) /* If halo vertex not assigned yet */ + orgindxhaltax[orgvhallocend] = indvhallocend = indvhallocnum ++; /* Set new halo number */ + indgrafptr->s.edgeloctax[indedgelocnum ++] = indvhallocend; + } + } + indvertloctax[indvertlocnum] = indedgelocnum; /* Mark end of edge array for vhndloctax */ + indedgelocsiz = indedgelocnum - orggrafptr->s.baseval; /* Global number of edges, both non-halo and halo */ + + indgrafptr->s.edgeloctax = memRealloc (indgrafptr->s.edgeloctax + orggrafptr->s.baseval, + (size_t) (indedgelocsiz * sizeof (Gnum))); + indgrafptr->s.edgeloctax -= orggrafptr->s.baseval; + + if (orggrafptr->s.vnumloctax != NULL) { /* Adjust vnumloctax */ + for (indvertlocnum = orggrafptr->s.baseval; indvertlocnum < indvertlocnnd; indvertlocnum ++) + indgrafptr->s.vnumloctax[indvertlocnum] = orggrafptr->s.vnumloctax[indlisttax[indvertlocnum]]; + } + else { + Gnum orgvertglbadj; + + orgvertglbadj = orggrafptr->s.procvrttab[orggrafptr->s.proclocnum] - orggrafptr->s.baseval; /* Set adjustement for global ordering */ + for (indvertlocnum = orggrafptr->s.baseval; indvertlocnum < indvertlocnnd; indvertlocnum ++) + indgrafptr->s.vnumloctax[indvertlocnum] = indlisttax[indvertlocnum] + orgvertglbadj; + } + indgrafptr->vhallocnbr = indvhallocnum - orggrafptr->s.baseval; + indgrafptr->vhndloctax = indgrafptr->s.vertloctax + 1; /* Compact edge array with halo vertices */ + indgrafptr->ehallocnbr = indedgelocsiz - indedgelocnbr; /* Get number of halo edges by difference */ + indgrafptr->levlnum = orggrafptr->levlnum + 1; /* Induced subgraph is one level below */ + + indgrafptr->s.baseval = orggrafptr->s.baseval; + indgrafptr->s.vertlocnbr = indlistnbr; + indgrafptr->s.vertlocnnd = indlistnbr + orggrafptr->s.baseval; + indgrafptr->s.velolocsum = indvelolocsum; + indgrafptr->s.edgelocnbr = indedgelocnbr; + indgrafptr->s.edgelocsiz = indedgelocsiz; + indgrafptr->s.degrglbmax = orggrafptr->s.degrglbmax; + if (dgraphBuild4 (&indgrafptr->s) != 0) { + errorPrint ("hdgraphInduceList: cannot build induced graph"); + return (1); + } +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (hdgraphCheck (indgrafptr) != 0) { /* Check graph consistency */ + errorPrint ("hdgraphInduceList: internal error (5)"); + hdgraphExit (indgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph_order_nd.c b/scotch_6.0.3/src/libscotch/hdgraph_order_nd.c new file mode 100644 index 00000000..13e5e0fd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_order_nd.c @@ -0,0 +1,436 @@ +/* Copyright 2007,2008,2012 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_order_nd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders distributed graphs **/ +/** using the nested dissection algorithm. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 apr 2006 **/ +/** to 01 mar 2008 **/ +/** # Version 5.1 : from : 27 sep 2008 **/ +/** to 11 nov 2008 **/ +/** # Version 6.0 : from : 12 sep 2012 **/ +/** to 12 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH_ORDER_ND + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_st.h" +#include "dgraph.h" +#include "dorder.h" +#include "hdgraph.h" +#include "hdgraph_order_nd.h" +#include "hdgraph_order_sq.h" +#include "hdgraph_order_st.h" +#include "vdgraph.h" +#include "vdgraph_separate_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine builds either a centralized or a +** distributed subgraph, according to the number +** of processes in the given part. The calling +** conventions of this routine have been designed +** so as to allow for multi-threading. +*/ + +static +void * +hdgraphOrderNdFold2 ( +void * const dataptr) /* Pointer to thread data */ +{ + HdgraphOrderNdData * fldthrdptr; /* Thread input parameters */ + HdgraphOrderNdGraph * restrict fldgrafptr; /* Pointer to folded graph area */ + Hdgraph indgrafdat; /* Induced distributed halo graph */ + void * o; + + fldthrdptr = (HdgraphOrderNdData *) dataptr; + fldgrafptr = fldthrdptr->fldgrafptr; + + if (hdgraphInduceList (fldthrdptr->orggrafptr, fldthrdptr->indlistnbr, /* Compute unfinished induced subgraph on all processes */ + fldthrdptr->indlisttab, &indgrafdat) != 0) + return ((void *) 1); + + o = ((void *) 0); + if (fldthrdptr->fldprocnbr > 1) { /* If subpart has several processes, fold a distributed graph */ + if (hdgraphFold2 (&indgrafdat, fldthrdptr->fldpartval, /* Fold temporary induced subgraph from all processes */ + &fldgrafptr->data.dgrfdat, fldthrdptr->fldproccomm) != 0) + o = ((void *) 1); + } + else { /* Create a centralized graph */ + Hgraph * restrict fldcgrfptr; + + fldcgrfptr = (fldthrdptr->fldprocnum == 0) ? &fldgrafptr->data.cgrfdat : NULL; /* See if we are the receiver */ + if (hdgraphGather (&indgrafdat, fldcgrfptr) != 0) /* Gather centralized subgraph from all other processes */ + o = ((void *) 1); + } + hdgraphExit (&indgrafdat); /* Free temporary induced graph */ + + return (o); +} + +static +int +hdgraphOrderNdFold ( +Hdgraph * restrict const orggrafptr, +const Gnum indlistnbr0, /* Number of vertices in subgraph 0 */ +const Gnum * restrict const indlisttab0, /* List of vertices in subgraph 0 */ +const Gnum indlistnbr1, /* Number of vertices in subgraph 1 */ +const Gnum * restrict const indlisttab1, /* List of vertices in subgraph 1 */ +HdgraphOrderNdGraph * restrict const fldgrafptr) +{ + HdgraphOrderNdData fldthrdtab[2]; + MPI_Comm fldproccomm; + int fldprocnbr; + int fldprocnum; + int fldproccol; + int fldpartval; +#ifdef SCOTCH_PTHREAD + Hdgraph orggrafdat; /* Structure for copying graph fields except communicator */ + pthread_t thrdval; /* Data of second thread */ +#endif /* SCOTCH_PTHREAD */ + int o; + + if (dgraphGhst (&orggrafptr->s) != 0) { /* Compute ghost edge array if not already present, before copying graph fields */ + errorPrint ("hdgraphOrderNdFold: cannot compute ghost edge array"); + return (1); + } + + fldprocnbr = (orggrafptr->s.procglbnbr + 1) / 2; /* Median cut on number of processors */ + fldthrdtab[0].fldprocnbr = fldprocnbr; + fldthrdtab[1].fldprocnbr = orggrafptr->s.procglbnbr - fldprocnbr; + if (orggrafptr->s.proclocnum < fldprocnbr) { /* Compute color and rank in two subparts */ + fldpartval = 0; + fldprocnum = orggrafptr->s.proclocnum; + fldthrdtab[0].fldprocnum = fldprocnum; + fldthrdtab[1].fldprocnum = -1; + fldthrdtab[1].fldproccomm = MPI_COMM_NULL; + } + else { + fldpartval = 1; + fldprocnum = orggrafptr->s.proclocnum - fldprocnbr; + fldprocnbr = orggrafptr->s.procglbnbr - fldprocnbr; + fldthrdtab[0].fldproccomm = MPI_COMM_NULL; + fldthrdtab[0].fldprocnum = -1; + fldthrdtab[1].fldprocnum = fldprocnum; + } + fldgrafptr->typeval = HDGRAPHORDERNDTYPEDIST; /* Assume we belong to a distributed subpart */ + fldproccol = fldpartval; /* Split color is the part value */ + if (fldprocnbr <= 1) { /* If our part will have only one processor */ + fldproccol = MPI_UNDEFINED; /* Do not create any sub-communicator for it */ + fldgrafptr->typeval = HDGRAPHORDERNDTYPECENT; /* We will host a centralized subgraph */ + } + + if (MPI_Comm_split (orggrafptr->s.proccomm, fldproccol, fldprocnum, &fldproccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphOrderNdFold: communication error"); + return (1); + } + fldthrdtab[fldpartval].fldproccomm = fldproccomm; /* Assign folded communicator to proper part */ + + fldthrdtab[0].orggrafptr = orggrafptr; /* Load data to pass to the subgraph building routines */ + fldthrdtab[0].indlistnbr = indlistnbr0; + fldthrdtab[0].indlisttab = indlisttab0; + fldthrdtab[0].fldgrafptr = fldgrafptr; + fldthrdtab[0].fldpartval = 0; + fldthrdtab[1].indlistnbr = indlistnbr1; + fldthrdtab[1].indlisttab = indlisttab1; + fldthrdtab[1].fldgrafptr = fldgrafptr; + fldthrdtab[1].fldpartval = 1; + +#ifdef SCOTCH_PTHREAD + orggrafdat = *orggrafptr; /* Create a separate graph structure to change its communicator */ + fldthrdtab[1].orggrafptr = &orggrafdat; + MPI_Comm_dup (orggrafptr->s.proccomm, &orggrafdat.s.proccomm); /* Duplicate communicator to avoid interferences in communications */ + + if (pthread_create (&thrdval, NULL, hdgraphOrderNdFold2, (void *) &fldthrdtab[1]) != 0) /* If could not create thread */ + o = ((int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[0])) || /* Perform inductions in sequence */ + ((int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[1])); + else { /* Newly created thread is processing subgraph 1, so let's process subgraph 0 */ + void * o2; + + o = (int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[0]); /* Work on copy with private communicator */ + + pthread_join (thrdval, &o2); + o |= (int) (intptr_t) o2; + } + MPI_Comm_free (&orggrafdat.s.proccomm); +#else /* SCOTCH_PTHREAD */ + fldthrdtab[1].orggrafptr = orggrafptr; + + o = ((int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[0])) || /* Perform inductions in sequence */ + ((int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[1])); +#endif /* SCOTCH_PTHREAD */ + + return (o); +} + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hdgraphOrderNd ( +Hdgraph * restrict const grafptr, +DorderCblk * restrict const cblkptr, +const HdgraphOrderNdParam * restrict const paraptr) +{ + Vdgraph vspgrafdat; /* Vertex separation graph data */ + Gnum vspvertlocnum; /* Current vertex in separation graph */ + Gnum * restrict vspvnumtab[2]; /* Lists of separated parts */ + Gnum * restrict vspvnumptr0; + Gnum * restrict vspvnumptr1; + Gnum ordeglbval; + Gnum vnodglbnbr; + Gnum cblkfthnum; + HdgraphOrderNdGraph indgrafdat01; /* Induced folded graph area */ + DorderCblk * cblkptr01; + int partmax; /* Induced part having most vertices */ + int procnbr0; /* Number of processes in first part */ + int cheklocval; + int chekglbval; + int o; + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (cblkptr->vnodglbnbr != grafptr->s.vertglbnbr) { + errorPrint ("hdgraphOrderNd: inconsistent parameters"); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + if (grafptr->s.procglbnbr == 1) { /* If we are running on a single process */ + HdgraphOrderSqParam paradat; + + paradat.ordstratseq = paraptr->ordstratseq; + return (hdgraphOrderSq (grafptr, cblkptr, ¶dat)); /* Run sequentially */ + } + + if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present, to have vertgstnbr (and procsidtab) */ + errorPrint ("hdgraphOrderNd: cannot compute ghost edge array"); + return (1); + } + + vspgrafdat.s = grafptr->s; /* Get non-halo part of halo distributed graph */ + vspgrafdat.s.flagval &= ~DGRAPHFREEALL; /* Do not free contents of separation graph */ + vspgrafdat.s.vlblloctax = NULL; /* Never mind about vertex labels in the future */ + cheklocval = 0; + if ((vspgrafdat.fronloctab = (Gnum *) memAlloc (vspgrafdat.s.vertlocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("hdgraphOrderNd: out of memory (1)"); + vspgrafdat.partgsttax = NULL; + cheklocval = 1; + } + else if ((vspgrafdat.partgsttax = (GraphPart *) memAlloc (vspgrafdat.s.vertgstnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("hdgraphOrderNd: out of memory (2)"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_HDGRAPH1 /* Communication cannot be merged with a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("hdgraphOrderNd: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_HDGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_HDGRAPH1 */ + if (chekglbval != 0) { + if (vspgrafdat.fronloctab != NULL) { + if (vspgrafdat.partgsttax != NULL) + memFree (vspgrafdat.partgsttax); + memFree (vspgrafdat.fronloctab); + } + return (1); + } + + vspgrafdat.partgsttax -= vspgrafdat.s.baseval; + vspgrafdat.levlnum = grafptr->levlnum; /* Set level of separation graph as level of halo graph */ + vdgraphZero (&vspgrafdat); /* Set all local vertices to part 0 */ + + if (vdgraphSeparateSt (&vspgrafdat, paraptr->sepstrat) != 0) { /* Separate vertex-separation graph */ + memFree (vspgrafdat.partgsttax + vspgrafdat.s.baseval); + memFree (vspgrafdat.fronloctab); + return (1); + } + + if ((vspgrafdat.compglbsize[0] == 0) || /* If could not separate more */ + (vspgrafdat.compglbsize[1] == 0)) { + memFree (vspgrafdat.partgsttax + vspgrafdat.s.baseval); /* Free useless space */ + memFree (vspgrafdat.fronloctab); + + hdgraphOrderSt (grafptr, cblkptr, paraptr->ordstratlea); /* Order this leaf */ + return (0); /* Leaf has been processed */ + } + + vspvnumtab[0] = vspgrafdat.fronloctab + vspgrafdat.complocsize[2]; /* Build vertex lists within frontier array */ + vspvnumtab[1] = vspvnumtab[0] + vspgrafdat.complocsize[0]; + vspvnumptr0 = vspvnumtab[0]; + vspvnumptr1 = vspvnumtab[1]; + for (vspvertlocnum = vspgrafdat.s.baseval; vspvertlocnum < vspgrafdat.s.vertlocnnd; vspvertlocnum ++) { /* Fill lists */ + GraphPart partval; + + partval = vspgrafdat.partgsttax[vspvertlocnum]; + if (partval == 0) + *vspvnumptr0 ++ = vspvertlocnum; + else if (partval == 1) + *vspvnumptr1 ++ = vspvertlocnum; + } + memFree (vspgrafdat.partgsttax + vspgrafdat.s.baseval); /* Free useless space */ +#ifdef SCOTCH_DEBUG_HDGRAPH2 + vspgrafdat.partgsttax = NULL; /* Will cause bug if re-read */ + + if ((vspvnumptr0 != vspvnumtab[0] + vspgrafdat.complocsize[0]) || + (vspvnumptr1 != vspvnumtab[1] + vspgrafdat.complocsize[1])) { + errorPrint ("hdgraphOrderNd: internal error (1)"); + memFree (vspgrafdat.fronloctab); /* Free useless space */ + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + cblkptr->typeval = DORDERCBLKNEDI; /* Node becomes a nested dissection node */ + + o = 0; + if (vspgrafdat.compglbsize[2] != 0) { /* If separator not empty */ + DorderCblk * cblkptr2; + Hdgraph indgrafdat2; + + cblkptr2 = dorderNew (cblkptr, grafptr->s.proccomm); /* Create separator node */ + cblkptr2->ordeglbval = cblkptr->ordeglbval + grafptr->s.vertglbnbr - vspgrafdat.compglbsize[2]; + cblkptr2->vnodglbnbr = vspgrafdat.compglbsize[2]; + cblkptr2->cblkfthnum = 2; + + cblkptr->data.nedi.cblkglbnbr = 3; /* It is a three-cell node */ + + dgraphInit (&indgrafdat2.s, grafptr->s.proccomm); /* Re-use original graph communicator */ + if (dgraphInduceList (&grafptr->s, vspgrafdat.complocsize[2], /* Perform non-halo induction for separator, as it will get highest numbers */ + vspgrafdat.fronloctab, &indgrafdat2.s) != 0) { + errorPrint ("hdgraphOrderNd: cannot build induced subgraph (1)"); + memFree (vspgrafdat.fronloctab); /* Free remaining space */ + return (1); + } + indgrafdat2.vhallocnbr = 0; /* No halo on graph */ + indgrafdat2.vhndloctax = indgrafdat2.s.vendloctax; + indgrafdat2.ehallocnbr = 0; + indgrafdat2.levlnum = 0; /* Separator graph is at level zero not to be suppressed as an intermediate graph */ + + o = hdgraphOrderSt (&indgrafdat2, cblkptr2, paraptr->ordstratsep); + hdgraphExit (&indgrafdat2); + dorderDispose (cblkptr2); /* Dispose of separator column block (may be kept as leaf) */ + if (o != 0) { + memFree (vspgrafdat.fronloctab); /* Free remaining space */ + return (1); + } + } + else /* Separator is empty */ + cblkptr->data.nedi.cblkglbnbr = 2; /* It is a two-cell tree node */ + + partmax = (vspgrafdat.compglbsize[0] >= vspgrafdat.compglbsize[1]) ? 0 : 1; /* Get part of largest subgraph */ + procnbr0 = (grafptr->s.procglbnbr + 1) / 2; /* Get number of processes in part 0 (always more than in part 1) */ + + if (grafptr->s.proclocnum < procnbr0) { /* If process will handle part 0 (bigger part if odd number of processes) */ + ordeglbval = cblkptr->ordeglbval; + vnodglbnbr = vspgrafdat.compglbsize[partmax]; + cblkfthnum = 0; + } + else { /* If process will handle part 1 (smaller part if odd number of processes) */ + ordeglbval = cblkptr->ordeglbval + vspgrafdat.compglbsize[partmax]; + vnodglbnbr = vspgrafdat.compglbsize[partmax ^ 1]; + cblkfthnum = 1; + } + + o = hdgraphOrderNdFold (grafptr, vspgrafdat.complocsize[partmax], vspvnumtab[partmax], + vspgrafdat.complocsize[partmax ^ 1], vspvnumtab[partmax ^ 1], &indgrafdat01); + + if (o == 0) { + switch (indgrafdat01.typeval) { + case HDGRAPHORDERNDTYPECENT : + if ((cblkptr01 = dorderNewSequ (cblkptr)) == NULL) { + o = 1; + break; + } + if (grafptr->levlnum > 0) { /* If intermediate level nested dissection graph */ + hdgraphExit (grafptr); /* Free graph before going to next level */ + dorderDispose (cblkptr); /* Dispose of column block node too */ + } + cblkptr01->ordeglbval = ordeglbval; + cblkptr01->vnodglbnbr = vnodglbnbr; + cblkptr01->cblkfthnum = cblkfthnum; + o = hdgraphOrderSq2 (&indgrafdat01.data.cgrfdat, cblkptr01, paraptr->ordstratseq); + hgraphExit (&indgrafdat01.data.cgrfdat); /* Free centralized graph here as it is last level */ + break; /* No need to dispose of final column block as locally created by dorderNewSequ */ +#ifdef SCOTCH_DEBUG_HDGRAPH2 + case HDGRAPHORDERNDTYPEDIST : +#else /* SCOTCH_DEBUG_HDGRAPH2 */ + default : +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + if ((cblkptr01 = dorderNew (cblkptr, indgrafdat01.data.dgrfdat.s.proccomm)) == NULL) { + o = 1; + break; + } + if (grafptr->levlnum > 0) { /* If intermediate level nested dissection graph */ + hdgraphExit (grafptr); /* Free graph before going to next level */ + dorderDispose (cblkptr); /* Dispose of column block node too */ + } + cblkptr01->ordeglbval = ordeglbval; + cblkptr01->vnodglbnbr = vnodglbnbr; + cblkptr01->cblkfthnum = cblkfthnum; + o = hdgraphOrderNd (&indgrafdat01.data.dgrfdat, cblkptr01, paraptr); + break; +#ifdef SCOTCH_DEBUG_HDGRAPH2 + default : + errorPrint ("hdgraphOrderNd: internal error (2)"); + o = 1; +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + } + } + + memFree (vspgrafdat.fronloctab); /* Free remaining space */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph_order_nd.h b/scotch_6.0.3/src/libscotch/hdgraph_order_nd.h new file mode 100644 index 00000000..11b236eb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_order_nd.h @@ -0,0 +1,105 @@ +/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_order_nd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the halo distributed graph nested **/ +/** dissection ordering algorithm. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 apr 2006 **/ +/** to 16 jun 2007 **/ +/** # Version 5.1 : from : 11 nov 2008 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HdgraphOrderNdParam_ { + Strat * sepstrat; /*+ Separation strategy +*/ + Strat * ordstratlea; /*+ Leaf ordering strategy +*/ + Strat * ordstratsep; /*+ Separator ordering strategy +*/ + Strat * ordstratseq; /*+ Sequential ordering strategy +*/ +} HdgraphOrderNdParam; + +/*+ Method types. +*/ + +typedef enum HdgraphOrderNdType_ { + HDGRAPHORDERNDTYPECENT = 0, /*+ Centralized folded graph +*/ + HDGRAPHORDERNDTYPEDIST /*+ Distributed folded graph +*/ +} HdgraphOrderNdType; + +/*+ This structure holds folded graph data, whether centralized or distributed. +*/ + +typedef struct HdgraphOrderNdGraph_ { + HdgraphOrderNdType typeval; /*+ Halo graph type +*/ + union { + Hgraph cgrfdat; /*+ Centralized halo graph +*/ + Hdgraph dgrfdat; /*+ Distributed halo graph +*/ + } data; +} HdgraphOrderNdGraph; + +/*+ This structure holds the data passed to the subgraph building threads. +*/ + +typedef struct HdgraphOrderNdData_ { + Hdgraph * orggrafptr; /*+ Pointer to original graph +*/ + Gnum indlistnbr; /*+ Local number of vertices in subgraph +*/ + const Gnum * indlisttab; /*+ Local list of vertices in subgraph +*/ + HdgraphOrderNdGraph * fldgrafptr; /*+ Pointer to folded graph union area +*/ + int fldpartval; /*+ Part of processor array to which to fold to +*/ + int fldprocnbr; /*+ Number of processes in folded communicator +*/ + int fldprocnum; /*+ Rank of process in folded communicator, or -1 +*/ + MPI_Comm fldproccomm; /*+ Communicator for the folded graph, if any +*/ +} HdgraphOrderNdData; + +/* +** The function prototypes. +*/ + +#ifndef HDGRAPH_ORDER_ND +#define static +#endif + +static void * hdgraphOrderNdFold2 (void * const); +static int hdgraphOrderNdFold (Hdgraph * restrict const, const Gnum, const Gnum * restrict const, const Gnum, const Gnum * restrict const, HdgraphOrderNdGraph * restrict const); + +int hdgraphOrderNd (Hdgraph * const, DorderCblk * const, const HdgraphOrderNdParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hdgraph_order_si.c b/scotch_6.0.3/src/libscotch/hdgraph_order_si.c new file mode 100644 index 00000000..1d8d11a6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_order_si.c @@ -0,0 +1,129 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_order_si.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders halo distributed **/ +/** graph vertices using a simple method. **/ +/** **/ +/** DATES : # Version 5.0 : from : 15 apr 2006 **/ +/** to 25 jul 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH_ORDER_SI + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dorder.h" +#include "hdgraph.h" +#include "hdgraph_order_si.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hdgraphOrderSi ( +const Hdgraph * restrict const grafptr, +DorderCblk * restrict const cblkptr) /*+ Single column-block +*/ +{ + Gnum * restrict periloctab; + Gnum * restrict periloctax; + Gnum vnohlocnbr; + Gnum vertlocnum; +#ifdef SCOTCH_DEBUG_HDGRAPH1 + int cheklocval; + int chekglbval; + + cheklocval = 0; +#endif /* SCOTCH_DEBUG_HDGRAPH1 */ + vnohlocnbr = grafptr->s.vertlocnbr; /* Get number of local non-halo vertices */ + if ((periloctab = (Gnum *) memAlloc (vnohlocnbr * sizeof (Gnum))) == NULL) { /* Allocate local fragment */ + errorPrint ("hdgraphOrderSi: out of memory"); +#ifndef SCOTCH_DEBUG_HDGRAPH1 + return (1); + } +#else /* SCOTCH_DEBUG_HDGRAPH1 */ + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { /* Communication cannot be merged with a useful one */ + errorPrint ("hdgraphOrderSi: communication error (1)"); + return (1); + } + if (chekglbval != 0) { + if (periloctab != NULL) + memFree (periloctab); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH1 */ + + cblkptr->typeval = DORDERCBLKLEAF; /* Fill node as leaf */ + cblkptr->data.leaf.ordelocval = cblkptr->ordeglbval + grafptr->s.procdsptab[grafptr->s.proclocnum] - grafptr->s.baseval;; + cblkptr->data.leaf.vnodlocnbr = vnohlocnbr; + cblkptr->data.leaf.periloctab = periloctab; + cblkptr->data.leaf.nodelocnbr = 0; + cblkptr->data.leaf.nodeloctab = NULL; +#ifdef SCOTCH_DEBUG_HDGRAPH2 + cblkptr->data.leaf.cblklocnum = -1; +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + periloctax = periloctab - grafptr->s.baseval; + if (grafptr->s.vnumloctax == NULL) { /* If graph is original graph */ + Gnum vertglbadj; + + vertglbadj = grafptr->s.procdsptab[grafptr->s.proclocnum] - grafptr->s.baseval; /* Set adjustement for global ordering */ + for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) + periloctax[vertlocnum] = vertlocnum + vertglbadj; + } + else { /* Graph is not original graph */ + for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) + periloctax[vertlocnum] = grafptr->s.vnumloctax[vertlocnum]; + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph_order_si.h b/scotch_6.0.3/src/libscotch/hdgraph_order_si.h new file mode 100644 index 00000000..c0972fe7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_order_si.h @@ -0,0 +1,57 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_order_si.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the simple halo graph **/ +/** ordering routine. **/ +/** **/ +/** DATES : # Version 5.0 : from : 15 apr 2006 **/ +/** to 15 apr 2006 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef HDGRAPH_ORDER_SI +#define static +#endif + +int hdgraphOrderSi (const Hdgraph * const, DorderCblk * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hdgraph_order_sq.c b/scotch_6.0.3/src/libscotch/hdgraph_order_sq.c new file mode 100644 index 00000000..eb6351e8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_order_sq.c @@ -0,0 +1,223 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_order_sq.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders distributed graphs **/ +/** by centralizing them on a single **/ +/** process and running a sequential **/ +/** ordering strategy. **/ +/** **/ +/** DATES : # Version 5.1 : from : 11 nov 2008 **/ +/** to 11 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH_ORDER_SQ + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_st.h" +#include "dgraph.h" +#include "dorder.h" +#include "hdgraph.h" +#include "hdgraph_order_sq.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hdgraphOrderSq ( +Hdgraph * restrict const grafptr, +DorderCblk * restrict const cblkptr, +const HdgraphOrderSqParam * restrict const paraptr) +{ + Hgraph cgrfdat; /* Centralized halo graph data */ + Hgraph * cgrfptr; /* Pointer to centralized halo graph */ + int o; + + cgrfptr = (grafptr->s.proclocnum == 0) ? &cgrfdat : NULL; /* Set root process */ + if (hdgraphGather (grafptr, cgrfptr) != 0) { /* Gather centralized subgraph */ + errorPrint ("hdgraphOrderSq: cannot create centralized graph"); + return (1); + } + + o = 0; + if (cgrfptr != NULL) { + o = hdgraphOrderSq2 (&cgrfdat, cblkptr, paraptr->ordstratseq); + hgraphFree (&cgrfdat); + } + + return (o); +} + +int +hdgraphOrderSq2 ( +Hgraph * restrict const grafptr, +DorderCblk * restrict const cblkptr, +const Strat * restrict const stratptr) +{ + Order corddat; /* Centralized ordering structure */ + Gnum * restrict vnumtax; + Gnum * restrict peritab; + int o; + + if (orderInit (&corddat, grafptr->s.baseval, cblkptr->vnodglbnbr, NULL) != 0) { + errorPrint ("hdgraphOrderSq2: cannot initialize centralized ordering"); + return (1); + } + + vnumtax = grafptr->s.vnumtax; /* Save number array of subgraph to order */ + grafptr->s.vnumtax = NULL; /* Assume graph does not have one (fake original graph) */ + + if (hgraphOrderSt (grafptr, &corddat, 0, &corddat.cblktre, stratptr) != 0) { /* Compute sequential ordering */ + orderExit (&corddat); + return (1); + } +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (orderCheck (&corddat) != 0) { + errorPrint ("hdgraphOrderSq2: invalid centralized ordering"); + orderExit (&corddat); + return (1); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + peritab = corddat.peritab; /* Get permutation array */ + + if (vnumtax != NULL) { + Gnum perinum; + + grafptr->s.vnumtax = vnumtax; /* Restore vertex number array */ + for (perinum = 0; perinum < grafptr->vnohnbr; perinum ++) /* Adjust inverse permutation */ + peritab[perinum] = vnumtax[peritab[perinum]]; + } + + cblkptr->typeval = DORDERCBLKLEAF; /* Fill node as leaf */ + cblkptr->data.leaf.ordelocval = cblkptr->ordeglbval; + cblkptr->data.leaf.vnodlocnbr = cblkptr->vnodglbnbr; + cblkptr->data.leaf.periloctab = peritab; + cblkptr->data.leaf.nodelocnbr = corddat.treenbr - 1; /* Get number of tree nodes, save for root */ + o = 0; + if (corddat.treenbr > 1) { + cblkptr->data.leaf.cblklocnum = dorderNewSequIndex (cblkptr, corddat.treenbr - 1); /* Reserve local indices for local nodes */ + if ((cblkptr->data.leaf.nodeloctab = hdgraphOrderSqTree (&corddat)) == NULL) { + errorPrint ("hdgraphOrderSq2: cannot import centralized separation tree"); + o = 1; + } + if (corddat.cblktre.typeval == ORDERCBLKNEDI) /* If root of centralized tree is a nested dissection node */ + cblkptr->typeval |= DORDERCBLKNEDI; /* Distributed leaf is also a nested dissection node */ + } + else + cblkptr->data.leaf.nodeloctab = NULL; + + corddat.flagval = ORDERNONE; /* Do not free permutation array */ + orderExit (&corddat); /* Free permutation tree */ + + return (o); +} + +/* This routine builds the distributed part of +** a distributed halo graph. This is a distinct +** routine to allow for multi-threading. +*/ + +static +DorderNode * +hdgraphOrderSqTree ( +const Order * const cordptr) +{ + DorderNode * nodetab; + Gnum nodenum; + Gnum cblknum; + + if ((nodetab = memAlloc ((cordptr->treenbr - 1) * sizeof (DorderNode))) == NULL) { /* "- 1" as root of tree will not be copied */ + errorPrint ("hdgraphOrderSqTree: out of memory"); + return (NULL); + } + + nodenum = 0; /* Start labeling nodes from 0 */ + for (cblknum = 0; cblknum < cordptr->cblktre.cblknbr; cblknum ++) + hdgraphOrderSqTree2 (nodetab, &nodenum, &cordptr->cblktre.cblktab[cblknum], -1, cblknum); /* Root of tree is labeled "-1" */ + +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if (nodenum != (cordptr->treenbr - 1)) { + errorPrint ("hdgraphOrderSqTree: internal error"); + return (NULL); + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + + return (nodetab); +} + +static +void +hdgraphOrderSqTree2 ( +DorderNode * const nodetab, +Gnum * const nodeptr, +const OrderCblk * const cblkptr, +const Gnum fathnum, +const Gnum fcbknum) +{ + Gnum nodenum; + DorderNode * nodetmp; + Gnum cblknum; + + nodenum = (*nodeptr) ++; + nodetmp = &nodetab[nodenum]; + nodetmp->fathnum = fathnum; + nodetmp->typeval = (Gnum) cblkptr->typeval; + nodetmp->vnodnbr = cblkptr->vnodnbr; + nodetmp->cblknum = fcbknum; + + for (cblknum = 0; cblknum < cblkptr->cblknbr; cblknum ++) + hdgraphOrderSqTree2 (nodetab, nodeptr, &cblkptr->cblktab[cblknum], nodenum, cblknum); +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph_order_sq.h b/scotch_6.0.3/src/libscotch/hdgraph_order_sq.h new file mode 100644 index 00000000..a909e2eb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_order_sq.h @@ -0,0 +1,71 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_order_sq.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the halo distributed graph centra- **/ +/** lized ordering algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 11 nov 2008 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HdgraphOrderSqParam_ { + Strat * ordstratseq; /*+ Sequential ordering strategy +*/ +} HdgraphOrderSqParam; + +/* +** The function prototypes. +*/ + +#ifndef HDGRAPH_ORDER_SQ +#define static +#endif + +int hdgraphOrderSq (Hdgraph * const, DorderCblk * const, const HdgraphOrderSqParam * const); + +int hdgraphOrderSq2 (Hgraph * restrict const, DorderCblk * restrict const, const Strat * restrict const); +static DorderNode * hdgraphOrderSqTree (const Order * const); +static void hdgraphOrderSqTree2 (DorderNode * const, Gnum * const, const OrderCblk * const, const Gnum, const Gnum); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hdgraph_order_st.c b/scotch_6.0.3/src/libscotch/hdgraph_order_st.c new file mode 100644 index 00000000..b03c09ee --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_order_st.c @@ -0,0 +1,224 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_order_st.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the generic call to the **/ +/** distributed graph ordering module, **/ +/** using a given strategy. **/ +/** **/ +/** DATES : # Version 5.0 : from : 15 apr 2006 **/ +/** to 21 aug 2006 **/ +/** # Version 5.1 : from : 11 nov 2008 **/ +/** to 11 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HDGRAPH_ORDER_ST + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_st.h" +#include "dgraph.h" +#include "dorder.h" +#include "hdgraph.h" +#include "hdgraph_order_nd.h" +#include "hdgraph_order_si.h" +#include "hdgraph_order_sq.h" +#include "hdgraph_order_st.h" +#include "vdgraph.h" +#include "vdgraph_separate_st.h" + +/* +** The static and global variables. +*/ + +static Hdgraph hdgraphorderstgraphdummy; /* Dummy graph for offset computations */ + +static union { /* Default parameters for nested dissection method */ + HdgraphOrderNdParam param; + StratNodeMethodData padding; +} hdgraphorderstdefaultnd = { { &stratdummy, &stratdummy, &stratdummy } }; + +static union { /* Default parameters for sequential method */ + HdgraphOrderSqParam param; + StratNodeMethodData padding; +} hdgraphorderstdefaultsq = { { &stratdummy } }; + +static StratMethodTab hdgraphorderstmethtab[] = { /* Graph ordering methods array */ + { HDGRAPHORDERSTMETHND, "n", hdgraphOrderNd, &hdgraphorderstdefaultnd }, + { HDGRAPHORDERSTMETHSI, "s", hdgraphOrderSi, NULL }, + { HDGRAPHORDERSTMETHSQ, "q", hdgraphOrderSq, &hdgraphorderstdefaultsq }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab hdgraphorderstparatab[] = { /* The method parameter list */ + { HDGRAPHORDERSTMETHND, STRATPARAMSTRAT, "sep", + (byte *) &hdgraphorderstdefaultnd.param, + (byte *) &hdgraphorderstdefaultnd.param.sepstrat, + (void *) &vdgraphseparateststratab }, + { HDGRAPHORDERSTMETHND, STRATPARAMSTRAT, "ole", + (byte *) &hdgraphorderstdefaultnd.param, + (byte *) &hdgraphorderstdefaultnd.param.ordstratlea, + (void *) &hdgraphorderststratab }, + { HDGRAPHORDERSTMETHND, STRATPARAMSTRAT, "ose", + (byte *) &hdgraphorderstdefaultnd.param, + (byte *) &hdgraphorderstdefaultnd.param.ordstratsep, + (void *) &hdgraphorderststratab }, + { HDGRAPHORDERSTMETHND, STRATPARAMSTRAT, "osq", + (byte *) &hdgraphorderstdefaultnd.param, + (byte *) &hdgraphorderstdefaultnd.param.ordstratseq, + (void *) &hgraphorderststratab }, + { HDGRAPHORDERSTMETHSQ, STRATPARAMSTRAT, "strat", + (byte *) &hdgraphorderstdefaultsq.param, + (byte *) &hdgraphorderstdefaultsq.param.ordstratseq, + (void *) &hgraphorderststratab }, + { HDGRAPHORDERSTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab hdgraphorderstcondtab[] = { /* Graph condition parameter table */ + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &hdgraphorderstgraphdummy, + (byte *) &hdgraphorderstgraphdummy.s.edgeglbnbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &hdgraphorderstgraphdummy, + (byte *) &hdgraphorderstgraphdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &hdgraphorderstgraphdummy, + (byte *) &hdgraphorderstgraphdummy.s.veloglbsum, + NULL }, + { STRATNODECOND, STRATPARAMDOUBLE, "mdeg", + (byte *) &hdgraphorderstgraphdummy, + (byte *) &hdgraphorderstgraphdummy.s.degrglbmax, + NULL }, + { STRATNODECOND, STRATPARAMINT, "proc", + (byte *) &hdgraphorderstgraphdummy, + (byte *) &hdgraphorderstgraphdummy.s.procglbnbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "rank", + (byte *) &hdgraphorderstgraphdummy, + (byte *) &hdgraphorderstgraphdummy.s.proclocnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vert", + (byte *) &hdgraphorderstgraphdummy, + (byte *) &hdgraphorderstgraphdummy.s.vertglbnbr, + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab hdgraphorderststratab = { /* Strategy tables for graph ordering methods */ + hdgraphorderstmethtab, + hdgraphorderstparatab, + hdgraphorderstcondtab }; + +/************************************/ +/* */ +/* This routine is the entry point */ +/* for the graph ordering routines. */ +/* */ +/************************************/ + +/* This routine computes an ordering +** with respect to a given strategy. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +hdgraphOrderSt ( +const Hdgraph * restrict const grafptr, /*+ Subgraph to order +*/ +DorderCblk * restrict const cblkptr, /*+ Current column block +*/ +const Strat * restrict const strat) /*+ Graph ordering strategy +*/ +{ + StratTest val; + int o; + + if (grafptr->s.vertglbnbr == 0) /* Return immediately if nothing to do */ + return (0); + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + errorPrint ("hdgraphOrderSt: concatenation operator not available for graph ordering strategies"); + return (1); + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_HDGRAPH2 + if ((val.typetest != STRATTESTVAL) && + (val.typenode != STRATPARAMLOG)) { + errorPrint ("hdgraphOrderSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = hdgraphOrderSt (grafptr, cblkptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = hdgraphOrderSt (grafptr, cblkptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + hdgraphOrderSi (grafptr, cblkptr); /* Always maintain a consistent ordering */ + break; + case STRATNODESELECT : + errorPrint ("hdgraphOrderSt: selection operator not available for graph ordering strategies"); + return (1); +#ifdef SCOTCH_DEBUG_HDGRAPH2 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_HDGRAPH2 */ + default : +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, cblkptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_HDGRAPH2 + default : + errorPrint ("hdgraphOrderSt: invalid parameter"); + return (1); +#endif /* SCOTCH_DEBUG_HDGRAPH2 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hdgraph_order_st.h b/scotch_6.0.3/src/libscotch/hdgraph_order_st.h new file mode 100644 index 00000000..06eb6073 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hdgraph_order_st.h @@ -0,0 +1,78 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hdgraph_order_st.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data **/ +/** declarations for the main distributed **/ +/** graph ordering routine. **/ +/** **/ +/** DATES : # Version 5.0 : from : 14 apr 2006 **/ +/** to : 14 apr 2006 **/ +/** # Version 5.1 : from : 11 nov 2008 **/ +/** to : 11 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum HdgraphOrderStMethodType_ { + HDGRAPHORDERSTMETHND = 0, /*+ Nested Dissection +*/ + HDGRAPHORDERSTMETHSI, /*+ Simple +*/ + HDGRAPHORDERSTMETHSQ, /*+ Sequential method +*/ + HDGRAPHORDERSTMETHNBR /*+ Number of methods +*/ +} HdgraphOrderStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab hdgraphorderststratab; + +/* +** The function prototypes. +*/ + +#ifndef HDGRAPH_ORDER_ST +#define static +#endif + +int hdgraphOrderSt (const Hdgraph * restrict const, DorderCblk * restrict const, const Strat * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph.c b/scotch_6.0.3/src/libscotch/hgraph.c new file mode 100644 index 00000000..97946030 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph.c @@ -0,0 +1,141 @@ +/* Copyright 2004,2007,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the source graph **/ +/** functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 17 jan 2002 **/ +/** to 01 dec 2003 **/ +/** # Version 5.0 : from : 19 dec 2006 **/ +/** to 30 may 2008 **/ +/** # Version 6.0 : from : 17 oct 2012 **/ +/** to 04 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "hgraph.h" + +/****************************************/ +/* */ +/* These routines handle source graphs. */ +/* */ +/****************************************/ + +/* This routine initializes a source graph +** structure. +** It returns: +** - 0 : in all cases. +*/ + +int +hgraphInit ( +Hgraph * restrict const grafptr) +{ + memSet (grafptr, 0, sizeof (Hgraph)); /* Initialize graph fields */ + grafptr->s.flagval = GRAPHFREETABS; /* By default, free all arrays */ + + return (0); +} + +/* This routine frees a source graph structure. +** It returns: +** - VOID : in all cases. +*/ + +void +hgraphExit ( +Hgraph * restrict const grafptr) +{ + hgraphFree (grafptr); +} + +/* This routine frees a source graph structure. +** It returns: +** - VOID : in all cases. +*/ + +void +hgraphFree ( +Hgraph * restrict const grafptr) +{ + if ((grafptr->vnhdtax != NULL) && /* Free end vertex array for non-halo vertices */ + ((grafptr->s.flagval & HGRAPHFREEVNHD) != 0)) + memFree (grafptr->vnhdtax + grafptr->s.baseval); + + graphFree (&grafptr->s); /* Free graph data */ + +#ifdef SCOTCH_DEBUG_HGRAPH2 + memSet (grafptr, ~0, sizeof (Hgraph)); /* Purge graph fields */ +#endif /* SCOTCH_DEBUG_HGRAPH2 */ +} + +/* This routine creates a non-halo graph from a +** halo graph. +** It returns: +** - VOID : in all cases. +*/ + +void +hgraphUnhalo ( +const Hgraph * restrict const grafptr, +Graph * restrict const ugrfptr) +{ + ugrfptr->flagval = grafptr->s.flagval & (GRAPHBITSUSED & ~GRAPHFREETABS); /* Remove extended graph class flags and do not allow freeing */ + ugrfptr->baseval = grafptr->s.baseval; + ugrfptr->vertnbr = grafptr->vnohnbr; + ugrfptr->vertnnd = grafptr->vnohnnd; + ugrfptr->verttax = grafptr->s.verttax; + ugrfptr->vendtax = grafptr->vnhdtax; + ugrfptr->velotax = grafptr->s.velotax; + ugrfptr->velosum = grafptr->vnlosum; + ugrfptr->vnumtax = grafptr->s.vnumtax; + ugrfptr->vlbltax = NULL; + ugrfptr->edgenbr = grafptr->enohnbr; + ugrfptr->edgetax = grafptr->s.edgetax; + ugrfptr->edlotax = grafptr->s.edlotax; + ugrfptr->edlosum = grafptr->enohsum; + ugrfptr->degrmax = grafptr->s.degrmax; /* Upper bound */ +} diff --git a/scotch_6.0.3/src/libscotch/hgraph.h b/scotch_6.0.3/src/libscotch/hgraph.h new file mode 100644 index 00000000..1486bcd8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph.h @@ -0,0 +1,96 @@ +/* Copyright 2004,2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source halo graph structure. **/ +/** **/ +/** DATES : # Version 4.0 : from : 02 jan 2002 **/ +/** to 30 apr 2004 **/ +/** # Version 5.0 : from : 19 dec 2006 **/ +/** to 19 dec 2006 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** # Version 6.0 : from : 17 oct 2012 **/ +/** to 17 oct 2012 **/ +/** **/ +/************************************************************/ + +#define HGRAPH_H + +/* +** The defines. +*/ + +/*+ Graph option flags. +*/ + +#define HGRAPHFREEVNHD 0x0400 /* Free vnhdtab array */ +#define HGRAPHFREETABS (GRAPHFREETABS | HGRAPHFREEVNHD) + +/* +** The type and structure definitions. +*/ + +/*+ Halo graph structure. +*/ + +typedef struct Hgraph_ { + Graph s; /*+ Source graph +*/ + Gnum vnohnbr; /*+ Number of non-halo vertices +*/ + Gnum vnohnnd; /*+ Based number of first halo vertex in graph (s.vertnnd if none) +*/ + Gnum * vnhdtax; /*+ End vertex array for non-halo vertices [vnohnbr, based] +*/ + Gnum vnlosum; /*+ Sum of vertex loads for non-halo vertices only (<= s.velosum) +*/ + Gnum enohnbr; /*+ Number of non-halo edges +*/ + Gnum enohsum; /*+ Sum of non-halo edge loads +*/ + Gnum levlnum; /*+ Nested dissection level +*/ +} Hgraph; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH +#define static +#endif + +int hgraphInit (Hgraph * const); +void hgraphExit (Hgraph * const); +void hgraphFree (Hgraph * const); +Gnum hgraphBase (Hgraph * const, const Gnum); +int hgraphCheck (const Hgraph *); +int hgraphInduceList (const Hgraph * const, const VertList * const, const Gnum, Hgraph * const); +void hgraphUnhalo (const Hgraph * const, Graph * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_check.c b/scotch_6.0.3/src/libscotch/hgraph_check.c new file mode 100644 index 00000000..7b693431 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_check.c @@ -0,0 +1,126 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the source graph **/ +/** functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 17 jan 2002 **/ +/** to 01 dec 2003 **/ +/** # Version 5.0 : from : 19 dec 2006 **/ +/** to 19 dec 2006 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "hgraph.h" + +/****************************************/ +/* */ +/* These routines handle source graphs. */ +/* */ +/****************************************/ + +/* This routine checks the consistency +** of the given halo graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +hgraphCheck ( +const Hgraph * restrict const grafptr) +{ + Gnum vertnum; /* Number of current vertex */ + Gnum edgenum; /* Number of current edge */ + Gnum enohsum; + + if (graphCheck (&grafptr->s) != 0) { + errorPrint ("hgraphCheck: invalid graph structure in halo graph"); + return (1); + } + + if ((grafptr->vnohnbr < 0) || + (grafptr->vnohnbr > grafptr->s.vertnbr) || + (grafptr->vnohnnd != (grafptr->vnohnbr + grafptr->s.baseval)) || + (grafptr->vnlosum > grafptr->s.velosum) || + (grafptr->enohnbr > grafptr->s.edgenbr) || + (grafptr->enohsum < grafptr->enohnbr)) { + errorPrint ("hgraphCheck: invalid halo graph parameters"); + return (1); + } + + enohsum = (grafptr->s.edlotax == NULL) ? grafptr->enohnbr : 0; + for (vertnum = grafptr->s.baseval; vertnum < grafptr->vnohnnd; vertnum ++) { /* For all non-halo vertices */ + if ((grafptr->vnhdtax[vertnum] < grafptr->s.verttax[vertnum]) || + (grafptr->vnhdtax[vertnum] > grafptr->s.vendtax[vertnum])) { + errorPrint ("hgraphCheck: invalid non-halo end vertex array"); + return (1); + } + + if (grafptr->s.edlotax != NULL) { + Gnum edgenum; + + for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->vnhdtax[vertnum]; edgenum ++) + enohsum += grafptr->s.edlotax[edgenum]; + } + } + + if (grafptr->enohsum != enohsum) { + errorPrint ("hgraphCheck: invalid non-halo edge load sum"); + return (1); + } + + for ( ; vertnum < grafptr->s.vertnnd; vertnum ++) { /* For all halo vertices */ + for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { + if (grafptr->s.edgetax[edgenum] >= grafptr->vnohnnd) { /* If two halo vertices connected together */ + errorPrint ("hgraphCheck: halo vertices should not be connected together"); + return (1); + } + } + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_induce.c b/scotch_6.0.3/src/libscotch/hgraph_induce.c new file mode 100644 index 00000000..cb0960c6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_induce.c @@ -0,0 +1,303 @@ +/* Copyright 2004,2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_induce.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the halo source **/ +/** graph subgraph-making functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 02 jan 2002 **/ +/** to 25 feb 2004 **/ +/** # Version 5.0 : from : 19 dec 2006 **/ +/** to 11 jun 2008 **/ +/** # Version 5.1 : from : 24 oct 2010 **/ +/** to 24 oct 2010 **/ +/** # Version 6.0 : from : 27 mar 2012 **/ +/** to 27 mar 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH +#define HGRAPH_INDUCE + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "hgraph.h" +#include "hgraph_induce.h" + +/*********************************************/ +/* */ +/* These routines handle halo source graphs. */ +/* */ +/*********************************************/ + +/* This routine builds the graph induced +** by the original graph and the list of +** selected vertices. +** The induced vnumtab array is the list +** array if the original graph does not have +** a vnumtab, or the proper subset of the +** original vnumtab else. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +hgraphInduceList ( +const Hgraph * restrict const orggrafptr, /* Pointer to original graph */ +const VertList * restrict const orglistptr, /* Pointer to vertex list */ +const Gnum orghalonbr, /* Upper bound of number of vertices in halo */ +Hgraph * restrict const indgrafptr) /* Pointer to induced subgraph */ +{ + Gnum * restrict orgindxtax; /* Original to induced vertex number translation */ + Gnum * restrict indedgetab; /* Origin of induced graph edge arrays */ + Gnum indvertnbr; /* Number of vertices in induced graph */ + Gnum indvertnum; /* Number of current vertex in induced graph */ + Gnum indvelosiz; + Gnum indedgenbr; /* (Approximate) number of edges in induced graph */ + Gnum indedgesiz; /* (Approximate) size of edge and edge load arrays */ + + memSet (indgrafptr, 0, sizeof (Hgraph)); /* Pre-initialize graph fields */ + + indgrafptr->s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; + indgrafptr->s.baseval = orggrafptr->s.baseval; + + indvertnbr = orglistptr->vnumnbr + orghalonbr; /* Compute upper bound on number of vertices */ + indvelosiz = (orggrafptr->s.velotax != NULL) ? indvertnbr : 0; + if (memAllocGroup ((void **) (void *) + &indgrafptr->s.verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), + &indgrafptr->vnhdtax, (size_t) ( orglistptr->vnumnbr * sizeof (Gnum)), /* Put closest to beginning of array because no padding after */ + &indgrafptr->s.velotax, (size_t) ( indvertnbr * sizeof (Gnum)), + &indgrafptr->s.vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hgraphInduceList: out of memory (1)"); /* Allocate induced graph structure */ + return (1); + } + memCpy (indgrafptr->s.vnumtax, orglistptr->vnumtab, orglistptr->vnumnbr * sizeof (Gnum)); /* Copy vertex number array from list */ + indgrafptr->s.velotax = (orggrafptr->s.velotax != NULL) ? (indgrafptr->s.velotax - indgrafptr->s.baseval) : NULL; + indgrafptr->s.verttax -= indgrafptr->s.baseval; + indgrafptr->s.vnumtax -= indgrafptr->s.baseval; + indgrafptr->vnhdtax -= indgrafptr->s.baseval; + indgrafptr->vnohnbr = orglistptr->vnumnbr; + indgrafptr->vnohnnd = orglistptr->vnumnbr + indgrafptr->s.baseval; + + indedgenbr = ((orggrafptr->s.degrmax > 0) && (indvertnbr < (orggrafptr->s.edgenbr / orggrafptr->s.degrmax))) /* Choose best upper bound on number of edges (avoid multiply overflow) */ + ? (indvertnbr * orggrafptr->s.degrmax) : orggrafptr->s.edgenbr; + indedgesiz = (orggrafptr->s.edlotax != NULL) ? indedgenbr * 2 : indedgenbr; /* Account for edge load array size if graph has edge weights */ + + if (memAllocGroup ((void **) (void *) /* If cannot allocate edge arrays with approximation */ + &indedgetab, (size_t) (indedgesiz * sizeof (Gnum)), + &orgindxtax, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { + indedgenbr = hgraphInduce3 (orggrafptr, orglistptr); /* Count real number of edges */ + + indedgesiz = (orggrafptr->s.edlotax != NULL) ? indedgenbr * 2 : indedgenbr; /* Account for edge load array size if graph has edge weights */ + + if ((indedgenbr < 0) || /* If cannot compute real number of edges */ + (memAllocGroup ((void **) (void *) /* Or cannot allocate edge arrays with real values */ + &indedgetab, (size_t) (indedgesiz * sizeof (Gnum)), + &orgindxtax, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL)) { + errorPrint ("hgraphInduceList: out of memory (2)"); + hgraphExit (indgrafptr); + return (1); + } + } + memSet (orgindxtax, ~0, orggrafptr->s.vertnbr * sizeof (Gnum)); /* Preset index array */ + orgindxtax -= orggrafptr->s.baseval; /* Base access to orgindxtab */ + + for (indvertnum = indgrafptr->s.baseval; indvertnum < indgrafptr->vnohnnd; indvertnum ++) /* For all non-halo vertices */ + orgindxtax[indgrafptr->s.vnumtax[indvertnum]] = indvertnum; /* Mark selected vertices */ + + return (hgraphInduce2 (orggrafptr, orgindxtax, indgrafptr, indedgenbr, indedgetab)); +} + +/* This routine finalizes the building of the +** halo graph induced by the original halo graph. +** Vertices belonging to the old halo remain to +** be numbered. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +int +hgraphInduce2 ( +const Hgraph * restrict const orggrafptr, /* Pointer to original graph */ +Gnum * restrict const orgindxtax, /* Array of numbers of selected vertices */ +Hgraph * restrict const indgrafptr, /* Pointer to induced graph */ +const Gnum indedgenbr, /* (Approximate) number of edges in induced graph */ +Gnum * restrict const indedgetab) /* Pointer to pre-allocated space for edge arrays */ +{ + void * restrict indedgetnd; /* End of compacted edge array */ + Gnum indvertnum; /* Current vertex number in induced halo graph */ + + indedgetnd = memOffset (indedgetab, &indgrafptr->s.edgetax, (size_t) (indedgenbr * sizeof (Gnum)), NULL); + indgrafptr->s.edgetax = indedgetab - indgrafptr->s.baseval; +#ifdef SCOTCH_DEBUG_HGRAPH2 + if (indedgetnd > (void *) (orgindxtax + orggrafptr->s.baseval)) { + errorPrint ("hgraphInduce2: invalid edge array size (1)"); + hgraphExit (indgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + if (orggrafptr->s.edlotax != NULL) { + size_t indedlooftval; /* Offset of edge load array with respect to edge array */ + + indedgetnd = memOffset (indedgetnd, &indgrafptr->s.edlotax, (size_t) (indedgenbr * sizeof (Gnum)), NULL); + indgrafptr->s.edlotax -= indgrafptr->s.baseval; +#ifdef SCOTCH_DEBUG_HGRAPH2 + if (indedgetnd > (void *) (orgindxtax + orggrafptr->s.baseval)) { + errorPrint ("hgraphInduce2: invalid edge array size (2)"); + hgraphExit (indgrafptr); /* Indedgetab is now freed as part of indgrafptr */ + return (1); + } +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + hgraphInduce2L (orggrafptr, orgindxtax, indgrafptr); + + indedlooftval = indgrafptr->s.edlotax - indgrafptr->s.edgetax; + memReallocGroup ((void *) indedgetab, /* Implicitely free orgindxtab */ + &indgrafptr->s.edgetax, (size_t) (indedgenbr * sizeof (Gnum)), /* Keep first offset as estimated number of edges */ + &indgrafptr->s.edlotax, (size_t) (indgrafptr->s.edgenbr * sizeof (Gnum)), /* Use real number of edges for second array */ + NULL); + indgrafptr->s.edgetax -= indgrafptr->s.baseval; + indgrafptr->s.edlotax = indgrafptr->s.edgetax + indedlooftval; /* Use old index into old array as new index */ + } + else { + hgraphInduce2U (orggrafptr, orgindxtax, indgrafptr); + + indgrafptr->s.edgetax = memRealloc ((void *) indedgetab, indgrafptr->s.edgenbr * sizeof (Gnum)); /* Use real number of edges, implicitely free orgindxtab */ + indgrafptr->s.edgetax -= indgrafptr->s.baseval; + } + indgrafptr->s.vendtax = indgrafptr->s.verttax + 1; /* Use compact representation of arrays */ + indgrafptr->levlnum = orggrafptr->levlnum + 1; /* Induced subgraph is one level below */ + + if (orggrafptr->s.vnumtax != NULL) { /* Adjust vnumtax */ + for (indvertnum = indgrafptr->s.baseval; indvertnum < indgrafptr->s.vertnnd; indvertnum ++) + indgrafptr->s.vnumtax[indvertnum] = orggrafptr->s.vnumtax[indgrafptr->s.vnumtax[indvertnum]]; + } + +#ifdef SCOTCH_DEBUG_HGRAPH2 + if (hgraphCheck (indgrafptr) != 0) { /* Check graph consistency */ + errorPrint ("hgraphInduce2: inconsistent graph data"); + hgraphExit (indgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + + return (0); +} + +#define HGRAPHINDUCE2U +#define HGRAPHINDUCE2NAME hgraphInduce2U +#define HGRAPHINDUCE2EDLOINIT(e) +#define HGRAPHINDUCE2EDLOSUM indgrafptr->s.edgenbr +#define HGRAPHINDUCE2ENOHINIT +#define HGRAPHINDUCE2ENOHSUM indgrafptr->enohnbr +#include "hgraph_induce_edge.c" +#undef HGRAPHINDUCE2NAME +#undef HGRAPHINDUCE2EDLOINIT +#undef HGRAPHINDUCE2EDLOSUM +#undef HGRAPHINDUCE2ENOHINIT +#undef HGRAPHINDUCE2ENOHSUM +#undef HGRAPHINDUCE2U + +#define HGRAPHINDUCE2L +#define HGRAPHINDUCE2NAME hgraphInduce2L +#define HGRAPHINDUCE2EDLOINIT(e) indedlosum += indgrafptr->s.edlotax[e] = orggrafptr->s.edlotax[orgedgenum] +#define HGRAPHINDUCE2EDLOSUM indedlosum +#define HGRAPHINDUCE2ENOHINIT indenohsum += orggrafptr->s.edlotax[orgedgenum] +#define HGRAPHINDUCE2ENOHSUM indenohsum +#include "hgraph_induce_edge.c" +#undef HGRAPHINDUCE2NAME +#undef HGRAPHINDUCE2EDLOINIT +#undef HGRAPHINDUCE2EDLOSUM +#undef HGRAPHINDUCE2ENOHINIT +#undef HGRAPHINDUCE2ENOHSUM +#undef HGRAPHINDUCE2L + +/* This routine computes the exact number of edges +** required to build the induced halo subgraph. It +** is used when larger approximations lead to an +** out-of-memory error message. As a side effect, +** yet unnumbered halo vertices of the induced +** subgraph are numbered and the induced halo graph +** data are updated accordingly. +** It returns: +** - >=0 : number of edges in induced halo graph. +** - -1 : if out of memory (this is helpless). +*/ + +static +Gnum +hgraphInduce3 ( +const Hgraph * restrict const orggrafptr, /* Pointer to original graph */ +const VertList * restrict const orglistptr) /* Pointer to vertex list */ +{ + Gnum indedgenbr; /* Revised number of edges in induced halo graph */ + Gnum indvertnum; /* Current vertex number in induced halo graph */ + Gnum * restrict orgindxtax; /* Array of numbers of selected vertices */ + + if ((orgindxtax = memAlloc (orggrafptr->s.vertnbr * sizeof (Gnum))) == NULL) + return (-1); + memSet (orgindxtax, ~0, orggrafptr->s.vertnbr * sizeof (Gnum)); /* Preset index array */ + orgindxtax -= orggrafptr->s.baseval; /* Base access to orgindxtab */ + + for (indvertnum = 0; indvertnum < orglistptr->vnumnbr; indvertnum ++) /* For all vertices in list */ + orgindxtax[orglistptr->vnumtab[indvertnum]] = indvertnum; /* Mark selected vertices */ + + for (indvertnum = 0, indedgenbr = 0; /* For all vertices in list */ + indvertnum < orglistptr->vnumnbr; indvertnum ++) { + Gnum orgvertnum; /* Current vertex number in original halo graph */ + Gnum orgedgenum; /* Current edge number in original halo graph */ + + orgvertnum = orglistptr->vnumtab[indvertnum]; /* Get number of original vertex */ + indedgenbr += orggrafptr->s.vendtax[orgvertnum] - orggrafptr->s.verttax[orgvertnum]; /* Add degree of original vertex */ + + for (orgedgenum = orggrafptr->s.verttax[orgvertnum]; /* For all neighbors of original halo vertex */ + orgedgenum < orggrafptr->s.vendtax[orgvertnum]; orgedgenum ++) { + if (orgindxtax[orggrafptr->s.edgetax[orgedgenum]] == ~0) /* If neighbor is halo vertex */ + indedgenbr ++; /* Account for the arc once more */ + } + } + + memFree (orgindxtax + orggrafptr->s.baseval); + + return (indedgenbr); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_induce.h b/scotch_6.0.3/src/libscotch/hgraph_induce.h new file mode 100644 index 00000000..cdc5cbd8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_induce.h @@ -0,0 +1,60 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_induce.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the halo graph subgraph making **/ +/** functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 10 jan 2002 **/ +/** to 22 dec 2002 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_INDUCE +#define static +#endif + +static int hgraphInduce2 (const Hgraph * const, Gnum * const, Hgraph * const, const Gnum, Gnum * const); +static void hgraphInduce2L (const Hgraph * const, Gnum * const, Hgraph * const); +static void hgraphInduce2U (const Hgraph * const, Gnum * const, Hgraph * const); +static Gnum hgraphInduce3 (const Hgraph * const, const VertList * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_induce_edge.c b/scotch_6.0.3/src/libscotch/hgraph_induce_edge.c new file mode 100644 index 00000000..1b4a78dd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_induce_edge.c @@ -0,0 +1,198 @@ +/* Copyright 2004,2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_induce_edge.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This commodity file contains the edge **/ +/** arrays building subroutine which is **/ +/** duplicated, with minor modifications, **/ +/** into hgraph_induce.c **/ +/** **/ +/** DATES : # Version 4.0 : from : 10 jan 2002 **/ +/** to 17 jan 2003 **/ +/** # Version 5.0 : from : 19 dec 2006 **/ +/** to 19 dec 2006 **/ +/** # Version 5.1 : from : 24 oct 2010 **/ +/** to 24 oct 2010 **/ +/** # Version 6.0 : from : 22 mar 2012 **/ +/** to 22 mar 2012 **/ +/** **/ +/************************************************************/ + +static +void +HGRAPHINDUCE2NAME ( +const Hgraph * restrict const orggrafptr, /* Pointer to original halo graph */ +Gnum * restrict const orgindxtax, /* Array of numbers of selected vertices */ +Hgraph * restrict const indgrafptr) /* Pointer to induced halo graph */ +{ + Gnum indvertnum; /* Number of current induced vertex */ + Gnum indvertnnd; /* Number of after-last induced (halo) vertex */ + Gnum indvelosum; /* Overall induced vertex load */ + Gnum indedgenum; /* Number of current edge in induced halo subgraph */ + Gnum indenohnbr; /* Number of non-halo edges in halo subgraph */ + Gnum inddegrmax; /* Maximum degree */ +#ifdef SCOTCH_DEBUG_HGRAPH2 + Gnum indedgenbs; /* Revised number of edges in halo subgraph */ +#endif /* SCOTCH_DEBUG_HGRAPH2 */ +#ifdef HGRAPHINDUCE2L /* If edge loads present */ + Gnum indedlosum; + Gnum indenohsum; + + indedlosum = + indenohsum = 0; +#endif /* HGRAPHINDUCE2L */ + inddegrmax = 0; + for (indvertnum = indedgenum = indgrafptr->s.baseval, indvelosum = indenohnbr = 0, indvertnnd = indgrafptr->vnohnnd; /* For all non-halo vertices */ + indvertnum < indgrafptr->vnohnnd; indvertnum ++) { + Gnum orgvertnum; /* Number of current vertex in original halo graph */ + Gnum orgedgenum; /* Number of current edge in original halo graph */ + Gnum indedgennd; /* Index of after-last edge position in edge array */ + Gnum indedhdnum; /* Index of after-last edge linking to non-halo vertices */ + Gnum inddegrval; + + orgvertnum = indgrafptr->s.vnumtax[indvertnum]; + indgrafptr->s.verttax[indvertnum] = indedgenum; + indenohnbr -= indedgenum; /* Subtract base of non-halo edges */ + if (indgrafptr->s.velotax != NULL) { /* If graph has vertex weights */ + indvelosum += /* Accumulate vertex loads */ + indgrafptr->s.velotax[indvertnum] = orggrafptr->s.velotax[orgvertnum]; + } + + inddegrval = orggrafptr->s.vendtax[orgvertnum] - orggrafptr->s.verttax[orgvertnum]; /* Get degree of non-halo node */ + if (inddegrmax < inddegrval) /* Keep maximum degree */ + inddegrmax = inddegrval; + + for (orgedgenum = orggrafptr->s.verttax[orgvertnum], indedhdnum = indedgennd = indedgenum + inddegrval; + orgedgenum < orggrafptr->s.vendtax[orgvertnum]; orgedgenum ++) { + Gnum orgvertend; /* Number of current end vertex in original halo graph */ + Gnum indvertend; /* Number of current end vertex in induced halo subgraph */ + + orgvertend = orggrafptr->s.edgetax[orgedgenum]; + indvertend = orgindxtax[orgvertend]; + if (indvertend == ~0) { /* If neighbor is yet undeclared halo vertex */ + indgrafptr->s.vnumtax[indvertnnd] = orgvertend; /* Add number of halo vertex to array */ + indvertend = orgindxtax[orgvertend] = indvertnnd ++; /* Get induced number of vertex */ + } + if (indvertend >= indgrafptr->vnohnnd) { /* If neighbor is halo vertex */ + indedhdnum --; /* Add neighbor at end of edge sub-array */ + indgrafptr->s.edgetax[indedhdnum] = indvertend; + HGRAPHINDUCE2EDLOINIT (indedhdnum); + } + else { /* If heighbor is non-halo vertex */ + indgrafptr->s.edgetax[indedgenum] = indvertend; /* Add neighbor at beginning of edge sub-array */ + HGRAPHINDUCE2EDLOINIT (indedgenum); + HGRAPHINDUCE2ENOHINIT; + indedgenum ++; + } + } +#ifdef SCOTCH_DEBUG_HGRAPH2 + if (indedgenum != indedhdnum) { + errorPrint (STRINGIFY (HGRAPHINDUCE2NAME) ": internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + indenohnbr += indedhdnum; /* Add position to number of non-halo edges */ + indgrafptr->vnhdtax[indvertnum] = indedhdnum; /* Set end of non-halo sub-array */ + indedgenum = indedgennd; /* Point to next free space in edge array */ + } + indgrafptr->vnlosum = (indgrafptr->s.velotax != NULL) ? indvelosum : indgrafptr->vnohnbr; + indgrafptr->enohnbr = indenohnbr; + +#ifdef SCOTCH_DEBUG_HGRAPH2 + indedgenbs = 2 * (indedgenum - indgrafptr->s.baseval) - indenohnbr; /* Compute total number of edges */ +#endif /* SCOTCH_DEBUG_HGRAPH2 */ +#ifdef HGRAPHINDUCE2L /* If edge loads present */ + { + Gnum * indedgetab; /* Dummy area to recieve un-based edgetab */ + Gnum * indedlotab; /* Save of old position of edgetab array */ +#ifndef SCOTCH_DEBUG_HGRAPH2 + Gnum indedgenbs; /* Revised number of edges in halo subgraph */ + + indedgenbs = 2 * (indedgenum - indgrafptr->s.baseval) - indenohnbr; /* Compute total number of edges */ +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + + indedlotab = indgrafptr->s.edlotax + indgrafptr->s.baseval; /* Save old offset of move area */ + memOffset (indgrafptr->s.edgetax + indgrafptr->s.baseval, /* Compute new offsets */ + &indedgetab, (size_t) (indedgenbs * sizeof (Gnum)), + &indgrafptr->s.edlotax, (size_t) (indedgenbs * sizeof (Gnum)), NULL); + memMov (indgrafptr->s.edlotax, indedlotab, (indedgenum - indgrafptr->s.baseval) * sizeof (Gnum)); /* Move already existing edge load array */ + indgrafptr->s.edlotax -= indgrafptr->s.baseval; + } +#endif /* HGRAPHINDUCE2L */ + + for ( ; indvertnum < indvertnnd; indvertnum ++) { /* For all halo vertices found during first pass */ + Gnum orgvertnum; /* Number of current vertex in original halo graph */ + Gnum orgedgenum; /* Number of current edge in original halo graph */ + + orgvertnum = indgrafptr->s.vnumtax[indvertnum]; + indgrafptr->s.verttax[indvertnum] = indedgenum; + if (indgrafptr->s.velotax != NULL) { /* If graph has vertex weights */ + indvelosum += /* Accumulate vertex loads */ + indgrafptr->s.velotax[indvertnum] = orggrafptr->s.velotax[orgvertnum]; + } + + for (orgedgenum = orggrafptr->s.verttax[orgvertnum]; + orgedgenum < orggrafptr->s.vendtax[orgvertnum]; orgedgenum ++) { + Gnum orgvertend; /* Number of current end vertex in original halo graph */ + Gnum indvertend; /* Number of current end vertex in induced halo subgraph */ + + orgvertend = orggrafptr->s.edgetax[orgedgenum]; + indvertend = orgindxtax[orgvertend]; + if ((indvertend != ~0) && /* If end vertex in induced halo subgraph */ + (indvertend < indgrafptr->vnohnnd)) { /* And in its non-halo part only */ + indgrafptr->s.edgetax[indedgenum] = indvertend; + HGRAPHINDUCE2EDLOINIT (indedgenum); + indedgenum ++; + } + } + if (inddegrmax < (indedgenum - indgrafptr->s.verttax[indvertnum])) + inddegrmax = (indedgenum - indgrafptr->s.verttax[indvertnum]); + } +#ifdef SCOTCH_DEBUG_HGRAPH2 + if ((indedgenum - indgrafptr->s.baseval) != indedgenbs) { + errorPrint (STRINGIFY (HGRAPHINDUCE2NAME) ": internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + indgrafptr->s.verttax[indvertnnd] = indedgenum; /* Set end of compact vertex array */ + indgrafptr->s.vertnbr = indvertnnd - indgrafptr->s.baseval; + indgrafptr->s.vertnnd = indvertnnd; + indgrafptr->s.velosum = (indgrafptr->s.velotax != NULL) ? indvelosum : indgrafptr->s.vertnbr; + indgrafptr->s.edgenbr = indedgenum - indgrafptr->s.baseval; /* Set actual number of edges */ + indgrafptr->s.edlosum = HGRAPHINDUCE2EDLOSUM; + indgrafptr->s.degrmax = inddegrmax; + indgrafptr->enohsum = HGRAPHINDUCE2ENOHSUM; +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_bl.c b/scotch_6.0.3/src/libscotch/hgraph_order_bl.c new file mode 100644 index 00000000..d509ea01 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_bl.c @@ -0,0 +1,126 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_bl.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module resizes block data using **/ +/** the block splitting post-processing **/ +/** algorithm. **/ +/** **/ +/** DATES : # Version 3.4 : from : 24 jun 2002 **/ +/** to 24 jun 2002 **/ +/** # Version 4.0 : from : 26 jun 2002 **/ +/** to 17 mar 2005 **/ +/** # Version 5.0 : from : 25 jul 2007 **/ +/** to : 25 jul 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_BL + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_bl.h" +#include "hgraph_order_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hgraphOrderBl ( +const Hgraph * restrict const grafptr, +Order * restrict const ordeptr, +const Gnum ordenum, /*+ Zero-based ordering number +*/ +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HgraphOrderBlParam * restrict const paraptr) +{ + Gnum cblknbr; /* Number of old column blocks before splitting */ + Gnum cblknum; /* Number of current column block */ + + if (paraptr->cblkmin <= 0) { + errorPrint ("hgraphOrderBl: invalid minimum block size"); + return (1); + } + + if (hgraphOrderSt (grafptr, ordeptr, ordenum, cblkptr, paraptr->strat) != 0) /* Perform ordering strategy */ + return (1); + + if (cblkptr->cblktab == NULL) { /* If single column block */ + if (cblkptr->vnodnbr < (2 * paraptr->cblkmin)) /* If block cannot be split */ + return (0); + + cblknbr = cblkptr->vnodnbr / paraptr->cblkmin; /* Get new number of blocks */ + + if ((cblkptr->cblktab = (OrderCblk *) memAlloc (cblknbr * sizeof (OrderCblk))) == NULL) { + errorPrint ("hgraphOrderBl: out of memory"); + return (1); + } + ordeptr->treenbr += cblknbr; /* These more number of tree nodes */ + ordeptr->cblknbr += cblknbr - 1; /* These more number of column blocks */ + cblkptr->cblknbr = cblknbr; + + for (cblknum = 0; cblknum < cblknbr; cblknum ++) { + cblkptr->cblktab[cblknum].typeval = ORDERCBLKOTHR; + cblkptr->cblktab[cblknum].vnodnbr = ((cblkptr->vnodnbr + cblknbr - 1) - cblknum) / cblknbr; + cblkptr->cblktab[cblknum].cblknbr = 0; + cblkptr->cblktab[cblknum].cblktab = NULL; + } + } + else { /* Block already partitioned */ + for (cblknum = 0; cblknum < cblkptr->cblknbr; cblknum ++) { + if (hgraphOrderBl (grafptr, ordeptr, ordenum, cblkptr->cblktab + cblknum, paraptr) != 0) + return (1); + } + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_bl.h b/scotch_6.0.3/src/libscotch/hgraph_order_bl.h new file mode 100644 index 00000000..42060d93 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_bl.h @@ -0,0 +1,71 @@ +/* Copyright 2004,2007,2009,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_bl.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the block splitting algorithm. **/ +/** **/ +/** DATES : # Version 3.4 : from : 24 jun 2002 **/ +/** to 24 jun 2002 **/ +/** # Version 4.0 : from : 26 jun 2002 **/ +/** to 29 dec 2004 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HgraphOrderBlParam_ { + Strat * strat; /*+ Ordering strategy +*/ + INT cblkmin; /*+ Block splitting size +*/ +} HgraphOrderBlParam; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_BL +#define static +#endif + +int hgraphOrderBl (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderBlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_cp.c b/scotch_6.0.3/src/libscotch/hgraph_order_cp.c new file mode 100644 index 00000000..3a95e9e7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_cp.c @@ -0,0 +1,527 @@ +/* Copyright 2004,2007,2009,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_cp.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders vertices by compres- **/ +/** sing vertices with identical adjacency **/ +/** structure. **/ +/** **/ +/** DATES : # Version 3.2 : from : 29 aug 1998 **/ +/** to 12 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 03 jan 1999 **/ +/** # Version 4.0 : from : 01 jan 2003 **/ +/** to 05 jan 2005 **/ +/** # Version 5.0 : from : 29 dec 2006 **/ +/** to 22 may 2008 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 01 oct 2009 **/ +/** # Version 6.0 : from : 04 aug 2014 **/ +/** to : 05 aug 2014 **/ +/** **/ +/** NOTES : # Pre-hashing proves itself extremely **/ +/** efficient, since for graphs that **/ +/** will be compressed very few writes **/ +/** will be performed in the pre-hashing **/ +/** array, and for others, for which pre- **/ +/** hashing costs much more, it will save **/ +/** time in the end. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_CP + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_cp.h" +#include "hgraph_order_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hgraphOrderCp ( +const Hgraph * restrict const finegrafptr, +Order * restrict const fineordeptr, +const Gnum ordenum, /*+ Zero-based ordering number +*/ +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HgraphOrderCpParam * const paraptr) +{ + Hgraph coargrafdat; /* Compressed halo subgraph */ + Order coarordedat; /* Ordering of compressed halo subgraph */ + Gnum * coarperitab; /* Coarse permutation array */ + const Gnum * restrict coarperitax; /* Temporary based access to coarperitab */ + Gnum coarvertnbr; /* Number of compressed vertices */ + Gnum coarvertnum; /* Number of current compressed vertex */ + Gnum coarvnhdsiz; /* Size of non-halo end vertex array; zero if graph has no halo */ + Gnum coarvsizsiz; /* Size of coarse vertex sizes array; zero if no fine vertex loads */ + Gnum * restrict coarvsiztax; /* Array of coarse vertex sizes (as number of merged fine vertices) */ + Gnum coaredgenbr; /* Number of compressed edges */ + Gnum coaredgenum; /* Number of current compressed edge */ + Gnum coarenohnnd; /* Position in edge array of first edge of first halo vertex */ + Gnum * restrict coarvpostax; /* Position in fine permutation of fine vertices merged into same vertex */ + Gnum * restrict finecoartax; /* Original to compressed vertex number array */ + HgraphOrderCpMate * restrict finematetab; /* Array of fine vertices that may be compressed with current vertex */ + HgraphOrderCpHash * restrict finehashtab; /* Neighbor hash table */ + Gnum finehashmsk; /* Mask for access to hash table */ + int * restrict finehasptab; /* Pre-hashing table */ + Gnum finehaspmsk; /* Mask for access to pre-hashing table */ + Gnum * restrict finehsumtax; /* Array of hash values for each original vertex */ + Gnum finevertnbr; /* Number of fine vertices in compressed elimination tree */ + Gnum finevertnum; /* Number of current original vertex */ + Gnum finevsizsum; /* Sum of compressed vertex sizes to build fine inverse permutation */ + void * dataptr; /* Flag of memory allocation success */ + + Gnum * restrict const fineperitab = fineordeptr->peritab; + const Gnum * restrict const fineverttax = finegrafptr->s.verttax; + const Gnum * restrict const finevelotax = finegrafptr->s.velotax; + const Gnum * restrict const finevendtax = finegrafptr->s.vendtax; + const Gnum * restrict const finevnumtax = finegrafptr->s.vnumtax; + const Gnum * restrict const finevnhdtax = finegrafptr->vnhdtax; + const Gnum * restrict const fineedgetax = finegrafptr->s.edgetax; + + for (finehashmsk = 15; /* Set neighbor hash table sizes */ + finehashmsk < finegrafptr->s.degrmax; + finehashmsk = finehashmsk * 2 + 1) ; + finehashmsk = finehashmsk * 4 + 3; /* Fill hash table at 1/4 of capacity */ + + if (((finecoartax = (Gnum *) memAlloc (finegrafptr->s.vertnbr * sizeof (Gnum))) == NULL) || + (memAllocGroup ((void **) (void *) + &finehashtab, (size_t) ((finehashmsk + 1) * sizeof (HgraphOrderCpHash)), + &finematetab, (size_t) (finegrafptr->s.degrmax * sizeof (HgraphOrderCpMate)), NULL) == NULL) || + ((finehsumtax = (Gnum *) memAlloc (finegrafptr->vnohnbr * sizeof (Gnum))) == NULL)) { + errorPrint ("hgraphOrderCp: out of memory (1)"); + if (finecoartax != NULL) { + if (finehashtab != NULL) + memFree (finehashtab); + memFree (finecoartax); + } + return (1); + } + finehsumtax -= finegrafptr->s.baseval; /* TRICK: do not base finecoartax yet (see later) */ + + finehasptab = (int *) finecoartax; /* Use finecoartab as temporary pre-hash table */ + for (finehaspmsk = 1; /* Get pre-hash mask that fits in finecoartab */ + finehaspmsk < finegrafptr->s.vertnbr; /* Smallest (2^i)-1 value >= vertnbr */ + finehaspmsk = finehaspmsk * 2 + 1) ; + finehaspmsk >>= 1; /* Ensure masked data will always fit into finecoartab array */ + finehaspmsk = (finehaspmsk * (sizeof (Gnum) / sizeof (int))) + ((sizeof (Gnum) / sizeof (int)) - 1); + if (finehaspmsk >= ((sizeof (int) << (3 + 1)) - 1)) /* Only use 1/8 of array for pre-hashing, for increased cache locality */ + finehaspmsk >>= 3; + memSet (finehasptab, 0, (finehaspmsk + 1) * sizeof (int)); /* Initialize pre-hash table */ + + for (finevertnum = finegrafptr->s.baseval, coarvertnbr = finegrafptr->vnohnbr; /* For all non-halo vertices */ + finevertnum < finegrafptr->vnohnnd; finevertnum ++) { + Gnum fineedgenum; /* Current edge number */ + Gnum finehsumval; /* Hash sum value */ + Gnum finehsumbit; + + for (fineedgenum = fineverttax[finevertnum], finehsumval = finevertnum; /* For all edges, including halo edges */ + fineedgenum < finevendtax[finevertnum]; fineedgenum ++) + finehsumval += fineedgetax[fineedgenum]; + + finehsumtax[finevertnum] = finehsumval; + + finehsumbit = finehsumval & ((sizeof (int) << 3) - 1); /* Get bit mask and byte position (division should be optimized into a shift) */ + finehsumval /= (sizeof (int) << 3); + finehsumval &= finehaspmsk; /* Make hash sum value fit into finehasptab */ + coarvertnbr -= (finehasptab[finehsumval] >> finehsumbit) & 1; /* If hash value already in pre-hash table, maybe one more vertex compressed */ + finehasptab[finehsumval] |= (1 << finehsumbit); /* Put value into pre-hash table anyway */ + } + + if ((double) coarvertnbr > ((double) finegrafptr->vnohnbr * paraptr->comprat)) { /* If graph needs not be compressed */ + memFree (finehsumtax + finegrafptr->s.baseval); + memFree (finehashtab); + memFree (finecoartax); /* Not yet based */ + return (hgraphOrderSt (finegrafptr, fineordeptr, ordenum, cblkptr, paraptr->stratunc)); + } + + finecoartax -= finegrafptr->s.baseval; /* Base finecoartab array */ + + memSet (finehashtab, ~0, (finehashmsk + 1) * sizeof (HgraphOrderCpHash)); + + hgraphInit (&coargrafdat); /* Initialize compressed halo graph structure */ + coargrafdat.s.baseval = 1; /* Base coarse graph to 1 because hgraphOrderHb and hgraphOrderHf prefer it */ + + for (finevertnum = finegrafptr->s.baseval, coarvertnbr = coargrafdat.s.baseval, coaredgenbr = finegrafptr->s.edgenbr; /* For all non-halo vertices */ + finevertnum < finegrafptr->vnohnnd; finevertnum ++) { + Gnum finedegrval; /* Degree of current fine vertex */ + Gnum finehsumval; /* Current hash sum value */ + Gnum finematenbr; /* Number of mates of current vertex */ + Gnum fineedgenum; /* Current edge number */ + + finedegrval = finevendtax[finevertnum] - fineverttax[finevertnum]; + finehsumval = finehsumtax[finevertnum]; + finematenbr = 0; /* Reset potential mate array */ + + for (fineedgenum = fineverttax[finevertnum]; /* For all edges, including halo edges */ + fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { + Gnum finevertend; + + finevertend = fineedgetax[fineedgenum]; + + if ((finevertend < finevertnum) && /* If neighbor has same characteristics */ + (finehsumval == finehsumtax[finevertend]) && + (finedegrval == (finevendtax[finevertend] - fineverttax[finevertend]))) { + Gnum finematenum; + Gnum coarvertend; + + for (finematenum = 0, coarvertend = finecoartax[finevertend]; /* Search if end vertex has already been compressed with some mate */ + (finematenum < finematenbr) && (finematetab[finematenum].coarvertend != coarvertend); finematenum ++) ; + + if (finematenum == finematenbr) { /* If new slot needed */ + finematetab[finematenum].coarvertend = coarvertend; /* Build it */ + finematetab[finematenum].finevertend = finevertend; + finematenbr ++; + } + } + } + + finecoartax[finevertnum] = coarvertnbr ++; /* Assume no mate found */ + + if (finematenbr > 0) { /* If potential mates exist */ + Gnum fineedgenum; /* Current edge number */ + Gnum finehashnum; + + for (fineedgenum = fineverttax[finevertnum]; /* For all edges, including halo edges */ + fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { + Gnum finevertend; + + finevertend = fineedgetax[fineedgenum]; /* Add end vertex to hash table */ + + for (finehashnum = (finevertend * HGRAPHORDERCPHASHPRIME) & finehashmsk; /* Search for empty slot in hash table */ + finehashtab[finehashnum].vertnum == finevertnum; finehashnum = (finehashnum + 1) & finehashmsk) ; + finehashtab[finehashnum].vertnum = finevertnum; + finehashtab[finehashnum].vertend = finevertend; + } + for (finehashnum = (finevertnum * HGRAPHORDERCPHASHPRIME) & finehashmsk; /* Add current vertex to hash table */ + finehashtab[finehashnum].vertnum == finevertnum; finehashnum = (finehashnum + 1) & finehashmsk) ; + finehashtab[finehashnum].vertnum = finevertnum; + finehashtab[finehashnum].vertend = finevertnum; + + finematenbr --; /* Point to first potential mate */ + do { /* For all potential mates */ + Gnum fineedgenum; /* Current edge number */ + Gnum fineedgennd; + + for (fineedgenum = fineverttax[finematetab[finematenbr].finevertend], /* For all edges, including halo edges */ + fineedgennd = finevendtax[finematetab[finematenbr].finevertend]; + fineedgenum < fineedgennd; fineedgenum ++) { + Gnum finevertend; + + finevertend = fineedgetax[fineedgenum]; + + for (finehashnum = (finevertend * HGRAPHORDERCPHASHPRIME) & finehashmsk; ; + finehashnum = (finehashnum + 1) & finehashmsk) { + if (finehashtab[finehashnum].vertnum != finevertnum) /* If mate neighbor not found in hash table */ + goto loop_failed; /* Vertex cannot be merged to mate, so skip to next mate */ + if (finehashtab[finehashnum].vertend == finevertend) /* Else if mate neighbor found in hash table */ + break; /* Skip to next mate neighbor to find */ + } + } + coarvertnbr --; /* Same adjacency structure */ + finecoartax[finevertnum] = finematetab[finematenbr].coarvertend; /* Get number */ + coaredgenbr -= finedegrval + 1; /* Remove exceeding edges */ + break; +loop_failed: ; + } while (finematenbr -- > 0); + } + } + + coargrafdat.vnohnnd = coarvertnbr; /* Save number of non-halo vertices */ + + memFree (finehsumtax + finegrafptr->s.baseval); + + if ((double) (coarvertnbr - coargrafdat.s.baseval) > ((double) finegrafptr->vnohnbr * paraptr->comprat)) { /* If graph needs not be compressed */ + memFree (finehashtab); + memFree (finecoartax + finegrafptr->s.baseval); + return (hgraphOrderSt (finegrafptr, fineordeptr, ordenum, cblkptr, paraptr->stratunc)); + } + + for ( ; finevertnum < finegrafptr->s.vertnnd; finevertnum ++) /* For all halo vertices */ + finecoartax[finevertnum] = coarvertnbr ++; /* Halo vertices are never compressed */ + + coargrafdat.s.flagval = GRAPHFREETABS | GRAPHVERTGROUP; /* Do not set HGRAPHFREEVNHD since vnhdtax allocated in group */ + coargrafdat.s.vertnbr = coarvertnbr - coargrafdat.s.baseval; + coargrafdat.s.vertnnd = coarvertnbr; + coargrafdat.s.velosum = finegrafptr->s.velosum; + coargrafdat.s.degrmax = finegrafptr->s.degrmax; + coargrafdat.vnohnbr = coargrafdat.vnohnnd - coargrafdat.s.baseval; + coargrafdat.vnlosum = finegrafptr->vnlosum; + + coarvnhdsiz = (finegrafptr->s.vertnbr == finegrafptr->vnohnbr) ? 0 : coargrafdat.vnohnbr; /* If no halo, no need for vnhdtax; will use vendtax */ + coarvsizsiz = (finevelotax == NULL) ? 0 : coarvertnbr; /* If no fine vertex loads, use coarse velotax as coarvsiztax */ + if ((dataptr = memAllocGroup ((void **) (void *) + &coargrafdat.s.verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), + &coargrafdat.vnhdtax, (size_t) (coarvnhdsiz * sizeof (Gnum)), + &coargrafdat.s.velotax, (size_t) (coarvertnbr * sizeof (Gnum)), + &coarvsiztax, (size_t) (coarvsizsiz * sizeof (Gnum)), NULL)) != NULL) { + dataptr = + coargrafdat.s.edgetax = (Gnum *) memAlloc (coaredgenbr * sizeof (Gnum)); + } + if (dataptr == NULL) { + errorPrint ("hgraphOrderCp: out of memory (2)"); + hgraphExit (&coargrafdat); + memFree (finehashtab); + memFree (finecoartax + finegrafptr->s.baseval); + return (1); + } + coargrafdat.s.verttax -= coargrafdat.s.baseval; + coargrafdat.s.vendtax = coargrafdat.s.verttax + 1; /* Use compact representation of arrays */ + coargrafdat.s.velotax -= coargrafdat.s.baseval; + coargrafdat.s.edgetax -= coargrafdat.s.baseval; + coargrafdat.vnhdtax = (finegrafptr->s.vertnbr == finegrafptr->vnohnbr) ? coargrafdat.s.vendtax : coargrafdat.vnhdtax - coargrafdat.s.baseval; + coarvsiztax = (finevelotax == NULL) ? coargrafdat.s.velotax : coarvsiztax - coargrafdat.s.baseval; + + memSet (finehashtab, ~0, (finehashmsk + 1) * sizeof (HgraphOrderCpHash)); + + for (finevertnum = finegrafptr->s.baseval, coarvertnum = coaredgenum = coargrafdat.s.baseval; /* For all non-halo vertices */ + finevertnum < finegrafptr->vnohnnd; finevertnum ++) { + Gnum fineedgenum; /* Current edge number */ + + if (finecoartax[finevertnum] != coarvertnum) /* Skip fine vertices until we find one that is part of current coarse vertex */ + continue; + + coargrafdat.s.verttax[coarvertnum] = coaredgenum; + coarvsiztax[coarvertnum] = 1; /* Fill coargrafdat.s.velotax if finegrafptr has no vertex loads */ + + for (fineedgenum = fineverttax[finevertnum]; /* For all non-halo edges of vertex */ + fineedgenum < finevnhdtax[finevertnum]; fineedgenum ++) { + Gnum finevertend; + Gnum finehashnum; + + finevertend = fineedgetax[fineedgenum]; + if (finecoartax[finevertend] == coarvertnum) { /* If neighbor is merged into us, merge load but do not write edge */ + coarvsiztax[coarvertnum] ++; /* Fill coargrafdat.s.velotax if finegrafptr has no vertex loads */ + continue; + } + for (finehashnum = (finecoartax[finevertend] * HGRAPHORDERCPHASHPRIME) & finehashmsk; ; /* Search for end vertex in hash table */ + finehashnum = (finehashnum + 1) & finehashmsk) { + if (finehashtab[finehashnum].vertnum != coarvertnum) { + finehashtab[finehashnum].vertnum = coarvertnum; + finehashtab[finehashnum].vertend = + coargrafdat.s.edgetax[coaredgenum ++] = finecoartax[finevertend]; + break; + } + if (finehashtab[finehashnum].vertend == finecoartax[finevertend]) + break; /* If edge already exists */ + } + } + coargrafdat.vnhdtax[coarvertnum] = coaredgenum; /* Set end of non-halo edge sub-array */ + + for ( ; fineedgenum < finegrafptr->s.vendtax[finevertnum]; fineedgenum ++) { /* For edges linking to halo vertices */ + Gnum finevertend; + + finevertend = fineedgetax[fineedgenum]; + coargrafdat.s.edgetax[coaredgenum ++] = finecoartax[finevertend]; /* Halo vertices are always defined and unique */ + } + coarvertnum ++; + } + for (coarenohnnd = coaredgenum; finevertnum < finegrafptr->s.vertnnd; finevertnum ++) { /* For all halo vertices */ + Gnum fineedgenum; /* Current edge number */ + +#ifdef SCOTCH_DEBUG_ORDER2 + if (finecoartax[finevertnum] != coarvertnum) { + errorPrint ("hgraphOrderCp: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + coargrafdat.s.verttax[coarvertnum] = coaredgenum; + coarvsiztax[coarvertnum] = 1; /* Fill coargrafdat.s.velotax if finegrafptr has no vertex loads */ + + for (fineedgenum = fineverttax[finevertnum]; /* For all edges of halo vertex */ + fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { + Gnum finevertend; + Gnum finehashnum; + + finevertend = fineedgetax[fineedgenum]; +#ifdef SCOTCH_DEBUG_ORDER2 + if (finecoartax[finevertend] == coarvertnum) { /* No neighbor can be merged into us since halo vertices are unique */ + errorPrint ("hgraphOrderCp: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + for (finehashnum = (finecoartax[finevertend] * HGRAPHORDERCPHASHPRIME) & finehashmsk; ; /* Search for end vertex in hash table */ + finehashnum = (finehashnum + 1) & finehashmsk) { + if (finehashtab[finehashnum].vertnum != coarvertnum) { + finehashtab[finehashnum].vertnum = coarvertnum; + finehashtab[finehashnum].vertend = + coargrafdat.s.edgetax[coaredgenum ++] = finecoartax[finevertend]; + break; + } + if (finehashtab[finehashnum].vertend == finecoartax[finevertend]) + break; /* If edge already exists */ + } + } + coarvertnum ++; + } + coargrafdat.s.verttax[coarvertnum] = coaredgenum; /* Set end of compact vertex array */ + coargrafdat.s.edlosum = + coargrafdat.s.edgenbr = coaredgenum - coargrafdat.s.baseval; + coargrafdat.enohsum = + coargrafdat.enohnbr = coargrafdat.s.edgenbr - 2 * (coaredgenum - coarenohnnd); + + if (finevelotax != NULL) { /* If fine graph has vertex loads */ + memSet (coargrafdat.s.velotax + coargrafdat.s.baseval, 0, coargrafdat.s.vertnbr * sizeof (Gnum)); + + for (finevertnum = finegrafptr->s.baseval; finevertnum < finegrafptr->s.vertnnd; finevertnum ++) /* Compute vertex loads for compressed graph */ + coargrafdat.s.velotax[finecoartax[finevertnum]] += finevelotax[finevertnum]; + } + + memFree (finehashtab); + + coargrafdat.s.edgetax = (Gnum *) memRealloc (coargrafdat.s.edgetax + coargrafdat.s.baseval, coargrafdat.s.edgenbr * sizeof (Gnum)) - coargrafdat.s.baseval; + +#ifdef SCOTCH_DEBUG_ORDER2 + if (hgraphCheck (&coargrafdat) != 0) { + errorPrint ("hgraphOrderCp: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + if ((coarperitab = memAlloc (coargrafdat.vnohnbr * sizeof (Gnum))) == NULL) { /* Coarse permutation only for non-halo vertices */ + errorPrint ("hgraphOrderCp: out of memory (3)"); + hgraphExit (&coargrafdat); + memFree (finecoartax + finegrafptr->s.baseval); + return (1); + } + orderInit (&coarordedat, coargrafdat.s.baseval, coargrafdat.vnohnbr, coarperitab); /* Build ordering of compressed subgraph */ + if (hgraphOrderSt (&coargrafdat, &coarordedat, 0, &coarordedat.cblktre, paraptr->stratcpr) != 0) { + memFree (coarperitab); + hgraphExit (&coargrafdat); + memFree (finecoartax + finegrafptr->s.baseval); + return (1); + } + + *cblkptr = coarordedat.cblktre; /* Link sub-tree to ordering */ + coarordedat.cblktre.cblktab = NULL; /* Unlink sub-tree from sub-ordering */ + finevertnbr = hgraphOrderCpTree (coarordedat.peritab, /* Expand sub-tree */ + coarvsiztax, cblkptr, 0); +#ifdef SCOTCH_DEBUG_ORDER2 + if (finevertnbr != finegrafptr->vnohnbr) { + errorPrint ("hgraphOrderCp: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + fineordeptr->treenbr += coarordedat.treenbr - 1; /* Adjust number of tree nodes */ + fineordeptr->cblknbr += coarordedat.cblknbr - 1; /* Adjust number of column blocks */ + + coarvpostax = coargrafdat.s.verttax; /* Re-cycle verttab (not velotab as may be merged with coarvsiztab) */ + coarperitax = coarperitab - coargrafdat.s.baseval; + + for (coarvertnum = coargrafdat.s.baseval, finevsizsum = 0; /* Compute initial indices for inverse permutation expansion */ + coarvertnum < coargrafdat.vnohnnd; coarvertnum ++) { + coarvpostax[coarperitax[coarvertnum]] = finevsizsum; + finevsizsum += coarvsiztax[coarperitax[coarvertnum]]; + } + if (finevnumtax == NULL) { /* If fine graph is original graph */ + for (finevertnum = finegrafptr->s.baseval; finevertnum < finegrafptr->vnohnnd; finevertnum ++) /* Compute fine permutation */ + fineperitab[coarvpostax[finecoartax[finevertnum]] ++] = finevertnum; + } + else { /* Graph is not original graph */ + for (finevertnum = finegrafptr->s.baseval; finevertnum < finegrafptr->vnohnnd; finevertnum ++) /* Compute fine permutation */ + fineperitab[coarvpostax[finecoartax[finevertnum]] ++] = finevnumtax[finevertnum]; + } + + memFree (coarperitab); + memFree (finecoartax + finegrafptr->s.baseval); + orderExit (&coarordedat); + hgraphExit (&coargrafdat); /* Free coarvsiztab as part of vertex group */ + + return (0); +} + +/* This routine turns the coarse elimination +** tree produced by the ordering of the coarse +** graph into a fine elimination tree, according +** to the cardinality of the coarse vertices. +** It returns: +** - !0 : overall number of fine vertices, in all cases. +*/ + +static +Gnum +hgraphOrderCpTree ( +const Gnum * restrict const coarperitab, /* Coarse inverse permutation */ +const Gnum * restrict const coarvsiztax, /* Array of fine sizes of coarse vertices */ +OrderCblk * restrict const coficblkptr, /* Current coarse/fine column block cell */ +Gnum coarordenum) /* Compressed vertex to start expansion at */ +{ + Gnum finevertnbr; /* Number of fine vertices in subtree */ + + finevertnbr = 0; /* No fine vertices yet */ + + if (coficblkptr->cblktab == NULL) { /* If leaf of column block tree */ + Gnum coarvnumnum; + + for (coarvnumnum = coarordenum; + coarvnumnum < coarordenum + coficblkptr->vnodnbr; coarvnumnum ++) + finevertnbr += coarvsiztax[coarperitab[coarvnumnum]]; /* Sum-up fine vertices */ + } + else { + Gnum coarvertnbr; /* Number of coarse vertices in cell */ + Gnum coarvertsum; /* Number of coarse vertices in subtree */ + Gnum coficblknum; /* Index in column block array */ + + for (coficblknum = 0, coarvertsum = coarordenum; /* Start at current coarse index */ + coficblknum < coficblkptr->cblknbr; coficblknum ++) { + coarvertnbr = coficblkptr->cblktab[coficblknum].vnodnbr; /* Save number of coarse vertices */ + finevertnbr += hgraphOrderCpTree (coarperitab, coarvsiztax, &coficblkptr->cblktab[coficblknum], coarvertsum); + coarvertsum += coarvertnbr; /* Sum-up coarse vertices */ + } + } + coficblkptr->vnodnbr = finevertnbr; /* Set number of fine vertices */ + + return (finevertnbr); /* Return accumulated number */ +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_cp.h b/scotch_6.0.3/src/libscotch/hgraph_order_cp.h new file mode 100644 index 00000000..df2a5a76 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_cp.h @@ -0,0 +1,99 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_cp.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the graph compression **/ +/** ordering routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 29 aug 1998 **/ +/** to : 09 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to : 03 jan 1999 **/ +/** # Version 4.0 : from : 01 jan 2003 **/ +/** to : 01 jan 2003 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Prime number for hashing vertex numbers. +*/ + +#define HGRAPHORDERCPHASHPRIME 17 /* Prime number */ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HgraphOrderCpParam_ { + double comprat; /*+ Compression ratio threshold +*/ + Strat * stratcpr; /*+ Compressed subgraph ordering strategy +*/ + Strat * stratunc; /*+ Uncompressed subgraph ordering strategy +*/ +} HgraphOrderCpParam; + +/*+ This structure holds fine neighbor hashing data. +*/ + +typedef struct HgraphOrderCpHash_ { + Gnum vertnum; /*+ Origin vertex (i.e. pass) number +*/ + Gnum vertend; /*+ Adjacent end vertex number +*/ +} HgraphOrderCpHash; + +/*+ This structure holds coarse neighbor mate data. +*/ + +typedef struct HgraphOrderCpMate_ { + Gnum coarvertend; /*+ Adjacent coarse end vertex number +*/ + Gnum finevertend; /*+ Adjacent end vertex number +*/ +} HgraphOrderCpMate; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_CP +#define static +#endif + +int hgraphOrderCp (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderCpParam * const); + +static Gnum hgraphOrderCpTree (const Gnum * const, const Gnum * const, OrderCblk * const, Gnum); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_gp.c b/scotch_6.0.3/src/libscotch/hgraph_order_gp.c new file mode 100644 index 00000000..e36cf6fd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_gp.c @@ -0,0 +1,248 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_gp.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a subgraph (most **/ +/** likely a separator) using the Gibbs, **/ +/** Poole, and Stockmeyer algorithm. **/ +/** **/ +/** DATES : # Version 3.2 : from : 31 oct 1996 **/ +/** to 27 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 4.0 : from : 28 jun 2002 **/ +/** to : 01 dec 2003 **/ +/** # Version 4.0 : from : 10 sep 2007 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 01 oct 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_GP + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_gp.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hgraphOrderGp ( +const Hgraph * restrict const grafptr, +Order * restrict const ordeptr, +const Gnum ordenum, +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HgraphOrderGpParam * restrict const paraptr) +{ + HgraphOrgerGpQueue queudat; /* Neighbor queue */ + HgraphOrderGpVertex * restrict vexxtax; /* Based access to vertex array */ + Gnum passnum; /* Pass number */ + Gnum rootnum; /* Number of root vertex */ + Gnum diamnum; /* Vertex which achieves diameter */ + int diamflag; /* Flag set if diameter changed */ + Gnum diamdist; /* Maximum diameter value found */ + Gnum vertdist; /* DIstance of current vertex */ + Gnum vertnum; /* Number of current vertex */ + Gnum edgenum; /* Number of current edge */ + Gnum ordeval; /* Current ordering value */ + Gnum ordevnd; /* End value of ordering */ + + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vnumtax = grafptr->s.vnumtax; + const Gnum * restrict const vnhdtax = grafptr->vnhdtax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + + if (memAllocGroup ((void **) (void *) + &queudat.qtab, (size_t) (grafptr->vnohnbr * sizeof (Gnum)), + &vexxtax, (size_t) (grafptr->vnohnbr * sizeof (HgraphOrderGpVertex)), NULL) == NULL) { + errorPrint ("hgraphOrderGp: out of memory"); + return (1); + } + memSet (vexxtax, 0, grafptr->vnohnbr * sizeof (HgraphOrderGpVertex)); /* Initialize pass numbers */ + vexxtax -= grafptr->s.baseval; + +#ifdef SCOTCH_DEBUG_ORDER2 + memSet (ordeptr->peritab + ordenum, ~0, grafptr->vnohnbr * sizeof (Gnum)); +#endif /* SCOTCH_DEBUG_ORDER2 */ + + for (ordeval = ordenum, rootnum = grafptr->s.baseval, /* For all connected components */ + ordevnd = ordeval + grafptr->vnohnbr; + ordeval < ordevnd; ) { + while (vexxtax[rootnum].passnum != 0) { /* Find first unallocated root */ + rootnum ++; +#ifdef SCOTCH_DEBUG_ORDER2 + if (rootnum >= grafptr->vnohnnd) { + errorPrint ("hgraphOrderGp: internal error (1)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + } + + diamnum = rootnum; /* Start from found root */ + diamdist = 0; + for (diamflag = 0, passnum = 1; /* Loop if modifications */ + (diamflag ++ == 0) && (passnum <= paraptr->passnbr); passnum ++) { + Gnum diamdegr; /* Degree of current pseudo-peripherial vertex */ + + hgraphOrderGpQueueFlush (&queudat); /* Flush vertex queue */ + hgraphOrderGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ + vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ + vexxtax[diamnum].vertdist = 0; /* It is at distance zero */ + diamdegr = vnhdtax[diamnum] - verttax[diamnum]; + + do { /* Loop on vertices in queue */ + vertnum = hgraphOrderGpQueueGet (&queudat); /* Get vertex from queue */ +#ifdef SCOTCH_DEBUG_ORDER2 + if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->vnohnnd)) { + errorPrint ("hgraphOrderGp: internal error (2)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + vertdist = vexxtax[vertnum].vertdist; /* Get vertex distance */ + + if ((vertdist > diamdist) || /* If vertex increases diameter */ + ((vertdist == diamdist) && /* Or is at diameter distance */ + ((vnhdtax[vertnum] - verttax[vertnum]) < diamdegr))) { /* With smaller degree */ + diamnum = vertnum; /* Set it as new diameter vertex */ + diamdist = vertdist; + diamdegr = vnhdtax[vertnum] - verttax[vertnum]; + diamflag = 0; + } + + vertdist ++; /* Set neighbor distance */ + for (edgenum = verttax[vertnum]; edgenum < vnhdtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = edgetax[edgenum]; +#ifdef SCOTCH_DEBUG_ORDER2 + if ((vertend < grafptr->s.baseval) || (vertend >= grafptr->vnohnnd)) { + errorPrint ("hgraphOrderGp: internal error (3)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + if (vexxtax[vertend].passnum < passnum) { /* If vertex not queued yet */ + hgraphOrderGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ + vexxtax[vertend].passnum = passnum; + vexxtax[vertend].vertdist = vertdist; + } + } + } while (! hgraphOrderGpQueueEmpty (&queudat)); /* As long as queue is not empty */ + } + + hgraphOrderGpQueueFlush (&queudat); /* Flush vertex queue */ + hgraphOrderGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ + vexxtax[diamnum].passnum = passnum; /* Vertex has been enqueued */ + + do { /* Loop on vertices in queue */ + vertnum = hgraphOrderGpQueueGet (&queudat); /* Get vertex from queue */ + + if (vexxtax[vertnum].passnum > passnum) /* If vertex already ordered (by-level ordering) */ + continue; /* Skip to next vertex in queue */ + + vertdist = vexxtax[vertnum].vertdist; /* Get vertex distance */ + do { /* Loop on vertices in layer */ + Gnum edgennd; /* End of edge sub-array */ + + ordeptr->peritab[ordeval ++] = (vnumtax == NULL) ? vertnum : vnumtax[vertnum]; + vexxtax[vertnum].passnum = passnum + 1; /* Set vertex as ordered */ + + for (edgenum = verttax[vertnum], edgennd = vnhdtax[vertnum], vertnum = ~0; + edgenum < edgennd; edgenum ++) { /* Need edgennd because vertnum is overwritten */ + Gnum vertend; + + vertend = edgetax[edgenum]; + + if ((vexxtax[vertend].vertdist == vertdist) && /* If neighbor vertex in same layer */ + (vexxtax[vertend].passnum <= passnum)) { /* And not yet ordered */ + vertnum = vertend; /* Set neighbor as next vertex */ + edgenum ++; /* Process next neighbors, not this one again */ + break; /* Process next neighbors without further testing */ + } + if (vexxtax[vertend].passnum < passnum) { /* Else if vertex not yet enqueued */ + hgraphOrderGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ + vexxtax[vertend].passnum = passnum; /* Set it as enqueued */ + } + } + for ( ; edgenum < edgennd; edgenum ++) { /* Enqueue remaining neighbors */ + Gnum vertend; + + vertend = edgetax[edgenum]; + + if (vexxtax[vertend].passnum < passnum) { /* If neighbor not yet enqueued */ + hgraphOrderGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ + vexxtax[vertend].passnum = passnum; /* Set it as enqueued */ + } + } + } while (vertnum != ~0); + } while (! hgraphOrderGpQueueEmpty (&queudat)); /* As long as queue is not empty */ + } + +#ifdef SCOTCH_DEBUG_ORDER2 + for (ordeval = ordenum; ordeval < ordenum + grafptr->vnohnbr; ordeval ++) { + if (ordeptr->peritab[ordeval] == ~0) { + errorPrint ("hgraphOrderGp: internal error (4)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + memFree (queudat.qtab); /* Group freeing */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_gp.h b/scotch_6.0.3/src/libscotch/hgraph_order_gp.h new file mode 100644 index 00000000..ae6c4e3a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_gp.h @@ -0,0 +1,97 @@ +/* Copyright 2004,2007,2009,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_gp.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the Gibbs-Poole-Stockmeyer **/ +/** node ordering routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 31 oct 1996 **/ +/** to : 27 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 4.0 : from : 03 feb 2002 **/ +/** to : 01 dec 2003 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HgraphOrderGpParam_ { + INT passnbr; /*+ Number of passes to do +*/ +} HgraphOrderGpParam; + +/*+ Complementary vertex structure. +*/ + +typedef struct HgraphOrgerGpVertex_ { + Gnum passnum; /*+ Number of pass when vertex selected +*/ + Gnum vertdist; /*+ Current distance from diameter vertex +*/ +} HgraphOrderGpVertex; + +/*+ Neighbor queue. +*/ + +typedef struct HgraphOrgerGpQueue_ { + Gnum * head; /*+ Head of distance queue +*/ + Gnum * tail; /*+ Tail of distance queue +*/ + Gnum * qtab; /*+ Array of queue elements +*/ +} HgraphOrgerGpQueue; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_GP +#define static +#endif + +int hgraphOrderGp (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderGpParam * restrict const); + +#undef static + +/* +** The macro definitions. +*/ + +#define hgraphOrderGpQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) +#define hgraphOrderGpQueueEmpty(queue) ((queue)->head <= (queue)->tail) +#define hgraphOrderGpQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) +#define hgraphOrderGpQueueGet(queue) (* ((queue)->tail ++)) diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_hd.c b/scotch_6.0.3/src/libscotch/hgraph_order_hd.c new file mode 100644 index 00000000..79852a7f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_hd.c @@ -0,0 +1,159 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_hd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a separator using **/ +/** the block-oriented Halo Approximate **/ +/** (Multiple) Minimum Degree algorithm, **/ +/** with super-variable accounting (HaloAMD **/ +/** v2.0). **/ +/** **/ +/** DATES : # Version 3.2 : from : 09 aug 1998 **/ +/** to 18 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 05 jan 1999 **/ +/** # Version 4.0 : from : 14 jan 2003 **/ +/** to : 23 jan 2004 **/ +/** # Version 5.0 : from : 10 sep 2007 **/ +/** to : 10 sep 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_HD + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hall_order_hx.h" +#include "hall_order_hd.h" +#include "hgraph_order_hd.h" +#include "hgraph_order_hx.h" +#include "hgraph_order_si.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hgraphOrderHd ( +const Hgraph * restrict const grafptr, +Order * restrict const ordeptr, +const Gnum ordenum, /*+ Zero-based ordering number +*/ +OrderCblk * restrict const cblkptr, /*+ Multiple column-block +*/ +const HgraphOrderHdParam * restrict const paraptr) +{ + Gnum * restrict petab; + Gnum pfree; + Gnum iwlen; + Gnum * restrict iwtab; + Gnum * restrict lentab; + Gnum * restrict nvartab; + Gnum * restrict elentab; + Gnum * restrict lasttab; + Gnum * restrict leaftab; + Gnum * restrict secntab; /* Array of index to first secondary variable */ + Gnum * restrict nexttab; /* Array of index of next principal variable */ + Gnum * restrict frsttab; + Gnum ncmpa; + Gnum n; /* Number of nodes to order (with halo or not) */ + int o; + + if (grafptr->s.vertnbr < paraptr->colmin) /* If graph is too small, order simply */ + return (hgraphOrderSi (grafptr, ordeptr, ordenum, cblkptr)); + + n = grafptr->s.vertnbr; + iwlen = (Gnum) ((double) grafptr->s.edgenbr * HGRAPHORDERHDCOMPRAT) + 32; + if (iwlen < n) /* Prepare to re-use array */ + iwlen = n; + + if (memAllocGroup ((void **) (void *) + &petab, (size_t) (n * sizeof (Gnum)), + &iwtab, (size_t) (iwlen * sizeof (Gnum)), + &lentab, (size_t) (n * sizeof (Gnum)), + &nvartab, (size_t) (n * sizeof (Gnum)), + &elentab, (size_t) (n * sizeof (Gnum)), + &lasttab, (size_t) (n * sizeof (Gnum)), + &leaftab, (size_t) (n * sizeof (Gnum)), + &frsttab, (size_t) (n * sizeof (Gnum)), + &secntab, (size_t) (n * sizeof (Gnum)), + &nexttab, (size_t) (n * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hgraphOrderHd: out of memory"); + return (1); + } + + hgraphOrderHxFill (grafptr, petab, lentab, iwtab, elentab, &pfree); + + hallOrderHdHalmd (n, 0, iwlen, petab, pfree, /* No elements here */ + lentab, iwtab, nvartab, elentab, lasttab, &ncmpa, + leaftab, secntab, nexttab, frsttab); + if (ncmpa < 0) { + errorPrint ("hgraphOrderHd: internal error"); + memFree (petab); /* Free group leader */ + return (1); + } + + o = hallOrderHxBuild (grafptr->s.baseval, n, grafptr->vnohnbr, + grafptr->s.vnumtax, ordeptr, cblkptr, + nvartab - grafptr->s.baseval, + lentab - grafptr->s.baseval, + petab - grafptr->s.baseval, + frsttab - grafptr->s.baseval, + nexttab - grafptr->s.baseval, + secntab - grafptr->s.baseval, + iwtab - grafptr->s.baseval, + elentab - grafptr->s.baseval, + ordeptr->peritab + ordenum, /* Use given inverse permutation as inverse permutation space, never based */ + leaftab, + paraptr->colmin, paraptr->colmax, (float) paraptr->fillrat); + + memFree (petab); /* Free group leader */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_hd.h b/scotch_6.0.3/src/libscotch/hgraph_order_hd.h new file mode 100644 index 00000000..423190c6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_hd.h @@ -0,0 +1,82 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_hd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the block-oriented Halo **/ +/** Approximate (Multiple) Minimum Degree **/ +/** ordering routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 09 aug 1998 **/ +/** to : 18 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 19 oct 1998 **/ +/** # Version 4.0 : from : 14 jan 2003 **/ +/** to : 24 jan 2004 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 01 oct 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#define HGRAPHORDERHDCOMPRAT 1.2L /*+ Compression ratio +*/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HgraphOrderHdParam_ { + INT colmin; /*+ Minimum number of columns +*/ + INT colmax; /*+ Maximum number of columns +*/ + double fillrat; /*+ Fill-in ratio +*/ +} HgraphOrderHdParam; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_HD +#define static +#endif + +int hgraphOrderHd (const Hgraph * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HgraphOrderHdParam * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_hf.c b/scotch_6.0.3/src/libscotch/hgraph_order_hf.c new file mode 100644 index 00000000..01d2ed5a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_hf.c @@ -0,0 +1,161 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_hf.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a subgraph using **/ +/** the block-oriented Halo Approximate **/ +/** (Multiple) Minimum Fill algorithm, **/ +/** with super-variable accounting **/ +/** R2HAMDf4 v2.0). **/ +/** **/ +/** DATES : # Version 3.4 : from : 15 may 2001 **/ +/** to : 23 nov 2001 **/ +/** # Version 4.0 : from : 10 jan 2003 **/ +/** to : 24 jan 2004 **/ +/** # Version 5.0 : from : 10 sep 2007 **/ +/** to : 10 sep 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_HF + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hall_order_hf.h" +#include "hall_order_hx.h" +#include "hgraph_order_hf.h" +#include "hgraph_order_hx.h" +#include "hgraph_order_si.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hgraphOrderHf ( +const Hgraph * restrict const grafptr, +Order * restrict const ordeptr, +const Gnum ordenum, /*+ Zero-based ordering number +*/ +OrderCblk * restrict const cblkptr, /*+ Multiple column-block +*/ +const HgraphOrderHfParam * restrict const paraptr) +{ + Gnum nbbuck; + Gnum * restrict petab; + Gnum pfree; + Gnum iwlen; + Gnum * restrict iwtab; + Gnum * restrict lentab; + Gnum * restrict nvartab; + Gnum * restrict elentab; + Gnum * restrict lasttab; + Gnum * restrict leaftab; + Gnum * restrict secntab; /* Array of index to first secondary variable */ + Gnum * restrict nexttab; /* Array of index of next principal variable */ + Gnum * restrict frsttab; + Gnum * restrict headtab; /* Head array : nbbuck = 2 * n */ + Gnum ncmpa; + Gnum n; /* Number of nodes to order (with halo or not) */ + int o; + + if (grafptr->s.vertnbr < paraptr->colmin) /* If graph is too small, order simply */ + return (hgraphOrderSi (grafptr, ordeptr, ordenum, cblkptr)); + + n = grafptr->s.vertnbr; + nbbuck = n * 2; + iwlen = (Gnum) ((double) grafptr->s.edgenbr * HGRAPHORDERHFCOMPRAT) + 32; + if (iwlen < n) /* Prepare to re-use array */ + iwlen = n; + + if (memAllocGroup ((void **) (void *) + &petab, (size_t) (n * sizeof (Gnum)), + &iwtab, (size_t) (iwlen * sizeof (Gnum)), + &lentab, (size_t) (n * sizeof (Gnum)), + &nvartab, (size_t) (n * sizeof (Gnum)), + &elentab, (size_t) (n * sizeof (Gnum)), + &lasttab, (size_t) (n * sizeof (Gnum)), + &leaftab, (size_t) (n * sizeof (Gnum)), + &frsttab, (size_t) (n * sizeof (Gnum)), + &secntab, (size_t) (n * sizeof (Gnum)), + &nexttab, (size_t) (n * sizeof (Gnum)), + &headtab, (size_t) ((nbbuck + 2) * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hgraphOrderHf: out of memory"); + return (1); + } + + hgraphOrderHxFill (grafptr, petab, lentab, iwtab, elentab, &pfree); + + hallOrderHfR2hamdf4 (n, 0, nbbuck, iwlen, petab, pfree, /* No elements here */ + lentab, iwtab, nvartab, elentab, lasttab, &ncmpa, + leaftab, secntab, nexttab, frsttab, headtab); + if (ncmpa < 0) { + errorPrint ("hgraphOrderHf: internal error"); + memFree (petab); /* Free group leader */ + return (1); + } + + o = hallOrderHxBuild (grafptr->s.baseval, n, grafptr->vnohnbr, + grafptr->s.vnumtax, ordeptr, cblkptr, + nvartab - grafptr->s.baseval, + lentab - grafptr->s.baseval, + petab - grafptr->s.baseval, + frsttab - grafptr->s.baseval, + nexttab - grafptr->s.baseval, + secntab - grafptr->s.baseval, + iwtab - grafptr->s.baseval, + elentab - grafptr->s.baseval, + ordeptr->peritab + ordenum, /* Use given inverse permutation as inverse permutation space, never based */ + leaftab, + paraptr->colmin, paraptr->colmax, (float) paraptr->fillrat); + + memFree (petab); /* Free group leader */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_hf.h b/scotch_6.0.3/src/libscotch/hgraph_order_hf.h new file mode 100644 index 00000000..7024eb3e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_hf.h @@ -0,0 +1,80 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_hf.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the block-oriented Halo **/ +/** Approximate (Multiple) Minimum Fill **/ +/** graph ordering routine. **/ +/** **/ +/** DATES : # Version 3.4 : from : 15 may 2001 **/ +/** to : 15 may 2001 **/ +/** # Version 4.0 : from : 10 jan 2003 **/ +/** to : 24 jan 2004 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 01 oct 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#define HGRAPHORDERHFCOMPRAT 1.2L /*+ Compression ratio +*/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HgraphOrderHfParam_ { + INT colmin; /*+ Minimum number of columns +*/ + INT colmax; /*+ Maximum number of columns +*/ + double fillrat; /*+ Fill-in ratio +*/ +} HgraphOrderHfParam; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_HF +#define static +#endif + +int hgraphOrderHf (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderHfParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_hx.c b/scotch_6.0.3/src/libscotch/hgraph_order_hx.c new file mode 100644 index 00000000..9efdfa2d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_hx.c @@ -0,0 +1,124 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_hx.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains service routines **/ +/** for the hgraphOrderH{d|f} ordering **/ +/** routines. **/ +/** **/ +/** DATES : # Version 4.0 : from : 23 jan 2004 **/ +/** to : 28 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_HX + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "hgraph.h" +#include "hgraph_order_hx.h" + +/***********************************/ +/* */ +/* These are the service routines. */ +/* */ +/***********************************/ + +/* This routine fills the input arrays for +** the graph ordering routines. +** It returns: +** - void : in all cases. +*/ + +void +hgraphOrderHxFill ( +const Hgraph * restrict const grafptr, +Gnum * restrict const petab, +Gnum * restrict const lentab, +Gnum * restrict const iwtab, +Gnum * restrict const elentab, +Gnum * restrict const pfreptr) +{ + Gnum * restrict petax; + Gnum * restrict iwtax; + Gnum * restrict lentax; + Gnum * restrict elentax; + Gnum vertadj; /* Index adjustment for vertices */ + Gnum vertnum; + Gnum vertnew; + Gnum edgenew; + + petax = petab - 1; /* Base HAMF arrays at base 1 */ + iwtax = iwtab - 1; + lentax = lentab - 1; + elentax = elentab - 1; + + vertadj = 1 - grafptr->s.baseval; + for (vertnum = grafptr->s.baseval, vertnew = edgenew = 1; /* Process non-halo vertices */ + vertnum < grafptr->vnohnnd; vertnum ++, vertnew ++) { + Gnum degrval; + Gnum edgenum; + + degrval = grafptr->s.vendtax[vertnum] - grafptr->s.verttax[vertnum]; + petax[vertnew] = edgenew; + lentax[vertnew] = degrval; + elentax[vertnew] = degrval; + + for (edgenum = grafptr->s.verttax[vertnum]; + edgenum < grafptr->s.vendtax[vertnum]; edgenum ++, edgenew ++) + iwtax[edgenew] = grafptr->s.edgetax[edgenum] + vertadj; + } + for ( ; vertnum < grafptr->s.vertnnd; vertnum ++, vertnew ++) { /* Process halo vertices */ + Gnum degrval; + Gnum edgenum; + + degrval = grafptr->s.verttax[vertnum] - grafptr->s.vendtax[vertnum]; + petax[vertnew] = edgenew; + lentax[vertnew] = (degrval != 0) ? degrval : (-1 - grafptr->s.vertnbr); + elentax[vertnew] = 0; + + for (edgenum = grafptr->s.verttax[vertnum]; + edgenum < grafptr->s.vendtax[vertnum]; edgenum ++, edgenew ++) + iwtax[edgenew] = grafptr->s.edgetax[edgenum] + vertadj; + } + + *pfreptr = edgenew; /* Set index to first free area */ +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_hx.h b/scotch_6.0.3/src/libscotch/hgraph_order_hx.h new file mode 100644 index 00000000..c7b4d8a1 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_hx.h @@ -0,0 +1,58 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_hx.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the halo graph block Approxi- **/ +/** mate (Multiple) Minimum Degree and Fill **/ +/** ordering routines. **/ +/** **/ +/** DATES : # Version 4.0 : from : 24 jan 2004 **/ +/** to 24 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_HX +#define static +#endif + +void hgraphOrderHxFill (const Hgraph * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_kp.c b/scotch_6.0.3/src/libscotch/hgraph_order_kp.c new file mode 100644 index 00000000..ede2a3b5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_kp.c @@ -0,0 +1,176 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_kp.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a block ordering **/ +/** from a k-way edge partition. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 oct 2012 **/ +/** to : 17 oct 2012 **/ +/** # Version 6.0 : from : 23 aug 2014 **/ +/** to : 23 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_KP + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_kp.h" +#include "hgraph_order_si.h" +#include "kgraph.h" +#include "kgraph_map_st.h" +#include "scotch.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hgraphOrderKp ( +const Hgraph * restrict const grafptr, +Order * restrict const ordeptr, +const Gnum ordenum, /*+ Zero-based ordering number +*/ +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HgraphOrderKpParam * restrict const paraptr) +{ + Kgraph actgrafdat; + Gnum * restrict ordetab; + Gnum ordeadj; + Anum * restrict parttax; + Gnum partnbr; + Gnum partnum; + Gnum * restrict peritab; + Gnum vertnnd; + Gnum vertnum; + Gnum cblknbr; + + if ((paraptr->partsiz < 1) || /* If nothing to do, order consecutively */ + ((partnbr = grafptr->vnohnbr / paraptr->partsiz) <= 1)) + return (hgraphOrderSi (grafptr, ordeptr, ordenum, cblkptr)); + + if ((cblkptr->cblktab = (OrderCblk *) memAlloc (partnbr * sizeof (OrderCblk))) == NULL) { /* Allocate first as it will remain */ + errorPrint ("hgraphOrderKp: out of memory (1)"); + return (1); + } + + hgraphUnhalo (grafptr, &actgrafdat.s); /* Extract non-halo part of given graph */ + actgrafdat.s.vnumtax = NULL; /* Do not keep numbers from nested dissection */ + + SCOTCH_archCmplt ((SCOTCH_Arch *) &actgrafdat.a, (SCOTCH_Num) partnbr); /* Build complete graph architecture */ + + if ((kgraphInit (&actgrafdat, &actgrafdat.s, &actgrafdat.a, NULL, 0, NULL, NULL, 1, 1, NULL) != 0) || + (kgraphMapSt (&actgrafdat, paraptr->strat) != 0)) { + errorPrint ("hgraphOrderKp: cannot compute partition"); + memFree (cblkptr->cblktab); + cblkptr->cblktab = NULL; + return (1); + } + + if (memAllocGroup ((void **) (void *) + &ordetab, (size_t) (partnbr * sizeof (Gnum)), + &parttax, (size_t) (grafptr->vnohnbr * sizeof (Anum)), NULL) == NULL) { + errorPrint ("hgraphOrderKp: out of memory (2)"); + memFree (cblkptr->cblktab); + cblkptr->cblktab = NULL; + return (1); + } + parttax -= actgrafdat.s.baseval; + + mapTerm (&actgrafdat.m, parttax); /* Get result of partitioning as terminal part array */ + + memSet (ordetab, 0, partnbr * sizeof (Gnum)); /* Reset part count array */ + for (vertnum = actgrafdat.s.baseval, vertnnd = actgrafdat.s.vertnnd; + vertnum < vertnnd; vertnum ++) { + ordetab[parttax[vertnum]] ++; /* Count number of vertices in each part */ + } + + for (partnum = 0, cblknbr = 0, ordeadj = ordenum; /* For all potential column blocks */ + partnum < partnbr; partnum ++) { + Gnum ordetmp; + + ordetmp = ordetab[partnum]; + ordetab[partnum] = ordeadj; + ordeadj += ordetmp; + if (ordetmp != 0) { /* If part is not empty, one more column block */ + cblkptr->cblktab[cblknbr].typeval = ORDERCBLKOTHR; + cblkptr->cblktab[cblknbr].vnodnbr = ordetmp; + cblkptr->cblktab[cblknbr].cblknbr = 0; + cblkptr->cblktab[cblknbr].cblktab = NULL; + cblknbr ++; + } + } + + ordeptr->treenbr += cblknbr; /* These more number of tree nodes */ + ordeptr->cblknbr += cblknbr - 1; /* These more number of column blocks */ + cblkptr->cblknbr = cblknbr; + + peritab = ordeptr->peritab; + if (grafptr->s.vnumtax == NULL) { /* If graph is original graph */ + for (vertnum = actgrafdat.s.baseval; vertnum < vertnnd; vertnum ++) + peritab[ordetab[parttax[vertnum]] ++] = vertnum; + } + else { /* Graph is not original graph */ + const Gnum * restrict vnumtax; + + vnumtax = grafptr->s.vnumtax; + for (vertnum = actgrafdat.s.baseval; vertnum < vertnnd; vertnum ++) + peritab[ordetab[parttax[vertnum]] ++] = vnumtax[vertnum]; + } + + memFree (ordetab); /* Free group leader */ + kgraphExit (&actgrafdat); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_kp.h b/scotch_6.0.3/src/libscotch/hgraph_order_kp.h new file mode 100644 index 00000000..a1a28779 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_kp.h @@ -0,0 +1,68 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_kp.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the k-way partitioning block **/ +/** ordering module. **/ +/** **/ +/** DATES : # Version 6.0 : from : 17 oct 2012 **/ +/** to 17 oct 2012 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HgraphOrderKpParam_ { + INT partsiz; /*+ Minimum part size +*/ + Strat * strat; /*+ k-way partitioning strategy used +*/ +} HgraphOrderKpParam; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_KP +#define static +#endif + +int hgraphOrderKp (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderKpParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_nd.c b/scotch_6.0.3/src/libscotch/hgraph_order_nd.c new file mode 100644 index 00000000..0a37b206 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_nd.c @@ -0,0 +1,248 @@ +/* Copyright 2004,2007,2010,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_nd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders graphs using the **/ +/** nested dissection algorithm. **/ +/** **/ +/** DATES : # Version 3.2 : from : 17 oct 1996 **/ +/** to : 21 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 13 mar 1999 **/ +/** # Version 4.0 : from : 03 jan 2002 **/ +/** to 24 dec 2004 **/ +/** # Version 5.0 : from : 19 dec 2006 **/ +/** to 25 jul 2007 **/ +/** # Version 5.1 : from : 24 oct 2010 **/ +/** to 24 oct 2010 **/ +/** # Version 6.0 : from : 17 oct 2012 **/ +/** to 05 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_ND + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_nd.h" +#include "hgraph_order_st.h" +#include "vgraph.h" +#include "vgraph_separate_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hgraphOrderNd ( +const Hgraph * restrict const grafptr, +Order * restrict const ordeptr, +const Gnum ordenum, +OrderCblk * restrict const cblkptr, +const HgraphOrderNdParam * restrict const paraptr) +{ + Hgraph indgrafdat; /* Halo graph data */ + Gnum * vspvnumptr[3]; /* Pointers to vertex lists to fill */ + VertList vsplisttab[3]; /* Array of separated part lists */ + Vgraph vspgrafdat; /* Vertex separation graph data */ + Gnum vspvertnum; /* Current vertex in separation graph */ + int o; + + hgraphUnhalo (grafptr, &vspgrafdat.s); /* Keep only non-halo vertices for separation */ + + if ((vspgrafdat.frontab = (Gnum *) memAlloc (vspgrafdat.s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("hgraphOrderNd: out of memory (1)"); + return (1); + } + if ((vspgrafdat.parttax = (GraphPart *) memAlloc (vspgrafdat.s.vertnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("hgraphOrderNd: out of memory (2)"); + memFree (vspgrafdat.frontab); + return (1); + } + memSet (vspgrafdat.parttax, 0, vspgrafdat.s.vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ + vspgrafdat.parttax -= vspgrafdat.s.baseval; + vspgrafdat.fronnbr = 0; + vspgrafdat.compload[0] = vspgrafdat.s.velosum; + vspgrafdat.compload[1] = 0; + vspgrafdat.compload[2] = 0; + vspgrafdat.comploaddlt = vspgrafdat.s.velosum; + vspgrafdat.compsize[0] = vspgrafdat.s.vertnbr; + vspgrafdat.compsize[1] = 0; + vspgrafdat.fronnbr = 0; + vspgrafdat.levlnum = grafptr->levlnum; /* Set level of separation graph as level of halo graph */ + + if (vgraphSeparateSt (&vspgrafdat, paraptr->sepstrat) != 0) { /* Separate vertex-separation graph */ + vgraphExit (&vspgrafdat); + return (1); + } + + if ((vspgrafdat.compsize[0] == 0) || /* If could not separate more */ + (vspgrafdat.compsize[1] == 0)) { + vgraphExit (&vspgrafdat); /* Free useless space */ + hgraphOrderSt (grafptr, ordeptr, ordenum, cblkptr, paraptr->ordstratlea); /* Order this leaf */ + return (0); /* Leaf has been processed */ + } + + vsplisttab[0].vnumnbr = vspgrafdat.compsize[0]; /* Build vertex lists within frontier array */ + vsplisttab[0].vnumtab = vspgrafdat.frontab + vspgrafdat.fronnbr; + vsplisttab[1].vnumnbr = vspgrafdat.compsize[1]; + vsplisttab[1].vnumtab = vsplisttab[0].vnumtab + vsplisttab[0].vnumnbr; + vsplisttab[2].vnumnbr = vspgrafdat.fronnbr; + vsplisttab[2].vnumtab = vspgrafdat.frontab; + vspvnumptr[0] = vsplisttab[0].vnumtab; + vspvnumptr[1] = vsplisttab[1].vnumtab; + vspvnumptr[2] = vsplisttab[2].vnumtab; + for (vspvertnum = vspgrafdat.s.baseval; vspvertnum < vspgrafdat.s.vertnnd; vspvertnum ++) { /* Fill lists */ + *vspvnumptr[vspgrafdat.parttax[vspvertnum]] ++ = vspvertnum; +#ifdef SCOTCH_DEBUG_HGRAPH2 + if (vspgrafdat.parttax[vspvertnum] != 2) { /* If vertex does not separate */ + Gnum vspedgenum; + GraphPart vsppartnum; + + vsppartnum = 1 - vspgrafdat.parttax[vspvertnum]; /* Get opposite part value */ + for (vspedgenum = vspgrafdat.s.verttax[vspvertnum]; + vspedgenum < vspgrafdat.s.vendtax[vspvertnum]; vspedgenum ++) { + if (vspgrafdat.parttax[vspgrafdat.s.edgetax[vspedgenum]] == vsppartnum) { /* If an edge crosses the separator */ + errorPrint ("hgraphOrderNd: internal error (1)"); + vgraphExit (&vspgrafdat); + return (1); + } + } + } +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + } +#ifdef SCOTCH_DEBUG_HGRAPH2 + if ((vspvnumptr[0] != vsplisttab[0].vnumtab + vsplisttab[0].vnumnbr) || + (vspvnumptr[1] != vsplisttab[1].vnumtab + vsplisttab[1].vnumnbr) || + (vspvnumptr[2] != vsplisttab[2].vnumtab + vsplisttab[2].vnumnbr)) { + errorPrint ("hgraphOrderNd: internal error (2)"); + vgraphExit (&vspgrafdat); + return (1); + } +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + + memFree (vspgrafdat.parttax + vspgrafdat.s.baseval); /* Free useless space */ +#ifdef SCOTCH_DEBUG_HGRAPH2 + vspgrafdat.parttax = NULL; /* Will cause bug if re-read */ +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + + cblkptr->typeval = ORDERCBLKNEDI; /* Node becomes a nested dissection node */ + if ((cblkptr->cblktab = (OrderCblk *) memAlloc (3 * sizeof (OrderCblk))) == NULL) { + errorPrint ("hgraphOrderNd: out of memory (2)"); + memFree (vspgrafdat.frontab); /* Free remaining space */ + return (1); + } + cblkptr->cblktab[0].typeval = ORDERCBLKOTHR; /* Build column blocks */ + cblkptr->cblktab[0].vnodnbr = vsplisttab[0].vnumnbr; + cblkptr->cblktab[0].cblknbr = 0; + cblkptr->cblktab[0].cblktab = NULL; + cblkptr->cblktab[1].typeval = ORDERCBLKOTHR; + cblkptr->cblktab[1].vnodnbr = vsplisttab[1].vnumnbr; + cblkptr->cblktab[1].cblknbr = 0; + cblkptr->cblktab[1].cblktab = NULL; + + if (vsplisttab[2].vnumnbr != 0) { /* If separator not empty */ + cblkptr->cblknbr = 3; /* It is a three-cell tree node */ + ordeptr->cblknbr += 2; /* Two more column blocks created */ + ordeptr->treenbr += 3; /* Three more tree nodes created */ + + cblkptr->cblktab[2].typeval = ORDERCBLKOTHR; + cblkptr->cblktab[2].vnodnbr = vsplisttab[2].vnumnbr; + cblkptr->cblktab[2].cblknbr = 0; + cblkptr->cblktab[2].cblktab = NULL; + + if (graphInduceList (&grafptr->s, &vsplisttab[2], &indgrafdat.s) != 0) { /* Perform non-halo induction for separator, as it will get highest numbers */ + errorPrint ("hgraphOrderNd: cannot build induced subgraph (1)"); + memFree (vspgrafdat.frontab); /* Free remaining space */ + return (1); + } + indgrafdat.vnohnbr = indgrafdat.s.vertnbr; /* Fill halo graph structure of non-halo graph */ + indgrafdat.vnohnnd = indgrafdat.s.vertnnd; + indgrafdat.vnhdtax = indgrafdat.s.vendtax; + indgrafdat.vnlosum = indgrafdat.s.velosum; + indgrafdat.enohnbr = indgrafdat.s.edgenbr; + indgrafdat.enohsum = indgrafdat.s.edlosum; + indgrafdat.levlnum = grafptr->levlnum; /* Separator graph is at level of original graph */ + + o = hgraphOrderSt (&indgrafdat, ordeptr, ordenum + vsplisttab[0].vnumnbr + vsplisttab[1].vnumnbr, + cblkptr->cblktab + 2, paraptr->ordstratsep); + hgraphExit (&indgrafdat); + } + else { /* Separator is empty */ + cblkptr->cblknbr = 2; /* It is a two-cell tree node */ + ordeptr->cblknbr ++; /* One more column block created */ + ordeptr->treenbr += 2; /* Two more tree nodes created */ + o = 0; /* No separator ordering computed */ + } + if (o == 0) { + if ((hgraphInduceList (grafptr, &vsplisttab[0], vsplisttab[2].vnumnbr + grafptr->s.vertnbr - grafptr->vnohnbr, &indgrafdat)) != 0) { + errorPrint ("hgraphOrderNd: cannot build induced subgraph (2)"); + memFree (vspgrafdat.frontab); /* Free remaining space */ + return (1); + } + o = hgraphOrderNd (&indgrafdat, ordeptr, ordenum, cblkptr->cblktab, paraptr); + hgraphExit (&indgrafdat); + } + if (o == 0) { + if ((hgraphInduceList (grafptr, &vsplisttab[1], vsplisttab[2].vnumnbr + grafptr->s.vertnbr - grafptr->vnohnbr, &indgrafdat)) != 0) { + errorPrint ("hgraphOrderNd: cannot build induced subgraph (3)"); + memFree (vspgrafdat.frontab); /* Free remaining space */ + return (1); + } + o = hgraphOrderNd (&indgrafdat, ordeptr, ordenum + vsplisttab[0].vnumnbr, cblkptr->cblktab + 1, paraptr); + hgraphExit (&indgrafdat); + } + + memFree (vspgrafdat.frontab); /* Free remaining space */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_nd.h b/scotch_6.0.3/src/libscotch/hgraph_order_nd.h new file mode 100644 index 00000000..b0442b32 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_nd.h @@ -0,0 +1,75 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_nd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the halo graph nested dissection **/ +/** ordering algorithm. **/ +/** **/ +/** DATES : # Version 3.2 : from : 17 oct 1996 **/ +/** to : 18 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 13 mar 1999 **/ +/** # Version 4.0 : from : 03 jan 2002 **/ +/** to 24 apr 2004 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HgraphOrderNdParam_ { + Strat * sepstrat; /*+ Separation strategy +*/ + Strat * ordstratlea; /*+ Leaf ordering strategy +*/ + Strat * ordstratsep; /*+ Separator ordering strategy +*/ +} HgraphOrderNdParam; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_ND +#define static +#endif + +int hgraphOrderNd (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderNdParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_si.c b/scotch_6.0.3/src/libscotch/hgraph_order_si.c new file mode 100644 index 00000000..3ca87365 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_si.c @@ -0,0 +1,104 @@ +/* Copyright 2004,2007,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_si.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders halo graph vertices **/ +/** using a simple method. **/ +/** **/ +/** DATES : # Version 3.2 : from : 01 nov 1996 **/ +/** to 21 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 02 oct 1998 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 11 dec 2002 **/ +/** # Version 6.0 : from : 17 oct 2012 **/ +/** to : 04 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_SI + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_si.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hgraphOrderSi ( +const Hgraph * restrict const grafptr, +Order * restrict const ordeptr, +const Gnum ordenum, /*+ Zero-based ordering number +*/ +OrderCblk * restrict const cblkptr) /*+ Single column-block +*/ +{ + Gnum vnohnnd; + Gnum vertnum; + Gnum vnumnum; + + Gnum * restrict const peritab = ordeptr->peritab; + const Gnum * restrict const vnumtax = grafptr->s.vnumtax; + + vnohnnd = grafptr->vnohnnd; + if (vnumtax == NULL) { /* If graph is original graph */ + for (vertnum = grafptr->s.baseval, vnumnum = ordenum; + vertnum < vnohnnd; vertnum ++, vnumnum ++) + peritab[vnumnum] = vertnum; + } + else { /* Graph is not original graph */ + for (vertnum = grafptr->s.baseval, vnumnum = ordenum; + vertnum < vnohnnd; vertnum ++, vnumnum ++) + peritab[vnumnum] = vnumtax[vertnum]; + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_si.h b/scotch_6.0.3/src/libscotch/hgraph_order_si.h new file mode 100644 index 00000000..bc1b62c3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_si.h @@ -0,0 +1,61 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_si.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the simple halo graph **/ +/** ordering routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 01 nov 1996 **/ +/** to : 18 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 02 oct 1998 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 11 dec 2002 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_SI +#define static +#endif + +int hgraphOrderSi (const Hgraph * const, Order * const, const Gnum, OrderCblk * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_st.c b/scotch_6.0.3/src/libscotch/hgraph_order_st.c new file mode 100644 index 00000000..00e1dfe1 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_st.c @@ -0,0 +1,307 @@ +/* Copyright 2004,2007,2008,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_st.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the generic call to the **/ +/** graph ordering module, using a given **/ +/** strategy. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 oct 1996 **/ +/** to 09 sep 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 07 sep 2001 **/ +/** # Version 4.0 : from : 27 dec 2001 **/ +/** to 05 jan 2005 **/ +/** # Version 5.0 : from : 31 may 2008 **/ +/** to 31 may 2008 **/ +/** # Version 6.0 : from : 17 oct 2012 **/ +/** to 17 oct 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HGRAPH_ORDER_ST + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_bl.h" +#include "hgraph_order_cp.h" +#include "hgraph_order_gp.h" +#include "hgraph_order_hd.h" +#include "hgraph_order_hf.h" +#include "hgraph_order_kp.h" +#include "hgraph_order_nd.h" +#include "hgraph_order_si.h" +#include "hgraph_order_st.h" +#include "kgraph.h" +#include "kgraph_map_st.h" +#include "vgraph.h" +#include "vgraph_separate_st.h" + +/* +** The static and global variables. +*/ + +static Hgraph hgraphorderstgraphdummy; /* Dummy graph for offset computations */ + +static union { /* Default parameters for block splitting method */ + HgraphOrderBlParam param; /* Parameter zone */ + StratNodeMethodData padding; /* To avoid reading out of structure */ +} hgraphorderstdefaultbl = { { &stratdummy, 8 } }; + +static union { + HgraphOrderCpParam param; + StratNodeMethodData padding; +} hgraphorderstdefaultcp = { { 0.70L, &stratdummy, &stratdummy } }; + +static union { + HgraphOrderGpParam param; + StratNodeMethodData padding; +} hgraphorderstdefaultgp = { { 3 } }; + +static union { + HgraphOrderHdParam param; + StratNodeMethodData padding; +} hgraphorderstdefaulthd = { { 1, 10000, 0.08L } }; + +static union { + HgraphOrderHfParam param; + StratNodeMethodData padding; +} hgraphorderstdefaulthf = { { 1, 1000000, 0.08L } }; + +static union { + HgraphOrderKpParam param; + StratNodeMethodData padding; +} hgraphorderstdefaultkp = { { 1, &stratdummy } }; + +static union { /* Default parameters for nested dissection method */ + HgraphOrderNdParam param; + StratNodeMethodData padding; +} hgraphorderstdefaultnd = { { &stratdummy, &stratdummy, &stratdummy } }; + +static StratMethodTab hgraphorderstmethtab[] = { /* Graph ordering methods array */ + { HGRAPHORDERSTMETHBL, "b", hgraphOrderBl, &hgraphorderstdefaultbl }, + { HGRAPHORDERSTMETHCP, "c", hgraphOrderCp, &hgraphorderstdefaultcp }, + { HGRAPHORDERSTMETHGP, "g", hgraphOrderGp, &hgraphorderstdefaultgp }, + { HGRAPHORDERSTMETHHD, "d", hgraphOrderHd, &hgraphorderstdefaulthd }, + { HGRAPHORDERSTMETHHF, "f", hgraphOrderHf, &hgraphorderstdefaulthf }, + { HGRAPHORDERSTMETHKP, "k", hgraphOrderKp, &hgraphorderstdefaultkp }, + { HGRAPHORDERSTMETHND, "n", hgraphOrderNd, &hgraphorderstdefaultnd }, + { HGRAPHORDERSTMETHSI, "s", hgraphOrderSi, NULL }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab hgraphorderstparatab[] = { /* The method parameter list */ + { HGRAPHORDERSTMETHBL, STRATPARAMSTRAT, "strat", + (byte *) &hgraphorderstdefaultbl.param, + (byte *) &hgraphorderstdefaultbl.param.strat, + (void *) &hgraphorderststratab }, + { HGRAPHORDERSTMETHBL, STRATPARAMINT, "cmin", + (byte *) &hgraphorderstdefaultbl.param, + (byte *) &hgraphorderstdefaultbl.param.cblkmin, + NULL }, + { HGRAPHORDERSTMETHCP, STRATPARAMDOUBLE, "rat", + (byte *) &hgraphorderstdefaultcp.param, + (byte *) &hgraphorderstdefaultcp.param.comprat, + NULL }, + { HGRAPHORDERSTMETHCP, STRATPARAMSTRAT, "cpr", + (byte *) &hgraphorderstdefaultcp.param, + (byte *) &hgraphorderstdefaultcp.param.stratcpr, + (void *) &hgraphorderststratab }, + { HGRAPHORDERSTMETHCP, STRATPARAMSTRAT, "unc", + (byte *) &hgraphorderstdefaultcp.param, + (byte *) &hgraphorderstdefaultcp.param.stratunc, + (void *) &hgraphorderststratab }, + { HGRAPHORDERSTMETHGP, STRATPARAMINT, "pass", + (byte *) &hgraphorderstdefaultgp.param, + (byte *) &hgraphorderstdefaultgp.param.passnbr, + NULL }, + { HGRAPHORDERSTMETHHD, STRATPARAMINT, "cmin", + (byte *) &hgraphorderstdefaulthd.param, + (byte *) &hgraphorderstdefaulthd.param.colmin, + NULL }, + { HGRAPHORDERSTMETHHD, STRATPARAMINT, "cmax", + (byte *) &hgraphorderstdefaulthd.param, + (byte *) &hgraphorderstdefaulthd.param.colmax, + NULL }, + { HGRAPHORDERSTMETHHD, STRATPARAMDOUBLE, "frat", + (byte *) &hgraphorderstdefaulthd.param, + (byte *) &hgraphorderstdefaulthd.param.fillrat, + NULL }, + { HGRAPHORDERSTMETHHF, STRATPARAMINT, "cmin", + (byte *) &hgraphorderstdefaulthf.param, + (byte *) &hgraphorderstdefaulthf.param.colmin, + NULL }, + { HGRAPHORDERSTMETHHF, STRATPARAMINT, "cmax", + (byte *) &hgraphorderstdefaulthf.param, + (byte *) &hgraphorderstdefaulthf.param.colmax, + NULL }, + { HGRAPHORDERSTMETHHF, STRATPARAMDOUBLE, "frat", + (byte *) &hgraphorderstdefaulthf.param, + (byte *) &hgraphorderstdefaulthf.param.fillrat, + NULL }, + { HGRAPHORDERSTMETHKP, STRATPARAMINT, "siz", + (byte *) &hgraphorderstdefaultkp.param, + (byte *) &hgraphorderstdefaultkp.param.partsiz, + NULL }, + { HGRAPHORDERSTMETHKP, STRATPARAMSTRAT, "strat", + (byte *) &hgraphorderstdefaultkp.param, + (byte *) &hgraphorderstdefaultkp.param.strat, + (void *) &kgraphmapststratab }, + { HGRAPHORDERSTMETHND, STRATPARAMSTRAT, "sep", + (byte *) &hgraphorderstdefaultnd.param, + (byte *) &hgraphorderstdefaultnd.param.sepstrat, + (void *) &vgraphseparateststratab }, + { HGRAPHORDERSTMETHND, STRATPARAMSTRAT, "ole", + (byte *) &hgraphorderstdefaultnd.param, + (byte *) &hgraphorderstdefaultnd.param.ordstratlea, + (void *) &hgraphorderststratab }, + { HGRAPHORDERSTMETHND, STRATPARAMSTRAT, "ose", + (byte *) &hgraphorderstdefaultnd.param, + (byte *) &hgraphorderstdefaultnd.param.ordstratsep, + (void *) &hgraphorderststratab }, + { HGRAPHORDERSTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab hgraphorderstcondtab[] = { /* Graph condition parameter table */ + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &hgraphorderstgraphdummy, + (byte *) &hgraphorderstgraphdummy.s.edgenbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &hgraphorderstgraphdummy, + (byte *) &hgraphorderstgraphdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &hgraphorderstgraphdummy, + (byte *) &hgraphorderstgraphdummy.vnlosum, + NULL }, + { STRATNODECOND, STRATPARAMDOUBLE, "mdeg", + (byte *) &hgraphorderstgraphdummy, + (byte *) &hgraphorderstgraphdummy.s.degrmax, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vert", + (byte *) &hgraphorderstgraphdummy, + (byte *) &hgraphorderstgraphdummy.vnohnbr, /* Only consider non-halo vertices */ + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab hgraphorderststratab = { /* Strategy tables for graph ordering methods */ + hgraphorderstmethtab, + hgraphorderstparatab, + hgraphorderstcondtab }; + +/************************************/ +/* */ +/* This routine is the entry point */ +/* for the graph ordering routines. */ +/* */ +/************************************/ + +/* This routine computes an ordering +** with respect to a given strategy. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +hgraphOrderSt ( +const Hgraph * restrict const grafptr, /*+ Subgraph to order +*/ +Order * restrict const ordeptr, /*+ Ordering to complete +*/ +const Gnum ordenum, /*+ Index to start ordering at +*/ +OrderCblk * restrict const cblkptr, /*+ Current column block +*/ +const Strat * restrict const strat) /*+ Graph ordering strategy +*/ +{ + StratTest val; + int o; + + if (grafptr->vnohnbr == 0) /* Return immediately if nothing to do */ + return (0); + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + errorPrint ("hgraphOrderSt: concatenation operator not available for graph ordering strategies"); + return (1); + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_HGRAPH2 + if ((val.typetest != STRATTESTVAL) && + (val.typenode != STRATPARAMLOG)) { + errorPrint ("hgraphOrderSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = hgraphOrderSt (grafptr, ordeptr, ordenum, cblkptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = hgraphOrderSt (grafptr, ordeptr, ordenum, cblkptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + hgraphOrderSi (grafptr, ordeptr, ordenum, cblkptr); /* Always maintain a consistent ordering */ + break; + case STRATNODESELECT : + errorPrint ("hgraphOrderSt: selection operator not available for graph ordering strategies"); + return (1); +#ifdef SCOTCH_DEBUG_HGRAPH2 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_HGRAPH2 */ + default : +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, ordeptr, ordenum, cblkptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_HGRAPH2 + default : + errorPrint ("hgraphOrderSt: invalid parameter"); + return (1); +#endif /* SCOTCH_DEBUG_HGRAPH2 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hgraph_order_st.h b/scotch_6.0.3/src/libscotch/hgraph_order_st.h new file mode 100644 index 00000000..8b252ab1 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hgraph_order_st.h @@ -0,0 +1,87 @@ +/* Copyright 2004,2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hgraph_order_st.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data **/ +/** declarations for the main graph **/ +/** ordering routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 31 oct 1996 **/ +/** to : 29 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 07 sep 2001 **/ +/** # Version 4.0 : from : 29 dec 2001 **/ +/** to : 15 jan 2003 **/ +/** # Version 6.0 : from : 17 oct 2012 **/ +/** to : 17 oct 2012 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum HgraphOrderStMethodType_ { + HGRAPHORDERSTMETHBL = 0, /*+ Block splitting post-processing +*/ + HGRAPHORDERSTMETHCP, /*+ Graph compression +*/ + HGRAPHORDERSTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ + HGRAPHORDERSTMETHHD, /*+ Block Halo Approximate Minimum Degree +*/ + HGRAPHORDERSTMETHHF, /*+ Block Halo Approximate Minimum Fill +*/ + HGRAPHORDERSTMETHKP, /*+ K-way block partitioning +*/ + HGRAPHORDERSTMETHND, /*+ Nested Dissection +*/ + HGRAPHORDERSTMETHSI, /*+ Simple +*/ + HGRAPHORDERSTMETHNBR /*+ Number of methods +*/ +} HgraphOrderStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab hgraphorderststratab; + +/* +** The function prototypes. +*/ + +#ifndef HGRAPH_ORDER_ST +#define static +#endif + +int hgraphOrderSt (const Hgraph * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const Strat * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh.c b/scotch_6.0.3/src/libscotch/hmesh.c new file mode 100644 index 00000000..a749580e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh.c @@ -0,0 +1,115 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the halo source **/ +/** mesh functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 12 sep 2002 **/ +/** to 10 feb 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "hmesh.h" + +/****************************************/ +/* */ +/* These routines handle source meshes. */ +/* */ +/****************************************/ + +/* This routine frees a source halo mesh structure. +** It returns: +** - VOID : in all cases. +*/ + +void +hmeshExit ( +Hmesh * const meshptr) +{ + if ((meshptr->vehdtax != NULL) && /* Exit halo mesh data */ + (meshptr->vehdtax != (meshptr->m.vendtax + (meshptr->m.baseval - meshptr->m.velmbas))) && + ((meshptr->m.flagval & MESHVERTGROUP) == 0)) + memFree (meshptr->vehdtax + meshptr->m.velmbas); + meshExit (&meshptr->m); /* Exit mesh data */ + +#ifdef SCOTCH_DEBUG_HMESH2 + memSet (meshptr, ~0, sizeof (Hmesh)); /* Purge halo mesh fields */ +#endif /* SCOTCH_DEBUG_HMESH2 */ +} + +/* This routine sets the base of the given +** halo mesh to the given base value, and +** returns the old base value. +** It returns: +** - old base value : in all cases. +*/ + +Gnum +hmeshBase ( +Hmesh * const meshptr, +const Gnum baseval) +{ + Gnum baseold; /* Old base value */ + Gnum baseadj; /* Base adjustment */ + Gnum velmnum; + + if (meshptr->m.baseval == baseval) /* If nothing to do */ + return (baseval); + + baseold = meshptr->m.baseval; /* Record old base value */ + baseadj = baseval - baseold; /* Compute adjustment */ + + meshBase (&meshptr->m, baseval); /* Change base of mesh */ + + for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++) + meshptr->vehdtax[velmnum] += baseadj; /* Change base of array */ + + meshptr->vnohnnd += baseadj; + meshptr->vehdtax -= baseadj; + + return (baseold); /* Return old base value */ +} diff --git a/scotch_6.0.3/src/libscotch/hmesh.h b/scotch_6.0.3/src/libscotch/hmesh.h new file mode 100644 index 00000000..8f5081ca --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh.h @@ -0,0 +1,108 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data **/ +/** declarations for the halo mesh **/ +/** structure. **/ +/** **/ +/** DATES : # Version 4.0 : from : 31 dec 2001 **/ +/** to 29 apr 2004 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Halo mesh structure. Only node vertices + can be halo vertices, not element vertices. + Halo node vertices are numbered with the + highest available node numbers. + Since un-haloing of a mesh should be costless, + and since the vertex array must be continuous, + when a halo mesh indeed bears halo nodes, it is + preferrable that elements be numbered first, then + non-halo node vertices, then halo vertices, so + that the removal of the halo does not create + holes in the vertex array. Else, the indices of + the halo nodes must be reassigned to empty elements, + which results in a larger structure until it is + coarsened or induced. If no halo is present, the + order of nodes and elements is not relevant. + As for the halo graph structure, in the + adjacency list of elements, halo node neighbors + must all be put after non-halo node neighbors, + so that the edge sub-array comprised between + verttab[i] and vnhdtab[i] refer only to non-halo + node neighbors, such that edgetab can be re-used + by the un-halo-ed mesh. + Since Hmesh halo meshes are used only for node + ordering, the velotab and vnumtab arrays that are + created by hmesh*() routines can be restricted to + their node part. It must be guaranteed that this + does not create problems at freeing time, for + instance by grouping these arrays with verttab. +*/ + +typedef struct Hmesh_ { + Mesh m; /*+ Source mesh +*/ + Gnum * restrict vehdtax; /*+ End vertex array for elements [based] (non-halo nodes look at m.vendtax) +*/ + Gnum veihnbr; /*+ Number of halo isolated element vertices, which have halo nodes only +*/ + Gnum vnohnbr; /*+ Number of non-halo node vertices +*/ + Gnum vnohnnd; /*+ Based number of first halo node vertex in mesh graph (m.vnodnnd if none) +*/ + Gnum vnhlsum; /*+ Sum of non-halo node vertex weights +*/ + Gnum enohnbr; /*+ Number of non-halo edges +*/ + Gnum levlnum; /*+ Nested dissection level +*/ +} Hmesh; + +/* +** The function prototypes. +*/ + +#ifndef HMESH +#define static +#endif + +void hmeshExit (Hmesh * const); +Gnum hmeshBase (Hmesh * const, const Gnum); +#ifdef HGRAPH_H +int hmeshHgraph (const Hmesh * restrict const, Hgraph * restrict const); +#endif /* HGRAPH_H */ +int hmeshInducePart (const Hmesh * const, const GraphPart * const, const GraphPart, const Gnum, const Gnum, const Gnum, Hmesh * const); +int hmeshMesh (const Hmesh * restrict const, Mesh * restrict const); +int hmeshCheck (const Hmesh *); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_check.c b/scotch_6.0.3/src/libscotch/hmesh_check.c new file mode 100644 index 00000000..fc4679fa --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_check.c @@ -0,0 +1,129 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the halo source **/ +/** mesh functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 12 sep 2002 **/ +/** to 11 may 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "hmesh.h" + +/****************************************/ +/* */ +/* These routines handle source meshes. */ +/* */ +/****************************************/ + +/* This routine checks the consistency +** of the given halo mesh. +** It returns: +** - 0 : if halo mesh data are consistent. +** - !0 : on error. +*/ + +int +hmeshCheck ( +const Hmesh * const meshptr) +{ + Gnum vnhlsum; + + if ((meshptr->vnohnnd < meshptr->m.vnodbas) || + (meshptr->vnohnnd > meshptr->m.vnodnnd)) { + errorPrint ("hmeshCheck: invalid halo node numbers"); + return (1); + } + + if (meshCheck (&meshptr->m) != 0) { + errorPrint ("hmeshCheck: invalid non-halo mesh structure"); + return (1); + } + + if (meshptr->vehdtax != meshptr->m.vendtax) { + Gnum veihnbr; + Gnum velmnum; + + for (velmnum = meshptr->m.velmbas, veihnbr = 0; /* For all element vertices */ + velmnum < meshptr->m.velmnnd; velmnum ++) { + if ((meshptr->vehdtax[velmnum] < meshptr->m.verttax[velmnum]) || + (meshptr->vehdtax[velmnum] > meshptr->m.vendtax[velmnum])) { + errorPrint ("hmeshCheck: invalid non-halo end vertex array"); + return (1); + } + if (meshptr->vehdtax[velmnum] == meshptr->m.verttax[velmnum]) + veihnbr ++; + } + if (veihnbr != meshptr->veihnbr) { + errorPrint ("hmeshCheck: invalid number of halo-isolated element vertices (1)"); + return (1); + } + } + else { + if (meshptr->veihnbr != 0) { + errorPrint ("hmeshCheck: invalid number of halo-isolated element vertices (2)"); + return (1); + } + } + + if (meshptr->m.vnlotax == NULL) /* Recompute non-halo node vertex load sum */ + vnhlsum = meshptr->vnohnnd - meshptr->m.vnodbas; + else { + Gnum vnodnum; + + for (vnodnum = meshptr->m.vnodbas, vnhlsum = 0; + vnodnum < meshptr->vnohnnd; vnodnum ++) + vnhlsum += meshptr->m.vnlotax[vnodnum]; + } + if (vnhlsum != meshptr->vnhlsum) { + errorPrint ("hmeshCheck: invalid non-halo vertex load sum"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_hgraph.c b/scotch_6.0.3/src/libscotch/hmesh_hgraph.c new file mode 100644 index 00000000..5a1c22af --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_hgraph.c @@ -0,0 +1,318 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_hgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the source halo **/ +/** mesh to halo graph conversion function. **/ +/** **/ +/** DATES : # Version 4.0 : from : 30 nov 2003 **/ +/** to 05 may 2004 **/ +/** # Version 5.0 : from : 10 sep 2007 **/ +/** to : 10 sep 2007 **/ +/** **/ +/** NOTES : # From a given halo mesh is created a **/ +/** halo graph, such that all vertices of **/ +/** the graph represent the nodes of the **/ +/** mesh, and there exists an edge **/ +/** between two vertices if there exists **/ +/** at least one element to which the two **/ +/** associated nodes belong. **/ +/** While all non-halo nodes become non- **/ +/** halo vertices, some halo nodes may **/ +/** disappear from the graph if their **/ +/** elements are only connected to other **/ +/** halo nodes. **/ +/** Since the contents of vnumtab are **/ +/** based with respect to s.baseval and **/ +/** not to vnodbas, the vnumtab array can **/ +/** simply be shared by the graph. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_HGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "hgraph.h" +#include "mesh.h" +#include "hmesh.h" +#include "hmesh_hgraph.h" + +/************************************/ +/* */ +/* The halo graph building routine. */ +/* */ +/************************************/ + +/* This routine builds a halo graph from +** the given halo mesh. +** It returns: +** - 0 : if the halo graph has been successfully built. +** - 1 : on error. +*/ + +int +hmeshHgraph ( +const Hmesh * restrict const meshptr, /*+ Original mesh +*/ +Hgraph * restrict const grafptr) /*+ Graph to build +*/ +{ + Gnum hashnbr; /* Number of vertices in hash table */ + Gnum hashsiz; /* Size of hash table */ + Gnum hashmsk; /* Mask for access to hash table */ + HmeshHgraphHash * restrict hashtab; /* Table of edges to other node vertices */ + Gnum edgemax; /* Upper bound of number of edges in mesh */ + Gnum edgennd; /* Based upper bound on number of edges */ + Gnum enohnbr; /* Number of non-halo edges */ + Gnum edgenum; /* Number of current graph edge */ + Gnum vertnum; /* Number of current graph vertex */ + Gnum degrmax; + +#ifdef SCOTCH_DEBUG_HMESH2 + if (hmeshCheck (meshptr) != 0) { + errorPrint ("hmeshHgraph: invalid input halo mesh"); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + + grafptr->s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; + grafptr->s.baseval = meshptr->m.baseval; + grafptr->s.vertnbr = meshptr->m.vnodnbr; + grafptr->s.vertnnd = meshptr->m.vnodnbr + meshptr->m.baseval; + grafptr->vnohnbr = meshptr->vnohnbr; + grafptr->vnohnnd = meshptr->vnohnbr + grafptr->s.baseval; + grafptr->vnlosum = meshptr->vnhlsum; + + for (hashsiz = 2, hashnbr = meshptr->m.degrmax * meshptr->m.degrmax * 2; /* Compute size of hash table */ + hashsiz < hashnbr; hashsiz <<= 1) ; + hashmsk = hashsiz - 1; + + if (memAllocGroup ((void **) (void *) + &grafptr->s.verttax, (size_t) ((grafptr->s.vertnbr + 1) * sizeof (Gnum)), + &grafptr->vnhdtax, (size_t) ( grafptr->vnohnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hmeshHgraph: out of memory (1)"); + return (1); + } + if ((hashtab = memAlloc (hashsiz * sizeof (HmeshHgraphHash))) == NULL) { + errorPrint ("hmeshHgraph: out of memory (2)"); + memFree (grafptr->s.verttax); + return (1); + } + grafptr->s.verttax -= grafptr->s.baseval; + grafptr->s.vendtax = grafptr->s.verttax + 1; + grafptr->vnhdtax -= grafptr->s.baseval; + if (meshptr->m.vnumtax != NULL) /* If (node) vertex index array present, point to its relevant part */ + grafptr->s.vnumtax = meshptr->m.vnumtax + (meshptr->m.vnodbas - grafptr->s.baseval); /* Since GRAPHVERTGROUP, no problem on graphFree */ + + if (meshptr->m.vnlotax != NULL) /* Keep node part of mesh (node) vertex load array as graph vertex load array */ + grafptr->s.velotax = meshptr->m.vnlotax + (meshptr->m.vnodbas - grafptr->s.baseval); /* Since GRAPHVERTGROUP, no problem on graphFree */ + + grafptr->s.velosum = meshptr->m.vnlosum; + + edgemax = ((meshptr->m.degrmax * meshptr->m.degrmax) / 2 + 1) * meshptr->m.vnodnbr; /* Compute estimated number of edges in graph */ +#ifdef SCOTCH_DEBUG_HMESH2 + edgemax = meshptr->m.degrmax + 4; /* Test dynamic reallocation of edge array; 4 guarantees that 25% > 0 */ +#endif /* SCOTCH_DEBUG_HMESH2 */ + + if ((grafptr->s.edgetax = memAlloc (edgemax * sizeof (Gnum))) == NULL) { + errorPrint ("hmeshHgraph: out of memory (3)"); + hgraphFree (grafptr); + return (1); + } + grafptr->s.edgetax -= grafptr->s.baseval; + + memSet (hashtab, ~0, hashsiz * sizeof (HmeshHgraphHash)); /* Initialize hash table */ + + for (vertnum = edgenum = grafptr->s.baseval, edgennd = edgemax + grafptr->s.baseval, enohnbr = degrmax = 0; /* Build graph edges for non-halo vertices */ + vertnum < grafptr->vnohnnd; vertnum ++) { + Gnum vnodnum; + Gnum hnodnum; + Gnum enodnum; + Gnum enhdnum; /* Index of first non-halo neighbor in edge array for current vertex */ + + grafptr->s.verttax[vertnum] = edgenum; + + vnodnum = vertnum + (meshptr->m.vnodbas - meshptr->m.baseval); + hnodnum = (vnodnum * HMESHHGRAPHHASHPRIME) & hashmsk; /* Prevent adding loop edge */ + hashtab[hnodnum].vertnum = vnodnum; + hashtab[hnodnum].vertend = vnodnum; + + for (enodnum = meshptr->m.verttax[vnodnum], enhdnum = edgenum; + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { + Gnum velmnum; + Gnum eelmnum; + + velmnum = meshptr->m.edgetax[enodnum]; + + for (eelmnum = meshptr->m.verttax[velmnum]; + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnodend; + Gnum hnodend; + + vnodend = meshptr->m.edgetax[eelmnum]; + + for (hnodend = (vnodend * HMESHHGRAPHHASHPRIME) & hashmsk; ; hnodend = (hnodend + 1) & hashmsk) { + if (hashtab[hnodend].vertnum != vnodnum) { /* If edge not yet created */ + Gnum vertend; + + if (edgenum == edgennd) { /* If edge array already full */ + Gnum edgemax; + Gnum * restrict edgetmp; + + edgemax = edgennd - grafptr->s.baseval; /* Increase size by 25 % */ + edgemax = edgemax + (edgemax >> 2); + + if ((edgetmp = memRealloc (grafptr->s.edgetax + grafptr->s.baseval, edgemax * sizeof (Gnum))) == NULL) { + errorPrint ("hmeshHgraph: out of memory (4)"); + hgraphFree (grafptr); + memFree (hashtab); + return (1); + } + + grafptr->s.edgetax = edgetmp - grafptr->s.baseval; + edgennd = edgemax + grafptr->s.baseval; + } + + hashtab[hnodend].vertnum = vnodnum; /* Record new edge */ + hashtab[hnodend].vertend = vnodend; + vertend = vnodend - (meshptr->m.vnodbas - grafptr->s.baseval); + if (vnodend >= meshptr->vnohnnd) /* If halo edge */ + grafptr->s.edgetax[edgenum ++] = vertend; /* Build at end of array */ + else { /* If non-halo edge */ + if (edgenum != enhdnum) /* If already halo edges */ + grafptr->s.edgetax[edgenum] = grafptr->s.edgetax[enhdnum]; /* Make room */ + grafptr->s.edgetax[enhdnum ++] = vertend; /* Record new edge */ + edgenum ++; /* One more edge created */ + } + break; + } + if (hashtab[hnodend].vertend == vnodend) /* If edge already exists */ + break; /* Skip to next neighbor */ + } + } + } + grafptr->vnhdtax[vertnum] = enhdnum; /* Set end of non-halo edge array */ + enohnbr += enhdnum - grafptr->s.verttax[vertnum]; + + if ((edgenum - grafptr->s.verttax[vertnum]) > degrmax) /* Compute maximum degree */ + degrmax = (edgenum - grafptr->s.verttax[vertnum]); + } + grafptr->enohnbr = enohnbr; /* All other edges will be halo edges */ + + for ( ; vertnum < grafptr->s.vertnnd; vertnum ++) { /* Build graph edges for halo vertices */ + Gnum vnodnum; + Gnum enodnum; + + vnodnum = vertnum + (meshptr->m.vnodbas - meshptr->m.baseval); + grafptr->s.verttax[vertnum] = edgenum; + + for (enodnum = meshptr->m.verttax[vnodnum]; + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { + Gnum velmnum; + Gnum eelmnum; + + velmnum = meshptr->m.edgetax[enodnum]; + + for (eelmnum = meshptr->m.verttax[velmnum]; /* Only consider non-halo edges of elements this time */ + eelmnum < meshptr->vehdtax[velmnum]; eelmnum ++) { + Gnum vnodend; + Gnum hnodend; + + vnodend = meshptr->m.edgetax[eelmnum]; + +#ifdef SCOTCH_DEBUG_HMESH2 + if (vnodend >= meshptr->vnohnnd) { /* Not visiting halo edges should prevent this */ + errorPrint ("hmeshHgraph: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + + for (hnodend = (vnodend * HMESHHGRAPHHASHPRIME) & hashmsk; ; hnodend = (hnodend + 1) & hashmsk) { + if (hashtab[hnodend].vertnum != vnodnum) { /* If edge not yet created */ + Gnum vertend; + + if (edgenum == edgennd) { /* If edge array already full */ + Gnum edgemax; + Gnum * restrict edgetmp; + + edgemax = edgennd - grafptr->s.baseval; /* Increase size by 25 % */ + edgemax = edgemax + (edgemax >> 2); + + if ((edgetmp = memRealloc (grafptr->s.edgetax + grafptr->s.baseval, edgemax * sizeof (Gnum))) == NULL) { + errorPrint ("hmeshHgraph: out of memory (5)"); + hgraphFree (grafptr); + memFree (hashtab); + return (1); + } + + grafptr->s.edgetax = edgetmp - grafptr->s.baseval; + edgennd = edgemax + grafptr->s.baseval; + } + + hashtab[hnodend].vertnum = vnodnum; /* Record new edge */ + hashtab[hnodend].vertend = vnodend; + vertend = vnodend - (meshptr->m.vnodbas - grafptr->s.baseval); + grafptr->s.edgetax[edgenum ++] = vertend; /* Build halo edge */ + break; + } + if (hashtab[hnodend].vertend == vnodend) /* If edge already exists */ + break; /* Skip to next neighbor */ + } + } + } + + if ((edgenum - grafptr->s.verttax[vertnum]) > degrmax) /* Compute maximum degree */ + degrmax = (edgenum - grafptr->s.verttax[vertnum]); + } + grafptr->s.verttax[vertnum] = edgenum; /* Set end of vertex array */ + grafptr->s.edgenbr = edgenum - grafptr->s.baseval; + grafptr->s.degrmax = degrmax; + + memFree (hashtab); + +#ifdef SCOTCH_DEBUG_HMESH2 + if (hgraphCheck (grafptr) != 0) { + errorPrint ("hmeshHgraph: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_hgraph.h b/scotch_6.0.3/src/libscotch/hmesh_hgraph.h new file mode 100644 index 00000000..5cc02eaa --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_hgraph.h @@ -0,0 +1,66 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_hgraph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source halo mesh to source halo **/ +/** graph building routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 30 nov 2003 **/ +/** to 30 nov 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** Prime number for cache-friendly perturbations. **/ + +#define HMESHHGRAPHHASHPRIME 37 /* Prime number */ + +/* +** The type and structure definitions. +*/ + +/*+ A table made of such elements is used during + graph building to build the edge array of the + graph from the one of the mesh. +*/ + +typedef struct HmeshHgraphHash_ { + Gnum vertnum; /*+ Origin vertex (i.e. pass) number in mesh +*/ + Gnum vertend; /*+ End vertex number in mesh +*/ +} HmeshHgraphHash; diff --git a/scotch_6.0.3/src/libscotch/hmesh_induce.c b/scotch_6.0.3/src/libscotch/hmesh_induce.c new file mode 100644 index 00000000..d1ed7e5a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_induce.c @@ -0,0 +1,373 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_induce.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the halo source **/ +/** mesh subgraph-making functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 07 jan 2002 **/ +/** to 11 may 2004 **/ +/** # Version 5.0 : from : 22 dec 2006 **/ +/** to 11 jun 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH +#define HMESH_INDUCE + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "hmesh.h" + +/*********************************************/ +/* */ +/* These routines handle halo source meshes. */ +/* */ +/*********************************************/ + +/* This routine builds the halo mesh induced +** by the original halo mesh and the array of +** selected node vertices. Elements which are +** adjacent to the selected nodes are themselves +** selected, as well as their adjacent node +** vertices, which comprise the new halo. +** In the induced halo mesh, elements are +** placed first, then non-halo nodes, then +** halo nodes. This order is quite important +** as it eases the building of vertex separation +** meshes from halo meshes, just by ignoring +** halo nodes. +** The induced vnumtab array is a baseval-based +** list of the selected node vertices if the +** original halo mesh does not have a vnumtab, or +** the proper subset of the original vnumtab else. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +hmeshInducePart ( +const Hmesh * restrict const orgmeshptr, /* Pointer to original graph */ +const GraphPart * restrict const orgparttax, /* Array of vertex partition flags */ +const GraphPart orgpartval, /* Partition value of vertices to keep (0 or 1) */ +const Gnum orgvelmnbr, /* Number of (maybe isolated) element vertices in selected part */ +const Gnum orgvnodnbr, /* Number of node vertices in selected part */ +const Gnum orgvnspnbr, /* Number of node vertices in separator */ +Hmesh * restrict const indmeshptr) /* Pointer to induced halo submesh */ +{ + Gnum orgvelmnum; /* Number of current element vertex in original halo mesh */ + Gnum orgvnodnum; /* Number of current node vertex in original halo mesh */ + Gnum * restrict orgindxtax; /* Original to induced vertex number translation array */ + Gnum indvertnbr; /* Upper bound on the number of vertices in induced halo mesh */ + Gnum indvertnum; /* Number of current vertex in induced mesh graph */ + Gnum indvelmnbr; /* Number of element vertices in induced halo mesh */ + Gnum indveihnbr; /* Number of newly created halo-isolated elements */ + Gnum indvnodnbr; /* Upper bound on the number of node vertices in induced halo mesh */ + Gnum indvnodnum; /* Number of current node vertex in induced halo mesh */ + Gnum * restrict indedgetax; /* Based access to induced mesh graph edge arrays */ + Gnum indedgenbr; /* (Approximate) number of edges in induced halo mesh */ + Gnum indedgenum; /* Number of current edge in induced halo mesh */ + Gnum * restrict indvnuhtax; /* Array of vertex numbers for halo nodes (aka vnumtab) */ + Gnum indvelonbr; + Gnum indvelosum; + Gnum indvnlonbr; + Gnum indvnlosum; + Gnum indvnhlsum; + + indvelmnbr = orgvelmnbr - orgmeshptr->veihnbr; /* Remove known halo-isolated elements */ + if (orgpartval == 0) /* If submesh is part zero */ + indvelmnbr -= orgmeshptr->m.veisnbr; /* Also remove isolated elements, which belong to it */ + + indvnodnbr = orgvnodnbr + orgvnspnbr + orgmeshptr->m.vnodnnd - orgmeshptr->vnohnnd; /* Compute upper bound on number of node vertices */ + indvertnbr = indvnodnbr + indvelmnbr; + + indedgenbr = ((orgmeshptr->m.degrmax > 0) && (indvertnbr < (orgmeshptr->m.edgenbr / orgmeshptr->m.degrmax))) /* Choose best upper bound on number of edges (avoid multiply overflow) */ + ? (indvertnbr * orgmeshptr->m.degrmax) : orgmeshptr->m.edgenbr; + + memSet (indmeshptr, 0, sizeof (Hmesh)); /* Initialize halo mesh fields */ + indmeshptr->m.baseval = orgmeshptr->m.baseval; /* Inherit mesh properties */ + indmeshptr->m.flagval = MESHFREETABS | MESHVERTGROUP; + indmeshptr->m.velmnbr = indvelmnbr; + indmeshptr->m.velmbas = indmeshptr->m.baseval; /* Elements are placed first */ + indmeshptr->m.velmnnd = + indmeshptr->m.vnodbas = orgvelmnbr + indmeshptr->m.baseval; /* Node vertices are placed after elements */ + indmeshptr->m.veisnbr = 0; /* All isolated elements will be removed in submesh */ + + indvelonbr = (orgmeshptr->m.velotax != NULL) ? indmeshptr->m.velmnbr : 0; + indvnlonbr = (orgmeshptr->m.vnlotax != NULL) ? indvnodnbr : 0; + + if (memAllocGroup ((void **) (void *) + &indmeshptr->m.verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), + &indmeshptr->vehdtax, (size_t) ( orgvelmnbr * sizeof (Gnum)), /* vehdtab is limited to elements */ + &indmeshptr->m.velotax, (size_t) ( indvelonbr * sizeof (Gnum)), + &indmeshptr->m.vnlotax, (size_t) ( indvnlonbr * sizeof (Gnum)), + &indmeshptr->m.vnumtax, (size_t) ( orgvnodnbr * sizeof (Gnum)), NULL) == NULL) { /* vnumtab is of size vnohnbr */ + errorPrint ("hmeshInducePart: out of memory (1)"); /* Allocate induced mesh graph structure */ + return (1); + } + indmeshptr->m.verttax -= indmeshptr->m.baseval; + indmeshptr->m.vendtax = indmeshptr->m.verttax + 1; /* Compact array */ + indmeshptr->m.velotax = (indvelonbr != 0) ? (indmeshptr->m.velotax - indmeshptr->m.velmbas) : NULL; + indmeshptr->m.vnlotax = (indvnlonbr != 0) ? (indmeshptr->m.vnlotax - indmeshptr->m.vnodbas) : NULL; + indmeshptr->m.vnumtax -= indmeshptr->m.vnodbas; /* Only for non-halo nodes */ + indmeshptr->m.degrmax = orgmeshptr->m.degrmax; + indmeshptr->vnohnbr = orgvnodnbr; + indmeshptr->vnohnnd = indmeshptr->m.vnodbas + orgvnodnbr; + indmeshptr->vehdtax -= indmeshptr->m.velmbas; + indmeshptr->vnhlsum = orgvnodnbr; /* Assume no vertex loads */ + + if (memAllocGroup ((void **) (void *) + &indedgetax, (size_t) (indedgenbr * sizeof (Gnum)), + &orgindxtax, (size_t) ((orgmeshptr->m.velmnbr + orgmeshptr->m.vnodnbr) * sizeof (Gnum)), + &indvnuhtax, (size_t) ((orgvnspnbr + orgmeshptr->m.vnodnnd - orgmeshptr->vnohnnd) * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hmeshInducePart: out of memory (2)"); /* Allocate induced mesh graph structure */ + hmeshExit (indmeshptr); + return (1); + } + indedgetax -= indmeshptr->m.baseval; + orgindxtax -= orgmeshptr->m.baseval; + indvnuhtax -= indmeshptr->vnohnnd; /* Base array so as to catch halo nodes only */ + + indvnhlsum = 0; + for (orgvnodnum = orgmeshptr->m.vnodbas, /* For all original non-halo node vertices */ + indvnodnum = indmeshptr->m.vnodbas; /* And assuming all elements will be kept */ + orgvnodnum < orgmeshptr->vnohnnd; orgvnodnum ++) { + if (orgparttax[orgvnodnum] == orgpartval) { /* If in right part */ + orgindxtax[orgvnodnum] = indvnodnum; /* Set new index of node */ + indmeshptr->m.vnumtax[indvnodnum] = orgvnodnum - (orgmeshptr->m.vnodbas - orgmeshptr->m.baseval); + if (orgmeshptr->m.vnlotax != NULL) + indvnhlsum += (indmeshptr->m.vnlotax[indvnodnum] = orgmeshptr->m.vnlotax[orgvnodnum]); + indvnodnum ++; + } + else if (orgparttax[orgvnodnum] == 2) /* If node belongs to separator */ + orgindxtax[orgvnodnum] = ~0; /* Pre-set array for separator nodes */ + } +#ifdef SCOTCH_DEBUG_HMESH2 + if ((indvnodnum - indmeshptr->m.vnodbas) != orgvnodnbr) { + errorPrint ("hmeshInducePart: internal error (1)"); + memFree (indedgetax + indmeshptr->m.baseval); + hmeshExit (indmeshptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + memSet (orgindxtax + orgmeshptr->vnohnnd, ~0, (orgmeshptr->m.vnodnnd - orgmeshptr->vnohnnd) * sizeof (Gnum)); /* Pre-set halo node vertices */ + + indveihnbr = 0; + indvelosum = 0; + indvnlosum = 0; + for (orgvelmnum = orgmeshptr->m.velmbas, /* For all elements of original graph */ + indvertnum = indedgenum = indmeshptr->m.baseval; /* Elements are placed first in vertex array */ + orgvelmnum < orgmeshptr->m.velmnnd; orgvelmnum ++) { + if (orgparttax[orgvelmnum] == orgpartval) { /* If element belongs to right part */ + Gnum orgedgenum; + Gnum indedgennd; /* Index of after-last edge position in edge array */ + Gnum indedhdnum; /* Index of after-last edge linking to non-halo vertices */ + + orgedgenum = orgmeshptr->m.verttax[orgvelmnum]; + if (orgedgenum == orgmeshptr->vehdtax[orgvelmnum]) /* If (halo-)isolated element vertex */ + continue; /* Discard element in induced submesh */ + +#ifdef SCOTCH_DEBUG_HMESH2 + if (indvertnum >= indmeshptr->m.velmnnd) { /* If too many element vertices kept */ + errorPrint ("hmeshInducePart: internal error (2)"); /* Maybe a problem with veisnbr or veihnbr */ + memFree (indedgetax + indmeshptr->m.baseval); + hmeshExit (indmeshptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + + indmeshptr->m.verttax[indvertnum] = indedgenum; + indedhdnum = orgmeshptr->m.vendtax[orgvelmnum] - orgmeshptr->m.verttax[orgvelmnum] + indedgenum; + indedgennd = indedhdnum; + if (orgmeshptr->m.velotax != NULL) { + Gnum orgveloval; + + orgveloval = orgmeshptr->m.velotax[orgvelmnum]; + indmeshptr->m.velotax[indvertnum] = orgveloval; + indvelosum += orgveloval; + } + + for ( ; orgedgenum < orgmeshptr->m.vendtax[orgvelmnum]; orgedgenum ++) { + Gnum orgvertend; + + orgvertend = orgmeshptr->m.edgetax[orgedgenum]; + + if (orgindxtax[orgvertend] == ~0) { /* If found yet un-numbered halo node */ +#ifdef SCOTCH_DEBUG_HMESH2 + if ((orgvertend < orgmeshptr->vnohnnd) && + (orgparttax[orgvertend] != 2)) { + errorPrint ("hmeshInducePart: internal error (3)"); + memFree (indedgetax + indmeshptr->m.baseval); + hmeshExit (indmeshptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + if (orgmeshptr->m.vnlotax != NULL) { + Gnum orgvnloval; + + orgvnloval = orgmeshptr->m.vnlotax[orgvertend]; + indmeshptr->m.vnlotax[indvnodnum] = orgvnloval; + indvnlosum += orgvnloval; + } + orgindxtax[orgvertend] = indvnodnum; /* Set number of halo node */ + indvnuhtax[indvnodnum] = orgvertend; /* Keep number of halo node */ + indvnodnum ++; + indedgetax[-- indedhdnum] = orgindxtax[orgvertend]; + continue; + } + if (orgindxtax[orgvertend] < indmeshptr->vnohnnd) /* If non-halo vertex */ + indedgetax[indedgenum ++] = orgindxtax[orgvertend]; + else /* Else if halo vertex */ + indedgetax[-- indedhdnum] = orgindxtax[orgvertend]; + } +#ifdef SCOTCH_DEBUG_HMESH2 + if (indedgenum != indedhdnum) { + errorPrint ("hmeshInducePart: internal error (4)"); + memFree (indedgetax + indmeshptr->m.baseval); + hmeshExit (indmeshptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + if (indedhdnum == indmeshptr->m.verttax[indvertnum]) /* If element has halo nodes only */ + indveihnbr ++; /* One more halo-isolated element created */ + + indmeshptr->vehdtax[indvertnum] = indedhdnum; + indedgenum = indedgennd; + orgindxtax[orgvelmnum] = indvertnum; + indvertnum ++; /* One more element created */ + } + else + orgindxtax[orgvelmnum] = ~0; + } +#ifdef SCOTCH_DEBUG_HMESH2 + if (indvertnum != indmeshptr->m.velmnnd) { + errorPrint ("hmeshInducePart: internal error (5)"); /* Maybe a problem with veisnbr or veihnbr */ + memFree (indedgetax + indmeshptr->m.baseval); + hmeshExit (indmeshptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + + indmeshptr->veihnbr = indveihnbr; + + indmeshptr->m.vnodnbr = indvnodnum - indmeshptr->m.vnodbas; + indmeshptr->m.vnodnnd = indvertnum + indmeshptr->m.vnodnbr; + indmeshptr->m.velosum = (indmeshptr->m.velotax != NULL) ? indvelosum : indmeshptr->m.velmnbr; + if (indmeshptr->m.vnlotax != NULL) { /* If vertex loads wanted */ + indmeshptr->m.vnlosum = indvnhlsum + indvnlosum; + indmeshptr->vnhlsum = indvnhlsum; + } + else { + indmeshptr->m.vnlosum = indmeshptr->m.vnodnbr; + indmeshptr->vnhlsum = indmeshptr->vnohnbr; + } + + indedgenbr = 2 * (indedgenum - indmeshptr->m.baseval); /* Twice as many arcs as element arcs */ + for ( ; indvertnum < indmeshptr->vnohnnd; indvertnum ++) { /* For all non-halo induced node vertices */ + Gnum orgvnodnum; + Gnum orgedgenum; + + orgvnodnum = indmeshptr->m.vnumtax[indvertnum] + (orgmeshptr->m.vnodbas - orgmeshptr->m.baseval); /* Get number of original node */ + + indmeshptr->m.verttax[indvertnum] = indedgenum; + + for (orgedgenum = orgmeshptr->m.verttax[orgvnodnum]; + orgedgenum < orgmeshptr->m.vendtax[orgvnodnum]; orgedgenum ++) { + Gnum orgvertend; + + orgvertend = orgmeshptr->m.edgetax[orgedgenum]; +#ifdef SCOTCH_DEBUG_HMESH2 + if (orgindxtax[orgvertend] == ~0) { + errorPrint ("hmeshInducePart: internal error (6)"); + memFree (indedgetax + indmeshptr->m.baseval); + hmeshExit (indmeshptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + indedgetax[indedgenum ++] = orgindxtax[orgvertend]; + } + } + + indmeshptr->enohnbr = indedgenum - indmeshptr->m.baseval; + + for ( ; indvertnum < indmeshptr->m.vnodnnd; indvertnum ++) { /* For all halo induced node vertices */ + Gnum orgvnodnum; + Gnum orgedgenum; + + orgvnodnum = indvnuhtax[indvertnum]; /* Get number of original node */ + + indmeshptr->m.verttax[indvertnum] = indedgenum; + + for (orgedgenum = orgmeshptr->m.verttax[orgvnodnum]; + orgedgenum < orgmeshptr->m.vendtax[orgvnodnum]; orgedgenum ++) { + Gnum orgvertend; + + orgvertend = orgmeshptr->m.edgetax[orgedgenum]; + if (orgindxtax[orgvertend] != ~0) { /* If end element belongs to right part */ + indedgetax[indedgenum ++] = orgindxtax[orgvertend]; + } + } + } + indmeshptr->m.verttax[indvertnum] = indedgenum; /* Set end of edge array */ + indmeshptr->m.edgenbr = indedgenum - indmeshptr->m.baseval; + indmeshptr->m.vnodnnd = indvertnum; /* Record number of induced non-element vertices */ + indmeshptr->m.vnodnbr = indvertnum - indmeshptr->m.vnodbas; + + if (orgmeshptr->m.vnumtax != NULL) { /* If source mesh is not original mesh */ + for (indvnodnum = indmeshptr->m.vnodbas; indvnodnum < indmeshptr->vnohnnd; indvnodnum ++) + indmeshptr->m.vnumtax[indvnodnum] = orgmeshptr->m.vnumtax[indmeshptr->m.vnumtax[indvnodnum] + (orgmeshptr->m.vnodbas - orgmeshptr->m.baseval)]; + } + + indmeshptr->m.edgetax = memRealloc (indedgetax + indmeshptr->m.baseval, indedgenbr * sizeof (Gnum)); + indmeshptr->m.edgetax -= indmeshptr->m.baseval; + +#ifdef SCOTCH_DEBUG_HMESH2 + if (hmeshCheck (indmeshptr) != 0) { /* Check halo mesh consistency */ + errorPrint ("hmeshInducePart: inconsistent halo mesh data"); + hmeshExit (indmeshptr); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_induce.h b/scotch_6.0.3/src/libscotch/hmesh_induce.h new file mode 100644 index 00000000..616a4afe --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_induce.h @@ -0,0 +1,32 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_mesh.c b/scotch_6.0.3/src/libscotch/hmesh_mesh.c new file mode 100644 index 00000000..f527e484 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_mesh.c @@ -0,0 +1,147 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_mesh.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the mesh un- **/ +/** haloing routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 28 apr 2004 **/ +/** to 11 may 2004 **/ +/** **/ +/** NOTES : # From a given halo mesh is created a **/ +/** non-halo mesh. When nodes are **/ +/** numbered after elements, halo nodes **/ +/** are simply removed. When nodes are **/ +/** numbered before elements, halo nodes **/ +/** are turned into empty elements such **/ +/** that the numbering of vertices **/ +/** remains continuous, without holes. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_MESH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "hgraph.h" +#include "mesh.h" +#include "hmesh.h" + +/***************************************/ +/* */ +/* The non-halo mesh building routine. */ +/* */ +/***************************************/ + +/* This routine builds a non-halo mesh from +** the given halo mesh. +** It returns: +** - 0 : if the non-halo mesh has been successfully built. +** - 1 : on error. +*/ + +int +hmeshMesh ( +const Hmesh * restrict const hmshptr, /*+ Original halo mesh +*/ +Mesh * restrict const meshptr) /*+ Mesh to build +*/ +{ + meshptr->baseval = hmshptr->m.baseval; + meshptr->veisnbr = hmshptr->m.veisnbr + hmshptr->veihnbr; /* Add halo isolated elements to isolated elements */ + meshptr->vnodnbr = hmshptr->vnohnbr; + meshptr->vnodbas = hmshptr->m.vnodbas; + meshptr->vnodnnd = hmshptr->vnohnbr + hmshptr->m.vnodbas; + meshptr->verttax = hmshptr->m.verttax; + meshptr->velotax = hmshptr->m.velotax; + meshptr->vnlotax = hmshptr->m.vnlotax; /* Use non-halo part of node vertex load array, if any */ + meshptr->velosum = hmshptr->m.velosum; + meshptr->vnlosum = hmshptr->vnhlsum; + meshptr->vnumtax = hmshptr->m.vnumtax; /* The same for vnumtab */ + meshptr->vlbltax = NULL; + meshptr->edgenbr = hmshptr->enohnbr; + meshptr->edgetax = hmshptr->m.edgetax; + meshptr->degrmax = hmshptr->m.degrmax; + + if (hmshptr->vnohnbr == hmshptr->m.vnodnbr) { /* If halo mesh does not have any halo */ + meshptr->flagval = MESHNONE; /* Just create a clone of the original mesh */ + meshptr->velmnbr = hmshptr->m.velmnbr; + meshptr->velmbas = hmshptr->m.velmbas; + meshptr->velmnnd = hmshptr->m.velmnnd; + meshptr->vendtax = hmshptr->m.vendtax; + return (0); + } + + meshptr->flagval = MESHFREEVEND; + if (hmshptr->m.velmbas <= hmshptr->m.vnodbas) { /* If elements numbered before nodes */ + if ((meshptr->vendtax = memAlloc ((hmshptr->m.velmnbr + hmshptr->vnohnbr) * sizeof (Gnum))) == NULL) { /* Do not keep halo nodes at end of array */ + errorPrint ("hmeshHgraph: out of memory (1)"); + return (1); + } + memCpy (meshptr->vendtax, hmshptr->vehdtax + hmshptr->m.velmbas, hmshptr->m.velmnbr * sizeof (Gnum)); + memCpy (meshptr->vendtax + hmshptr->m.velmnbr, hmshptr->m.vendtax + hmshptr->m.vnodbas, hmshptr->vnohnbr * sizeof (Gnum)); + + meshptr->velmnbr = hmshptr->m.velmnbr; + meshptr->velmbas = hmshptr->m.velmbas; + meshptr->velmnnd = hmshptr->m.velmnnd; + } + else { /* If nodes numbered before elements */ + if ((meshptr->vendtax = memAlloc ((hmshptr->m.velmnbr + hmshptr->m.vnodnbr) * sizeof (Gnum))) == NULL) { /* Turn halo nodes into empty elements */ + errorPrint ("hmeshHgraph: out of memory (2)"); + return (1); + } + memCpy (meshptr->vendtax, hmshptr->m.vendtax + hmshptr->m.baseval, hmshptr->vnohnbr * sizeof (Gnum)); /* Copy non-halo node part */ + memCpy (meshptr->vendtax + hmshptr->vnohnbr, hmshptr->m.verttax + hmshptr->vnohnnd, hmshptr->m.vnodnbr - hmshptr->vnohnbr * sizeof (Gnum)); /* Create empty fake element part */ + memCpy (meshptr->vendtax + hmshptr->m.vnodnbr, hmshptr->vehdtax + hmshptr->m.velmbas, hmshptr->m.velmnbr * sizeof (Gnum)); + + meshptr->velmnbr = hmshptr->m.velmnbr + hmshptr->m.vnodnbr - hmshptr->vnohnbr; /* Turn halo node vertices into element vertices */ + meshptr->velmbas = hmshptr->vnohnnd; + meshptr->velmnnd = hmshptr->m.velmnnd; + } + meshptr->vendtax -= meshptr->baseval; + +#ifdef SCOTCH_DEBUG_HMESH2 + if (meshCheck (meshptr) != 0) { + errorPrint ("hmeshMesh: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_bl.c b/scotch_6.0.3/src/libscotch/hmesh_order_bl.c new file mode 100644 index 00000000..f023bf2f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_bl.c @@ -0,0 +1,125 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_bl.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module resizes block data using **/ +/** the block splitting post-processing **/ +/** algorithm. **/ +/** **/ +/** DATES : # Version 4.0 : from : 28 sep 2002 **/ +/** to 09 feb 2005 **/ +/** # Version 5.0 : from : 25 jul 2007 **/ +/** to : 25 jul 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_BL + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "mesh.h" +#include "hmesh.h" +#include "hmesh_order_bl.h" +#include "hmesh_order_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hmeshOrderBl ( +const Hmesh * restrict const meshptr, +Order * restrict const ordeptr, +const Gnum ordenum, /*+ Zero-based ordering number +*/ +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HmeshOrderBlParam * restrict const paraptr) +{ + Gnum cblknbr; /* Number of old column blocks before splitting */ + Gnum cblknum; /* Number of current column block */ + + if (paraptr->cblkmin <= 0) { + errorPrint ("hmeshOrderBl: invalid minimum block size"); + return (1); + } + + if (hmeshOrderSt (meshptr, ordeptr, ordenum, cblkptr, paraptr->strat) != 0) /* Perform ordering strategy */ + return (1); + + if (cblkptr->cblktab == NULL) { /* If single column block */ + if (cblkptr->vnodnbr < (2 * paraptr->cblkmin)) /* If block cannot be split */ + return (0); + + cblknbr = cblkptr->vnodnbr / paraptr->cblkmin; /* Get new number of blocks */ + + if ((cblkptr->cblktab = (OrderCblk *) memAlloc (cblknbr * sizeof (OrderCblk))) == NULL) { + errorPrint ("hgraphOrderBl: out of memory"); + return (1); + } + ordeptr->treenbr += cblknbr; /* These more number of tree nodes */ + ordeptr->cblknbr += cblknbr - 1; /* These more number of column blocks */ + cblkptr->cblknbr = cblknbr; + + for (cblknum = 0; cblknum < cblknbr; cblknum ++) { + cblkptr->cblktab[cblknum].typeval = ORDERCBLKOTHR; + cblkptr->cblktab[cblknum].vnodnbr = ((cblkptr->vnodnbr + cblknbr - 1) - cblknum) / cblknbr; + cblkptr->cblktab[cblknum].cblknbr = 0; + cblkptr->cblktab[cblknum].cblktab = NULL; + } + } + else { /* Block already partitioned */ + for (cblknum = 0; cblknum < cblkptr->cblknbr; cblknum ++) { + if (hmeshOrderBl (meshptr, ordeptr, ordenum, cblkptr->cblktab + cblknum, paraptr) != 0) + return (1); + } + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_bl.h b/scotch_6.0.3/src/libscotch/hmesh_order_bl.h new file mode 100644 index 00000000..30c38c82 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_bl.h @@ -0,0 +1,69 @@ +/* Copyright 2004,2007,2009,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_bl.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the block splitting algorithm. **/ +/** **/ +/** DATES : # Version 4.0 : from : 28 sep 2002 **/ +/** to 04 jan 2005 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HmeshOrderBlParam_ { + Strat * strat; /*+ Ordering strategy +*/ + INT cblkmin; /*+ Block splitting size +*/ +} HmeshOrderBlParam; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_BL +#define static +#endif + +int hmeshOrderBl (const Hmesh * const, Order * const, const Gnum, OrderCblk * const, const HmeshOrderBlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_cp.c b/scotch_6.0.3/src/libscotch/hmesh_order_cp.c new file mode 100644 index 00000000..c9d2fe60 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_cp.c @@ -0,0 +1,465 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_cp.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module performs compession of mesh **/ +/** nodes, by merging nodes having the same **/ +/** adjacency structure. **/ +/** **/ +/** DATES : # Version 4.0 : from : 08 feb 2004 **/ +/** to 05 jan 2005 **/ +/** # Version 5.0 : from : 25 jul 2007 **/ +/** to : 12 sep 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_CP + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "mesh.h" +#include "hmesh.h" +#include "hmesh_order_cp.h" +#include "hmesh_order_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hmeshOrderCp ( +const Hmesh * restrict const finemeshptr, +Order * restrict const fineordeptr, +const Gnum ordenum, /*+ Zero-based ordering number +*/ +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HmeshOrderCpParam * restrict const paraptr) +{ + Hmesh coarmeshdat; /* Compressed halo submesh */ + Order coarordedat; /* Ordering of compressed halo submesh */ + Gnum * restrict coarperitab; /* Coarse permutation array */ + const Gnum * restrict coarperitax; /* Temporary based access to coarperitab */ + Gnum coarvertnum; /* Number of current compressed vertex */ + Gnum * restrict coarvsiztax; /* Array of coarse vertex sizes (as number of merged fine vertices) */ + Gnum coaredgenum; /* Number of current compressed edge */ + Gnum * restrict coarvpostax; /* Position in fine permutation of fine vertices merged into same vertex */ + Gnum coarvnodmax; + Gnum coarvertmax; + Gnum * restrict finecoartax; /* Original to compressed vertex number array */ + HmeshOrderCpHash * restrict finehashtab; /* Neighbor hash table */ + Gnum finehashmsk; /* Mask for access to hash table */ + int * restrict finehasptab; /* Pre-hashing table */ + Gnum finehaspmsk; /* Mask for access to pre-hashing table */ + Gnum * restrict finehsumtax; /* Array of hash values for each original vertex */ + Gnum finevertnbr; /* Number of fine vertices in compressed elimination tree */ + Gnum finevsizsum; /* Sum of compressed vertex sizes to build fine inverse permutation */ + Gnum coarvsizsiz; /* Size of array of sizes of coarse nodes */ + Gnum coarvelmnbr; /* Number of coarse element vertices */ + Gnum * restrict coarverttax; + Gnum * restrict coarvnlotax; + Gnum * restrict coaredgetax; + Gnum * restrict coarfinetax; + Gnum finevnodnum; + Gnum coarvnodnbr; + Gnum finevelmnum; + Gnum coarvnodnnd; + Gnum coardegrmax; + Gnum coarvnodnum; + + if (finemeshptr->vnohnbr != finemeshptr->m.vnodnbr) { + errorPrint ("hmeshOrderCp: halo meshes not supported yet"); + return (1); + } + + coarvelmnbr = finemeshptr->m.velmnbr; /* To date, keep isolated elements */ + coarvnodmax = (Gnum) ((double) finemeshptr->vnohnbr * paraptr->comprat) + + (finemeshptr->m.vnodnbr - finemeshptr->vnohnbr); + coarvertmax = coarvnodmax + coarvelmnbr; + coarvsizsiz = (finemeshptr->m.vnlotax == NULL) ? 0 : coarvnodmax; + + for (finehashmsk = 15; /* Set neighbor hash table size */ + finehashmsk < finemeshptr->m.degrmax; + finehashmsk = finehashmsk * 2 + 1) ; + finehashmsk = finehashmsk * 4 + 3; /* Fill hash table at 1/4 of capacity */ + + if (memAllocGroup ((void **) (void *) + &coarverttax, (size_t) ((coarvertmax + 1) * sizeof (Gnum)), + &coarvsiztax, (size_t) (coarvsizsiz * sizeof (Gnum)), /* TRICK: if no vertex loads, coarvsiztax points to coarvnodtax */ + &coarvnlotax, (size_t) (coarvnodmax * sizeof (Gnum)), /* Only change node weights */ + &finecoartax, (size_t) (finemeshptr->m.vnodnbr * sizeof (Gnum)), + &coaredgetax, (size_t) (finemeshptr->m.edgenbr * sizeof (Gnum)), + &finehsumtax, (size_t) (finemeshptr->m.vnodnbr * sizeof (Gnum)), + &finehashtab, (size_t) ((finehashmsk + 1) * sizeof (HmeshOrderCpHash)), + &coarperitab, (size_t) (coarvnodmax * sizeof (Gnum)), /* TODO: move after resize */ + &coarfinetax, (size_t) (coarvnodmax * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hmeshOrderCp: out of memory (1)"); + return (1); + } +/* TODO : resize after success */ + + finehsumtax -= finemeshptr->m.vnodbas; /* TRICK: do not base finecoartax yet (see later) */ + finehasptab = (int *) finecoartax; /* Use finecoartab as temporary pre-hash table */ + for (finehaspmsk = 1; /* Get pre-hash mask that fits in finecoartab */ + finehaspmsk <= finemeshptr->m.vnodnbr; /* Smallest (2^i)-1 value > vertnbr */ + finehaspmsk = finehaspmsk * 2 + 1) ; + finehaspmsk >>= 1; /* Ensure masked data will always fit into finecoartab array */ + finehaspmsk = (finehaspmsk * (sizeof (Gnum) / sizeof (int))) + ((sizeof (Gnum) / sizeof (int)) - 1); + if (finehaspmsk >= ((sizeof (int) << (3 + 1)) - 1)) /* Only use 1/8 of array for pre-hashing, for increased cache locality */ + finehaspmsk >>= 3; + memSet (finehasptab, 0, (finehaspmsk + 1) * sizeof (int)); /* Initialize pre-hash table */ + + for (finevnodnum = finemeshptr->m.vnodbas, coarvnodnbr = finemeshptr->m.vnodnbr; /* For all non-halo node vertices */ + finevnodnum < finemeshptr->vnohnnd; finevnodnum ++) { + Gnum fineenodnum; /* Current edge number */ + Gnum finehsumval; /* Hash sum value */ + Gnum finehsumbit; + + for (fineenodnum = finemeshptr->m.verttax[finevnodnum], finehsumval = 0; + fineenodnum < finemeshptr->m.vendtax[finevnodnum]; fineenodnum ++) + finehsumval += finemeshptr->m.edgetax[fineenodnum]; + + finehsumtax[finevnodnum] = finehsumval; + + finehsumbit = finehsumval & ((sizeof (int) << 3) - 1); /* Get bit mask and byte position (division should be optimized into a shift) */ + finehsumval /= (sizeof (int) << 3); + finehsumval &= finehaspmsk; /* Make hash sum value fit into finehasptab */ + coarvnodnbr -= (finehasptab[finehsumval] >> finehsumbit) & 1; /* If hash value already in pre-hash table, maybe one more vertex compressed */ + finehasptab[finehsumval] |= (1 << finehsumbit); /* Put value into pre-hash table anyway */ + } + + if (coarvnodnbr > coarvnodmax) { /* If mesh needs not be compressed */ + memFree (coarverttax); /* Group leader not yet based */ + return (hmeshOrderSt (finemeshptr, fineordeptr, ordenum, cblkptr, paraptr->stratunc)); + } + + memSet (finecoartax, ~0, finemeshptr->m.vnodnbr * sizeof (Gnum)); + + memSet (&coarmeshdat, 0, sizeof (Hmesh)); /* Initialize compressed halo mesh structure */ + coarmeshdat.m.flagval = MESHFREEVERT | MESHVERTGROUP; /* Free only coarverttab as group leader */ + coarmeshdat.m.baseval = finemeshptr->m.baseval; + coarmeshdat.m.velmbas = coarmeshdat.m.baseval; + coarmeshdat.m.velmnbr = coarvelmnbr; /* Mesh compression does not touch elements, apart from isolated elements */ + coarmeshdat.m.velmnnd = + coarmeshdat.m.vnodbas = coarvelmnbr + coarmeshdat.m.baseval; + coarmeshdat.m.veisnbr = finemeshptr->m.veisnbr; /* To date, keep all isolated element vertices, if any */ + coarmeshdat.m.velosum = finemeshptr->m.velosum; + coarmeshdat.m.vnlosum = finemeshptr->m.vnlosum; + + coarverttax -= coarmeshdat.m.baseval; + coarvsiztax -= coarmeshdat.m.vnodbas; /* TRICK: if no vertex loads, coarvsiztax points to coarvnodtax */ + coarvnlotax -= coarmeshdat.m.vnodbas; + coaredgetax -= coarmeshdat.m.baseval; + finecoartax -= finemeshptr->m.vnodbas; + + coarmeshdat.m.verttax = coarverttax; + coarmeshdat.m.vendtax = coarverttax + 1; /* Use compact representation of arrays */ + coarmeshdat.m.velotax = finemeshptr->m.velotax; /* Re-use element vertex load array, if any */ + coarmeshdat.m.vnlotax = coarvnlotax; + coarmeshdat.m.edgetax = coaredgetax; + + coarfinetax -= coarmeshdat.m.vnodbas; + + memSet (finehashtab, ~0, (finehashmsk + 1) * sizeof (HmeshOrderCpHash)); + + for (finevelmnum = finemeshptr->m.velmbas, coarvertnum = coaredgenum = coarmeshdat.m.baseval, /* Build element arrays */ + coarvnodnnd = coarmeshdat.m.baseval + finemeshptr->m.velmnbr, coardegrmax = 0; + finevelmnum < finemeshptr->m.velmnnd; finevelmnum ++) { + Gnum fineeelmnum; + Gnum coardegrval; + + fineeelmnum = finemeshptr->m.verttax[finevelmnum]; +#ifdef DEAD_CODE + if (fineeelmnum == finemeshptr->m.vendtax[finevelmnum]) /* Skip isolated elements */ + continue; +#endif +#ifdef SCOTCH_DEBUG_ORDER2 + if (coarvertnum >= coarmeshdat.m.velmnnd) { /* If too many elements declared */ + errorPrint ("hmeshOrderCp: internal error (1)"); /* Maybe problem with veisnbr */ + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + coarverttax[coarvertnum] = coaredgenum; + + for ( ; fineeelmnum < finemeshptr->m.vendtax[finevelmnum]; fineeelmnum ++) { + Gnum finevnodnum; + Gnum coarvnodnum; + + finevnodnum = finemeshptr->m.edgetax[fineeelmnum]; + coarvnodnum = finecoartax[finevnodnum]; + if (coarvnodnum != ~0) { /* If fine node already considered */ + if (coarvnodnum >= 0) /* If node is leader of cluster */ + coaredgetax[coaredgenum ++] = coarvnodnum; /* Add it to coarse mesh */ + } + else { /* Fine node not yet considered */ + Gnum finehsumval; + Gnum finedegrval; + Gnum fineeelmngb; + Gnum coarvsizval; /* Number of fine node vertices in coarse node vertex */ + + if (coarvnodnnd >= (coarvnodmax + coarmeshdat.m.vnodbas)) { /* If mesh needs not be compressed */ + memFree (coarverttax + coarmeshdat.m.baseval); + return (hmeshOrderSt (finemeshptr, fineordeptr, ordenum, cblkptr, paraptr->stratunc)); + } + + coarvsizval = 1; /* Cluster leader it at least alone */ + coarvnodnum = coarvnodnnd ++; /* Node is leader of future cluster */ + finecoartax[finevnodnum] = coarvnodnum; /* Record node as cluster leader */ + coaredgetax[coaredgenum ++] = coarvnodnum; /* Add leader to coarse mesh */ + coarfinetax[coarvnodnum] = finevnodnum; /* Record node to build edge sub-array */ + finehsumval = finehsumtax[finevnodnum]; /* Get hash sum of cluster leader */ + finedegrval = finemeshptr->m.vendtax[finevnodnum] - finemeshptr->m.verttax[finevnodnum]; + + for (fineeelmngb = fineeelmnum + 1; /* For all remaining edges of current element */ + fineeelmngb < finemeshptr->m.vendtax[finevelmnum]; fineeelmngb ++) { + Gnum finevnodngb; + Gnum fineenodngb; + + finevnodngb = finemeshptr->m.edgetax[fineeelmngb]; /* Get index of neighboring node */ + + if ((finecoartax[finevnodngb] != ~0) || /* If node has already been processed or */ + (finehsumval != finehsumtax[finevnodngb]) || /* If hash sum does not match, skip node */ + (finedegrval != (finemeshptr->m.vendtax[finevnodngb] - finemeshptr->m.verttax[finevnodngb]))) + continue; + + if (finehashtab[(finevelmnum * HMESHORDERCPHASHPRIME) & finehashmsk].vnodnum != finevnodnum) { /* If hash table not yet filled */ + Gnum fineenodnum; + + for (fineenodnum = finemeshptr->m.verttax[finevnodnum]; + fineenodnum < finemeshptr->m.vendtax[finevnodnum]; fineenodnum ++) { + Gnum finevelmend; + Gnum finehelmend; + + finevelmend = finemeshptr->m.edgetax[fineenodnum]; + for (finehelmend = (finevelmend * HMESHORDERCPHASHPRIME) & finehashmsk; + finehashtab[finehelmend].vnodnum == finevnodnum; + finehelmend = (finehelmend + 1) & finehashmsk) ; + finehashtab[finehelmend].vnodnum = finevnodnum; /* Fill hash table with node adjacency */ + finehashtab[finehelmend].velmnum = finevelmend; + } + } + + for (fineenodngb = finemeshptr->m.verttax[finevnodngb]; + fineenodngb < finemeshptr->m.vendtax[finevnodngb]; fineenodngb ++) { + Gnum finevelmngb; + Gnum finehelmngb; + + finevelmngb = finemeshptr->m.edgetax[fineenodngb]; + for (finehelmngb = (finevelmngb * HMESHORDERCPHASHPRIME) & finehashmsk; ; finehelmngb = (finehelmngb + 1) & finehashmsk) { + if (finehashtab[finehelmngb].vnodnum != finevnodnum) /* If adjacencies differ, break */ + goto loop_failed; + if (finehashtab[finehelmngb].velmnum == finevelmngb) /* If neighbor found, process next neighbor */ + break; + } + } + finecoartax[finevnodngb] = -2 - coarvnodnum; /* Set index of cluster non-leader */ + coarvsizval ++; /* One more non-leader in cluster */ +loop_failed: ; + } + coarvsiztax[coarvnodnum] = coarvsizval; + } + } + + coardegrval = coaredgenum - coarverttax[coarvertnum]; + if (coardegrval > coardegrmax) + coardegrmax = coardegrval; + + coarvertnum ++; /* One more coarse element created */ + } +#ifdef SCOTCH_DEBUG_ORDER2 + if (coarvertnum != coarmeshdat.m.velmnnd) { /* If too many elements declared */ + errorPrint ("hmeshOrderCp: internal error (2)"); /* Maybe problem with veisnbr */ + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + coarmeshdat.m.vnodnnd = coarvnodnnd; + coarmeshdat.m.vnodnbr = coarvnodnnd - coarmeshdat.m.vnodbas; + +#ifdef SCOTCH_DEBUG_ORDER2 + for (finevnodnum = finemeshptr->m.vnodbas; + finevnodnum < finemeshptr->m.vnodnnd; finevnodnum ++) { + if (finecoartax[finevnodnum] == ~0) { + errorPrint ("hmeshOrderCp: internal error (3)"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + for ( ; coarvertnum < coarmeshdat.m.vnodnnd; coarvertnum ++) { /* Build node arrays */ + Gnum finevnodnum; + Gnum fineenodnum; + Gnum coardegrval; + + coarverttax[coarvertnum] = coaredgenum; + + finevnodnum = coarfinetax[coarvertnum]; + coardegrval = finemeshptr->m.vendtax[finevnodnum] - finemeshptr->m.verttax[finevnodnum]; + for (fineenodnum = finemeshptr->m.verttax[finevnodnum]; + fineenodnum < finemeshptr->m.vendtax[finevnodnum]; fineenodnum ++) + coaredgetax[coaredgenum ++] = finemeshptr->m.edgetax[fineenodnum] - (finemeshptr->m.velmbas - coarmeshdat.m.velmbas); + + if (coardegrval > coardegrmax) + coardegrmax = coardegrval; + } + coarverttax[coarvertnum] = coaredgenum; /* Set end of vertex array */ + + coarmeshdat.m.edgenbr = coaredgenum - coarmeshdat.m.baseval; + coarmeshdat.m.degrmax = coardegrmax; + coarmeshdat.vnohnbr = coarmeshdat.m.vnodnbr; /* Halo meshes not yet supported */ + coarmeshdat.vnohnnd = coarmeshdat.m.vnodnnd; + coarmeshdat.vehdtax = coarmeshdat.m.vendtax; /* Only element part of vendtab will be accessed through vehdtab */ + coarmeshdat.vnhlsum = coarmeshdat.m.vnlosum; + coarmeshdat.enohnbr = coarmeshdat.m.edgenbr; + + if (finemeshptr->m.vnlotax != NULL) { /* If fine mesh has node vertex loads */ + memSet (coarmeshdat.m.vnlotax + coarmeshdat.m.vnodbas, 0, coarmeshdat.m.vnodnbr * sizeof (Gnum)); + + for (finevnodnum = finemeshptr->m.vnodbas; finevnodnum < finemeshptr->m.vnodnnd; finevnodnum ++) { /* Compute vertex loads for compressed mesh */ + coarmeshdat.m.vnlotax[finecoartax[finevnodnum]] += finemeshptr->m.vnlotax[finevnodnum]; + } + } + +#ifdef SCOTCH_DEBUG_ORDER2 + if (hmeshCheck (&coarmeshdat) != 0) { + errorPrint ("hmeshOrderCp: internal error (4)"); + hmeshExit (&coarmeshdat); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + orderInit (&coarordedat, coarmeshdat.m.baseval, coarmeshdat.m.vnodnbr, coarperitab); /* Build ordering of compressed submesh */ + if (hmeshOrderSt (&coarmeshdat, &coarordedat, 0, &coarordedat.cblktre, paraptr->stratcpr) != 0) { + hmeshExit (&coarmeshdat); + return (1); + } + + coarvsiztax += (coarmeshdat.m.vnodbas - coarmeshdat.m.baseval); /* Adjust array to match permutation bounds */ + + *cblkptr = coarordedat.cblktre; /* Link sub-tree to ordering */ + coarordedat.cblktre.cblktab = NULL; /* Unlink sub-tree from sub-ordering */ + finevertnbr = hmeshOrderCpTree (coarordedat.peritab, /* Expand sub-tree */ + coarvsiztax, cblkptr, 0); +#ifdef SCOTCH_DEBUG_ORDER2 + if (finevertnbr != finemeshptr->m.vnodnbr) { + errorPrint ("hmeshOrderCp: internal error (5)"); + hmeshExit (&coarmeshdat); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + fineordeptr->treenbr += coarordedat.cblknbr; /* Adjust number of tree nodes */ + fineordeptr->cblknbr += coarordedat.cblknbr - 1; /* Adjust number of column blocks */ + + coarvpostax = coarmeshdat.m.verttax; /* Recycle verttab (not velotab as may be merged with coarvsiztab) */ + coarperitax = coarperitab - coarmeshdat.m.vnodbas; + + for (coarvnodnum = coarmeshdat.m.vnodbas, finevsizsum = 0; /* Compute initial indices for inverse permutation expansion */ + coarvnodnum < coarmeshdat.m.vnodnnd; coarvnodnum ++) { + coarvpostax[coarperitax[coarvnodnum]] = finevsizsum; + finevsizsum += coarvsiztax[coarperitax[coarvnodnum]]; + } + coarvpostax = coarmeshdat.m.verttax + (coarmeshdat.m.baseval - coarmeshdat.m.vnodbas); + for (finevnodnum = finemeshptr->m.vnodbas; finevnodnum < finemeshptr->m.vnodnnd; finevnodnum ++) { /* Compute fine permutation */ + Gnum coarvnodnum; + + coarvnodnum = finecoartax[finevnodnum]; /* Get index of corresponding coarse node */ + if (coarvnodnum < 0) /* If node is not cluster leader */ + coarvnodnum = -2 - coarvnodnum; /* Get index of cluster leader */ + fineordeptr->peritab[coarvpostax[coarvnodnum] ++] = finevnodnum + (finemeshptr->m.baseval - finemeshptr->m.vnodbas); + } + + orderExit (&coarordedat); + hmeshExit (&coarmeshdat); + + return (0); +} + +/* This routine turns the coarse elimination +** tree produced by the ordering of the coarse +** mesh into a fine elimination tree, according +** to the cardinality of the coarse vertices. +** It returns: +** - !0 : overall number of fine vertices, in all cases. +*/ + +static +Gnum +hmeshOrderCpTree ( +const Gnum * restrict const coarperitab, /* Coarse inverse permutation */ +const Gnum * restrict const coarvsiztax, /* Array of fine sizes of coarse vertices */ +OrderCblk * restrict const coficblkptr, /* Current coarse/fine column block cell */ +Gnum coarordenum) /* Compressed vertex to start expansion at */ +{ + Gnum finevertnbr; /* Number of fine vertices in subtree */ + + finevertnbr = 0; /* No fine vertices yet */ + + if (coficblkptr->cblktab == NULL) { /* If leaf of column block tree */ + Gnum coarvnumnum; + + for (coarvnumnum = coarordenum; + coarvnumnum < coarordenum + coficblkptr->vnodnbr; coarvnumnum ++) + finevertnbr += coarvsiztax[coarperitab[coarvnumnum]]; /* Sum-up fine vertices */ + } + else { + Gnum coarvertnbr; /* Number of coarse vertices in cell */ + Gnum coarvertsum; /* Number of coarse vertices in subtree */ + Gnum coficblknum; /* Index in column block array */ + + for (coficblknum = 0, coarvertsum = coarordenum; /* Start at current coarse index */ + coficblknum < coficblkptr->cblknbr; coficblknum ++) { + coarvertnbr = coficblkptr->cblktab[coficblknum].vnodnbr; /* Save number of coarse vertices */ + finevertnbr += hmeshOrderCpTree (coarperitab, coarvsiztax, &coficblkptr->cblktab[coficblknum], coarvertsum); + coarvertsum += coarvertnbr; /* Sum-up coarse vertices */ + } + } + coficblkptr->vnodnbr = finevertnbr; /* Set number of fine vertices */ + + return (finevertnbr); /* Return accumulated number */ +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_cp.h b/scotch_6.0.3/src/libscotch/hmesh_order_cp.h new file mode 100644 index 00000000..758833e8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_cp.h @@ -0,0 +1,94 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_cp.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the mesh compression algorithm. **/ +/** **/ +/** DATES : # Version 4.0 : from : 08 feb 2004 **/ +/** to 08 feb 2004 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** Prime number for hashing vertex numbers. **/ + +#define HMESHORDERCPHASHPRIME 17 /* Prime number */ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HmeshOrderCpParam_ { + double comprat; /*+ Compression ratio threshold +*/ + Strat * stratcpr; /*+ Compressed submesh ordering strategy +*/ + Strat * stratunc; /*+ Uncompressed submesh ordering strategy +*/ +} HmeshOrderCpParam; + +/*+ This structure holds fine neighbor hashing data. +*/ + +typedef struct HmeshOrderCpHash_ { + Gnum vnodnum; /*+ Origin node vertex (i.e. pass) number +*/ + Gnum velmnum; /*+ Adjacent end element vertex number +*/ +} HmeshOrderCpHash; + +/*+ This structure holds coarse neighbor mate data. +*/ + +typedef struct HgraphOrderCpMate_ { + Gnum coarvertend; /*+ Adjacent coarse end vertex number +*/ + Gnum finevertend; /*+ Adjacent end vertex number +*/ +} HgraphOrderCpMate; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_CP +#define static +#endif + +int hmeshOrderCp (const Hmesh * const, Order * const, const Gnum, OrderCblk * const, const HmeshOrderCpParam * const); + +static Gnum hmeshOrderCpTree (const Gnum * const, const Gnum * const, OrderCblk * const, Gnum); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_gp.c b/scotch_6.0.3/src/libscotch/hmesh_order_gp.c new file mode 100644 index 00000000..be2b9477 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_gp.c @@ -0,0 +1,244 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_gp.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a subgraph (most **/ +/** likely a separator) using the Gibbs, **/ +/** Poole, and Stockmeyer algorithm. **/ +/** **/ +/** DATES : # Version 3.2 : from : 31 oct 1996 **/ +/** to 27 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 4.0 : from : 05 nov 2002 **/ +/** to : 27 jan 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to : 12 sep 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_GP + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "mesh.h" +#include "hmesh.h" +#include "hmesh_order_gp.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hmeshOrderGp ( +const Hmesh * restrict const meshptr, +Order * restrict const ordeptr, +const Gnum ordenum, +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HmeshOrderGpParam * restrict const paraptr) +{ + HmeshOrderGpQueue queue; /* Neighbor queue */ + HmeshOrderGpVertex * restrict vexxtax; /* Based access to vertex array */ + HmeshOrderGpVertex * rootptr; /* Pointer to root vertex */ + Gnum passnum; /* Pass number */ + int passflag; /* Flag set if diameter changed */ + Gnum vdianum; /* Vertex which achieves diameter */ + Gnum vdiadist; /* Maximum diameter value found */ + Gnum vnodnbr; /* Number of vertices found yet */ + Gnum ordeval; /* Current ordering value */ + + if (memAllocGroup ((void **) (void *) + &queue.qtab, (size_t) ((meshptr->vnohnnd - meshptr->m.baseval) * sizeof (Gnum)), + &vexxtax, (size_t) ((meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (HmeshOrderGpVertex)), NULL) == NULL) { + errorPrint ("hmeshOrderGp: out of memory"); + return (1); + } + vexxtax -= meshptr->m.baseval; /* Base vexxtab array */ + memSet (vexxtax + meshptr->m.velmbas, 0, meshptr->m.velmnbr * sizeof (HmeshOrderGpVertex)); /* Initialize pass numbers for */ + memSet (vexxtax + meshptr->m.vnodbas, 0, (meshptr->vnohnnd - meshptr->m.vnodbas) * sizeof (HmeshOrderGpVertex)); /* All but halo node vertices */ + + for (vnodnbr = 0, ordeval = ordenum, rootptr = vexxtax + meshptr->m.vnodbas, passnum = 1; /* For all connected components */ + vnodnbr < meshptr->vnohnbr; passnum ++) { + while (rootptr->passnum != 0) /* Find first unallocated root */ + rootptr ++; + + vdianum = rootptr - vexxtax; /* Start from found root */ + vdiadist = 0; + for (passflag = 1; (passflag -- != 0) && (passnum <= paraptr->passnbr); passnum ++) { /* Loop if modifications */ + hmeshOrderGpQueueFlush (&queue); /* Flush vertex queue */ + hmeshOrderGpQueuePut (&queue, vdianum); /* Start from diameter vertex */ + vexxtax[vdianum].passnum = passnum; /* It has been enqueued */ + vexxtax[vdianum].vertdist = 0; /* It is at distance zero */ + + do { /* Loop on vertices in queue */ + Gnum vnodnum; /* Number of current vertex */ + Gnum vnoddist; /* Distance of current vertex */ + Gnum enodnum; + + vnodnum = hmeshOrderGpQueueGet (&queue); /* Get vertex from queue */ + vnoddist = vexxtax[vnodnum].vertdist; /* Get vertex distance */ + + if ((vnoddist > vdiadist) || /* If vertex increases diameter */ + ((vnoddist == vdiadist) && /* Or is at diameter distance */ + ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) < /* With smaller degree */ + (meshptr->m.vendtax[vdianum] - meshptr->m.verttax[vdianum])))) { + vdianum = vnodnum; /* Set it as new diameter vertex */ + vdiadist = vnoddist; + passflag = 1; + } + + vnoddist ++; /* Set neighbor distance */ + + for (enodnum = meshptr->m.verttax[vnodnum]; enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { + Gnum velmnum; + Gnum eelmnum; + + velmnum = meshptr->m.edgetax[enodnum]; /* Get neighboring element */ + + if (vexxtax[velmnum].passnum >= passnum) /* If element already scanned */ + continue; /* Skip to next element */ + + vexxtax[velmnum].passnum = passnum; /* Set element as scanned */ + + for (eelmnum = meshptr->m.verttax[velmnum]; /* For all neighboring non-halo nodes */ + eelmnum < meshptr->vehdtax[velmnum]; eelmnum ++) { + Gnum vnodend; /* Neighboring node */ + + vnodend = meshptr->m.edgetax[eelmnum]; /* Get neighboring node */ + + if (vexxtax[vnodend].passnum < passnum) { /* If node vertex not yet enqueued */ + hmeshOrderGpQueuePut (&queue, vnodend); /* Enqueue neighbor vertex */ + vexxtax[vnodend].passnum = passnum; + vexxtax[vnodend].vertdist = vnoddist; + } + } + } + } while (! hmeshOrderGpQueueEmpty (&queue)); /* As long as queue is not empty */ + } + + hmeshOrderGpQueueFlush (&queue); /* Flush vertex queue */ + hmeshOrderGpQueuePut (&queue, vdianum); /* Start from diameter vertex */ + vexxtax[vdianum].passnum = passnum; /* It has been enqueued */ + + do { /* Loop on vertices in queue */ + Gnum vnodnum; /* Number of current vertex */ + Gnum vnoddist; /* Distance of current vertex */ + + vnodnum = hmeshOrderGpQueueGet (&queue); /* Get vertex from queue */ + if (vexxtax[vnodnum].passnum > passnum) /* If vertex already ordered */ + continue; /* Skip to next vertex in queue */ + + vnoddist = vexxtax[vnodnum].vertdist; /* Get vertex distance */ + do { /* Loop on vertices in layer */ + Gnum enodnum; + Gnum enodnnd; + + ordeptr->peritab[ordeval] = (meshptr->m.vnumtax == NULL) /* Order node vertex */ + ? vnodnum - (meshptr->m.vnodbas - meshptr->m.baseval) + : meshptr->m.vnumtax[vnodnum]; +#ifdef SCOTCH_DEBUG_ORDER2 + if ((ordeptr->peritab[ordeval] < ordeptr->baseval) || + (ordeptr->peritab[ordeval] >= (ordeptr->baseval + ordeptr->vnodnbr))) { + errorPrint ("hmeshOrderGp: invalid permutation index"); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + ordeval ++; + + vexxtax[vnodnum].passnum = (passnum + 1); /* Set vertex as ordered */ + vnodnbr ++; /* Count it */ + + for (enodnum = meshptr->m.verttax[vnodnum], enodnnd = meshptr->m.vendtax[vnodnum], vnodnum = ~0; + enodnum < enodnnd; enodnum ++) { /* Order node vertices with high locality */ + Gnum velmnum; /* Neighboring element */ + Gnum eelmnum; + + velmnum = meshptr->m.edgetax[enodnum]; /* Get neighboring element */ + + if (vexxtax[velmnum].passnum >= passnum) /* If element already scanned */ + continue; /* Skip to next element */ + + vexxtax[velmnum].passnum = passnum; /* Set element as scanned */ + + for (eelmnum = meshptr->m.verttax[velmnum]; /* For all neighboring non-halo nodes */ + eelmnum < meshptr->vehdtax[velmnum]; eelmnum ++) { + Gnum vnodend; /* Neighboring node */ + + vnodend = meshptr->m.edgetax[eelmnum]; /* Get neighboring node */ + + if (vexxtax[vnodend].passnum <= passnum) { /* If vertex not ordered yet */ + if ((vnodnum == ~0) && /* If no next vertex set yet */ + (vexxtax[vnodend].vertdist == vnoddist)) /* And in same layer */ + vnodnum = vnodend; /* Set neighbor as next vertex */ + else if (vexxtax[vnodend].passnum < passnum) { /* If not enqueued yet */ + hmeshOrderGpQueuePut (&queue, vnodend); /* Enqueue neighbor vertex */ + vexxtax[vnodend].passnum = passnum; /* Set it as enqueued */ + } + } + } + } + } while (vnodnum != ~0); + } while (! hmeshOrderGpQueueEmpty (&queue)); /* As long as queue is not empty */ + } + +#ifdef SCOTCH_DEBUG_ORDER2 + for (ordeval = ordenum; ordeval < (ordenum + meshptr->vnohnbr); ordeval ++) { + if (ordeptr->peritab[ordeval] == ~0) { + errorPrint ("hmeshOrderGp: internal error"); + memFree (queue.qtab); /* Free group leader */ + return (1); + } + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + + memFree (queue.qtab); /* Free group leader */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_gp.h b/scotch_6.0.3/src/libscotch/hmesh_order_gp.h new file mode 100644 index 00000000..2d3c190b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_gp.h @@ -0,0 +1,97 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_gp.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the Gibbs-Poole-Stockmeyer **/ +/** node ordering routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 31 oct 1996 **/ +/** to : 27 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 4.0 : from : 04 nov 2002 **/ +/** to : 01 dec 2003 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 01 oct 2009 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HmeshOrderGpParam_ { + INT passnbr; /*+ Number of passes to do +*/ +} HmeshOrderGpParam; + +/*+ Complementary vertex structure. +*/ + +typedef struct HmeshOrderGpVertex_ { + Gnum passnum; /*+ Number of pass when vertex selected +*/ + Gnum vertdist; /*+ Current distance from diameter vertex +*/ +} HmeshOrderGpVertex; + +/*+ Neighbor queue. +*/ + +typedef struct HmeshOrderGpQueue_ { + Gnum * head; /*+ Head of distance queue +*/ + Gnum * tail; /*+ Tail of distance queue +*/ + Gnum * qtab; /*+ Array of queue elements +*/ +} HmeshOrderGpQueue; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_GP +#define static +#endif + +int hmeshOrderGp (const Hmesh * const, Order * const, const Gnum, OrderCblk * const, const HmeshOrderGpParam * restrict const); + +#undef static + +/* +** The macro definitions. +*/ + +#define hmeshOrderGpQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) +#define hmeshOrderGpQueueEmpty(queue) ((queue)->head <= (queue)->tail) +#define hmeshOrderGpQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) +#define hmeshOrderGpQueueGet(queue) (* ((queue)->tail ++)) diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_gr.c b/scotch_6.0.3/src/libscotch/hmesh_order_gr.c new file mode 100644 index 00000000..fe500973 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_gr.c @@ -0,0 +1,99 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_gr.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a halo mesh by **/ +/** turning it into a graph and using a **/ +/** graph separation strategy. **/ +/** **/ +/** DATES : # Version 4.0 : from : 30 nov 2003 **/ +/** to 27 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_GR + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_st.h" +#include "mesh.h" +#include "hmesh.h" +#include "hmesh_order_gr.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hmeshOrderGr ( +const Hmesh * restrict const meshptr, +Order * restrict const ordeptr, +const Gnum ordenum, +OrderCblk * restrict const cblkptr, +const HmeshOrderGrParam * const paraptr) +{ + Hgraph grafdat; + int o; + + hgraphInit (&grafdat); + if (hmeshHgraph (meshptr, &grafdat) != 0) { /* Build halo graph with improper vnumtab */ + errorPrint ("hmeshOrderGr: cannot build halo graph"); + return (1); + } + + if ((o = hgraphOrderSt (&grafdat, ordeptr, ordenum, cblkptr, paraptr->stratptr)) != 0) + errorPrint ("hmeshOrderGr: cannot order graph"); + + hgraphFree (&grafdat); /* Free graph structure */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_gr.h b/scotch_6.0.3/src/libscotch/hmesh_order_gr.h new file mode 100644 index 00000000..764e142e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_gr.h @@ -0,0 +1,67 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_gr.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the graph-based node ordering **/ +/** routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 30 nov 2003 **/ +/** to : 30 nov 2003 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HmeshOrderGrParam_ { + Strat * stratptr; /*+ Graph ordering strategy +*/ +} HmeshOrderGrParam; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_GR +#define static +#endif + +int hmeshOrderGr (const Hmesh * const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HmeshOrderGrParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_hd.c b/scotch_6.0.3/src/libscotch/hmesh_order_hd.c new file mode 100644 index 00000000..9897fac4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_hd.c @@ -0,0 +1,159 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_hd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a submesh using **/ +/** the block-oriented Halo Approximate **/ +/** (Multiple) Minimum Degree algorithm, **/ +/** with super-variable accounting **/ +/** R2HAMDf4 v2.0). **/ +/** **/ +/** DATES : # Version 4.0 : from : 10 dec 2003 **/ +/** to : 24 jan 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to : 12 sep 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_HD + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "mesh.h" +#include "hmesh.h" +#include "hall_order_hd.h" +#include "hall_order_hx.h" +#include "hmesh_order_hd.h" +#include "hmesh_order_hx.h" +#include "hmesh_order_si.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hmeshOrderHd ( +const Hmesh * restrict const meshptr, +Order * restrict const ordeptr, +const Gnum ordenum, +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HmeshOrderHdParam * restrict const paraptr) +{ + Gnum * restrict petab; + Gnum pfree; + Gnum iwlen; + Gnum * restrict iwtab; + Gnum * restrict lentab; + Gnum * restrict nvartab; + Gnum * restrict elentab; + Gnum * restrict lasttab; + Gnum * restrict leaftab; + Gnum * restrict secntab; /* Array of index to first secondary variable */ + Gnum * restrict nexttab; /* Array of index of next principal variable */ + Gnum * restrict frsttab; + Gnum ncmpa; + Gnum n; /* Number of nodes to order */ + int o; + + n = meshptr->m.velmnbr + meshptr->m.vnodnbr; + + if (n < paraptr->colmin) /* If graph is too small, order simply */ + return (hmeshOrderSi (meshptr, ordeptr, ordenum, cblkptr)); + + iwlen = (Gnum) ((double) meshptr->m.edgenbr * HMESHORDERHDCOMPRAT) + 32; + if (iwlen < n) /* Prepare to re-use array */ + iwlen = n; + + if (memAllocGroup ((void **) (void *) + &petab, (size_t) (n * sizeof (Gnum)), + &iwtab, (size_t) (iwlen * sizeof (Gnum)), + &lentab, (size_t) (n * sizeof (Gnum)), + &nvartab, (size_t) (n * sizeof (Gnum)), + &elentab, (size_t) (n * sizeof (Gnum)), + &lasttab, (size_t) (n * sizeof (Gnum)), + &leaftab, (size_t) (n * sizeof (Gnum)), + &frsttab, (size_t) (n * sizeof (Gnum)), + &secntab, (size_t) (n * sizeof (Gnum)), + &nexttab, (size_t) (n * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hmeshOrderHd: out of memory"); + return (1); + } + + hmeshOrderHxFill (meshptr, petab, lentab, iwtab, elentab, &pfree); + + hallOrderHdHalmd (n, meshptr->m.velmnbr, iwlen, petab, pfree, + lentab, iwtab, nvartab, elentab, lasttab, &ncmpa, + leaftab, secntab, nexttab, frsttab); + + if (ncmpa < 0) { + errorPrint ("hmeshOrderHd: internal error"); + memFree (petab); /* Free group leader */ + return (1); + } + + o = hallOrderHxBuild (meshptr->m.baseval, n, meshptr->vnohnbr, + (meshptr->m.vnumtax == NULL) ? NULL : meshptr->m.vnumtax + (meshptr->m.vnodbas - meshptr->m.baseval), /* Point to node part of vnumtab array */ + ordeptr, cblkptr, + nvartab - meshptr->m.baseval, + lentab - meshptr->m.baseval, + petab - meshptr->m.baseval, + frsttab - meshptr->m.baseval, + nexttab - meshptr->m.baseval, + secntab - meshptr->m.baseval, + iwtab - meshptr->m.baseval, + elentab - meshptr->m.baseval, + ordeptr->peritab + ordenum, /* Use given inverse permutation as inverse permutation space, never based */ + leaftab, + paraptr->colmin, paraptr->colmax, (float) paraptr->fillrat); + + memFree (petab); /* Free group leader */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_hd.h b/scotch_6.0.3/src/libscotch/hmesh_order_hd.h new file mode 100644 index 00000000..a2437643 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_hd.h @@ -0,0 +1,78 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_hd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the block-oriented Halo **/ +/** Approximate (Multiple) Minimum Degree **/ +/** mesh ordering routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 09 dec 2003 **/ +/** to 10 dec 2003 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 01 oct 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#define HMESHORDERHDCOMPRAT 1.2L /*+ Compression ratio +*/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HmeshOrderHdParam_ { + INT colmin; /*+ Minimum number of columns +*/ + INT colmax; /*+ Maximum number of columns +*/ + double fillrat; /*+ Fill-in ratio +*/ +} HmeshOrderHdParam; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_HD +#define static +#endif + +int hmeshOrderHd (const Hmesh * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HmeshOrderHdParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_hf.c b/scotch_6.0.3/src/libscotch/hmesh_order_hf.c new file mode 100644 index 00000000..ca99b297 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_hf.c @@ -0,0 +1,162 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_hf.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders a submesh using **/ +/** the block-oriented Halo Approximate **/ +/** (Multiple) Minimum Fill algorithm, **/ +/** with super-variable accounting **/ +/** R2HAMDf4 v2.0). **/ +/** **/ +/** DATES : # Version 4.0 : from : 08 dec 2003 **/ +/** to : 09 dec 2003 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to : 12 sep 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_HF + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "mesh.h" +#include "hmesh.h" +#include "hall_order_hf.h" +#include "hall_order_hx.h" +#include "hmesh_order_hf.h" +#include "hmesh_order_hx.h" +#include "hmesh_order_si.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hmeshOrderHf ( +const Hmesh * restrict const meshptr, +Order * restrict const ordeptr, +const Gnum ordenum, +OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ +const HmeshOrderHfParam * restrict const paraptr) +{ + Gnum nbbuck; + Gnum * restrict petab; + Gnum pfree; + Gnum iwlen; + Gnum * restrict iwtab; + Gnum * restrict lentab; + Gnum * restrict nvartab; + Gnum * restrict elentab; + Gnum * restrict lasttab; + Gnum * restrict leaftab; + Gnum * restrict secntab; /* Array of index to first secondary variable */ + Gnum * restrict nexttab; /* Array of index of next principal variable */ + Gnum * restrict frsttab; + Gnum * restrict headtab; /* Head array : nbbuck = 2 * n */ + Gnum ncmpa; + Gnum n; /* Number of nodes to order */ + int o; + + n = meshptr->m.velmnbr + meshptr->m.vnodnbr; + + if (n < paraptr->colmin) /* If graph is too small, order simply */ + return (hmeshOrderSi (meshptr, ordeptr, ordenum, cblkptr)); + + nbbuck = n * 2; + iwlen = (Gnum) ((double) meshptr->m.edgenbr * HMESHORDERHFCOMPRAT) + 32; + if (iwlen < n) /* Prepare to re-use array */ + iwlen = n; + + if (memAllocGroup ((void **) (void *) + &petab, (size_t) (n * sizeof (Gnum)), + &iwtab, (size_t) (iwlen * sizeof (Gnum)), + &lentab, (size_t) (n * sizeof (Gnum)), + &nvartab, (size_t) (n * sizeof (Gnum)), + &elentab, (size_t) (n * sizeof (Gnum)), + &lasttab, (size_t) (n * sizeof (Gnum)), + &leaftab, (size_t) (n * sizeof (Gnum)), + &frsttab, (size_t) (n * sizeof (Gnum)), + &secntab, (size_t) (n * sizeof (Gnum)), + &nexttab, (size_t) (n * sizeof (Gnum)), + &headtab, (size_t) ((nbbuck + 2) * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hmeshOrderHf: out of memory"); + return (1); + } + + hmeshOrderHxFill (meshptr, petab, lentab, iwtab, elentab, &pfree); + + hallOrderHfR2hamdf4 (n, meshptr->m.velmnbr, nbbuck, iwlen, petab, pfree, + lentab, iwtab, nvartab, elentab, lasttab, &ncmpa, + leaftab, secntab, nexttab, frsttab, headtab); + if (ncmpa < 0) { + errorPrint ("hmeshOrderHf: internal error"); + memFree (petab); /* Free group leader */ + return (1); + } + + o = hallOrderHxBuild (meshptr->m.baseval, n, meshptr->vnohnbr, + (meshptr->m.vnumtax == NULL) ? NULL : meshptr->m.vnumtax + (meshptr->m.vnodbas - meshptr->m.baseval), /* Point to node part of vnumtab array */ + ordeptr, cblkptr, + nvartab - meshptr->m.baseval, + lentab - meshptr->m.baseval, + petab - meshptr->m.baseval, + frsttab - meshptr->m.baseval, + nexttab - meshptr->m.baseval, + secntab - meshptr->m.baseval, + iwtab - meshptr->m.baseval, + elentab - meshptr->m.baseval, + ordeptr->peritab + ordenum, /* Use given inverse permutation as inverse permutation space, never based */ + leaftab, + paraptr->colmin, paraptr->colmax, (float) paraptr->fillrat); + + memFree (petab); /* Free group leader */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_hf.h b/scotch_6.0.3/src/libscotch/hmesh_order_hf.h new file mode 100644 index 00000000..1cd13cc9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_hf.h @@ -0,0 +1,78 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_hf.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the block-oriented Halo **/ +/** Approximate (Multiple) Minimum Fill **/ +/** mesh ordering routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 09 dec 2003 **/ +/** to 10 dec 2003 **/ +/** # Version 5.1 : from : 01 oct 2009 **/ +/** to : 01 oct 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#define HMESHORDERHFCOMPRAT 1.2L /*+ Compression ratio +*/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HmeshOrderHfParam_ { + INT colmin; /*+ Minimum number of columns +*/ + INT colmax; /*+ Maximum number of columns +*/ + double fillrat; /*+ Fill-in ratio +*/ +} HmeshOrderHfParam; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_HF +#define static +#endif + +int hmeshOrderHf (const Hmesh * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HmeshOrderHfParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_hx.c b/scotch_6.0.3/src/libscotch/hmesh_order_hx.c new file mode 100644 index 00000000..f300144b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_hx.c @@ -0,0 +1,183 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_hx.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains service routines **/ +/** for the hmeshOrderH{d|f} ordering **/ +/** routines. **/ +/** **/ +/** DATES : # Version 4.0 : from : 09 dec 2003 **/ +/** to : 24 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_HX + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "hmesh.h" +#include "hmesh_order_hx.h" + +/***********************************/ +/* */ +/* These are the service routines. */ +/* */ +/***********************************/ + +/* This routine fills the input arrays for +** the mesh ordering routines. +** It returns: +** - void : in all cases. +*/ + +int +hmeshOrderHxFill ( +const Hmesh * restrict const meshptr, +Gnum * restrict const petab, +Gnum * restrict const lentab, +Gnum * restrict const iwtab, +Gnum * restrict const elentab, +Gnum * restrict const pfreptr) +{ + Gnum * restrict petax; + Gnum * restrict iwtax; + Gnum * restrict lentax; + Gnum * restrict elentax; + HmeshOrderHxHash * restrict hashtab; /* Neighbor hash table */ + Gnum hashsiz; + Gnum hashmsk; + Gnum n; /* Number of nodes to order */ + Gnum velmadj; /* Index adjustment for element indices */ + Gnum vnodadj; /* Index adjustment for node indices */ + Gnum velmnum; + Gnum vnodnum; + Gnum degrval; + Gnum vertnum; + Gnum edgenum; + + n = meshptr->m.velmnbr + meshptr->m.vnodnbr; + for (hashsiz = 16, degrval = meshptr->m.degrmax * (meshptr->m.degrmax - 1); /* Compute hash table size */ + hashsiz < degrval; hashsiz <<= 1) ; + hashsiz <<= 1; + hashmsk = hashsiz - 1; + + if ((hashtab = memAlloc (hashsiz * sizeof (HmeshOrderHxHash))) == NULL) { + errorPrint ("hmeshOrderHxFill: out of memory"); + return (1); + } + memSet (hashtab, ~0, hashsiz * sizeof (HmeshOrderHxHash)); + + petax = petab - 1; /* Base HAMF arrays at base 1 */ + iwtax = iwtab - 1; + lentax = lentab - 1; + elentax = elentab - 1; + + velmadj = 1 + meshptr->m.vnodnbr - meshptr->m.velmbas; + for (vnodnum = meshptr->m.vnodbas, vertnum = edgenum = 1; /* Copy non-halo node data with base 1 */ + vnodnum < meshptr->vnohnnd; vertnum ++, vnodnum ++) { + Gnum enodnum; + Gnum nghbnbr; + + petax[vertnum] = edgenum; + lentax[vertnum] = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]; + + for (enodnum = meshptr->m.verttax[vnodnum], nghbnbr = -1; /* -1 since loop edge will be processed in the main loop */ + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { + Gnum velmnum; + Gnum eelmnum; + + velmnum = meshptr->m.edgetax[enodnum]; + + iwtax[edgenum ++] = velmnum + velmadj; /* Adjust end element index */ + for (eelmnum = meshptr->m.verttax[velmnum]; eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnodend; + Gnum hnodend; + + vnodend = meshptr->m.edgetax[eelmnum]; + + for (hnodend = (vnodend * HMESHORDERHXHASHPRIME) & hashmsk; ; hnodend = (hnodend + 1) & hashmsk) { + if (hashtab[hnodend].vertnum != vnodnum) { + hashtab[hnodend].vertnum = vnodnum; + hashtab[hnodend].vertend = vnodend; + nghbnbr ++; + } + if (hashtab[hnodend].vertend == vnodend) /* If end vertex already present */ + break; /* Skip to next end vertex */ + } + } + elentax[vertnum] = nghbnbr; + } + } + + for ( ; vnodnum < meshptr->m.vnodnnd; vnodnum ++, vertnum ++) { /* Copy halo vertices with base 1 */ + Gnum degrval; + Gnum enodnum; + + degrval = meshptr->m.verttax[vnodnum] - meshptr->m.vendtax[vnodnum]; + petax[vertnum] = edgenum; + lentax[vertnum] = (degrval != 0) ? degrval : - (n + 1); + elentax[vertnum] = 0; + + for (enodnum = meshptr->m.verttax[vnodnum]; + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) + iwtax[edgenum ++] = meshptr->m.edgetax[enodnum] + velmadj; /* Adjust end element index */ + } + + vnodadj = 1 - meshptr->m.vnodbas; /* Base nodes at 1 */ + for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++, vertnum ++) { + Gnum eelmnum; + + petax[vertnum] = edgenum; + lentax[vertnum] = meshptr->m.vendtax[velmnum] - meshptr->m.verttax[velmnum]; + elentax[vertnum] = - (n + 1); + + for (eelmnum = meshptr->m.verttax[velmnum]; + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) + iwtax[edgenum ++] = meshptr->m.edgetax[eelmnum] + vnodadj; /* Adjust end node index */ + } + + *pfreptr = edgenum; /* Set index to first free area */ + + memFree (hashtab); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_hx.h b/scotch_6.0.3/src/libscotch/hmesh_order_hx.h new file mode 100644 index 00000000..3fd5f70b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_hx.h @@ -0,0 +1,76 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_hx.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the halo mesh block Approxi- **/ +/** mate (Multiple) Minimum Degree and Fill **/ +/** ordering routines. **/ +/** **/ +/** DATES : # Version 4.0 : from : 09 dec 2003 **/ +/** to 09 dec 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#define HMESHORDERHXHASHPRIME 17 /* Prime number */ + +/* +** The type and structure definitions. +*/ + +/*+ A table made of such elements is used to compute + the external degree of non-halo vertices. +*/ + +typedef struct HmeshOrderHxHash_ { + Gnum vertnum; /*+ Origin vertex (i.e. pass) number +*/ + Gnum vertend; /*+ End vertex number in mesh +*/ +} HmeshOrderHxHash; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_HX +#define static +#endif + +int hmeshOrderHxFill (const Hmesh * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_nd.c b/scotch_6.0.3/src/libscotch/hmesh_order_nd.c new file mode 100644 index 00000000..1a093a58 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_nd.c @@ -0,0 +1,204 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_nd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders mesh nodes using the **/ +/** nested dissection algorithm. **/ +/** **/ +/** DATES : # Version 4.0 : from : 06 jan 2002 **/ +/** to 05 jan 2005 **/ +/** # Version 5.0 : from : 25 jul 2007 **/ +/** to : 12 sep 2007 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to : 09 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_ND + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "mesh.h" +#include "hmesh.h" +#include "hmesh_order_nd.h" +#include "hmesh_order_st.h" +#include "vmesh.h" +#include "vmesh_separate_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hmeshOrderNd ( +const Hmesh * restrict const meshptr, +Order * restrict const ordeptr, +const Gnum ordenum, +OrderCblk * restrict const cblkptr, +const HmeshOrderNdParam * const paraptr) +{ + Hmesh indmeshdat; /* Induced halo mesh data */ + Vmesh nspmeshdat; /* Node separation mesh */ + Gnum vertnbr; + int o; + + if (hmeshMesh (meshptr, &nspmeshdat.m) != 0) { + errorPrint ("hmeshOrderNd: cannot create node separation mesh"); + return (1); + } + nspmeshdat.ecmpsize[0] = nspmeshdat.m.velmnbr; + nspmeshdat.ecmpsize[1] = 0; + nspmeshdat.ncmpload[0] = nspmeshdat.m.vnlosum; + nspmeshdat.ncmpload[1] = 0; + nspmeshdat.ncmpload[2] = 0; + nspmeshdat.ncmploaddlt = nspmeshdat.m.vnlosum; + nspmeshdat.ncmpsize[0] = nspmeshdat.m.vnodnbr; + nspmeshdat.ncmpsize[1] = 0; + nspmeshdat.fronnbr = 0; + nspmeshdat.levlnum = meshptr->levlnum; + + vertnbr = nspmeshdat.m.velmnbr + nspmeshdat.m.vnodnbr; + if (memAllocGroup ((void **) (void *) + &nspmeshdat.parttax, (size_t) (vertnbr * sizeof (GraphPart)), + &nspmeshdat.frontab, (size_t) (vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("hmeshOrderNd: out of memory (1)"); + return (1); + } + memSet (nspmeshdat.parttax, 0, vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ + nspmeshdat.parttax -= nspmeshdat.m.baseval; + + if (vmeshSeparateSt (&nspmeshdat, paraptr->sepstrat) != 0) { /* Separate mesh */ + vmeshExit (&nspmeshdat); + return (1); + } + + if ((nspmeshdat.ncmpsize[0] == 0) || /* If could not separate more */ + (nspmeshdat.ncmpsize[1] == 0)) { + vmeshExit (&nspmeshdat); + + return (hmeshOrderSt (meshptr, ordeptr, ordenum, cblkptr, paraptr->ordstratlea)); /* Order this leaf */ + } + + cblkptr->typeval = ORDERCBLKNEDI; /* Node becomes a nested dissection node */ + if ((cblkptr->cblktab = (OrderCblk *) memAlloc (3 * sizeof (OrderCblk))) == NULL) { + errorPrint ("hmeshOrderNd: out of memory (2)"); + vmeshExit (&nspmeshdat); + return (1); + } + cblkptr->cblktab[0].typeval = ORDERCBLKOTHR; /* Build column blocks */ + cblkptr->cblktab[0].vnodnbr = nspmeshdat.ncmpsize[0]; + cblkptr->cblktab[0].cblknbr = 0; + cblkptr->cblktab[0].cblktab = NULL; + cblkptr->cblktab[1].typeval = ORDERCBLKOTHR; + cblkptr->cblktab[1].vnodnbr = nspmeshdat.ncmpsize[1]; + cblkptr->cblktab[1].cblknbr = 0; + cblkptr->cblktab[1].cblktab = NULL; + cblkptr->cblktab[2].vnodnbr = nspmeshdat.fronnbr; + cblkptr->cblktab[2].cblknbr = 0; + cblkptr->cblktab[2].cblktab = NULL; + + if (nspmeshdat.fronnbr != 0) { /* If separator not empty */ + cblkptr->cblknbr = 3; /* It is a three-cell tree node */ + ordeptr->cblknbr += 2; /* Two more column blocks created */ + ordeptr->treenbr += 3; /* Three more tree nodes created */ + + cblkptr->cblktab[2].typeval = ORDERCBLKOTHR; + cblkptr->cblktab[2].vnodnbr = nspmeshdat.fronnbr; + cblkptr->cblktab[2].cblknbr = 0; + cblkptr->cblktab[2].cblktab = NULL; + + if (meshInduceSepa (&nspmeshdat.m, nspmeshdat.parttax, nspmeshdat.fronnbr, nspmeshdat.frontab, &indmeshdat.m) != 0) { + errorPrint ("hmeshOrderNd: cannot build induced subgraph (1)"); + memFree (nspmeshdat.frontab); /* Free remaining space */ + return (1); + } + indmeshdat.vnohnbr = indmeshdat.m.vnodnbr; /* Fill halo mesh structure of non-halo mesh */ + indmeshdat.vnohnnd = indmeshdat.m.vnodnnd; + indmeshdat.vehdtax = indmeshdat.m.vendtax; + indmeshdat.vnhlsum = indmeshdat.m.vnlosum; + indmeshdat.enohnbr = indmeshdat.m.edgenbr; + indmeshdat.levlnum = meshptr->levlnum; /* Separator mesh is at level of original mesh */ + + o = hmeshOrderSt (&indmeshdat, ordeptr, ordenum + nspmeshdat.ncmpsize[0] + nspmeshdat.ncmpsize[1], + cblkptr->cblktab + 2, paraptr->ordstratsep); + hmeshExit (&indmeshdat); + } + else { /* Separator is empty */ + cblkptr->cblknbr = 2; /* It is a two-cell tree node */ + ordeptr->cblknbr ++; /* One more column block created */ + ordeptr->treenbr += 2; /* Two more tree nodes created */ + o = 0; /* No separator ordering computed */ + } + if (o == 0) { + if (hmeshInducePart (meshptr, nspmeshdat.parttax, 0, nspmeshdat.ecmpsize[0], + nspmeshdat.ncmpsize[0], nspmeshdat.fronnbr, &indmeshdat) != 0) { + errorPrint ("hmeshOrderNd: cannot build induced subgraph (2)"); + memFree (nspmeshdat.frontab); /* Free remaining space */ + return (1); + } + o = hmeshOrderNd (&indmeshdat, ordeptr, ordenum, cblkptr->cblktab, paraptr); + hmeshExit (&indmeshdat); + } + if (o == 0) { + if (hmeshInducePart (meshptr, nspmeshdat.parttax, 1, nspmeshdat.ecmpsize[1], + nspmeshdat.ncmpsize[1], nspmeshdat.fronnbr, &indmeshdat) != 0) { + errorPrint ("hmeshOrderNd: cannot build induced subgraph (3)"); + memFree (nspmeshdat.frontab); /* Free remaining space */ + return (1); + } + o = hmeshOrderNd (&indmeshdat, ordeptr, ordenum + nspmeshdat.ncmpsize[0], cblkptr->cblktab + 1, paraptr); + hmeshExit (&indmeshdat); + } + + vmeshExit (&nspmeshdat); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_nd.h b/scotch_6.0.3/src/libscotch/hmesh_order_nd.h new file mode 100644 index 00000000..b97df51c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_nd.h @@ -0,0 +1,69 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_nd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the halo mesh nested dissection **/ +/** ordering algorithm. **/ +/** **/ +/** DATES : # Version 4.0 : from : 06 jan 2002 **/ +/** to 23 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct HmeshOrderNdParam_ { + Strat * sepstrat; /*+ Separation strategy +*/ + Strat * ordstratlea; /*+ Leaf ordering strategy +*/ + Strat * ordstratsep; /*+ Separator ordering strategy +*/ +} HmeshOrderNdParam; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_ND +#define static +#endif + +int hmeshOrderNd (const Hmesh * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HmeshOrderNdParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_si.c b/scotch_6.0.3/src/libscotch/hmesh_order_si.c new file mode 100644 index 00000000..e8f5058b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_si.c @@ -0,0 +1,109 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_si.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module orders halo mesh vertices **/ +/** using the natural order. **/ +/** **/ +/** DATES : # Version 4.0 : from : 01 jan 2002 **/ +/** to 27 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_SI + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" +#include "mesh.h" +#include "hmesh.h" +#include "hmesh_order_si.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the ordering. +** It returns: +** - 0 : if the ordering could be computed. +** - !0 : on error. +*/ + +int +hmeshOrderSi ( +const Hmesh * restrict const meshptr, +Order * restrict const ordeptr, +const Gnum ordenum, +OrderCblk * restrict const cblkptr) /*+ Single column-block +*/ +{ + Gnum vnodnum; + Gnum ordeval; + + if (meshptr->m.vnumtax == NULL) { /* If mesh is original mesh (no halo) */ +#ifdef SCOTCH_DEBUG_ORDER2 + if (meshptr->m.vnodnbr != ordeptr->vnodnbr) { + errorPrint ("hmeshOrderSi: invalid permutation bounds"); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + for (vnodnum = ordeptr->baseval, ordeval = ordenum; + vnodnum < ordeptr->baseval + ordeptr->vnodnbr; vnodnum ++, ordeval ++) { + ordeptr->peritab[ordeval] = vnodnum; + } + } + else { /* Mesh is not original mesh */ + for (vnodnum = meshptr->m.vnodbas, ordeval = ordenum; + vnodnum < meshptr->vnohnnd; vnodnum ++, ordeval ++) { + ordeptr->peritab[ordeval] = meshptr->m.vnumtax[vnodnum]; +#ifdef SCOTCH_DEBUG_ORDER2 + if ((ordeptr->peritab[ordeval] < ordeptr->baseval) || + (ordeptr->peritab[ordeval] >= (ordeptr->baseval + ordeptr->vnodnbr))) { + errorPrint ("hmeshOrderSi: invalid permutation index"); + return (1); + } +#endif /* SCOTCH_DEBUG_ORDER2 */ + } + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_si.h b/scotch_6.0.3/src/libscotch/hmesh_order_si.h new file mode 100644 index 00000000..ce1963fb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_si.h @@ -0,0 +1,57 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_si.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the simple halo mesh ordering **/ +/** routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 01 jan 2002 **/ +/** to 28 sep 2002 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_SI +#define static +#endif + +int hmeshOrderSi (const Hmesh * const, Order * const, const Gnum, OrderCblk * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_st.c b/scotch_6.0.3/src/libscotch/hmesh_order_st.c new file mode 100644 index 00000000..ca7329d5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_st.c @@ -0,0 +1,298 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_st.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the generic call to the **/ +/** halo mesh ordering module, using a **/ +/** given strategy. **/ +/** **/ +/** DATES : # Version 4.0 : from : 28 sep 2002 **/ +/** to 05 jan 2005 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define HMESH_ORDER_ST + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "hgraph.h" +#include "mesh.h" +#include "hmesh.h" +#include "order.h" +#include "hgraph_order_st.h" +#include "hmesh_order_bl.h" +#include "hmesh_order_cp.h" +#include "hmesh_order_gp.h" +#include "hmesh_order_gr.h" +#include "hmesh_order_hd.h" +#include "hmesh_order_hf.h" +#include "hmesh_order_nd.h" +#include "hmesh_order_si.h" +#include "hmesh_order_st.h" +#include "vmesh.h" +#include "vmesh_separate_st.h" + +/* +** The static and global variables. +*/ + +static Hmesh hmeshorderstmeshdummy; /* Dummy mesh for offset computations */ + +static union { /* Default parameters for block splitting method */ + HmeshOrderBlParam param; /* Parameter zone */ + StratNodeMethodData padding; /* To avoid reading out of structure */ +} hmeshorderstdefaultbl = { { &stratdummy, 8 } }; + +static union { + HmeshOrderCpParam param; + StratNodeMethodData padding; +} hmeshorderstdefaultcp = { { 0.70L, &stratdummy, &stratdummy } }; + +static union { /* Default parameters for nested dissection method */ + HmeshOrderGpParam param; + StratNodeMethodData padding; +} hmeshorderstdefaultgp = { { 3 } }; + +static union { /* Default parameters for nested dissection method */ + HmeshOrderGrParam param; + StratNodeMethodData padding; +} hmeshorderstdefaultgr = { { &stratdummy } }; + +static union { + HmeshOrderHdParam param; + StratNodeMethodData padding; +} hmeshorderstdefaulthd = { { 1, 1000000, 0.08L } }; + +static union { + HmeshOrderHfParam param; + StratNodeMethodData padding; +} hmeshorderstdefaulthf = { { 1, 1000000, 0.08L } }; + +static union { /* Default parameters for nested dissection method */ + HmeshOrderNdParam param; + StratNodeMethodData padding; +} hmeshorderstdefaultnd = { { &stratdummy, &stratdummy, &stratdummy } }; + +static StratMethodTab hmeshorderstmethtab[] = { /* Mesh ordering methods array */ + { HMESHORDERSTMETHBL, "b", hmeshOrderBl, &hmeshorderstdefaultbl }, + { HMESHORDERSTMETHCP, "c", hmeshOrderCp, &hmeshorderstdefaultcp }, + { HMESHORDERSTMETHGP, "g", hmeshOrderGp, &hmeshorderstdefaultgp }, + { HMESHORDERSTMETHGR, "v", hmeshOrderGr, &hmeshorderstdefaultgr }, + { HMESHORDERSTMETHHD, "d", hmeshOrderHd, &hmeshorderstdefaulthd }, + { HMESHORDERSTMETHHF, "f", hmeshOrderHf, &hmeshorderstdefaulthf }, + { HMESHORDERSTMETHND, "n", hmeshOrderNd, &hmeshorderstdefaultnd }, + { HMESHORDERSTMETHSI, "s", hmeshOrderSi, NULL }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab hmeshorderstparatab[] = { /* The method parameter list */ + { HMESHORDERSTMETHBL, STRATPARAMSTRAT, "strat", + (byte *) &hmeshorderstdefaultbl.param, + (byte *) &hmeshorderstdefaultbl.param.strat, + (void *) &hmeshorderststratab }, + { HMESHORDERSTMETHBL, STRATPARAMINT, "cmin", + (byte *) &hmeshorderstdefaultbl.param, + (byte *) &hmeshorderstdefaultbl.param.cblkmin, + NULL }, + { HMESHORDERSTMETHCP, STRATPARAMDOUBLE, "rat", + (byte *) &hmeshorderstdefaultcp.param, + (byte *) &hmeshorderstdefaultcp.param.comprat, + NULL }, + { HMESHORDERSTMETHCP, STRATPARAMSTRAT, "cpr", + (byte *) &hmeshorderstdefaultcp.param, + (byte *) &hmeshorderstdefaultcp.param.stratcpr, + (void *) &hmeshorderststratab }, + { HMESHORDERSTMETHCP, STRATPARAMSTRAT, "unc", + (byte *) &hmeshorderstdefaultcp.param, + (byte *) &hmeshorderstdefaultcp.param.stratunc, + (void *) &hmeshorderststratab }, + { HMESHORDERSTMETHGP, STRATPARAMINT, "pass", + (byte *) &hmeshorderstdefaultgp.param, + (byte *) &hmeshorderstdefaultgp.param.passnbr, + NULL }, + { HMESHORDERSTMETHGR, STRATPARAMSTRAT, "strat", + (byte *) &hmeshorderstdefaultgr.param, + (byte *) &hmeshorderstdefaultgr.param.stratptr, + (void *) &hgraphorderststratab }, + { HMESHORDERSTMETHHD, STRATPARAMINT, "cmin", + (byte *) &hmeshorderstdefaulthd.param, + (byte *) &hmeshorderstdefaulthd.param.colmin, + NULL }, + { HMESHORDERSTMETHHD, STRATPARAMINT, "cmax", + (byte *) &hmeshorderstdefaulthd.param, + (byte *) &hmeshorderstdefaulthd.param.colmax, + NULL }, + { HMESHORDERSTMETHHD, STRATPARAMDOUBLE, "frat", + (byte *) &hmeshorderstdefaulthd.param, + (byte *) &hmeshorderstdefaulthd.param.fillrat, + NULL }, + { HMESHORDERSTMETHHF, STRATPARAMINT, "cmin", + (byte *) &hmeshorderstdefaulthf.param, + (byte *) &hmeshorderstdefaulthf.param.colmin, + NULL }, + { HMESHORDERSTMETHHF, STRATPARAMINT, "cmax", + (byte *) &hmeshorderstdefaulthf.param, + (byte *) &hmeshorderstdefaulthf.param.colmax, + NULL }, + { HMESHORDERSTMETHHF, STRATPARAMDOUBLE, "frat", + (byte *) &hmeshorderstdefaulthf.param, + (byte *) &hmeshorderstdefaulthf.param.fillrat, + NULL }, + { HMESHORDERSTMETHND, STRATPARAMSTRAT, "sep", + (byte *) &hmeshorderstdefaultnd.param, + (byte *) &hmeshorderstdefaultnd.param.sepstrat, + (void *) &vmeshseparateststratab }, + { HMESHORDERSTMETHND, STRATPARAMSTRAT, "ole", + (byte *) &hmeshorderstdefaultnd.param, + (byte *) &hmeshorderstdefaultnd.param.ordstratlea, + (void *) &hmeshorderststratab }, + { HMESHORDERSTMETHND, STRATPARAMSTRAT, "ose", + (byte *) &hmeshorderstdefaultnd.param, + (byte *) &hmeshorderstdefaultnd.param.ordstratsep, + (void *) &hmeshorderststratab }, + { HMESHORDERSTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab hmeshorderstcondtab[] = { /* Mesh condition parameter table */ + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &hmeshorderstmeshdummy, + (byte *) &hmeshorderstmeshdummy.m.edgenbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &hmeshorderstmeshdummy, + (byte *) &hmeshorderstmeshdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &hmeshorderstmeshdummy, + (byte *) &hmeshorderstmeshdummy.vnhlsum, + NULL }, + { STRATNODECOND, STRATPARAMDOUBLE, "mdeg", + (byte *) &hmeshorderstmeshdummy, + (byte *) &hmeshorderstmeshdummy.m.degrmax, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vnod", + (byte *) &hmeshorderstmeshdummy, + (byte *) &hmeshorderstmeshdummy.vnohnbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "velm", + (byte *) &hmeshorderstmeshdummy, + (byte *) &hmeshorderstmeshdummy.m.velmnbr, + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab hmeshorderststratab = { /* Strategy tables for mesh ordering methods */ + hmeshorderstmethtab, + hmeshorderstparatab, + hmeshorderstcondtab }; + +/***********************************/ +/* */ +/* This routine is the entry point */ +/* for the mesh ordering routines. */ +/* */ +/***********************************/ + +/* This routine computes an ordering +** with respect to a given strategy. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +hmeshOrderSt ( +const Hmesh * restrict const meshptr, /*+ Submesh to which list apply +*/ +Order * restrict const ordeptr, /*+ Ordering to complete +*/ +const Gnum ordenum, /*+ Index to start ordering at +*/ +OrderCblk * restrict const cblkptr, /*+ Current column block +*/ +const Strat * restrict const strat) /*+ Mesh ordering strategy +*/ +{ + StratTest val; + int o; + + if (meshptr->vnohnbr == 0) /* Return immediately if nothing to do */ + return (0); + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + errorPrint ("hmeshOrderSt: concatenation operator not implemented for ordering strategies"); + return (1); + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) meshptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_HMESH2 + if ((val.typetest != STRATTESTVAL) && + (val.typenode != STRATPARAMLOG)) { + errorPrint ("hmeshOrderSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_HMESH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = hmeshOrderSt (meshptr, ordeptr, ordenum, cblkptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = hmeshOrderSt (meshptr, ordeptr, ordenum, cblkptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + hmeshOrderSi (meshptr, ordeptr, ordenum, cblkptr); /* Always maintain a coherent ordering */ + break; + case STRATNODESELECT : + errorPrint ("hmeshOrderSt: selection operator not available for mesh ordering strategies"); + return (1); +#ifdef SCOTCH_DEBUG_HMESH2 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_HMESH2 */ + default : +#endif /* SCOTCH_DEBUG_HMESH2 */ + return (strat->tabl->methtab[strat->data.method.meth].func (meshptr, ordeptr, ordenum, cblkptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_HMESH2 + default : + errorPrint ("hmeshOrderSt: invalid parameter"); + return (1); +#endif /* SCOTCH_DEBUG_HMESH2 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/hmesh_order_st.h b/scotch_6.0.3/src/libscotch/hmesh_order_st.h new file mode 100644 index 00000000..1cfac1cf --- /dev/null +++ b/scotch_6.0.3/src/libscotch/hmesh_order_st.h @@ -0,0 +1,81 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : hmesh_order_st.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data **/ +/** declarations for the main halo mesh **/ +/** ordering routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 28 sep 2002 **/ +/** to : 08 feb 2004 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum HmeshOrderStMethodType_ { + HMESHORDERSTMETHBL = 0, /*+ Block splitting post-processing +*/ + HMESHORDERSTMETHCP, /*+ Mesh compression +*/ + HMESHORDERSTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ + HMESHORDERSTMETHGR, /*+ Graph-based ordering +*/ + HMESHORDERSTMETHHD, /*+ Block Halo Approximate Minimum Degree +*/ + HMESHORDERSTMETHHF, /*+ Block Halo Approximate Minimum Fill +*/ + HMESHORDERSTMETHND, /*+ Nested Dissection +*/ + HMESHORDERSTMETHSI, /*+ Simple +*/ + HMESHORDERSTMETHNBR /*+ Number of methods +*/ +} HmeshOrderStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab hmeshorderststratab; + +/* +** The function prototypes. +*/ + +#ifndef HMESH_ORDER_ST +#define static +#endif + +int hmeshOrderSt (const Hmesh * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const Strat * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kdgraph.c b/scotch_6.0.3/src/libscotch/kdgraph.c new file mode 100644 index 00000000..84a35dcc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph.c @@ -0,0 +1,110 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel bipartitioning **/ +/** mapper. **/ +/** This module handles the k-way active **/ +/** distributed graph and save data struct- **/ +/** ure handling routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 31 mar 2008 **/ +/** to 01 jul 2008 **/ +/** # Version 6.0 : from : 08 sep 2012 **/ +/** to 08 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KDGRAPH + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "dgraph.h" +#include "dmapping.h" +#include "kdgraph.h" + +/************************************/ +/* */ +/* Active dgraph handling routines. */ +/* */ +/************************************/ + +/* This routine builds the active dgraph +** corresponding to the given k-way +** partition parameters. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kdgraphInit ( +Kdgraph * restrict const actgrafptr, /* Active graph */ +const Dgraph * restrict const srcgrafptr, /* Source graph */ +Dmapping * restrict const dmapptr) /* Mapping */ +{ + actgrafptr->s = *srcgrafptr; /* Clone source graph */ + actgrafptr->s.flagval &= ~DGRAPHFREEALL; + actgrafptr->s.vlblloctax = NULL; /* Do not propagate vertex labels within computations (e.g. dgraphInduce) */ + actgrafptr->levlnum = 0; + actgrafptr->m.mappptr = dmapptr; + archDomFrst (&dmapptr->archdat, &actgrafptr->m.domnorg); + + return (0); +} + +/* This routine frees the contents +** of the given active graph +** It returns: +** - VOID : in all cases. +*/ + +void +kdgraphExit ( +Kdgraph * restrict const actgrafptr) /* Active graph */ +{ + dgraphExit (&actgrafptr->s); + +#ifdef SCOTCH_DEBUG_KDGRAPH1 + memSet (actgrafptr, 0, sizeof (Kdgraph)); +#endif /* SCOTCH_DEBUG_KDGRAPH1 */ +} diff --git a/scotch_6.0.3/src/libscotch/kdgraph.h b/scotch_6.0.3/src/libscotch/kdgraph.h new file mode 100644 index 00000000..c0344662 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph.h @@ -0,0 +1,86 @@ +/* Copyright 2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a static mapper. **/ +/** These lines are the data declarations **/ +/** for the parallel k-way graph partiton- **/ +/** ing structures and routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 31 mar 2008 **/ +/** to 04 nov 2010 **/ +/** # Version 6.0 : from : 29 aug 2012 **/ +/** to 29 aug 2012 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ The dynamic mapping structure. +*/ + +typedef struct Kdmapping_ { + Dmapping * mappptr; /*+ Resulting mapping +*/ + ArchDom domnorg; /*+ Initial domain +*/ +} Kdmapping; + +/*+ The graph structure. +*/ + +typedef struct Kdgraph_ { + Dgraph s; /*+ Source graph +*/ + Kdmapping m; /*+ Mapping +*/ + INT levlnum; +} Kdgraph; + +/* +** The function prototypes. +*/ + +#ifndef KDGRAPH +#define static +#endif + +int kdgraphInit (Kdgraph * const, const Dgraph * restrict const, Dmapping * restrict const); +void kdgraphExit (Kdgraph * const); +int kdgraphFold (const Kdgraph *, const int, Kdgraph * const); +int kdgraphFold2 (const Kdgraph *, const int, Kdgraph * const, MPI_Comm); +#ifdef KGRAPH_H +int kdgraphGather (Kdgraph *, Kgraph *); +#endif /* KGRAPH_H */ + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kdgraph_gather.c b/scotch_6.0.3/src/libscotch/kdgraph_gather.c new file mode 100644 index 00000000..35586ed7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_gather.c @@ -0,0 +1,89 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_gather.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the routine which **/ +/** builds a centralized mapping graph by **/ +/** gathering the pieces of a distributed **/ +/** mapping graph. **/ +/** **/ +/** DATES : # Version 5.1 : from : 17 jun 2008 **/ +/** to : 17 jun 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KDGRAPH_GATHER + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "graph.h" +#include "mapping.h" +#include "kgraph.h" +#include "dgraph.h" +#include "dmapping.h" +#include "kdgraph.h" + +/******************************/ +/* */ +/* These routines handle */ +/* distributed source graphs. */ +/* */ +/******************************/ + +/* This function gathers the pieces of +** a distributed mapping graph to build a +** centralized mapping graph. +** There is no gathered vnumtab array if +** the original graph did not have one, as +** vertices are gathered in global order, or +** else the original vnumloctab is gathered. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +kdgraphGather ( +Kdgraph * restrict const dgrfptr, /* Distributed halo graph */ +Kgraph * restrict const cgrfptr) /* Centralized halo graph */ +{ + return (dgraphGather (&dgrfptr->s, &cgrfptr->s)); +} diff --git a/scotch_6.0.3/src/libscotch/kdgraph_map_rb.c b/scotch_6.0.3/src/libscotch/kdgraph_map_rb.c new file mode 100644 index 00000000..9b83d5c9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_map_rb.c @@ -0,0 +1,262 @@ +/* Copyright 2008,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_map_rb.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module performs the Dual Recursive **/ +/** Bipartitioning mapping algorithm **/ +/** in parallel. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 apr 2008 **/ +/** to 01 jul 2008 **/ +/** # Version 6.0 : from : 03 oct 2012 **/ +/** to 10 oct 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KDGRAPH_MAP_RB + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "dgraph.h" +#include "dmapping.h" +#include "kdgraph.h" +#include "kdgraph_map_rb.h" +#include "kdgraph_map_rb_map.h" +#include "kdgraph_map_rb_part.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* These routines add mapping fragments to the distributed +** mapping structure. +*/ + +DmappingFrag * +kdgraphMapRbAdd2 ( +const Gnum vertnbr, +const Anum domnnbr) +{ + DmappingFrag * restrict fragptr; + + if ((fragptr = memAlloc (sizeof (DmappingFrag))) == NULL) { + errorPrint ("kdgraphMapRbAdd2: out of memory (1)"); + return (NULL); + } + if (((fragptr->vnumtab = memAlloc (vertnbr * sizeof (Gnum))) == NULL) || + ((fragptr->parttab = memAlloc (vertnbr * sizeof (Anum))) == NULL) || + ((fragptr->domntab = memAlloc (domnnbr * sizeof (ArchDom))) == NULL)) { + errorPrint ("kdgraphMapRbAdd2: out of memory (2)"); + if (fragptr->vnumtab != NULL) { + if (fragptr->parttab != NULL) + memFree (fragptr->parttab); + memFree (fragptr->vnumtab); + } + return (NULL); + } + fragptr->vertnbr = vertnbr; + fragptr->domnnbr = domnnbr; + + return (fragptr); +} + +int +kdgraphMapRbAddBoth ( +const Dgraph * restrict const grafptr, +Dmapping * restrict const mappptr, +const ArchDom * restrict const domnptr, /*+ Pointer to both subdomains +*/ +const GraphPart * restrict const parttab) /*+ Bipartition graph part array +*/ +{ + DmappingFrag * restrict fragptr; + Anum * restrict fragparttab; + Gnum vertlocnum; + + if ((fragptr = kdgraphMapRbAdd2 (grafptr->vertlocnbr, 2)) == NULL) /* Two domains */ + return (1); + + fragptr->domntab[0] = domnptr[0]; + fragptr->domntab[1] = domnptr[1]; + if (parttab == NULL) /* If bipartition part array not set */ + memSet (fragptr->parttab, 0, grafptr->vertlocnbr * sizeof (Anum)); + else { + fragparttab = fragptr->parttab; + for (vertlocnum = 0; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) + fragparttab[vertlocnum] = (Anum) parttab[vertlocnum]; + } + + if (grafptr->vnumloctax != NULL) + memCpy (fragptr->vnumtab, grafptr->vnumloctax + grafptr->baseval, fragptr->vertnbr * sizeof (Gnum)); + else { + Gnum * restrict fragvnumtab; + Gnum vertlocadj; + Gnum vertlocnum; + + fragvnumtab = fragptr->vnumtab; + for (vertlocnum = 0, vertlocadj = grafptr->procvrttab[grafptr->proclocnum]; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) + fragvnumtab[vertlocnum] = vertlocadj + vertlocnum; + } + + dmapAdd (mappptr, fragptr); + + return (0); +} + +int +kdgraphMapRbAddOne ( +const Dgraph * restrict const grafptr, +Dmapping * restrict const mappptr, +const ArchDom * restrict const domnptr) +{ + DmappingFrag * restrict fragptr; + + if ((fragptr = kdgraphMapRbAdd2 (grafptr->vertlocnbr, 1)) == NULL) /* Only one domain */ + return (1); + + fragptr->domntab[0] = *domnptr; /* Only one domain for this mapping fragment */ + memSet (fragptr->parttab, 0, fragptr->vertnbr * sizeof (Anum)); /* All vertices mapped to it */ + if (grafptr->vnumloctax != NULL) + memCpy (fragptr->vnumtab, grafptr->vnumloctax + grafptr->baseval, fragptr->vertnbr * sizeof (Gnum)); + else { + Gnum * restrict fragvnumtab; + Gnum vertlocadj; + Gnum vertlocnum; + + fragvnumtab = fragptr->vnumtab; + for (vertlocnum = 0, vertlocadj = grafptr->procvrttab[grafptr->proclocnum]; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) + fragvnumtab[vertlocnum] = vertlocadj + vertlocnum; + } + + dmapAdd (mappptr, fragptr); + + return (0); +} + +int +kdgraphMapRbAddPart ( +const Dgraph * restrict const grafptr, +Dmapping * restrict const mappptr, +const ArchDom * restrict const domnptr, /*+ Pointer to one subdomain +*/ +const Gnum vertnbr, +const GraphPart * const parttab, +const GraphPart partval) +{ + DmappingFrag * restrict fragptr; + Gnum * restrict fragvnumtab; + Gnum vertlocnum; + Gnum partlocnum; + + if ((fragptr = kdgraphMapRbAdd2 (vertnbr, 1)) == NULL) /* Only one domain and a limited number of vertices */ + return (1); + + fragptr->domntab[0] = *domnptr; /* Only one domain for this mapping fragment */ + memSet (fragptr->parttab, 0, fragptr->vertnbr * sizeof (Anum)); /* All vertices mapped to it */ + + fragvnumtab = fragptr->vnumtab; + + if (grafptr->vnumloctax != NULL) { + const Gnum * restrict vnumtab; + + for (vertlocnum = partlocnum = 0, vnumtab = grafptr->vnumloctax + grafptr->baseval; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) { + if (parttab[vertlocnum] == partval) { +#ifdef SCOTCH_DEBUG_KDMAP2 + if (partlocnum >= vertnbr) { + errorPrint ("kdgraphMapRbAddPart: invalid parameters (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KDMAP2 */ + fragvnumtab[partlocnum ++] = vnumtab[vertlocnum]; + } + } + } + else { + Gnum vertlocadj; + + for (vertlocnum = partlocnum = 0, vertlocadj = grafptr->procvrttab[grafptr->proclocnum]; + vertlocnum < grafptr->vertlocnbr; vertlocnum ++) { + if (parttab[vertlocnum] == partval) { +#ifdef SCOTCH_DEBUG_KDMAP2 + if (partlocnum >= vertnbr) { + errorPrint ("kdgraphMapRbAddPart: invalid parameters (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KDMAP2 */ + fragvnumtab[partlocnum ++] = vertlocadj + vertlocnum; + } + } + } +#ifdef SCOTCH_DEBUG_KDMAP2 + if (partlocnum != vertnbr) { + errorPrint ("kdgraphMapRbAddPart: invalid parameters (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KDMAP2 */ + + dmapAdd (mappptr, fragptr); + + return (0); +} + +/* +** This routine runs the parallel Dual +** Recursive Bipartitioning algorithm. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kdgraphMapRb ( +Kdgraph * restrict const grafptr, +Kdmapping * restrict const mappptr, +const KdgraphMapRbParam * restrict const paraptr) +{ + if (grafptr->s.vertglbnbr == 0) /* If nothing to do, return immediately */ + return (0); + + return (archPart (&mappptr->mappptr->archdat) /* If target architecture is some flavor of complete graph */ + ? kdgraphMapRbPart (grafptr, mappptr, paraptr) + : kdgraphMapRbMap (grafptr, mappptr, paraptr)); +} diff --git a/scotch_6.0.3/src/libscotch/kdgraph_map_rb.h b/scotch_6.0.3/src/libscotch/kdgraph_map_rb.h new file mode 100644 index 00000000..c3925842 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_map_rb.h @@ -0,0 +1,76 @@ +/* Copyright 2008,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_map_rb.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the Parallel Dual Recursive **/ +/** Bipartitioning mapping algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 apr 2008 **/ +/** to 14 apr 2011 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct KdgraphMapRbParam_ { + Strat * stratsep; /*+ Bipartitioning strategy used +*/ + Strat * stratseq; /*+ Sequential mapping strategy +*/ + double kbalval; /*+ K-way imbalance ratio +*/ +} KdgraphMapRbParam; + +/* +** The function prototypes. +*/ + +#ifndef KDGRAPH_MAP_RB +#define static +#endif + +DmappingFrag * kdgraphMapRbAdd2 (const Gnum, const Anum); +int kdgraphMapRbAddBoth (const Dgraph * restrict const, Dmapping * restrict const, const ArchDom * restrict const, const GraphPart * restrict const); +int kdgraphMapRbAddOne (const Dgraph * restrict const, Dmapping * restrict const, const ArchDom * restrict const); +int kdgraphMapRbAddPart (const Dgraph * restrict const, Dmapping * restrict const, const ArchDom * restrict const, const Gnum, const GraphPart * const, const GraphPart); + + +int kdgraphMapRb (Kdgraph * const, Kdmapping * const, const KdgraphMapRbParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kdgraph_map_rb_map.c b/scotch_6.0.3/src/libscotch/kdgraph_map_rb_map.c new file mode 100644 index 00000000..1c3102fb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_map_rb_map.c @@ -0,0 +1,79 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_map_rb_map.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : This module performs the Dual Recursive **/ +/** Bipartitioning mapping algorithm **/ +/** in parallel for non-complete graphs. **/ +/** **/ +/** DATES : # Version 5.1 : from : 24 jun 2008 **/ +/** to 24 jun 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KDGRAPH_MAP_RB_MAP + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "dgraph.h" +#include "dmapping.h" +#include "kdgraph.h" +#include "kdgraph_map_rb.h" +#include "kdgraph_map_rb_map.h" +#include "kdgraph_map_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +int +kdgraphMapRbMap ( +Kdgraph * restrict const grafptr, +Kdmapping * restrict const mappptr, +const KdgraphMapRbParam * restrict const paraptr) +{ + errorPrint ("kdgraphMapRbMap: not implemented yet"); + return (1); +} diff --git a/scotch_6.0.3/src/libscotch/kdgraph_map_rb_map.h b/scotch_6.0.3/src/libscotch/kdgraph_map_rb_map.h new file mode 100644 index 00000000..c91eec7b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_map_rb_map.h @@ -0,0 +1,62 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_map_rb_map.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the Parallel Dual Recursive **/ +/** Bipartitioning mapping algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 24 jun 2008 **/ +/** to 24 jun 2008 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/* +** The function prototypes. +*/ + +#ifndef KDGRAPH_MAP_RB +#define static +#endif + +int kdgraphMapRbMap (Kdgraph * const, Kdmapping * const, const KdgraphMapRbParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kdgraph_map_rb_part.c b/scotch_6.0.3/src/libscotch/kdgraph_map_rb_part.c new file mode 100644 index 00000000..b646751b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_map_rb_part.c @@ -0,0 +1,428 @@ +/* Copyright 2008-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_map_rb_part.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module performs the Dual Recursive **/ +/** Bipartitioning mapping algorithm **/ +/** in parallel. It does so for complete **/ +/** graph architectures, hence performing **/ +/** plain graph partitioning, which **/ +/** avoids to take care of what the other **/ +/** processes are doing. **/ +/** **/ +/** DATES : # Version 5.1 : from : 21 jun 2008 **/ +/** to 31 aug 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 31 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KDGRAPH_MAP_RB + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "mapping.h" +#include "kgraph.h" +#include "kgraph_map_st.h" +#include "dgraph.h" +#include "dmapping.h" +#include "bdgraph.h" +#include "bdgraph_bipart_st.h" +#include "kdgraph.h" +#include "kdgraph_map_rb.h" +#include "kdgraph_map_rb_part.h" +#include "kdgraph_map_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine sequentially computes a mapping +** of the given subgraph and adds its result to +** the given distributed mapping. Since no +** cocycle data is needed, the un-synchronized +** sequential Scotch routine can be used as is. +** It returns: +** - 0 : if the mapping could be computed. +** - !0 : on error. +*/ + +static +int +kdgraphMapRbPartSequ ( +KdgraphMapRbPartGraph * restrict const grafptr, +Dmapping * restrict const mappptr, +const KdgraphMapRbPartData * restrict const dataptr) +{ + Graph * restrict cgrfptr; + Kgraph kgrfdat; /* Centralized mapping graph */ + DmappingFrag * restrict fragptr; + + cgrfptr = &grafptr->data.cgrfdat; + if (kgraphInit (&kgrfdat, cgrfptr, &mappptr->archdat, &grafptr->domnorg, 0, NULL, NULL, 1, 1, NULL) != 0) { + errorPrint ("kdgraphMapRbPartSequ: cannot initialize centralized graph"); + return (1); + } + kgrfdat.s.flagval = (kgrfdat.s.flagval & ~GRAPHBITSUSED) | cgrfptr->flagval; /* Free sequential graph along with mapping data */ + kgrfdat.s.vnumtax = NULL; /* Remove index array if any */ + kgrfdat.comploadrat = dataptr->comploadrat; /* Use ideal load of full graph and not of subgraph */ + + if (kgraphMapSt (&kgrfdat, dataptr->paraptr->stratseq) != 0) { /* Compute sequential mapping */ + kgraphExit (&kgrfdat); + return (1); + } + + if (((fragptr = memAlloc (sizeof (DmappingFrag))) == NULL) || + ((fragptr->vnumtab = memAlloc (cgrfptr->vertnbr * sizeof (Gnum))) == NULL)) { + errorPrint ("kdgraphMapRbPartSequ: out of memory"); + if (fragptr != NULL) + memFree (fragptr); + kgraphExit (&kgrfdat); + return (1); + } + + fragptr->vertnbr = cgrfptr->vertnbr; + fragptr->parttab = kgrfdat.m.parttax + kgrfdat.s.baseval; + fragptr->domnnbr = kgrfdat.m.domnnbr; + fragptr->domntab = kgrfdat.m.domntab; + kgrfdat.m.parttax = NULL; /* Keep sequential mapping arrays for distributed mapping fragment */ + kgrfdat.m.domntab = NULL; + if (kgrfdat.m.domnmax > kgrfdat.m.domnnbr) + fragptr->domntab = memRealloc (fragptr->domntab, kgrfdat.m.domnnbr * sizeof (ArchDom)); /* Reallocate mapping array */ + + if (cgrfptr->vnumtax != NULL) + memCpy (fragptr->vnumtab, cgrfptr->vnumtax + cgrfptr->baseval, cgrfptr->vertnbr * sizeof (Gnum)); + else { + Gnum vertadj; + Gnum vertnum; + + for (vertnum = 0, vertadj = cgrfptr->baseval; vertnum < cgrfptr->vertnbr; vertnum ++) + fragptr->vnumtab[vertnum] = vertadj + vertnum; + } + + dmapAdd (mappptr, fragptr); /* Add mapping fragment */ + + kgraphExit (&kgrfdat); /* Free mapping without some of its arrays */ + + return (0); +} + +/* This routine builds either a centralized or a +** distributed subgraph, according to the number +** of processes in the given part. The calling +** conventions of this routine have been designed +** so as to allow for multi-threading. +*/ + +static +void * +kdgraphMapRbPartFold2 ( +void * const dataptr) /* Pointer to thread data */ +{ + KdgraphMapRbPartThread * fldthrdptr; /* Thread input parameters */ + KdgraphMapRbPartGraph * restrict fldgrafptr; /* Pointer to folded graph area */ + Dgraph indgrafdat; /* Induced distributed graph */ + void * o; + + fldthrdptr = (KdgraphMapRbPartThread *) dataptr; + fldgrafptr = fldthrdptr->fldgrafptr; + + if (fldthrdptr->fldprocnbr == 0) /* If recursion stopped, build mapping of graph part */ + return ((void *) (intptr_t) kdgraphMapRbAddPart (fldthrdptr->orggrafptr, fldthrdptr->mappptr, fldthrdptr->inddomnptr, fldthrdptr->indvertnbr, + fldthrdptr->indparttax + fldthrdptr->orggrafptr->baseval, fldthrdptr->indpartval)); + + dgraphInit (&indgrafdat, fldthrdptr->orggrafptr->proccomm); /* Re-use communicator of original graph */ + if (dgraphInducePart (fldthrdptr->orggrafptr, fldthrdptr->indparttax, /* Compute unfinished induced subgraph on all processes */ + fldthrdptr->indvertnbr, fldthrdptr->indpartval, &indgrafdat) != 0) + return ((void *) 1); + + if (fldthrdptr->fldprocnbr > 1) { /* If subpart has several processes, fold a distributed graph */ + o = (void *) (intptr_t) dgraphFold2 (&indgrafdat, fldthrdptr->fldpartval, /* Fold temporary induced subgraph from all processes */ + &fldgrafptr->data.dgrfdat, fldthrdptr->fldproccomm, NULL, NULL, MPI_INT); + } + else { /* Create a centralized graph */ + Graph * restrict fldcgrfptr; + + fldcgrfptr = (fldthrdptr->fldprocnum == 0) ? &fldgrafptr->data.cgrfdat : NULL; /* See if we are the receiver */ + o = (void *) (intptr_t) dgraphGather (&indgrafdat, fldcgrfptr); /* Gather centralized subgraph from all other processes */ + } + dgraphExit (&indgrafdat); /* Free temporary induced graph */ + + return (o); +} + +static +int +kdgraphMapRbPartFold ( +Bdgraph * restrict const actgrafptr, +Dmapping * restrict const mappptr, +const ArchDom * restrict const domnsubtab, +KdgraphMapRbPartGraph * restrict const fldgrafptr) +{ + KdgraphMapRbPartThread fldthrdtab[2]; + int fldprocnbr; /* Number of processes in part of this process */ + int fldprocnbr0; /* Number of processes in first part */ + int fldprocnum; + int fldproccol; + int fldpartval; + Gnum indvertlocmax; /* Local number of vertices in biggest subgraph */ + int indconttab[2]; /* Array of subjob continuation flags */ + GraphPart indpartmax; /* Induced part having most vertices */ +#ifdef SCOTCH_PTHREAD + Dgraph orggrafdat; /* Structure for copying graph fields except communicator */ + pthread_t thrdval; /* Data of second thread */ +#endif /* SCOTCH_PTHREAD */ + int o; + + indconttab[0] = /* Assume both jobs will not continue */ + indconttab[1] = 0; + if ((actgrafptr->compglbsize0 != 0) && /* If graph has been bipartitioned */ + (actgrafptr->compglbsize0 != actgrafptr->s.vertglbnbr)) { + if (archVar (&mappptr->archdat)) { /* If architecture is variable-sized */ + if (actgrafptr->compglbsize0 > 1) /* If graph is not single vertex, go on */ + indconttab[0] = 1; + if ((actgrafptr->s.vertglbnbr - actgrafptr->compglbsize0) > 1) + indconttab[1] = 1; + } + else { /* Architecture is not variable-sized */ + if (archDomSize (&mappptr->archdat, &domnsubtab[0]) > 1) /* Stop when target is one vertex */ + indconttab[0] = 1; + if (archDomSize (&mappptr->archdat, &domnsubtab[1]) > 1) + indconttab[1] = 1; + } + } + + if ((indconttab[0] + indconttab[1]) == 0) { /* If both subjobs stop */ + fldgrafptr->procnbr = 0; /* Nothing to do on return */ + return (kdgraphMapRbAddBoth (&actgrafptr->s, mappptr, domnsubtab, actgrafptr->partgsttax + actgrafptr->s.baseval)); /* Map both subdomains in the same time */ + } + + if ((2 * actgrafptr->compglbsize0) >= actgrafptr->s.vertglbnbr) { /* Get part of largest subgraph */ + indpartmax = 0; + indvertlocmax = actgrafptr->complocsize0; + } + else { + indpartmax = 1; + indvertlocmax = actgrafptr->s.vertlocnbr - actgrafptr->complocsize0; + } + fldprocnbr0 = (actgrafptr->s.procglbnbr + 1) / 2; /* Get number of processes in part 0 (always more than in part 1) */ + + fldthrdtab[0].mappptr = mappptr; /* Load data to pass to the subgraph building routines */ + fldthrdtab[0].orggrafptr = &actgrafptr->s; + fldthrdtab[0].inddomnptr = &domnsubtab[indpartmax]; + fldthrdtab[0].indvertnbr = indvertlocmax; + fldthrdtab[0].indpartval = indpartmax; + fldthrdtab[0].indparttax = actgrafptr->partgsttax; + fldthrdtab[0].fldgrafptr = fldgrafptr; + fldthrdtab[0].fldpartval = 0; + fldthrdtab[0].fldprocnbr = indconttab[indpartmax] * fldprocnbr0; /* Stop if domain limited to one vertex */ + fldthrdtab[1].mappptr = mappptr; + fldthrdtab[1].orggrafptr = &actgrafptr->s; /* Assume jobs won't be run concurrently */ + fldthrdtab[1].inddomnptr = &domnsubtab[indpartmax ^ 1]; + fldthrdtab[1].indvertnbr = actgrafptr->s.vertlocnbr - indvertlocmax; + fldthrdtab[1].indpartval = indpartmax ^ 1; + fldthrdtab[1].indparttax = actgrafptr->partgsttax; + fldthrdtab[1].fldgrafptr = fldgrafptr; + fldthrdtab[1].fldpartval = 1; + fldthrdtab[1].fldprocnbr = indconttab[indpartmax ^ 1] * (actgrafptr->s.procglbnbr - fldprocnbr0); /* Stop if domain limited to one vertex */ + + if (actgrafptr->s.proclocnum < fldprocnbr0) { /* Compute color and rank in our future subpart */ + fldpartval = 0; + fldprocnum = actgrafptr->s.proclocnum; + fldprocnbr = fldprocnbr0; + } + else { + fldpartval = 1; + fldprocnum = actgrafptr->s.proclocnum - fldprocnbr0; + fldprocnbr = actgrafptr->s.procglbnbr - fldprocnbr0; + } + + fldgrafptr->domnorg = *fldthrdtab[fldpartval].inddomnptr; /* Set data of our folded graph */ + fldgrafptr->procnbr = fldthrdtab[fldpartval].fldprocnbr; + fldgrafptr->levlnum = actgrafptr->levlnum + 1; /* One level down in the DRB process */ + fldproccol = fldpartval; /* Split color is the part value */ + if (fldgrafptr->procnbr <= 1) /* If our part will have only one processor or will stop */ + fldproccol = MPI_UNDEFINED; /* Do not create any sub-communicator for it */ + if (MPI_Comm_split (actgrafptr->s.proccomm, fldproccol, fldprocnum, &fldthrdtab[fldpartval].fldproccomm) != MPI_SUCCESS) { /* Assign folded communicator to proper part */ + errorPrint ("kdgraphMapRbPartFold: communication error"); + return (1); + } + fldthrdtab[fldpartval].fldprocnum = fldprocnum; /* This will be our rank afterwards */ + fldthrdtab[fldpartval ^ 1].fldprocnum = -1; /* Other part will not be in communicator */ + fldthrdtab[fldpartval ^ 1].fldproccomm = MPI_COMM_NULL; + +#ifdef SCOTCH_PTHREAD + if ((indconttab[0] + indconttab[1]) == 2) { /* If both subjobs have meaningful things to do in parallel */ + orggrafdat = actgrafptr->s; /* Create a separate graph structure to change its communicator */ + orggrafdat.flagval = (orggrafdat.flagval & ~DGRAPHFREEALL) | DGRAPHFREECOMM; + fldthrdtab[1].orggrafptr = &orggrafdat; + MPI_Comm_dup (actgrafptr->s.proccomm, &orggrafdat.proccomm); /* Duplicate communicator to avoid interferences in communications */ + + if (pthread_create (&thrdval, NULL, kdgraphMapRbPartFold2, (void *) &fldthrdtab[1]) != 0) /* If could not create thread */ + o = ((int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[0])) || /* Perform inductions in sequence */ + ((int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[1])); + else { /* Newly created thread is processing subgraph 1, so let's process subgraph 0 */ + void * o2; + + o = (int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[0]); /* Work on copy with private communicator */ + + pthread_join (thrdval, &o2); + o |= (int) (intptr_t) o2; + } + MPI_Comm_free (&orggrafdat.proccomm); + } + else +#endif /* SCOTCH_PTHREAD */ + o = ((int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[0])) || /* Perform inductions in sequence */ + ((int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[1])); + + return (o); +} + +/* This routine performs the Dual Recursive +** Bipartitioning mapping in parallel. +** It returns: +** - 0 : if the mapping could be computed. +** - !0 : on error. +*/ + +static +int +kdgraphMapRbPart2 ( +KdgraphMapRbPartGraph * restrict const grafptr, +const KdgraphMapRbPartData * restrict const dataptr) +{ + ArchDom domnsubtab[2]; /* Temporary subdomains */ + Bdgraph actgrafdat; /* Active bipartitioning graph */ + KdgraphMapRbPartGraph indgrafdat; /* Induced folded graph area */ + Gnum comploadavg; + Dmapping * mappptr; + int o; + + mappptr = dataptr->mappptr; + + o = ((archVar (&mappptr->archdat)) && /* If architecture is variable-sized */ + (grafptr->data.dgrfdat.vertglbnbr <= 1)) /* And source subgraph is of minimal size */ + ? 1 /* Then do not bipartition target more */ + : archDomBipart (&mappptr->archdat, &grafptr->domnorg, &domnsubtab[0], &domnsubtab[1]); + + switch (o) { + case 1 : /* If target domain is terminal */ + return (kdgraphMapRbAddOne (&grafptr->data.dgrfdat, mappptr, &grafptr->domnorg)); /* Update mapping and return */ + case 2 : /* On error */ + errorPrint ("kdgraphMapRbPart2: cannot bipartition domain"); + return (1); + } + + if (dgraphGhst (&grafptr->data.dgrfdat) != 0) { /* Compute ghost edge array if not already present, to have vertgstnbr (and procsidtab) */ + errorPrint ("kdgraphMapRbPart2: cannot compute ghost edge array"); + return (1); + } + + o = bdgraphInit (&actgrafdat, &grafptr->data.dgrfdat, NULL, &mappptr->archdat, domnsubtab); /* Create active graph */ + actgrafdat.levlnum = grafptr->levlnum; /* Initial level of bipartition graph is DRB recursion level */ + + comploadavg = (double) actgrafdat.s.veloglbsum / (double) archDomWght (&mappptr->archdat, &grafptr->domnorg); + actgrafdat.compglbload0min = actgrafdat.compglbload0avg - + (Gnum) MIN ((dataptr->comploadmax - comploadavg) * actgrafdat.domnwght[0], + (comploadavg - dataptr->comploadmin) * actgrafdat.domnwght[1]); + actgrafdat.compglbload0max = actgrafdat.compglbload0avg + + (Gnum) MIN ((comploadavg - dataptr->comploadmin) * actgrafdat.domnwght[0], + (dataptr->comploadmax - comploadavg) * actgrafdat.domnwght[1]); + + if ((o != 0) || (bdgraphBipartSt (&actgrafdat, dataptr->paraptr->stratsep) != 0)) { /* Bipartition edge-separation graph */ + bdgraphExit (&actgrafdat); + return (1); + } + + o = kdgraphMapRbPartFold (&actgrafdat, mappptr, domnsubtab, &indgrafdat); + + bdgraphExit (&actgrafdat); /* Free additional bipartitioning data */ + dgraphExit (&grafptr->data.dgrfdat); /* Free graph before going to next level */ + + if (o == 0) { + if (indgrafdat.procnbr == 1) /* If sequential job */ + o = kdgraphMapRbPartSequ (&indgrafdat, mappptr, dataptr); + else if (indgrafdat.procnbr > 1) /* If distributed job */ + o = kdgraphMapRbPart2 (&indgrafdat, dataptr); + } + return (o); +} + +int +kdgraphMapRbPart ( +Kdgraph * restrict const grafptr, +Kdmapping * restrict const mappptr, +const KdgraphMapRbParam * restrict const paraptr) +{ + KdgraphMapRbPartGraph grafdat; + KdgraphMapRbPartData datadat; + + grafdat.domnorg = grafptr->m.domnorg; /* Used in all cases */ + grafdat.procnbr = grafptr->s.procglbnbr; + grafdat.levlnum = 0; /* Set initial DRB level to zero */ + + datadat.mappptr = mappptr->mappptr; + datadat.paraptr = paraptr; + datadat.comploadrat = (double) grafptr->s.veloglbsum / (double) archDomWght (&mappptr->mappptr->archdat, &grafptr->m.domnorg); + datadat.comploadmin = (1.0 - paraptr->kbalval) * datadat.comploadrat; + datadat.comploadmax = (1.0 + paraptr->kbalval) * datadat.comploadrat; + + if (grafptr->s.procglbnbr <= 1) { /* If single process, switch immediately to sequential mode */ + if (dgraphGather (&grafptr->s, &grafdat.data.cgrfdat) != 0) { + errorPrint ("kdgraphMapRbPart: cannot centralize graph"); + return (1); + } + return (kdgraphMapRbPartSequ (&grafdat, mappptr->mappptr, &datadat)); + } + + grafdat.data.dgrfdat = grafptr->s; /* Create a clone graph that will never be freed */ + grafdat.data.dgrfdat.flagval &= ~DGRAPHFREEALL; + + return (kdgraphMapRbPart2 (&grafdat, &datadat)); /* Perform DRB */ +} diff --git a/scotch_6.0.3/src/libscotch/kdgraph_map_rb_part.h b/scotch_6.0.3/src/libscotch/kdgraph_map_rb_part.h new file mode 100644 index 00000000..24fc83c8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_map_rb_part.h @@ -0,0 +1,99 @@ +/* Copyright 2008,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_map_rb_part.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the Parallel Dual Recursive **/ +/** Bipartitioning mapping algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 23 jun 2008 **/ +/** to 31 aug 2011 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds folded graph data, whether centralized or distributed +*/ + +typedef struct KdgraphMapRbPartGraph_ { + ArchDom domnorg; /*+ Domain to bipartition at this stage +*/ + int procnbr; /*+ Number of processes holding graph +*/ + INT levlnum; /*+ Level number +*/ + union { + Graph cgrfdat; /*+ Centralized graph +*/ + Dgraph dgrfdat; /*+ Distributed graph +*/ + } data; +} KdgraphMapRbPartGraph; + +/*+ This structure holds the data passed to the subgraph building threads. +*/ + +typedef struct KdgraphMapRbPartThread_ { + Dmapping * mappptr; /*+ Pointer to mapping structure +*/ + Dgraph * orggrafptr; /*+ Pointer to original graph +*/ + const ArchDom * inddomnptr; /*+ Pointer to subjob domain +*/ + Gnum indvertnbr; /*+ Local number of vertices in subgraph +*/ + GraphPart indpartval; /*+ Graph part from which to extract subgraph +*/ + GraphPart * indparttax; /*+ Based local vertex partition flags in subgraph +*/ + KdgraphMapRbPartGraph * fldgrafptr; /*+ Pointer to folded graph union area +*/ + int fldpartval; /*+ Part of processor array to which to fold to +*/ + int fldprocnbr; /*+ Number of processes in folded communicator +*/ + int fldprocnum; /*+ Rank of process in folded communicator, or -1 +*/ + MPI_Comm fldproccomm; /*+ Communicator for the folded graph, if any +*/ +} KdgraphMapRbPartThread; + +/*+ This structure holds the data passed to each bipartitioning job. +*/ + +typedef struct KdgraphMapRbPartData_ { + Dmapping * mappptr; + const KdgraphMapRbParam * paraptr; + double comploadrat; /*+ Ideal vertex load per target load +*/ + double comploadmin; /*+ Minimum vertex load per target load +*/ + double comploadmax; /*+ Maximum vertex load per target load +*/ +} KdgraphMapRbPartData; + +/* +** The function prototypes. +*/ + +#ifndef KDGRAPH_MAP_RB +#define static +#endif + +int kdgraphMapRbPart (Kdgraph * const, Kdmapping * const, const KdgraphMapRbParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kdgraph_map_st.c b/scotch_6.0.3/src/libscotch/kdgraph_map_st.c new file mode 100644 index 00000000..1ea40826 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_map_st.c @@ -0,0 +1,194 @@ +/* Copyright 2008-2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_map_st.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the strategy and **/ +/** method tables for the parallel **/ +/** multi-way static mapping routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 jun 2008 **/ +/** to 14 apr 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KDGRAPH_MAP_ST + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "arch.h" +#include "mapping.h" +#include "dmapping.h" +#include "bdgraph.h" +#include "bdgraph_bipart_st.h" +#include "kgraph.h" +#include "kgraph_map_st.h" +#include "kdgraph.h" +#include "kdgraph_map_rb.h" +#include "kdgraph_map_st.h" + +/* +** The static and global variables. +*/ + +static union { + KdgraphMapRbParam param; + StratNodeMethodData padding; +} kdgraphmapstdefaultrb = { { &stratdummy, &stratdummy, 0.05 } }; + +static StratMethodTab kdgraphmapstmethtab[] = { /* Mapping methods array */ + { KDGRAPHMAPSTMETHRB, "r", kdgraphMapRb, &kdgraphmapstdefaultrb }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab kdgraphmapstparatab[] = { /* Method parameter list */ + { KDGRAPHMAPSTMETHRB, STRATPARAMSTRAT, "sep", + (byte *) &kdgraphmapstdefaultrb.param, + (byte *) &kdgraphmapstdefaultrb.param.stratsep, + (void *) &bdgraphbipartststratab }, + { KDGRAPHMAPSTMETHRB, STRATPARAMSTRAT, "seq", + (byte *) &kdgraphmapstdefaultrb.param, + (byte *) &kdgraphmapstdefaultrb.param.stratseq, + (void *) &kgraphmapststratab }, + { KDGRAPHMAPSTMETHRB, STRATPARAMDOUBLE, "bal", + (byte *) &kdgraphmapstdefaultrb.param, + (byte *) &kdgraphmapstdefaultrb.param.kbalval, + NULL }, + { KDGRAPHMAPSTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab kdgraphmapstcondtab[] = { /* Graph condition parameter table */ + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab kdgraphmapststratab = { /* Strategy tables for graph mapping methods */ + kdgraphmapstmethtab, + kdgraphmapstparatab, + kdgraphmapstcondtab }; + +/****************************************/ +/* */ +/* This is the generic mapping routine. */ +/* */ +/****************************************/ + +/* This routine computes the given +** mapping according to the given +** strategy. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kdgraphMapSt ( +Kdgraph * restrict const grafptr, /*+ Mapping graph +*/ +Kdmapping * restrict const mappptr, /*+ Dynamic mapping +*/ +const Strat * restrict const strat) /*+ Mapping strategy +*/ +{ + StratTest val; + int o; + +#ifdef SCOTCH_DEBUG_KDGRAPH2 + if (sizeof (Gnum) != sizeof (INT)) { + errorPrint ("kdgraphMapSt: invalid type specification for parser variables"); + return (1); + } + if ((sizeof (KdgraphMapRbParam) > sizeof (StratNodeMethodData))) { + errorPrint ("kdgraphMapSt: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_KDGRAPH2 */ +#ifdef SCOTCH_DEBUG_KDGRAPH1 + if ((strat->tabl != &kdgraphmapststratab) && + (strat != &stratdummy)) { + errorPrint ("kdgraphMapSt: invalid parameter (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KDGRAPH1 */ + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + o = kdgraphMapSt (grafptr, mappptr, strat->data.concat.strat[0]); /* Apply first strategy */ + if (o == 0) /* If it worked all right */ + o |= kdgraphMapSt (grafptr, mappptr, strat->data.concat.strat[1]); /* Then apply second strategy */ + break; + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_KDGRAPH2 + if ((val.typetest != STRATTESTVAL) || + (val.typenode != STRATPARAMLOG)) { + errorPrint ("kdgraphMapSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_KDGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = kdgraphMapSt (grafptr, mappptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = kdgraphMapSt (grafptr, mappptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + break; + case STRATNODESELECT : + errorPrint ("kdgraphMapSt: selection operator not implemented for k-way strategies"); + return (1); +#ifdef SCOTCH_DEBUG_KDGRAPH1 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_KDGRAPH1 */ + default : +#endif /* SCOTCH_DEBUG_KDGRAPH1 */ + return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, mappptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_KDGRAPH1 + default : + errorPrint ("kdgraphMapSt: invalid parameter (2)"); + return (1); +#endif /* SCOTCH_DEBUG_KDGRAPH1 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/kdgraph_map_st.h b/scotch_6.0.3/src/libscotch/kdgraph_map_st.h new file mode 100644 index 00000000..feabd86e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kdgraph_map_st.h @@ -0,0 +1,76 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kdgraph_map_st.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the strategy and method **/ +/** tables and the generic entry point for **/ +/** the parallel multi-way static mapping **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 jun 2008 **/ +/** to 16 jun 2008 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum KdgraphMapStMethodType_ { + KDGRAPHMAPSTMETHRB = 0, /*+ Dual Recursive Bipartitioning +*/ + KDGRAPHMAPSTMETHNBR /*+ Number of methods +*/ +} KdgraphMapStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab kdgraphmapststratab; + +/* +** The function prototypes. +*/ + +#ifndef KDGRAPH_MAP_ST +#define static +#endif + +int kdgraphMapSt (Kdgraph * restrict const, Kdmapping * restrict const, const Strat * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph.c b/scotch_6.0.3/src/libscotch/kgraph.c new file mode 100644 index 00000000..3b1d36e8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph.c @@ -0,0 +1,381 @@ +/* Copyright 2004,2007,2008,2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : Part of a bipartitioning mapper. **/ +/** This module handles the k-way active **/ +/** graph and save data structure handling **/ +/** routines. **/ +/** **/ +/** DATES : # Version 3.2 : from : 03 oct 1997 **/ +/** to 26 may 1998 **/ +/** # Version 3.4 : from : 30 oct 2001 **/ +/** to 30 oct 2001 **/ +/** # Version 4.0 : from : 24 jun 2004 **/ +/** to 16 feb 2005 **/ +/** # Version 5.1 : from : 28 sep 2008 **/ +/** to 31 aug 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 15 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "kgraph.h" + +/***********************************/ +/* */ +/* Active graph handling routines. */ +/* */ +/***********************************/ + +/* This routine builds the active graph +** corresponding to the given k-way +** partition parameters. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kgraphInit ( +Kgraph * restrict const actgrafptr, /*+ Active graph +*/ +const Graph * restrict const srcgrafptr, /*+ Source graph +*/ +const Arch * restrict const archptr, /*+ Target architecture +*/ +const ArchDom * restrict const domnptr, /*+ Target architecture initial domain +*/ +const Gnum vfixnbr, /*+ Number of fixed vertices in array +*/ +const Anum * restrict const pfixtax, /*+ Fixed vertex part array +*/ +const Anum * restrict const parotax, /*+ Pointer to old part array +*/ +const Gnum crloval, /*+ Coefficient load for regular edges +*/ +const Gnum cmloval, /*+ Coefficient load for migration edges +*/ +const Gnum * restrict const vmlotax) /*+ Vertex migration cost array +*/ +{ + ArchDom domndat; /* First, largest domain */ + const ArchDom * restrict domntmp; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((crloval < 1) || (cmloval < 1)) { + errorPrint ("kgraphInit: invalid parameters"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + archDomFrst (archptr, &domndat); /* Get first, largest domain */ + + if (srcgrafptr != &actgrafptr->s) { /* If graph not already in place */ + actgrafptr->s = *srcgrafptr; /* Clone source graph */ + actgrafptr->s.flagval &= (GRAPHBITSUSED & ~GRAPHFREETABS); /* Remove extended graph class flags and do not allow freeing */ + } + if (archptr != &actgrafptr->a) /* If architecture not already in place */ + actgrafptr->a = *archptr; /* Clone it */ + + mapInit (&actgrafptr->m, &actgrafptr->s, &actgrafptr->a, + ((domnptr == NULL) ? &domndat : domnptr)); /* Use largest domain if none provided */ + + mapInit (&actgrafptr->r.m, &actgrafptr->s, &actgrafptr->a, + ((domnptr == NULL) ? &domndat : domnptr)); + if (parotax != NULL) { /* If old part array provided */ + if ((mapAlloc (&actgrafptr->r.m) != 0) || + (mapBuild (&actgrafptr->r.m, parotax) != 0)) { + errorPrint ("kgraphInit: cannot initialize remapping"); + return (1); + } + } + actgrafptr->r.crloval = crloval; + actgrafptr->r.cmloval = cmloval; + actgrafptr->r.vmlotax = vmlotax; /* Set vertex migration load array or NULL */ + + actgrafptr->vfixnbr = vfixnbr; + actgrafptr->pfixtax = pfixtax; + + if (mapAlloc (&actgrafptr->m) != 0) { + errorPrint ("kgraphInit: cannot initialize mapping"); + return (1); + } + + if (((actgrafptr->frontab = memAlloc (actgrafptr->s.vertnbr * sizeof (Gnum))) == NULL) || /* Allocation and initialization of imbalance arrays */ + (memAllocGroup ((void **) (void *) + &actgrafptr->comploadavg, (size_t) (actgrafptr->m.domnmax * sizeof (Gnum)), /* TRICK: can send both compload arrays in one piece */ + &actgrafptr->comploaddlt, (size_t) (actgrafptr->m.domnmax * sizeof (Gnum)), NULL) == NULL)) { + errorPrint ("kgraphInit: out of memory"); + if (actgrafptr->frontab != NULL) + memFree (actgrafptr->frontab); + return (1); + } + + actgrafptr->s.flagval |= KGRAPHFREECOMP | KGRAPHFREEFRON; /* comploadavg and comploaddlt are always grouped */ + + actgrafptr->comploadavg[0] = actgrafptr->s.velosum; + actgrafptr->comploaddlt[0] = 0; + + actgrafptr->fronnbr = 0; /* No frontier yet */ + actgrafptr->comploadrat = (double) srcgrafptr->velosum / (double) archDomWght (archptr, &domndat); /* Always balance with respect to whole original graph */ + actgrafptr->commload = 0; + actgrafptr->levlnum = 0; + actgrafptr->kbalval = 1; /* No information on imbalance yet */ + + return (0); +} + +/* This routine frees the contents +** of the given active graph and +** updates the mapping data accordingly. +** It returns: +** - VOID : in all cases. +*/ + +void +kgraphExit ( +Kgraph * restrict const grafptr) +{ + mapExit (&grafptr->m); + mapExit (&grafptr->r.m); + + if (((grafptr->s.flagval & KGRAPHFREEVMLO) != 0) && /* If vmlotax must be freed */ + (grafptr->r.vmlotax != NULL)) /* And if it exists */ + memFree (grafptr->r.vmlotax + grafptr->s.baseval); /* Free it */ + + if (((grafptr->s.flagval & KGRAPHFREEPFIX) != 0) && /* If pfixtax must be freed */ + (grafptr->pfixtax != NULL)) /* And if it exists */ + memFree (grafptr->pfixtax + grafptr->s.baseval); /* Free it */ + + if (((grafptr->s.flagval & KGRAPHFREEFRON) != 0) && /* If frontab must be freed */ + (grafptr->frontab != NULL)) /* And if it exists */ + memFree (grafptr->frontab); /* Free it */ + + if (((grafptr->s.flagval & KGRAPHFREECOMP) != 0) && /* If comptabs must be freed */ + (grafptr->comploadavg != NULL)) /* And if it exists */ + memFree (grafptr->comploadavg); /* Free it */ + + graphExit (&grafptr->s); + +#ifdef SCOTCH_DEBUG_KGRAPH2 + memSet (grafptr, ~0, sizeof (Kgraph)); /* Purge kgraph fields */ +#endif /* SCOTCH_DEBUG_KGRAPH2 */ +} + +/* This routine moves all of the graph +** vertices to the first subdomain, and +** computes the resulting gains. +** It returns: +** - VOID : in all cases. +*/ + +void +kgraphFrst ( +Kgraph * restrict const grafptr) +{ + archDomFrst (grafptr->m.archptr, &grafptr->m.domntab[0]); + grafptr->m.domnnbr = 1; + + memSet (grafptr->m.parttax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (Anum)); /* Set all vertices to subdomain 0 */ + memSet (grafptr->comploadavg + 1, 0, (2 * grafptr->m.domnmax - 1) * sizeof (Gnum)); + + grafptr->comploadavg[0] = grafptr->s.velosum; + grafptr->commload = 0; + grafptr->m.domntab[0] = grafptr->m.domnorg; /* Point to first domain */ + grafptr->fronnbr = 0; /* No frontier vertices */ +} + +/* This routine computes the cost of the +** current partition. +** It returns: +** - VOID : in all cases. +*/ + +void +kgraphCost ( +Kgraph * restrict const grafptr) +{ + Gnum vertnum; + Gnum * restrict compload; + Gnum commload; + double fdomwgt; + Gnum fvelsum; + Gnum velosum; + Anum domnnum; + ArchDom domndat; + double domnrat; + + const Arch * restrict const archptr = &grafptr->a; + const ArchDom * restrict const domntab = grafptr->m.domntab; + Anum * restrict const parttax = grafptr->m.parttax; + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Anum domnnbr = grafptr->m.domnnbr; + + commload = 0; + compload = grafptr->comploaddlt; /* Use delta array as temporary storage */ + memSet (compload, 0, domnnbr * sizeof (Gnum)); + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum edgenum; + Gnum edgennd; + Anum partval; /* Part of current vertex */ + Anum partlst; /* Part of last vertex for which a distance was computed */ + Anum distlst; /* Last distance computed */ + Gnum veloval; + + partval = parttax[vertnum]; + partlst = -1; /* Invalid part to recompute distance */ + distlst = -1; /* To prevent compiler from yielding */ + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((partval < 0) || (partval >= domnnbr)) { + errorPrint ("kgraphCost: invalid part number (1)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + compload[partval] += veloval; + + for (edgenum = verttax[vertnum], edgennd = vendtax[vertnum]; + edgenum < edgennd; edgenum ++) { + Gnum vertend; + Anum partend; + + vertend = edgetax[edgenum]; + if (vertend > vertnum) /* Compute loads only once */ + continue; + + partend = parttax[vertend]; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((partend < 0) || (partend >= domnnbr)) { + errorPrint ("kgraphCost: invalid part number (2)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + if (partval != partend) { + Anum distval; + + distval = (partend != partlst) ? archDomDist (archptr, &domntab[partval], &domntab[partend]) : distlst; + distlst = distval; + partlst = partend; + + commload += (Gnum) distval * ((edlotax != NULL) ? edlotax[edgenum] : 1); + } + } + } + grafptr->commload = commload; + + fdomwgt = 0; + fvelsum = 0; + if ((grafptr->s.flagval & KGRAPHHASANCHORS) != 0) { + const Gnum vertancnnd = grafptr->s.vertnnd - domnnbr; + Gnum veloval; + + for (domnnum = 0; domnnum < domnnbr; domnnum ++) + if ((grafptr->s.verttax[vertancnnd + domnnum + 1] - grafptr->s.verttax[vertancnnd + domnnum]) != 0) + continue; + + if (domnnum != domnnbr) { + for (domnnum = 0; domnnum < domnnbr; domnnum ++) { + if ((grafptr->s.verttax[vertancnnd + domnnum + 1] - grafptr->s.verttax[vertancnnd + domnnum]) == 0) { + veloval = grafptr->s.velotax[vertancnnd + domnnum]; + + fdomwgt += (double) archDomWght (archptr, &grafptr->m.domntab[domnnum]); + fvelsum += veloval; + compload[domnnum] -= + grafptr->comploadavg[domnnum] = veloval; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (compload[domnnum] != 0) { + errorPrint ("kgraphCost: invalid load difference"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + } + } + } + archDomFrst (archptr, &domndat); + domnrat = (double) archDomWght (archptr, &domndat); + domnrat -= fdomwgt; + velosum = grafptr->s.velosum - fvelsum; + for (domnnum = 0; domnnum < domnnbr; domnnum ++) { + compload[domnnum] -= + grafptr->comploadavg[domnnum] = (Gnum) ((double) velosum * ((double) archDomWght (archptr, &grafptr->m.domntab[domnnum]) / domnrat)); + } +} + +/* This routine computes the frontier +** array of the current partition. +** It returns: +** - VOID : in all cases. +*/ + +void +kgraphFron ( +Kgraph * restrict const grafptr) +{ + Gnum vertnum; + Gnum vertnnd; + Gnum fronnbr; + + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Anum * restrict const parttax = grafptr->m.parttax; + Gnum * restrict const frontab = grafptr->frontab; + + for (vertnum = grafptr->s.baseval, vertnnd = grafptr->s.vertnnd, fronnbr = 0; + vertnum < vertnnd; vertnum ++) { + Anum partval; /* Part of current vertex */ + Gnum edgenum; /* Number of current edge */ + + partval = parttax[vertnum]; + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + if (parttax[edgetax[edgenum]] != partval) { /* If neighbor does not belong to the same part */ + frontab[fronnbr ++] = vertnum; + break; + } + } + } + + grafptr->fronnbr = fronnbr; +} diff --git a/scotch_6.0.3/src/libscotch/kgraph.h b/scotch_6.0.3/src/libscotch/kgraph.h new file mode 100644 index 00000000..ab697258 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph.h @@ -0,0 +1,165 @@ +/* Copyright 2004,2007,2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : Part of a static mapper. **/ +/** These lines are the data declarations **/ +/** for the k-way graph mapping structures **/ +/** and routines. **/ +/** **/ +/** DATES : # Version 3.2 : from : 12 sep 1997 **/ +/** to 26 may 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 12 mar 1999 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 16 feb 2005 **/ +/** # Version 5.0 : from : 17 jun 2008 **/ +/** to 17 jun 2008 **/ +/** # Version 5.1 : from : 13 jul 2010 **/ +/** to 31 aug 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 23 aug 2014 **/ +/** **/ +/** NOTES : # The comploadavg and comploaddlt **/ +/** should always be allocated together, **/ +/** with comploaddlt just after **/ +/** comploadavg. **/ +/** **/ +/** # To date, the only k-way graph mapping **/ +/** method is recursive bipartitioning, **/ +/** which does not use the comploadavg, **/ +/** comploaddlt and frontab parameters. **/ +/** Consequently, although allocated, **/ +/** these parameters are not set by this **/ +/** method. However, when coupled with **/ +/** the kdgraphMapSq() parallel static **/ +/** mapping routine, these parameters **/ +/** have to be computed. This is why the **/ +/** kgraphCost() routine is called within **/ +/** kdgraphMapSq(). When other sequential **/ +/** mapping routines are proposed, it may **/ +/** be more interesting to move **/ +/** kgraphCost() to kgraphMapRb(). **/ +/** **/ +/** # When (pfixtax != NULL), we are **/ +/** handling fixed vertices. **/ +/** **/ +/** # When (r.m.parttax != NULL), we are **/ +/** doing repartitioning. **/ +/** **/ +/************************************************************/ + +#define KGRAPH_H + +/* +** The defines. +*/ + +/*+ Graph option flags. +*/ + +#define KGRAPHFREEFRON (GRAPHBITSNOTUSED) /*+ Free frontier array +*/ +#define KGRAPHFREECOMP (GRAPHBITSNOTUSED << 1) /*+ Free computational loads array +*/ +#define KGRAPHFREEPFIX (GRAPHBITSNOTUSED << 2) /*+ Free fixed vertex array +*/ +#define KGRAPHFREEVMLO (GRAPHBITSNOTUSED << 3) /*+ Free vertex migration cost array +*/ +#define KGRAPHHASANCHORS (GRAPHBITSNOTUSED << 4) /*+ The graph is a band graph +*/ + +/* +** The type and structure definitions. +*/ + +/*+ The graph structure. +*/ + +typedef struct Kgraph_ { + Graph s; /*+ Current graph +*/ + Arch a; /*+ Current architecture +*/ + Mapping m; /*+ Current mapping of graph vertices +*/ + struct { /*+ Remapping structure +*/ + Mapping m; /*+ Old mapping +*/ + Gnum crloval; /*+ Coefficient load for regular edges +*/ + Gnum cmloval; /*+ Coefficient load for migration edges; may be zero +*/ + const Gnum * vmlotax; /*+ Vertex migration cost array +*/ + } r; + Gnum vfixnbr; /*+ Number of fixed vertices +*/ + const Anum * pfixtax; /*+ Fixed terminal part array +*/ + Gnum fronnbr; /*+ Number of frontier vertices +*/ + Gnum * frontab; /*+ Array of frontier vertex numbers +*/ + Gnum * comploadavg; /*+ Array of target average loads +*/ + Gnum * comploaddlt; /*+ Array of target imbalances +*/ + double comploadrat; /*+ Ideal load balance per weight unit +*/ + double kbalval; /*+ Last k-way imbalance ratio +*/ + Gnum commload; /*+ Communication load +*/ + Gnum levlnum; /*+ Graph coarsening level +*/ +} Kgraph; + +/*+ The save graph structure. +*/ + +typedef struct KgraphStore_ { + Gnum partnbr; /*+ Number of parts +*/ + int mflaval; /*+ Mapping properties +*/ + Anum * parttab; /*+ Mapping array [vertnbr] +*/ + ArchDom * domntab; /*+ Array of domains [termmax] +*/ + Anum domnnbr; /*+ Current number of domains +*/ + Gnum fronnbr; /*+ Number of frontier vertices +*/ + Gnum * frontab; /*+ Array of frontier vertex numbers +*/ + Gnum * comploadavg; /*+ Array of target average loads +*/ + Gnum * comploaddlt; /*+ Array of target imbalances +*/ + double kbalval; /*+ Last k-way imbalance ratio +*/ + Gnum commload; /*+ Communication load +*/ +} KgraphStore; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH +#define static +#endif + +int kgraphInit (Kgraph * restrict const, const Graph * restrict const, const Arch * restrict const, const ArchDom * restrict const, const Gnum, const Anum * restrict const, const Anum * restrict const, const Gnum, const Gnum, const Gnum * restrict const); +void kgraphExit (Kgraph * const); +void kgraphFrst (Kgraph * const); +int kgraphCheck (const Kgraph * const); +void kgraphCost (Kgraph * const); +void kgraphFron (Kgraph * const); +int kgraphBand (Kgraph * restrict const, const Gnum, Kgraph * restrict const, Gnum * const, Gnum * restrict * restrict const); + +int kgraphStoreInit (const Kgraph * const, KgraphStore * const); +void kgraphStoreExit (KgraphStore * const); +void kgraphStoreSave (const Kgraph * const, KgraphStore * const); +void kgraphStoreUpdt (Kgraph * const, const KgraphStore * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph_band.c b/scotch_6.0.3/src/libscotch/kgraph_band.c new file mode 100644 index 00000000..f5734c69 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_band.c @@ -0,0 +1,690 @@ +/* Copyright 2009-2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_band.c **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a k-way band **/ +/** graph from the given frontier **/ +/** array. **/ +/** **/ +/** DATES : # Version 6.0 : from : 05 jan 2009 **/ +/** to : 15 sep 2014 **/ +/** **/ +/** NOTES : # This code derives from the code of **/ +/** kdgraph_band.c in version 5.2 for **/ +/** direct k-way partitioning. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_BAND + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "graph.h" +#include "mapping.h" +#include "kgraph.h" +#include "kgraph_band.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes a index array of given +** width around the current separator. +** It returns: +** - 0 : if the index array could be computed. +** - !0 : on error. +*/ + +int +kgraphBand ( +Kgraph * restrict const grafptr, /*+ Pointer to original graph +*/ +const Gnum distmax, /*+ Maximum distance from separator vertices +*/ +Kgraph * restrict const bandgrafptr, /*+ Pointer to band graph structure to fill +*/ +Gnum * const bandvertlvlptr, /*+ Pointer to based start index of last level +*/ +Gnum * restrict * restrict const bandvnumptr) /*+ Pointer to bandvnumtax +*/ +{ + Gnum bandvertnbr; /* Number of band vertices (including anchor vertices) */ + Gnum bandvertnnd; /* Based end of band vertex array (without anchor vertices) */ + Gnum bandvertnum; + Gnum * restrict bandverttax; + Gnum * restrict bandvelotax; + Gnum * restrict bandvmlotax; + Gnum * restrict bandvnumtax; /* Original numbers of vertices in band graph */ +#define bandedgetab bandcompload /* TRICK: use delta array to compute edge offsets */ + Gnum * restrict bandedgetax; + Gnum * restrict bandedlotax; + Gnum * restrict bandeeextab; + Gnum bandedgenbr; + Gnum bandedgenum; + Gnum banddegrmax; + Gnum * restrict bandfrontab; + Anum * restrict bandparttax; + Anum * restrict bandparotax; + Gnum bandvfixnbr; + Gnum bandvertlvlnum; /* Index of first band vertex belonging to last level */ + Gnum bandvertancadj; /* Flag set when anchor(s) represent inexistent vertices */ + Gnum * restrict vnumotbdtax; /* Original to band graph vertex numbers (~0 if not in band graph, -2 for fixed vertices) */ + Gnum * restrict bandanlotab; /* Temporary array to store loads to anchors */ + Gnum bandedlonbr; /* Size of local band edge load array */ + Gnum bandedlosum; + Gnum * restrict bandcompload; + Gnum bandcommload; + Gnum * restrict compload; /* Load of parts in original graph */ + Gnum fronnum; + Anum domnnbr; + Anum domnnum; + Gnum veloval; + Gnum vertnum; + Gnum vfixnum; + Gnum vfixflag; + KgraphBandHash * restrict termhashtab; + Anum termhashmsk; + + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const Gnum * restrict const frontab = grafptr->frontab; + const Gnum * restrict const pfixtax = grafptr->pfixtax; + const Anum * restrict const parttax = grafptr->m.parttax; + const Anum * restrict const parotax = grafptr->r.m.parttax; + const Gnum * restrict const vmlotax = grafptr->r.vmlotax; + + if (graphBand (&grafptr->s, grafptr->fronnbr, grafptr->frontab, distmax, + &vnumotbdtax, &bandvertlvlnum, &bandvertnbr, &bandedgenbr, + pfixtax, &bandvfixnbr) != 0) { /* Get vertices to keep in band graph */ + errorPrint ("kgraphBand: cannot number graph vertices"); + return (1); + } + + if (bandvertlvlptr != NULL) + *bandvertlvlptr = bandvertlvlnum; + + domnnbr = grafptr->m.domnnbr; + termhashtab = NULL; + bandanlotab = NULL; + bandeeextab = NULL; + if (pfixtax != NULL) { /* Fixed vertices may be neighbors of band graph vertices and may not belong to the band graph */ + Anum termhashsiz; + + const Arch * restrict const tgtarchptr = grafptr->m.archptr; + + for (termhashsiz = 0, termhashmsk = domnnbr; termhashmsk != 0; termhashsiz ++, termhashmsk >>= 1) ; /* Get upper power of two */ + termhashsiz = 1 << (termhashsiz + 2); /* Fill hash table at 25% maximum */ + termhashmsk = termhashsiz - 1; + + if (memAllocGroup ((void **) (void *) /* Allocation and initialization of fixed vertices temporary arrays */ + &termhashtab, (size_t) (termhashsiz * sizeof (KgraphBandHash)), + &bandanlotab, (size_t) (domnnbr * sizeof (Gnum)), + &bandeeextab, (size_t) (domnnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("kgraphBand: out of memory (1)"); + return (1); + } + memSet (termhashtab, ~0, termhashsiz * sizeof (KgraphBandHash)); + memSet (bandanlotab, 0, domnnbr * sizeof (Gnum)); /* Assume there are no extra loads to anchors */ + memSet (bandeeextab, 0, domnnbr * sizeof (Gnum)); + for (domnnum = 0; domnnum < domnnbr; domnnum ++) { + ArchDom * domnptr; + + domnptr = &grafptr->m.domntab[domnnum]; + if (archDomSize (tgtarchptr, domnptr) == 1) { /* If domain is terminal */ + Gnum termhashnum; + Anum termnum; + + termnum = archDomNum (tgtarchptr, domnptr); /* Get terminal domain number */ + + for (termhashnum = (termnum * KGRAPHBANDHASHPRIME) & termhashmsk; ; termhashnum = (termhashnum + 1) & termhashmsk) { + if (termhashtab[termhashnum].termnum == ~0) { /* If hash slot empty */ + termhashtab[termhashnum].termnum = termnum; /* Create slot */ + termhashtab[termhashnum].domnnum = domnnum; + break; + } +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (termhashtab[termhashnum].termnum == termnum) { /* If hash slot found */ + errorPrint ("kgraphBand: duplicate terminal domain in domain array"); + memFree (termhashtab); + kgraphExit (bandgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + } + } + } + + bandedgenbr += 2 * (bandvertnbr + grafptr->s.baseval - bandvertlvlnum) + /* Add edges to and from anchors */ + grafptr->s.degrmax * grafptr->vfixnbr; /* A band graph vertex that is the neighbour of a fixed vertex will get an extra edge, even if the fixed vertex is not in the band graph */ + bandvertnbr += domnnbr; /* Add anchor vertices */ + bandedlonbr = ((edlotax != NULL) || (pfixtax != NULL)) ? bandedgenbr : 0; + + graphInit (&bandgrafptr->s); + bandgrafptr->s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP | /* Arrays created by the routine itself */ + KGRAPHFREEFRON | KGRAPHFREECOMP | KGRAPHHASANCHORS; + bandgrafptr->s.baseval = grafptr->s.baseval; + bandgrafptr->s.vertnbr = bandvertnbr; + bandgrafptr->s.vertnnd = bandvertnbr + bandgrafptr->s.baseval; /* With anchor vertices */ + bandgrafptr->a = grafptr->a; + mapInit2 (&bandgrafptr->m, &bandgrafptr->s, &bandgrafptr->a, &grafptr->m.domnorg, grafptr->m.domnmax, grafptr->m.domnnbr); + mapInit2 (&bandgrafptr->r.m, &bandgrafptr->s, &bandgrafptr->a, &grafptr->m.domnorg, grafptr->r.m.domnmax, grafptr->r.m.domnnbr); + bandgrafptr->r.m.domntab = grafptr->r.m.domntab; /* Band old mapping domain array is a clone of old mapping (no freeing) */ + bandgrafptr->r.m.domnnbr = grafptr->r.m.domnnbr; + bandgrafptr->r.crloval = grafptr->r.crloval; + bandgrafptr->r.cmloval = grafptr->r.cmloval; + bandgrafptr->r.vmlotax = NULL; + bandgrafptr->vfixnbr = 0; /* Band graphs do not have fixed vertices */ + bandgrafptr->pfixtax = NULL; + bandgrafptr->frontab = NULL; /* Frontier array not yet allocated */ + bandgrafptr->comploadavg = NULL; /* Computation load arrays not yet allocated */ + bandgrafptr->comploaddlt = NULL; + bandgrafptr->commload = grafptr->commload; /* Communication load is preserved */ + bandgrafptr->kbalval = grafptr->kbalval; + bandgrafptr->levlnum = grafptr->levlnum; + + if (memAllocGroup ((void **) (void *) /* Allocate graph data */ + &bandgrafptr->s.verttax, (size_t) ((bandvertnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ + &bandgrafptr->s.velotax, (size_t) (bandvertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("kgraphBand: out of memory (2)"); + return (1); + } + if ((bandvnumtax = memAlloc ((bandvertnbr) * sizeof (Gnum))) == NULL) { /* Allocate alone since it is an output */ + errorPrint ("kgraphBand: out of memory (3)"); + return (1); + } + if (vmlotax != NULL) { + if ((bandvmlotax = memAlloc (bandvertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("kgraphBand: out of memory (4)"); + return (1); + } + memSet (bandvnumtax + bandvertnbr - domnnbr, ~0, domnnbr * sizeof (Gnum)); /* Prevent Valgrind from yelling when centralizing band graphs */ + bandgrafptr->r.vmlotax = bandvmlotax - bandgrafptr->s.baseval; + bandgrafptr->s.flagval |= KGRAPHFREEVMLO; + } + if (parotax != NULL) { + if ((bandparotax = memAlloc (bandvertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("kgraphBand: out of memory (5)"); + return (1); + } + memSet (bandparotax + bandvertnbr - bandgrafptr->r.m.domnnbr, ~0, bandgrafptr->r.m.domnnbr * sizeof (Gnum)); /* Prevent Valgrind from yelling when centralizing band graphs */ + bandgrafptr->r.m.parttax = bandparotax - bandgrafptr->s.baseval; + bandgrafptr->r.m.flagval |= MAPPINGFREEPART; + } + + bandgrafptr->s.verttax -= bandgrafptr->s.baseval; + bandvnumtax -= bandgrafptr->s.baseval; + bandgrafptr->s.velotax -= bandgrafptr->s.baseval; + + if ((bandgrafptr->s.edgetax = memAlloc ((bandedgenbr + bandedlonbr) * sizeof (Gnum))) == NULL) { + errorPrint ("kgraphBand: out of memory (6)"); + return (1); + } + bandedlotax = NULL; + bandedgetax = + bandgrafptr->s.edgetax -= bandgrafptr->s.baseval; + if ((edlotax != NULL) || (pfixtax != NULL)) { + bandgrafptr->s.edlotax = + bandedlotax = bandedgetax + bandedgenbr; + } + + if (((bandgrafptr->frontab = memAlloc (bandvertnbr * sizeof (Gnum))) == NULL) || /* Allocation and initialization of imbalance arrays */ + (memAllocGroup ((void **) (void *) + &bandgrafptr->comploadavg, (size_t) ((domnnbr + 2) * sizeof (Gnum)), /* TRICK: always keep two slots for collective communication */ + &bandgrafptr->comploaddlt, (size_t) ((domnnbr + 2) * sizeof (Gnum)), NULL) == NULL)) { + errorPrint ("kgraphBand: out of memory (7)"); + if (bandgrafptr->frontab != NULL) + memFree (bandgrafptr->frontab); + return (1); + } + bandfrontab = bandgrafptr->frontab; + + if ((bandparttax = memAlloc (bandvertnbr * sizeof (Anum))) == NULL) { + errorPrint ("kgraphBand: out of memory (8)"); + return (1); + } + bandgrafptr->m.parttax = + bandparttax -= bandgrafptr->s.baseval; + + if ((bandgrafptr->m.domntab = memAlloc (domnnbr * sizeof (ArchDom))) == NULL) { + errorPrint ("kgraphBand: out of memory (9)"); + return (1); + } + bandgrafptr->m.flagval |= MAPPINGFREEDOMN; +#ifdef SCOTCH_DEBUG_KGRAPH2 + memSet (bandvnumtax + bandgrafptr->s.baseval, ~0, (bandvertnbr * sizeof (Gnum))); +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + vfixnum = 0; + for (fronnum = 0, bandvertnum = bandgrafptr->s.baseval; + fronnum < grafptr->fronnbr; fronnum ++) { /* Turn all graph frontier vertices into band frontier vertices */ + Gnum vertnum; + + vertnum = frontab[fronnum]; + if ((pfixtax != NULL) && (pfixtax[vertnum] != -1)) /* It is a fixed vertex */ + vfixnum ++; + else { + bandfrontab[bandvertnum - bandgrafptr->s.baseval] = bandvertnum; /* All frontier vertices are first vertices of band graph */ + bandvnumtax[bandvertnum] = vertnum; + bandvertnum ++; + } + } + bandgrafptr->fronnbr = grafptr->fronnbr - vfixnum; /* Remove fixed vertices from frontier */ + for (bandvertnnd = bandvertnbr + bandgrafptr->s.baseval - domnnbr; /* Pick selected band vertices from rest of frontier array without anchors */ + bandvertnum < bandvertnnd + bandvfixnbr - vfixnum; fronnum ++) { + Gnum vertnum; + + vertnum = frontab[fronnum]; + if ((pfixtax != NULL) && (pfixtax[vertnum] != -1)) /* It is a fixed vertex */ + vfixnum ++; + else { + bandvnumtax[bandvertnum] = vertnum; + bandvertnum ++; + } + } +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vfixnum != bandvfixnbr) { + errorPrint ("kgraphBand: internal error (1)"); /* All fixed vertices indices must be at the beginning of frontab */ + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + memSet (bandvnumtax + bandvertnnd, ~0, domnnbr * sizeof (Gnum)); /* Prevent Valgrind from yelling when centralizing band graphs */ + + bandverttax = bandgrafptr->s.verttax; + bandvelotax = bandgrafptr->s.velotax; + banddegrmax = 0; + bandcommload = 0; + bandcompload = bandgrafptr->comploaddlt; /* TRICK: use delta array to compute load sums */ + memSet (bandcompload, 0, domnnbr * sizeof (Gnum)); + bandedlosum = 0; + vfixflag = 0; + for (bandvertnum = bandedgenum = bandgrafptr->s.baseval; /* Build vertex array of band graph */ + bandvertnum < bandvertlvlnum; bandvertnum ++) { /* For all vertices that do not belong to the last level */ + Gnum vertnum; + Gnum edgenum; + Anum partval; + Gnum degrval; + + vertnum = bandvnumtax[bandvertnum]; + if (vfixflag == 1) { /* Last vertex had neighbours fixed vertices */ + memSet (bandanlotab, 0, domnnbr * sizeof (Gnum)); /* Reset loads to anchors */ + vfixflag = 0; /* Guess that these are no extra loads to anchors */ + } + if (vmlotax != NULL) + bandvmlotax[bandvertnum] = vmlotax[vertnum]; + if (parotax != NULL) + bandparotax[bandvertnum] = parotax[vertnum]; + partval = parttax[vertnum]; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((partval < 0) || (partval >= domnnbr)) { + errorPrint ("kgraphBand: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + bandparttax[bandvertnum] = partval; + bandverttax[bandvertnum] = bandedgenum; + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + bandcompload[partval] += veloval; /* Sum vertex load for each part */ + bandvelotax[bandvertnum] = veloval; + + degrval = vendtax[vertnum] - verttax[vertnum]; + if (banddegrmax < degrval) + banddegrmax = degrval; + + for (edgenum = verttax[vertnum]; /* For all original edges */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = edgetax[edgenum]; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vnumotbdtax[vertend] == -1) { /* All ends should belong to the band graph too */ + errorPrint ("kgraphBand: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + if (bandedlotax != NULL) { /* If graph has edge weights (always true when fixed vertices present) */ + Gnum edloval; + Gnum termnum; + + edloval = (edlotax == NULL) ? 1 : edlotax[edgenum]; + if ((pfixtax != NULL) && + ((termnum = pfixtax[vertend]) >= 0)) { /* If end vertex is fixed */ + Gnum termhashnum; + + for (termhashnum = (termnum * KGRAPHBANDHASHPRIME) & termhashmsk; ; termhashnum = (termhashnum + 1) & termhashmsk) { + if (termhashtab[termhashnum].termnum == termnum) { /* If hash slot found */ + bandanlotab[termhashtab[termhashnum].domnnum] += edloval; + vfixflag = 1; /* Vertex have some end vertices fixed */ + break; + } +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (termhashtab[termhashnum].termnum == ~0) { /* If hash slot not found */ + errorPrint ("kgraphBand: missing terminal domain in domain array (1)"); + memFree (termhashtab); + kgraphExit (bandgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + } + else { /* End vertex is not fixed */ + bandedlosum += edloval; + bandedlotax[bandedgenum] = edloval; + bandedgetax[bandedgenum ++] = vnumotbdtax[vertend]; + } + } + else + bandedgetax[bandedgenum ++] = vnumotbdtax[vertend]; + } + + if (vfixflag == 1) { /* If vertex has at least one neighbours that is fixed */ + Gnum edloval; + + edloval = 0; + for (domnnum = 0; domnnum < domnnbr; domnnum ++) { /* Traverse bandanlotab to handle loads to anchors */ + if (bandanlotab[domnnum] != 0) /* Fixed neighbours are linked to this domain */ + edloval += bandanlotab[domnnum]; /* Add load induced by edges to fixed vertices */ + if (edloval != 0) { /* We have to add an edge to the anchor */ + Gnum degrval; + + bandedlotax[bandedgenum] = edloval; + bandedlosum += edloval; + bandedgetax[bandedgenum ++] = bandvertnnd + domnnum; /* Add edge to anchor of proper part */ + bandeeextab[domnnum] ++; /* One more extra edge to the anchor */ + + degrval = bandedgenum - bandverttax[bandvertnum]; + if (banddegrmax < degrval) + banddegrmax = degrval; + edloval = 0; + } + } + } + } + for ( ; bandvertnum < bandvertnnd; bandvertnum ++) { /* For all vertices that belong to the last level except anchors */ + Gnum vertnum; + Gnum edgenum; + Anum partval; + + vertnum = bandvnumtax[bandvertnum]; + if (vfixflag == 1) { /* Last vertex had neighbours fixed vertices */ + memSet (bandanlotab, 0, domnnbr * sizeof (Gnum)); /* Reset loads to anchors */ + vfixflag = 0; /* Guess that these are no extra loads to anchors */ + } + if (vmlotax != NULL) + bandvmlotax[bandvertnum] = vmlotax[vertnum]; + if (parotax != NULL) + bandparotax[bandvertnum] = parotax[vertnum]; + partval = parttax[vertnum]; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((partval < 0) || (partval >= domnnbr)) { + errorPrint ("kgraphBand: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + bandparttax[bandvertnum] = partval; + bandverttax[bandvertnum] = bandedgenum; + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + bandcompload[partval] += veloval; /* Sum vertex load for each part */ + bandvelotax[bandvertnum] = veloval; + + for (edgenum = verttax[vertnum]; /* For all original edges */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Gnum bandvertend; + + vertend = edgetax[edgenum]; + bandvertend = vnumotbdtax[vertend]; + if (bandedlotax != NULL) { /* If graph has edge weights, copy load */ + Gnum edloval; + Gnum termnum; + + edloval = (edlotax == NULL) ? 1 : edlotax[edgenum]; + if ((pfixtax != NULL) && + ((termnum = pfixtax[vertend]) >= 0)) { /* If end vertex is fixed */ + Gnum termhashnum; + + for (termhashnum = (termnum * KGRAPHBANDHASHPRIME) & termhashmsk; ; termhashnum = (termhashnum + 1) & termhashmsk) { + if (termhashtab[termhashnum].termnum == termnum) { /* If hash slot found */ + bandanlotab[termhashtab[termhashnum].domnnum] += edloval; + vfixflag = 1; /* Vertex have some end vertices fixed */ + break; + } +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (termhashtab[termhashnum].termnum == ~0) { /* If hash slot not found */ + errorPrint ("kgraphBand: missing terminal domain in domain array (2)"); + memFree (termhashtab); + kgraphExit (bandgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + } + else if (bandvertend >= 0) { /* If end vertex is not fixed and in the band graph */ + bandedlosum += edloval; + bandedlotax[bandedgenum] = edloval; + } + } + if (bandvertend >= 0) /* If end vertex is not fixed and in the band graph */ + bandedgetax[bandedgenum ++] = vnumotbdtax[vertend]; + } + if (vfixflag == 1) { /* If vertex has at least one fixed neighbor */ + Gnum edloval; + + for (domnnum = 0; domnnum < domnnbr; domnnum ++) { /* Traverse bandanlotab to handle loads to anchors */ + + edloval = 0; + if (domnnum == partval) /* The current vertex is mapped to current domain */ + edloval += 1; /* Add basic edge load to anchor */ + if (bandanlotab[domnnum] != 0) /* Fixed neighbours are linked to this domain */ + edloval += bandanlotab[domnnum]; /* Add load induced by edges to fixed vertices */ + if (edloval != 0) { /* We have to add an edge to the anchor */ + Gnum degrval; + + bandedlotax[bandedgenum] = edloval; + bandedlosum += edloval; + bandedgetax[bandedgenum ++] = bandvertnnd + domnnum; /* Add edge to anchor of proper part */ + if (domnnum != partval) + bandeeextab[domnnum] ++; /* One more extra edge to the anchor */ + + degrval = bandedgenum - bandverttax[bandvertnum]; + if (banddegrmax < degrval) + banddegrmax = degrval; + edloval = 0; + } + } + } + else { + Gnum degrval; + + if (bandedlotax != NULL) { /* If graph has edge weights */ + bandedlotax[bandedgenum] = 1; /* Edge to anchor has load 1 */ + bandedlosum ++; + } + bandedgetax[bandedgenum ++] = bandvertnnd + partval; /* Add edge to anchor of proper part */ + degrval = bandedgenum - bandverttax[bandvertnum]; + if (banddegrmax < degrval) + banddegrmax = degrval; + } + } + + memFree (vnumotbdtax + bandgrafptr->s.baseval); /* Free useless space */ + + compload = bandgrafptr->comploadavg; /* Use average array to store actual part loads */ + memSet (compload, 0, domnnbr * sizeof (Gnum)); + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) + compload[parttax[vertnum]] += (velotax != NULL) ? velotax[vertnum] : 1; + + for (domnnum = 0, bandvertancadj = 0; domnnum < domnnbr; domnnum ++) { /* For all anchors */ + Gnum bandveloval; + + bandveloval = compload[domnnum] - bandcompload[domnnum]; /* Get load of anchor */ + bandparttax[bandvertnnd + domnnum] = domnnum; /* Set parts of anchor vertices */ + bandvelotax[bandvertnnd + domnnum] = bandveloval; + if (bandveloval == 0) + bandvertancadj = 1; + } + + if (bandvertancadj == 1) /* Anchors have to be adjusted */ + for (domnnum = 0; domnnum < domnnbr; domnnum ++) /* Increase weight of all anchors to keep balance */ + bandvelotax[bandvertnnd + domnnum] ++; + + bandverttax[bandvertnum] = bandedgenum; /* Fill last element without anchors */ + if (pfixtax != NULL) + memCpy (bandedgetab, bandeeextab, domnnbr * sizeof (Gnum)); + else + memSet (bandedgetab, 0, domnnbr * sizeof (Gnum)); + + for (bandvertnum = bandvertlvlnum; bandvertnum < bandvertnnd; bandvertnum ++) + bandedgetab[bandparttax[bandvertnum]] ++; /* Fill array of anchors' degrees */ + + for (domnnum = 0; domnnum < domnnbr; domnnum ++) { /* Set bandverttax for anchors vertices and pre-set bandedgetab */ + Gnum degrval; /* to be able to quickly fill bandedgetax in next loop */ + Gnum dispval; + + degrval = bandedgetab[domnnum]; + dispval = bandverttax[bandvertnnd + domnnum]; + if (banddegrmax < degrval) /* Update maximum degree value */ + banddegrmax = degrval; + bandverttax[bandvertnnd + domnnum + 1] = dispval + degrval; + bandedgetab[domnnum] = dispval; /* Start index for edges to vertices of last layer */ + } + + if (pfixtax != NULL) { /* We have fixed vertices */ + memFree (termhashtab); /* Free group leader */ + for (bandvertnum = bandgrafptr->s.baseval, bandedgenum = 0; bandvertnum < bandvertnnd; + bandvertnum ++) { /* Link anchors to vertices */ + for ( ; bandedgenum < bandverttax[bandvertnum + 1]; bandedgenum ++) { + Gnum bandvertend; + + bandvertend = bandedgetax[bandedgenum]; + if (bandvertend >= bandvertnnd) { /* If it is an edge to an anchor */ + Gnum partval; /* Add the symmetric edge from the anchor */ + Gnum edloval; + + partval = bandvertend - bandvertnnd; + edloval = bandedlotax[bandedgenum]; + + bandedlotax[bandedgetab[partval]] = edloval; + bandedlosum += edloval; + bandedgetax[bandedgetab[partval] ++] = bandvertnum; + } + } + } + } + else { + if (bandedlotax != NULL) { /* If graph has edge weights */ + Gnum edgenum; + Gnum edgennd; + + for (bandvertnum = bandgrafptr->s.baseval; /* For all vertices not belonging to last level */ + bandvertnum < bandvertlvlnum; bandvertnum ++) { + Gnum vertnum; + Gnum bandedgenum; + + vertnum = bandvnumtax[bandvertnum]; + bandedgenum = bandverttax[bandvertnum]; + memCpy (&bandedlotax[bandedgenum], &edlotax[verttax[vertnum]], /* Copy edge load array */ + (bandverttax[bandvertnum + 1] - bandedgenum) * sizeof (Gnum)); + } /* Vertices of last level have been processed before */ + for (edgenum = bandverttax[bandvertnnd], /* Loads of anchor edges are all 1's too */ + edgennd = bandverttax[bandvertnnd + domnnbr]; + edgenum < edgennd; edgenum ++) + bandedlotax[edgenum] = 1; + } + for (bandvertnum = bandvertlvlnum; bandvertnum < bandvertnnd; /* We do not have fixed vertices */ + bandvertnum ++) { /* Link anchors to vertices of last level */ + Anum partval; + Gnum vertnum; + + vertnum = bandvnumtax[bandvertnum]; + partval = bandparttax[bandvertnum]; + bandedgetax[bandedgetab[partval] ++] = bandvertnum; + + if (bandedlotax != NULL) + bandedlotax[bandedgetab[partval] - 1] = 1; + bandedlosum ++; + } +#ifdef SCOTCH_DEBUG_KGRAPH2 + for (domnnum = 0; domnnum < domnnbr; domnnum ++) { + if (bandedgetab[domnnum] != bandverttax[bandvertnnd + 1 + domnnum]) { + errorPrint ("kgraphBand: internal error (6)"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + bandedgenbr = bandgrafptr->s.verttax[bandvertnnd + domnnbr] - bandgrafptr->s.baseval; /* Set real number of edges */ + + bandgrafptr->s.vendtax = bandgrafptr->s.verttax + 1; /* Band graph is compact */ + bandgrafptr->s.velosum = grafptr->s.velosum + domnnbr * bandvertancadj; + bandgrafptr->s.edgenbr = bandedgenbr; + if (bandedlotax == NULL) + bandedlosum = bandedgenbr; + bandgrafptr->s.edlosum = bandedlosum; + bandgrafptr->s.degrmax = banddegrmax; /* Local maximum degree will be turned into global maximum degree */ + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (graphCheck (&bandgrafptr->s) != 0) { + errorPrint ("kgraphBand: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + memCpy (bandgrafptr->m.domntab, grafptr->m.domntab, domnnbr * sizeof (ArchDom)); + + if (pfixtax != NULL) + kgraphFron (bandgrafptr); + + kgraphCost (bandgrafptr); + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (bandgrafptr) != 0) { + errorPrint ("kgraphBand: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + *bandvnumptr = bandvnumtax; + + return (0); +} + diff --git a/scotch_6.0.3/src/libscotch/kgraph_band.h b/scotch_6.0.3/src/libscotch/kgraph_band.h new file mode 100644 index 00000000..bc917da1 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_band.h @@ -0,0 +1,65 @@ +/* Copyright 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_band.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the k-way band graph extraction **/ +/** routine. **/ +/** **/ +/** DATES : # Version 6.0 : from : 15 sep 2014 **/ +/** to 15 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Prime number for hashing terminal domain numbers. +*/ + +#define KGRAPHBANDHASHPRIME 17 /*+ Prime number for hashing +*/ + +/* +** The type and structure definitions. +*/ + +/*+ Hash structure for linking fixed vertex + domains with non-fixed vertex domains. +*/ + +typedef struct KgraphBandHash_ { + Anum termnum; /*+ Terminal domain number +*/ + Anum domnnum; /*+ Domain number in domain array +*/ +} KgraphBandHash; diff --git a/scotch_6.0.3/src/libscotch/kgraph_check.c b/scotch_6.0.3/src/libscotch/kgraph_check.c new file mode 100644 index 00000000..d461d9ff --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_check.c @@ -0,0 +1,252 @@ +/* Copyright 2010,2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the mapping graph **/ +/** consistency checking routine. **/ +/** **/ +/** DATES : # Version 5.1 : from : 13 jul 2010 **/ +/** to 13 jul 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 14 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "kgraph.h" + +/*************************/ +/* */ +/* These routines handle */ +/* mapping graphs. */ +/* */ +/*************************/ + +/* This routine checks the consistency +** of the given mapping graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +kgraphCheck ( +const Kgraph * restrict const grafptr) +{ + int * restrict flagtax; /* Frontier flag array */ + Gnum vertnum; /* Number of current vertex */ + Gnum fronnum; /* Number of frontier vertex */ + Gnum vfixnbr; /* Number of fixed vertices */ + Gnum * restrict comploadtab; + Gnum commload; + Gnum edloval; + Anum domnnum; + int o; + + const Gnum baseval = grafptr->s.baseval; + const Gnum vertnnd = grafptr->s.vertnnd; + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const Anum * restrict const parttax = grafptr->m.parttax; + const ArchDom * restrict const domntab = grafptr->m.domntab; + const Arch * const archptr = grafptr->m.archptr; + const Anum * restrict const pfixtax = grafptr->pfixtax; + const Gnum * restrict const frontab = grafptr->frontab; + + if (&grafptr->s != grafptr->m.grafptr) { + errorPrint ("kgraphCheck: invalid mapping graph"); + return (1); + } + + if ((grafptr->m.domnmax <= 0) || + (grafptr->m.domnnbr > grafptr->m.domnmax) || + (grafptr->m.domnnbr > grafptr->s.vertnbr)) { + errorPrint ("kgraphCheck: invalid number of domains"); + return (1); + } + + if (memAllocGroup ((void **) (void *) + &comploadtab, (size_t) (grafptr->m.domnnbr * sizeof (Gnum)), + &flagtax, (size_t) (grafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("kgraphCheck: out of memory"); + return (1); + } + memSet (comploadtab, 0, grafptr->m.domnnbr * sizeof (Gnum)); + memSet (flagtax, ~0, grafptr->s.vertnbr * sizeof (Gnum)); + flagtax -= baseval; + + o = 1; /* Assume failure when checking */ + for (vertnum = baseval, vfixnbr = 0; + vertnum < vertnnd; vertnum ++) { + Anum partval; + + partval = parttax[vertnum]; + if ((partval < 0) || + (partval >= grafptr->m.domnnbr)) { + errorPrint ("kgraphCheck: invalid part array"); + goto fail; + } + if (pfixtax != NULL) { + Anum pfixval; + + pfixval = pfixtax[vertnum]; + if (pfixval != ~0) { + if (pfixval < 0) { + errorPrint ("kgraphCheck: invalid fixed part value"); + goto fail; + } + if (pfixval != archDomNum (archptr, &grafptr->m.domntab[partval])) { + errorPrint ("kgraphCheck: part index does not match fixed array"); + goto fail; + } + vfixnbr ++; + } + } + } + if (vfixnbr != grafptr->vfixnbr) { + errorPrint ("kgraphCheck: invalid number of fixed vertices"); + goto fail; + } + + if ((grafptr->fronnbr < 0) || + (grafptr->fronnbr > grafptr->s.vertnbr)) { + errorPrint ("kgraphCheck: invalid number of frontier vertices"); + goto fail; + } + for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { + Gnum vertnum; + Gnum edgenum; + Anum partval; + Anum flagval; + + vertnum = frontab[fronnum]; + if ((vertnum < baseval) || (vertnum >= vertnnd)) { + errorPrint ("kgraphCheck: invalid vertex index in frontier array"); + goto fail; + } + if (flagtax[vertnum] != ~0) { + errorPrint ("kgraphCheck: duplicate vertex in frontier array"); + goto fail; + } + flagtax[vertnum] = 0; + partval = parttax[vertnum]; + + for (edgenum = verttax[vertnum], flagval = 0; + edgenum < vendtax[vertnum]; edgenum ++) + flagval |= parttax[edgetax[edgenum]] ^ partval; /* Flag set if neighbor part differs from vertex part */ + + if (flagval == 0) { + errorPrint ("kgraphCheck: invalid vertex in frontier array"); + goto fail; + } + } + + commload = 0; + edloval = 1; /* Assume edges are not weighted */ + for (vertnum = baseval; vertnum < vertnnd; vertnum ++) { + Anum partval; /* Part of current vertex */ + Anum tdomnum; /* Terminal domain number of current vertex */ + Anum tdfinum; /* Terminal domain number of current fixed vertex */ + Gnum edgenum; /* Number of current edge */ + Gnum commcut; + + partval = parttax[vertnum]; + tdomnum = archDomNum (&grafptr->a, &grafptr->m.domntab[partval]); + tdfinum = (grafptr->pfixtax != NULL) ? grafptr->pfixtax[vertnum] : -1; + + if ((tdfinum != -1) && /* If it is a fixed vertex */ + (tdfinum != tdomnum)) { + errorPrint ("kgraphCheck: invalid fixed vertex part"); + goto fail; + } + + comploadtab[partval] += (velotax == NULL) ? 1 : velotax[vertnum]; + + commcut = 0; + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Anum partend; + + if (edlotax != NULL) + edloval = edlotax[edgenum]; + partend = parttax[edgetax[edgenum]]; + + if (partend == partval) /* If same part, no communication load */ + continue; + + commcut += edloval * archDomDist (archptr, &domntab[partval], &domntab[partend]); /* Loads are accounted for twice */ + } + + if ((commcut != 0) && (flagtax[vertnum] != 0)) { /* If vertex should be in frontier array */ + errorPrint ("kgraphCheck: vertex should be in frontier array"); + goto fail; + } + + commload += commcut; + } + commload /= 2; + if (commload != grafptr->commload) { + errorPrint ("kgraphCheck: invalid communication load"); + goto fail; + } + + for (domnnum = 0; domnnum < grafptr->m.domnnbr; domnnum ++) { + if (comploadtab[domnnum] != (grafptr->comploadavg[domnnum] + grafptr->comploaddlt[domnnum])) { + errorPrint ("kgraphCheck: invalid computation load"); + goto fail; + } + } + + o = 0; /* Everything turned well */ + +fail : + memFree (comploadtab); /* Free group leader */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_bd.c b/scotch_6.0.3/src/libscotch/kgraph_map_bd.c new file mode 100644 index 00000000..7eccfac9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_bd.c @@ -0,0 +1,329 @@ +/* Copyright 2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_bd.c **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module computes a partition of **/ +/** the given k-way mapping graph by **/ +/** creating a band graph of given **/ +/** width around the current frontier, **/ +/** computing an improved partition of the **/ +/** band graph, and projecting back the **/ +/** obtained frontier to the original **/ +/** graph. **/ +/** **/ +/** DATES : # Version 6.0 : from : 05 jan 2010 **/ +/** to : 03 mar 2011 **/ +/** **/ +/** NOTES : # Since only edges from local vertices **/ +/** to local anchors are created in **/ +/** kdgraphBand(), the communication cost **/ +/** might be wrong if a local vertex of **/ +/** the last layer is linked to a remote **/ +/** vertex of different part which was **/ +/** not in the band graph. Hence, commun- **/ +/** ication costs have to be recomputed **/ +/** from scratch. **/ +/** **/ +/** # This code derives from the code of **/ +/** bdgraph_bipart_bd.c in version 5.1 **/ +/** for direct k-way partitioning. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_BD + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "arch.h" +#include "graph.h" +#include "mapping.h" +#include "kgraph.h" +#include "kgraph_map_bd.h" +#include "kgraph_map_st.h" + +/* +** The static variables. +*/ + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes a band graph of given +** width around the current frontier and applies +** partitioning routines to it. +** The graph is not guaranteed to be balanced +** at all. +** It returns: +** - 0 : if the band graph could be computed. +** - !0 : on error. +*/ + +int +kgraphMapBd ( +Kgraph * const orggrafptr, /*+ Graph +*/ +const KgraphMapBdParam * const paraptr) /*+ Method parameters +*/ +{ + Kgraph bndgrafdat; /* Partitioning band graph structure */ + Gnum bndvertancnnd; /* End of local vertex array, without anchors */ + Gnum bndvertnum; + Gnum bndvertlvlnum; /* Based number of first band vertex in last layer */ + Gnum orgfronnum; + int * restrict orgflagtab; + Gnum commload; + Gnum commload2; /* Twice twice (4 times) the internal communication load of last layer */ + Anum domnnum; + Gnum * restrict bandvnumtax; /* Orignal numbers of vertices in band graph */ + Gnum * vertnbrtab; + Gnum vertnum; + + const Arch * restrict const archptr = orggrafptr->m.archptr; + const Anum domnnbr = orggrafptr->m.domnnbr; + Gnum * restrict const orgfrontab = orggrafptr->frontab; + Gnum * restrict const orgparttax = orggrafptr->m.parttax; + + if ((vertnbrtab = memAlloc (domnnbr * sizeof(Gnum))) == NULL) { + errorPrint ("kgraphMapBd: out of memory (1)"); + return (1); + } + memSet (vertnbrtab, 0, domnnbr * sizeof(Gnum)); + for (vertnum = orggrafptr->s.baseval; vertnum < orggrafptr->s.vertnnd; vertnum ++) + vertnbrtab[orgparttax[vertnum]] ++; /* TODO check optimize? */ + + if (orggrafptr->fronnbr == 0) /* If no separator vertices, apply strategy to full (original) graph */ + return (kgraphMapSt (orggrafptr, paraptr->stratorg)); + + if (kgraphBand (orggrafptr, paraptr->distmax, &bndgrafdat, &bndvertlvlnum, &bandvnumtax) != 0) { + errorPrint ("kgraphMapBd: cannot create band graph"); + return (1); + } + + bndvertancnnd = bndgrafdat.s.vertnnd - domnnbr; + for (domnnum = 0; domnnum < domnnbr; domnnum ++) { /* For all anchor domains */ + Gnum vertnum; + + vertnum = bndvertancnnd + domnnum; + if (((bndgrafdat.s.verttax[vertnum + 1] - bndgrafdat.s.verttax[vertnum]) == 0) && + (vertnbrtab[domnnum] != 0)) + break; + } + + memFree (vertnbrtab); + + if (domnnum != domnnbr) { /* If graph is too small to have any usable anchors, apply org strategy */ + memFree (bandvnumtax + bndgrafdat.s.baseval); + memFree (bndgrafdat.m.parttax + bndgrafdat.s.baseval); + kgraphExit (&bndgrafdat); + return (kgraphMapSt (orggrafptr, paraptr->stratorg)); + } + + if (kgraphMapSt (&bndgrafdat, paraptr->stratbnd) != 0) { /* Partition band graph */ + errorPrint ("kgraphMapBd: cannot partition band graph"); + kgraphExit (&bndgrafdat); + return (1); + } + if (bndgrafdat.m.domnnbr != orggrafptr->m.domnnbr) { + errorPrint ("kgraphMapBd: change in band graph number of parts not supported"); + kgraphExit (&bndgrafdat); + return (1); + } + + memCpy (orggrafptr->comploaddlt, bndgrafdat.comploaddlt, domnnbr * sizeof (Gnum)); /* Propagate back imbalance information */ + + for (bndvertnum = bndgrafdat.s.baseval; bndvertnum < bndvertancnnd; bndvertnum ++) /* Update part array of all vertices except anchors */ + orgparttax[bandvnumtax[bndvertnum]] = bndgrafdat.m.parttax[bndvertnum]; + + commload = 0; + for (bndvertnum = bndgrafdat.s.baseval; bndvertnum < bndvertlvlnum; bndvertnum ++) { /* For all vertices of band graph save for last layer */ + Gnum bndedgenum; + Gnum bndedgennd; + Anum bndpartval; + Anum bndpartlst; /* Part of last vertex for which a distance was computed */ + Anum bnddistlst; /* Last distance computed */ + int bndflagval; + + bndpartval = bndgrafdat.m.parttax[bndvertnum]; + bndpartlst = -1; /* Invalid part to recompute distance */ + bnddistlst = -1; /* To prevent compiler from yielding */ + + bndflagval = 0; + for (bndedgenum = bndgrafdat.s.verttax[bndvertnum], bndedgennd = bndgrafdat.s.vendtax[bndvertnum]; + bndedgenum < bndedgennd; bndedgenum ++) { + Gnum bndpartend; + + bndpartend = bndgrafdat.m.parttax[bndgrafdat.s.edgetax[bndedgenum]]; + + if (bndpartval != bndpartend) { /* TODO maybe can be optimized */ + Anum bnddistval; + + bndflagval |= 1; + bnddistval = (bndpartend != bndpartlst) ? archDomDist (archptr, &bndgrafdat.m.domntab[bndpartval], &bndgrafdat.m.domntab[bndpartend]) : bnddistlst; + bndpartlst = bndpartend; + bnddistlst = bnddistval; + + commload += (Gnum) bnddistval * ((bndgrafdat.s.edlotax != NULL) ? bndgrafdat.s.edlotax[bndedgenum] : 1); + } + } + } + for ( ; bndvertnum < bndvertancnnd; bndvertnum ++) { /* For all vertices of last layer, remove communication loads to band vertices once */ + Gnum bndedgenum; + Gnum bndedgennd; + Anum bndpartval; + Anum bndpartlst; /* Part of last vertex for which a distance was computed */ + Anum bnddistlst; /* Last distance computed */ + int bndflagval; + + bndpartval = bndgrafdat.m.parttax[bndvertnum]; + bndpartlst = -1; /* Invalid part to recompute distance */ + bnddistlst = -1; /* To prevent compiler from yielding */ + + bndflagval = 0; + + for (bndedgenum = bndgrafdat.s.verttax[bndvertnum], bndedgennd = bndgrafdat.s.vendtax[bndvertnum] - 1; /* "-1" to avoid anchor edges */ + bndedgenum < bndedgennd; bndedgenum ++) { + Gnum bndpartend; + + bndpartend = bndgrafdat.m.parttax[bndgrafdat.s.edgetax[bndedgenum]]; + + if (bndpartval != bndpartend) { + Anum bnddistval; + + bndflagval |= 1; + bnddistval = (bndpartend != bndpartlst) ? archDomDist (archptr, &bndgrafdat.m.domntab[bndpartval], &bndgrafdat.m.domntab[bndpartend]) : bnddistlst; + bndpartlst = bndpartend; + bnddistlst = bnddistval; + + commload -= (Gnum) bnddistval * ((bndgrafdat.s.edlotax != NULL) ? bndgrafdat.s.edlotax[bndedgenum] : 1); /* Remove communication loads to band graph vertices once because afterwards they will be accounted for twice */ + } + } + } + + if ((orgflagtab = memAlloc (kgraphMapBdFlagSize (orggrafptr->s.vertnnd) * sizeof (int))) == NULL) { + errorPrint ("kgraphMapBd: out of memory (2)"); + return (1); + } + + memSet (orgflagtab, 0, kgraphMapBdFlagSize (orggrafptr->s.vertnnd) * sizeof (int)); /* Set vertices as not already considered */ + + orgfronnum = 0; + + commload2 = 0; + for (bndvertnum = bndgrafdat.s.baseval; bndvertnum < bndvertancnnd; bndvertnum ++) { /* For all vertices */ + Gnum orgedgenum; + Gnum orgedgennd; + Gnum orgvertnum; + Anum orgpartval; + int orgflagval; + + orgvertnum = bandvnumtax[bndvertnum]; + orgpartval = bndgrafdat.m.parttax[bndvertnum]; + + orgflagval = 0; /* Assume vertex does not belong to the frontier */ + for (orgedgenum = orggrafptr->s.verttax[orgvertnum], orgedgennd = orggrafptr->s.vendtax[orgvertnum]; + orgedgenum < orgedgennd; orgedgenum ++) { + Gnum orgvertend; + Gnum orgpartend; + Anum orgdistval; + + orgvertend = orggrafptr->s.edgetax[orgedgenum]; + orgpartend = orgparttax[orgvertend]; + orgdistval = archDomDist (orggrafptr->m.archptr, &orggrafptr->m.domntab[orgpartval], &orggrafptr->m.domntab[orgpartend]); + + if (orgpartval != orgpartend) { + orgflagval = 1; + commload2 += ((orggrafptr->s.edlotax != NULL) ? orggrafptr->s.edlotax[orgedgenum] : 1) * orgdistval; /* Internal load to band and original graph vertices are accounted for twice */ + if ((orgvertend < orggrafptr->s.vertnnd) && (kgraphMapBdFlagVal (orgflagtab, orgvertend) == 0)) { + orgfrontab[orgfronnum ++] = orgvertend; + kgraphMapBdFlagSet (orgflagtab, orgvertend); + } + } + } + if ((orgflagval != 0) && (kgraphMapBdFlagVal (orgflagtab, orgvertnum) == 0)) + orgfrontab[orgfronnum ++] = orgvertnum; + + kgraphMapBdFlagSet (orgflagtab, orgvertnum); /* Set vertex as processed anyway */ + } + commload += 2 * commload2; /* Add twice the communication load of original graph edges and once the one of band edges (one removed before) */ + + if (orggrafptr->pfixtax != NULL) { /* Add fixed vertices with fixed neighbours only in the frontier array */ + Gnum vertnum; + + for (vertnum = orggrafptr->s.baseval; vertnum < orggrafptr->s.vertnnd; vertnum ++) { + Gnum partval; + Gnum edgenum; + + if ((orggrafptr->pfixtax[vertnum] == -1) || /* If it is not a fixed vertex */ + (kgraphMapBdFlagVal (orgflagtab, vertnum) != 0)) /* Or has already been processed */ + continue; /* Skip it */ + + partval = orggrafptr->m.parttax[vertnum]; + + for (edgenum = orggrafptr->s.verttax[vertnum]; edgenum < orggrafptr->s.vendtax[vertnum]; edgenum ++) { + if (orggrafptr->m.parttax[orggrafptr->s.edgetax[edgenum]] != partval) { /* If first vertex belongs to frontier */ + orggrafptr->frontab[orgfronnum] = vertnum; + orgfronnum ++; + break; + } + } + } + } + orggrafptr->fronnbr = orgfronnum; + orggrafptr->commload = commload / 2; + + memFree (orgflagtab); + memFree (bandvnumtax + bndgrafdat.s.baseval); + memFree (bndgrafdat.m.parttax + bndgrafdat.s.baseval); + + kgraphCost (orggrafptr); +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (orggrafptr) != 0) { + errorPrint ("kgraphMapBd: internal error"); + kgraphExit (&bndgrafdat); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + kgraphExit (&bndgrafdat); + + return (0); +} + diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_bd.h b/scotch_6.0.3/src/libscotch/kgraph_map_bd.h new file mode 100644 index 00000000..fcaf22be --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_bd.h @@ -0,0 +1,80 @@ +/* Copyright 2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_bd.h **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the band graph partitioning **/ +/** routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 6.0 : from : 05 jan 2010 **/ +/** to : 20 feb 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Flag array accessors. +*/ + +#define kgraphMapBdFlagSize(n) (((n) + (sizeof (int) << 3) - 1) / (sizeof (int) << 3)) +#define kgraphMapBdFlagVal(a,n) (((a)[(n) / (sizeof (int) << 3)] >> ((n) & ((sizeof (int) << 3) - 1))) & 1) +#define kgraphMapBdFlagSet(a,n) (a)[(n) / (sizeof (int) << 3)] |= (1 << ((n) & ((sizeof (int) << 3) - 1))) + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct KgraphMapBdParam_ { + INT distmax; /*+ Width of band surrounding the frontier +*/ + Strat * stratbnd; /*+ Strategy for band graph +*/ + Strat * stratorg; /*+ Strategy for original graph +*/ +} KgraphMapBdParam; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_BD +#define static +#endif + +int kgraphMapBd (Kgraph * const, const KgraphMapBdParam * const); + +#undef static + diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_cp.c b/scotch_6.0.3/src/libscotch/kgraph_map_cp.c new file mode 100644 index 00000000..a2153913 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_cp.c @@ -0,0 +1,116 @@ +/* Copyright 2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_cp.c **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This method copies a given old mapping **/ +/** as a mapping result. **/ +/** **/ +/** DATES : # Version 6.0 : from : 16 jan 2012 **/ +/** to 23 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_CP + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "parser.h" +#include "kgraph.h" +#include "kgraph_map_cp.h" +#include "kgraph_map_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the k-way partitioning. +** It returns: +** - 0 : if k-partition could be computed. +** - 1 : on error. +*/ + +/* TODO handle the case when the old and the new architectures are differents. */ + +int +kgraphMapCp ( +Kgraph * restrict const grafptr) /*+ Graph +*/ +{ + Gnum baseval; + Anum domnnbr; + + const Anum * restrict const pfixtax = grafptr->pfixtax; + + if (grafptr->r.m.parttax == NULL) { /* If we do not have an old partition */ + errorPrint ("kgraphMapCp: inconsistent old mapping data"); + return (1); + } + baseval = grafptr->s.baseval; + + if (mapCopy (&grafptr->m, &grafptr->r.m) != 0) { + errorPrint ("kgraphMapCp: cannot copy old mapping"); + return (1); + } + + if (pfixtax != NULL) { /* If we have fixed vertices */ + if (mapMerge (&grafptr->m, pfixtax) != 0) { + errorPrint ("kgraphMapCp: cannot merge with fixed vertices"); + return (1); + } + } + + kgraphFron (grafptr); + kgraphCost (grafptr); + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (grafptr) != 0) { + errorPrint ("kgraphMapCp: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + return (0); +} + + diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_cp.h b/scotch_6.0.3/src/libscotch/kgraph_map_cp.h new file mode 100644 index 00000000..9d83e441 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_cp.h @@ -0,0 +1,58 @@ +/* Copyright 2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_cp.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the mapping method that copy the **/ +/** old mapping has a mapping result. **/ +/** **/ +/** DATES : # Version 6.0 : from : 16 jan 2012 **/ +/** to 23 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_CP +#define static +#endif + +int kgraphMapCp (Kgraph * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_df.c b/scotch_6.0.3/src/libscotch/kgraph_map_df.c new file mode 100644 index 00000000..befcdaa5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_df.c @@ -0,0 +1,232 @@ +/* Copyright 2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_df.c **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a k-way partition **/ +/** of the given mapping graph by applying **/ +/** a diffusion method to what is assumed **/ +/** to be a band graph. **/ +/** **/ +/** DATES : # Version 6.0 : from : 05 jan 2010 **/ +/** to : 04 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_DF + +#ifdef SCOTCH_PTHREAD +#define KGRAPHMAPDFTHREAD +#endif /* SCOTCH_PTHREAD */ + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "graph.h" +#include "mapping.h" +#include "kgraph.h" +#include "kgraph_map_df.h" + +/************************/ +/* */ +/* The sorting routine. */ +/* */ +/************************/ + +/* This routine sorts an array of KgraphMapDfVertex +** values in descending order by their amount of liquid. +** By nature of the sorting algorithm, data are left in +** place in case of equality. Therefore, the original +** part of the vertex, which is put first in the sort +** array during the diffusion process, is always preserved +** when all liquid amounts are equal. +** It returns: +** - VOID : in all cases. +*/ + +#define INTSORTQUAL static +#define INTSORTNAME kgraphMapDfSort +#define INTSORTSIZE (sizeof (KgraphMapDfSort)) +#define INTSORTSWAP(p,q) do { \ + KgraphMapDfSort t; \ + t = *((KgraphMapDfSort *) (p)); \ + *((KgraphMapDfSort *) (p)) = *((KgraphMapDfSort *) (q)); \ + *((KgraphMapDfSort *) (q)) = t; \ + } while (0) +#define INTSORTCMP(p,q) (((KgraphMapDfSort *) (p))->diffval > ((KgraphMapDfSort *) (q))->diffval) +#include "common_sort.c" +#undef INTSORTQUAL +#undef INTSORTNAME +#undef INTSORTSIZE +#undef INTSORTSWAP +#undef INTSORTCMP + +/********************************/ +/* */ +/* The sequential loop routine. */ +/* */ +/********************************/ + +#define KGRAPHMAPDFLOOPNAME kgraphMapDfSeq +#include "kgraph_map_df_loop.c" +#undef KGRAPHMAPDFLOOPNAME + +/******************************/ +/* */ +/* The threaded loop routine. */ +/* */ +/******************************/ + +#ifdef KGRAPHMAPDFTHREAD + +#define KGRAPHMAPDFLOOPTHREAD +#define KGRAPHMAPDFLOOPNAME kgraphMapDfThr +#include "kgraph_map_df_loop.c" +#undef KGRAPHMAPDFLOOPNAME +#undef KGRAPHMAPDFLOOPTHREAD + +#endif /* KGRAPHMAPDFTHREAD */ + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes a k-way partition +** by diffusion across what is assumed +** to be a k-way band graph. +** It returns: +** - 0 : if the k-partition could be computed. +** - !0 : on error. +*/ + +int +kgraphMapDf ( +Kgraph * restrict const grafptr, /*+ Active graph +*/ +const KgraphMapDfParam * const paraptr) /*+ Method parameters +*/ +{ + KgraphMapDfData loopdat; /* Diffusion loop data */ + Gnum vertnbr; + Gnum vancnbr; + Gnum domnnbr; +#ifdef KGRAPHMAPDFTHREAD /* Threads can be accepted even when SCOTCH_DETERMINISTIC set */ + int thrdnbr; +#endif /* KGRAPHMAPDFTHREAD */ + + domnnbr = grafptr->m.domnnbr; + vertnbr = grafptr->s.vertnbr; + vancnbr = vertnbr - domnnbr; + if (memAllocGroup ((void **) (void *) + &loopdat.vanctab, (size_t) (domnnbr * sizeof (float)), + &loopdat.valotab, (size_t) (domnnbr * sizeof (Gnum)), + &loopdat.velstax, (size_t) (vertnbr * sizeof (Gnum)), + &loopdat.difntax, (size_t) (vertnbr * sizeof (KgraphMapDfVertex)), + &loopdat.difotax, (size_t) (vertnbr * sizeof (KgraphMapDfVertex)), NULL) == NULL) { + errorPrint ("kgraphMapDf: out of memory (1)"); + return (1); + } + loopdat.grafptr = grafptr; + loopdat.velstax -= grafptr->s.baseval; + loopdat.difntax -= grafptr->s.baseval; + loopdat.difotax -= grafptr->s.baseval; + loopdat.passnbr = paraptr->passnbr; + +#ifdef KGRAPHMAPDFTHREAD /* Threads can be accepted even when SCOTCH_DETERMINISTIC set */ + thrdnbr = SCOTCH_PTHREAD_NUMBER; + + loopdat.abrtval = 0; /* No one wants to abort yet */ + + if (thrdnbr > 1) { + KgraphMapDfThread * restrict thrdtab; + int thrdnum; + Gnum vertbas; + Anum domnbas; + + if ((thrdtab = memAlloc (thrdnbr * sizeof (KgraphMapDfThread))) == NULL) { + errorPrint ("kgraphMapDf: out of memory (2)"); + memFree (loopdat.vanctab); + return (1); + } + + for (thrdnum = 0, vertbas = grafptr->s.baseval, domnbas = 0; + thrdnum < thrdnbr; thrdnum ++) { + thrdtab[thrdnum].vertbas = vertbas; + thrdtab[thrdnum].vertnnd = vertbas += DATASIZE (vancnbr, thrdnbr, thrdnum); + thrdtab[thrdnum].domnbas = domnbas; + thrdtab[thrdnum].domnnnd = domnbas += DATASIZE (domnnbr, thrdnbr, thrdnum); + } + + threadLaunch (&loopdat, thrdtab, sizeof (KgraphMapDfThread), + (ThreadLaunchStartFunc) kgraphMapDfThr, + (ThreadLaunchJoinFunc) NULL, thrdnbr, THREADCANBARRIER); + + memFree (thrdtab); /* Free group leader */ + } + else +#endif /* KGRAPHMAPDFTHREAD */ + { + KgraphMapDfThread thrddat; + + thrddat.thrddat.grouptr = &loopdat; + thrddat.vertbas = grafptr->s.baseval; + thrddat.vertnnd = vertnbr + grafptr->s.baseval - domnnbr; + thrddat.domnbas = 0; + thrddat.domnnnd = domnnbr; +#ifdef KGRAPHMAPDFTHREAD + thrddat.thrddat.thrdnum = 0; /* Thread is thread 0 of 1 */ +#endif /* KGRAPHMAPDFTHREAD */ + + kgraphMapDfSeq (&thrddat); + } + + memFree (loopdat.vanctab); /* Free group leader */ + + kgraphFron (grafptr); + kgraphCost (grafptr); + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (grafptr) != 0) { + errorPrint ("kgraphMapDf: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_df.h b/scotch_6.0.3/src/libscotch/kgraph_map_df.h new file mode 100644 index 00000000..f135e583 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_df.h @@ -0,0 +1,130 @@ +/* Copyright 2009-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_ml.h **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the function **/ +/** declarations for the diffusion scheme **/ +/** k-partitioning method. **/ +/** **/ +/** DATES : # Version 6.0 : from : 22 dec 2009 **/ +/** to 02 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/* Small non-zero float value. */ + +#define KGRAPHMAPDFEPSILON (1.0F / (float) (GNUMMAX)) + +/*+ Sign masking operator. +*/ + +#define KGRAPHMAPDFGNUMSGNMSK(i) ((Gnum) 0 - (((Gunum) (i)) >> (sizeof (Gnum) * 8 - 1))) + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct KgraphMapDfParam_ { + INT passnbr; /*+ Number of passes to do +*/ + double cdifval; /*+ Coefficient of diffused load +*/ + double cremval; /*+ Coefficient of remaining load +*/ +} KgraphMapDfParam; + +/*+ The complementary vertex structure. +*/ + +typedef struct KgraphMapDfVertex_ { + Anum partval; /*+ Type of liquid in barrel +*/ + float diffval; /*+ Value to be diffused to everybody +*/ + float fdifval; /*+ Value to be diffused to other parts for mapping +*/ + float mdisval; /*+ Value to be diffused to vertnum if parotax[vertnum] == partval +*/ + float mdidval; /*= Value to be diffused to vertnum else +*/ +} KgraphMapDfVertex; + +/*+ The sort structure. +*/ + +typedef struct KgraphMapDfSort_ { + Anum partval; /*+ Type of liquid in barrel +*/ + float diffval; /*+ Value to be diffused +*/ + Anum distval; /*+ Distance value +*/ + Gnum edlosum; /*+ Sum of edge loads +*/ +} KgraphMapDfSort; + +/*+ The loop routine parameter + structure. It contains the + thread-independent data. +*/ + +typedef struct KgraphMapDfData_ { + ThreadGroupHeader thrddat; + const Kgraph * grafptr; /*+ Graph to work on +*/ + float * vanctab; + float * valotab; /*+ Fraction of load to leak +*/ + Gnum * velstax; /*+ Vertex edge load sum array +*/ + KgraphMapDfVertex * difntax; /*+ New diffusion value array +*/ + KgraphMapDfVertex * difotax; /*+ Old diffusion value array +*/ + int passnbr; /*+ Number of passes +*/ +#ifdef KGRAPHMAPDFTHREAD + int abrtval; /*+ Abort value +*/ +#endif /* KGRAPHMAPDFTHREAD */ +} KgraphMapDfData; + +/*+ The thread-specific data block. +*/ + +typedef struct KgraphMapDfThread_ { + ThreadHeader thrddat; /*+ Thread management data +*/ + Gnum vertbas; /*+ Minimum regular vertex index +*/ + Gnum vertnnd; /*+ After-last regular vertex index +*/ + Anum domnbas; /*+ Minimum anchor vertex index +*/ + Anum domnnnd; /*+ After-last anchor vertex index +*/ +} KgraphMapDfThread; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_DF +#define static +#endif + +int kgraphMapDf (Kgraph * restrict const, const KgraphMapDfParam * const); + +static void kgraphMapDfSort (void * const, const INT); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_df_loop.c b/scotch_6.0.3/src/libscotch/kgraph_map_df_loop.c new file mode 100644 index 00000000..06cd4885 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_df_loop.c @@ -0,0 +1,515 @@ +/* Copyright 2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_df_loop.c **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a k-way partition **/ +/** of the given mapping graph by applying **/ +/** a diffusion method to what is assumed **/ +/** to be a band graph. **/ +/** **/ +/** DATES : # Version 6.0 : from : 05 jan 2010 **/ +/** to : 23 aug 2014 **/ +/** **/ +/************************************************************/ + +/* Tests flags for mapping TODO remove it after performance tests */ +/* #define KGRAPHDIFFMAPPNONE */ /* No special code for mapping */ +/* #define KGRAPHDIFFMAPPMORE */ /* Give more liquid on expensive architecture edges */ +#define KGRAPHDIFFMAPPLESS /* Give less liquid on expensive architecture edges */ + +/* +** The defines and includes. +*/ + +/****************************/ +/* */ +/* The diffusion subroutine */ +/* pattern. */ +/* */ +/****************************/ + +/* This routine computes the diffusion of liquids +** on the given part of the k-way band graph. +** It returns: +** - void : in all cases +*/ + +static +int +KGRAPHMAPDFLOOPNAME ( +KgraphMapDfThread * restrict thrdptr) /* Thread-dependent data */ +{ + KgraphMapDfVertex * restrict difotax; /* Old diffusion value array */ + KgraphMapDfVertex * restrict difntax; /* New diffusion value array */ + KgraphMapDfSort * restrict sorttab; /* Liquid sort array */ + Gnum vancnnd; + Gnum vertnum; + Anum domnnum; + Gnum passnum; + int velsmsk; + int mappflag; /* We are computing a mapping */ + + KgraphMapDfData * restrict const loopptr = (KgraphMapDfData *) thrdptr->thrddat.grouptr; + const Kgraph * restrict const grafptr = loopptr->grafptr; + float * restrict const vanctab = loopptr->vanctab; + float * restrict const valotab = loopptr->valotab; /* Fraction of load to leak */ + Gnum * restrict const velstax = loopptr->velstax; + const Gnum vertbas = thrdptr->vertbas; /* Range of non-anchor vertices to process */ + const Gnum vertnnd = thrdptr->vertnnd; + const Anum domnbas = thrdptr->domnbas; /* Range of anchor vertices to process */ + const Anum domnnnd = thrdptr->domnnnd; + const Anum domnnbr = grafptr->m.domnnbr; + const Gnum crloval = grafptr->r.crloval; + const Gnum cmloval = grafptr->r.cmloval; + Anum * restrict const parttax = grafptr->m.parttax; + const Anum * restrict const parotax = grafptr->r.m.parttax; + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * const edgetax = grafptr->s.edgetax; + const Gnum * const edlotax = grafptr->s.edlotax; + + vancnnd = grafptr->s.vertnnd - domnnbr; + velsmsk = 1; /* Assume no anchors are isolated */ + if (edlotax != NULL) { + for (domnnum = domnbas; domnnum < domnnnd; domnnum ++) { /* For all local anchor vertices */ + Gnum edgenum; + Gnum edgennd; + Gnum velssum; + + for (edgenum = verttax[vancnnd + domnnum], edgennd = vendtax[vancnnd + domnnum], velssum = 0; + edgenum < edgennd; edgenum ++) + velssum += edlotax[edgenum]; + velstax[vancnnd + domnnum] = velssum; + velsmsk &= (velssum != 0); + } + } + else { + for (domnnum = domnbas; domnnum < domnnnd; domnnum ++) { + Gnum velssum; + + velssum = vendtax[vancnnd + domnnum] - verttax[vancnnd + domnnum]; /* Local degree of anchor vertices */ + velstax[vancnnd + domnnum] = velssum; + velsmsk &= (velssum != 0); + } + } + if (velsmsk == 0) { /* If graph is too small to have any usable anchors */ +#ifdef KGRAPHMAPDFLOOPTHREAD + loopptr->abrtval == 1; /* We will leave during the first iteration */ +#else /* KGRAPHMAPDFLOOPTHREAD */ + return (1); +#endif /* KGRAPHMAPDFLOOPTHREAD */ + } + + if ((sorttab = memAlloc (domnnbr * sizeof (KgraphMapDfSort))) == NULL) { /* Allocate here for memory affinity as it is a private array */ + errorPrint (STRINGIFY (KGRAPHMAPDFLOOPNAME) ": out of memory"); +#ifdef KGRAPHMAPDFLOOPTHREAD + loopptr->abrtval = 1; +#else /* KGRAPHMAPDFLOOPTHREAD */ + return (1); +#endif /* KGRAPHMAPDFLOOPTHREAD */ + } + + if (velotax == NULL) { + for (domnnum = domnbas; domnnum < domnnnd; domnnum ++) + valotab[domnnum] = 1.0F; + } + else { + for (domnnum = domnbas; domnnum < domnnnd; domnnum ++) + valotab[domnnum] = (float) velotax[vancnnd + domnnum]; + } + + difntax = loopptr->difntax; + difotax = loopptr->difotax; + + if (edlotax != NULL) { + for (vertnum = vertbas; vertnum < vertnnd; vertnum ++) { + Gnum velssum; + Gnum edgenum; + Gnum edgennd; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((vendtax[vertnum] - verttax[vertnum]) == 0) { + errorPrint (STRINGIFY (KGRAPHMAPDFLOOPNAME) ": internal error (1)"); +#ifdef KGRAPHMAPDFLOOPTHREAD + loopptr->abrtval = 1; +#else /* KGRAPHMAPDFLOOPTHREAD */ + return (1); +#endif /* KGRAPHMAPDFLOOPTHREAD */ + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + difotax[vertnum].partval = parttax[vertnum]; /* Set initial part by default */ + difotax[vertnum].diffval = + difotax[vertnum].fdifval = + difotax[vertnum].mdisval = + difotax[vertnum].mdidval = + difntax[vertnum].fdifval = + difntax[vertnum].mdisval = + difntax[vertnum].mdidval = 0.0F; + + for (edgenum = verttax[vertnum], edgennd = vendtax[vertnum], velssum = 0; + edgenum < edgennd; edgenum ++) + velssum += edlotax[edgenum]; + velstax[vertnum] = velssum; + } + } + else { /* Graph has no edge loads */ + for (vertnum = vertbas; vertnum < vertnnd; vertnum ++) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((vendtax[vertnum] - verttax[vertnum]) == 0) { + errorPrint (STRINGIFY (KGRAPHMAPDFLOOPNAME) ": internal error (2)"); +#ifdef KGRAPHMAPDFLOOPTHREAD + loopptr->abrtval = 1; +#else /* KGRAPHMAPDFLOOPTHREAD */ + return (1); +#endif /* KGRAPHMAPDFLOOPTHREAD */ + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + difotax[vertnum].partval = parttax[vertnum]; /* Set initial part by default */ + difotax[vertnum].diffval = + difotax[vertnum].fdifval = + difotax[vertnum].mdisval = + difotax[vertnum].mdidval = + difntax[vertnum].fdifval = + difntax[vertnum].mdisval = + difntax[vertnum].mdidval = 0.0F; + velstax[vertnum] = vendtax[vertnum] - verttax[vertnum]; + } + } + for (domnnum = domnbas, vertnum = vancnnd + domnbas; /* For all the subset of anchor vertices */ + domnnum < domnnnd; domnnum ++, vertnum ++) { + float vancval; + Gnum comploadbal; /* Compload to reach to get wished balance */ + + if (velstax[vancnnd + domnnum] <= 0) { + vancval = + vanctab[domnnum] = 0.0F; + velstax[vertnum] = -1; + } + else { + comploadbal = grafptr->comploadavg[domnnum]; + vancval = ((float) comploadbal - valotab[domnnum]) / (float) velstax[vancnnd + domnnum]; /* Amount of liquid to be added at each step */ + vanctab[domnnum] = comploadbal; + } + difotax[vertnum].diffval = vancval; /* Load anchor vertices for first pass */ + difotax[vertnum].partval = + difntax[vertnum].partval = domnnum; + difntax[vertnum].diffval = /* In case of isolated anchors, do not risk overflow because of NaN */ + difotax[vertnum].fdifval = + difotax[vertnum].mdisval = + difotax[vertnum].mdidval = + difntax[vertnum].fdifval = + difntax[vertnum].mdisval = + difntax[vertnum].mdidval = 0.0F; /* Do not consider migration costs for anchors */ + } + +#ifdef KGRAPHMAPDFLOOPTHREAD + threadBarrier (thrdptr); + + if (loopptr->abrtval == 1) { /* If process alone or some decided to quit */ + memFree (sorttab); /* Free local array */ + return (1); + } +#endif /* KGRAPHMAPDFLOOPTHREAD */ + +#ifndef KGRAPHDIFFMAPPNONE + if (archPart (grafptr->m.archptr)) + mappflag = 0; + else + mappflag = 1; +#else + mappflag = 0; +#endif /* KGRAPHDIFFMAPPNONE */ + + passnum = loopptr->passnbr; + for ( ; passnum > 0; passnum --) { /* For all passes */ + KgraphMapDfVertex * difttax; /* Temporary swap value */ + Gnum vertnum; + float veloval; + + veloval = 1.0F; /* Assume no vertex loads */ + + for (vertnum = vertbas; vertnum < vertnnd; vertnum ++) { /* For all local regular vertices */ + Gnum edgenum; + Gnum edgennd; + Gnum soplval; /* Load sum of edges going to vertex old part */ + Gnum sfplval; /* Load sum of edges going to vertex of other parts */ + Gnum dfplval; /* Load sum of edges going to vertex of other parts * distval */ + Gnum migrval; + Anum partnbr; /* Number of active parts */ + Anum partnum; + float diffval; + float signval; + Anum paronum; + Anum partcur; + + partnbr = 1; /* Keep vertex in first place to preserve its part */ + partcur = + sorttab[0].partval = difotax[vertnum].partval; /* Always keep old part value */ + sorttab[0].diffval = 0.0F; /* Assume at first it is null */ + sorttab[0].edlosum = 0; /* Assume at first there are no loads */ + sorttab[0].distval = 1; /* Do not take distval of our part into account */ + + for (edgenum = verttax[vertnum], edgennd = vendtax[vertnum]; + edgenum < edgennd; edgenum ++) { + Gnum vertend; + float diffval; + float fdifval; + float mdisval; + float mdidval; + Anum partval; + Anum partnum; + Gnum edloval; + Anum distval; + + vertend = edgetax[edgenum]; + edloval = (float) ((edlotax != NULL) ? edlotax[edgenum] : 1); + + partval = difotax[vertend].partval; + diffval = difotax[vertend].diffval; /* Value is not yet scaled with respect to diffusion coefficient */ + fdifval = difotax[vertend].fdifval; + mdisval = difotax[vertend].mdisval; + mdidval = difotax[vertend].mdidval; + + if ((mappflag == 1) && (partval != partcur)) + diffval = fdifval; + + diffval *= edloval * crloval; + if (parotax != NULL) { + if (difotax[vertnum].partval == parotax[vertend]) + diffval += mdisval; + else + diffval += mdidval; + } + + for (partnum = 0; partnum < partnbr; partnum ++) { + if (sorttab[partnum].partval == partval) { + sorttab[partnum].diffval += diffval; /* Accumulate contribution in slot */ + sorttab[partnum].edlosum += edloval; + goto endloop1; /* Do not consider creating a new slot */ + } + } + sorttab[partnbr].partval = partval; /* Create new slot */ + sorttab[partnbr].distval = ((mappflag == 1) && (partcur != partval)) ? archDomDist (&grafptr->a, &grafptr->m.domntab[partcur], &grafptr->m.domntab[partval]) : 1; + sorttab[partnbr].diffval = diffval; + sorttab[partnbr].edlosum = edloval; + partnbr ++; +endloop1 : ; + } + + if (mappflag == 1) + for (partnum = 0; partnum < partnbr; partnum ++) +#ifdef KGRAPHDIFFMAPPMORE + sorttab[partnum].diffval *= sorttab[partnum].distval; +#else /* KGRAPHDIFFMAPPLESS */ + sorttab[partnum].diffval /= sorttab[partnum].distval; +#endif /* KGRAPHDIFFMAPPMORE */ + + if (partnbr > 1) /* If not interior vertex */ + kgraphMapDfSort (sorttab, partnbr); /* Sort array by descending amounts */ + + soplval = 0; + if (parotax != NULL) { + for (partnum = 0; partnum < partnbr; partnum ++) { + if (sorttab[partnum].partval == parotax[vertnum]) { + soplval = sorttab[partnum].edlosum; + break; + } + } + } + + sfplval = 0; + dfplval = 0; + if (mappflag == 1) { /* We are doing a mapping */ + for (partnum = 1; partnum < partnbr; partnum ++) { + sfplval += sorttab[partnum].edlosum; +#ifdef KGRAPHDIFFMAPPMORE + dfplval += sorttab[partnum].edlosum * sorttab[partnum].distval; +#else /* KGRAPHDIFFMAPPLESS */ + dfplval += sorttab[partnum].edlosum / sorttab[partnum].distval; +#endif /* KGRAPHDIFFMAPPMORE */ + } + } + + difntax[vertnum].partval = sorttab[0].partval; /* New part is part of most abundant liquid */ + + diffval = sorttab[0].diffval; /* Get amount of most abundant liquid */ + + if (velotax != NULL) /* Account for capacity of barrel */ + veloval = (float) velotax[vertnum]; + diffval -= veloval; /* Leak liquid from barrel */ + if (diffval <= 0.0F) /* Amount of liquid cannot be negative */ + diffval = 0.0F; + migrval = ((soplval == 0) || (soplval == velstax[vertnum])) ? 0 : grafptr->r.cmloval * ((grafptr->r.vmlotax != NULL) ? grafptr->r.vmlotax[vertnum] : 1); + if (migrval > diffval) { + migrval = diffval; + diffval = 0; + } + else + diffval -= migrval; + diffval = diffval / (velstax[vertnum] * crloval); + if (isnan (diffval)) { /* If overflow occured */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + errorPrintW (STRINGIFY (KGRAPHMAPDFLOOPNAME) ": overflow (1)"); +#endif /* SCOTCH_DEBUG_KGRAPH2 */ +#ifdef KGRAPHMAPDFLOOPTHREAD + loopptr->abrtval = 1; /* Threads need to halt */ + goto abort1; /* Skip computations but synchronize */ +#else /* KGRAPHMAPDFLOOPTHREAD */ + goto abort2; /* Exit this loop without swapping arrays */ +#endif /* KGRAPHMAPDFLOOPTHREAD */ + } + + if (parotax != NULL) { + if (migrval == 0) { + difntax[vertnum].mdisval = + difntax[vertnum].mdidval = 0; + } + else { + if (parotax[vertnum] == sorttab[0].partval) { + difntax[vertnum].mdisval = migrval / soplval; + difntax[vertnum].mdidval = 0; + } + else { + difntax[vertnum].mdisval = 0; + difntax[vertnum].mdidval = migrval / (velstax[vertnum] - soplval); + } + } + } + + difntax[vertnum].diffval = diffval; + if (dfplval != 0) + difntax[vertnum].fdifval = diffval * sfplval / dfplval; + else + difntax[vertnum].fdifval = 0; + } + + for (domnnum = domnbas, vertnum = vancnnd + domnbas; /* For all the subset of anchor vertices */ + domnnum < domnnnd; domnnum ++, vertnum ++) { + Gnum edgenum; + Gnum edgennd; + Anum partnbr; /* Number of active parts */ + Anum partnum; + float diffval; + float signval; + + partnbr = 1; /* Keep vertex in first place to preserve its part */ + sorttab[0].partval = domnnum; /* Always keep initial part value */ + sorttab[0].diffval = 0.0F; /* Assume at first it is null */ + + edgenum = verttax[vertnum]; + edgennd = vendtax[vertnum]; + if (edgenum == edgennd) /* If isolated anchor */ + continue; /* Barrel is empty */ + + for ( ; edgenum < edgennd; edgenum ++) { /* For all edges except anchors */ + Gnum vertend; + float diffval; + Anum partval; + Anum partnum; + + vertend = edgetax[edgenum]; + + partval = difotax[vertend].partval; + diffval = difotax[vertend].diffval; /* Value is not yet scaled with respect to diffusion coefficient */ + + diffval *= (float) ((edlotax != NULL) ? edlotax[edgenum] : 1); + diffval *= crloval; + + for (partnum = 0; partnum < partnbr; partnum ++) { + if (sorttab[partnum].partval == partval) { + sorttab[partnum].diffval += diffval; /* Accumulate contribution in slot */ + goto endloop2; /* Do not consider creating a new slot */ + } + } + sorttab[partnbr].partval = partval; /* Create new slot */ + sorttab[partnbr].diffval = diffval; + partnbr ++; +endloop2 : ; + } + + if (partnbr > 1) /* If not interior vertex */ + kgraphMapDfSort (sorttab, partnbr); /* Sort array by descending amounts */ + + diffval = sorttab[0].diffval; /* Get amount of most abundant liquid */ + + if (sorttab[0].partval != domnnum) /* Add liquid from tap to barrel */ + diffval = vanctab[domnnum] - diffval; + else + diffval += vanctab[domnnum]; + + diffval = (diffval - valotab[domnnum]) / (velstax[vertnum] * crloval); /* Add input and leak liquid from barrel */ + + if (diffval <= 0.0F) /* Amount of liquid cannot be negative */ + diffval = 0.0F; + if (isnan (diffval)) { /* If overflow occured */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + errorPrintW (STRINGIFY (KGRAPHMAPDFLOOPNAME) ": overflow (2)"); +#endif /* SCOTCH_DEBUG_KGRAPH2 */ +#ifdef KGRAPHMAPDFLOOPTHREAD + loopptr->abrtval = 1; /* Threads need to halt */ + goto abort1; /* Skip computations but synchronize */ +#else /* KGRAPHMAPDFLOOPTHREAD */ + goto abort2; /* Exit this loop without swapping arrays */ +#endif /* KGRAPHMAPDFLOOPTHREAD */ + } + + difntax[vertnum].partval = domnnum; /* Anchor part is always domain part */ + difntax[vertnum].diffval = diffval; + } + + difttax = (KgraphMapDfVertex *) difntax; /* Swap old and new diffusion arrays */ + difntax = (KgraphMapDfVertex *) difotax; /* Casts to prevent IBM compiler from yelling */ + difotax = (KgraphMapDfVertex *) difttax; +abort1 : ; /* If overflow occured, resume here */ +#ifdef KGRAPHMAPDFLOOPTHREAD + threadBarrier (thrdptr); + + if (loopptr->abrtval == 1) /* If all threads need to abort */ + break; +#endif /* KGRAPHMAPDFLOOPTHREAD */ + } +abort2 : ; + + for (vertnum = vertbas; vertnum < vertnnd; vertnum ++) /* Set new part distribution of local vertices */ + parttax[vertnum] = difntax[vertnum].partval; + + memFree (sorttab); /* Free local array */ + + return (0); +} + diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_ex.c b/scotch_6.0.3/src/libscotch/kgraph_map_ex.c new file mode 100644 index 00000000..fc12fe33 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_ex.c @@ -0,0 +1,413 @@ +/* Copyright 2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_ex.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module tries to balance the **/ +/** subgraphs of the partition as best as **/ +/** it can. **/ +/** **/ +/** DATES : # Version 6.0 : from : 27 may 2011 **/ +/** to 21 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_EX + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "kgraph.h" +#include "kgraph_map_ex.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the balanced mapping. +** It returns: +** - 0 : if mapping could be computed. +** - 1 : on error. +*/ + +int +kgraphMapEx ( +Kgraph * const grafptr, /*+ Graph to map +*/ +const KgraphMapExParam * const paraptr) /*+ Method parameters +*/ +{ + KgraphMapExDom * restrict doextab; + KgraphMapExSort * restrict sorttab; + KgraphMapExTerm * restrict termtab; + KgraphMapExTree * restrict treetab; + Anum * restrict parttax; + Anum treenbr; /* Number of nodes in tree structure */ + const Arch * restrict archptr; + ArchDom domndat; /* Root domain */ + Anum domnnbr; + Anum domnnum; + Gnum sortnbr; /* Number of non-fixed vertices */ + Gnum sortnum; + Anum termnbr; /* Number of terminal domains in mapping */ + Gnum vertnum; + Gnum vertnnd; + double velosum; /* Sum of vertex weights */ + double wghtsum; /* Sum of architecture weights */ + Anum wghttmp; /* Sum of architecture weights for archVar */ + int flagval; /* Flag unset if load imbalance to fix */ + + const Gnum * restrict const velotax = grafptr->s.velotax; + const Anum * restrict const pfixtax = grafptr->pfixtax; + + grafptr->kbalval = paraptr->kbalval; /* Store last k-way imbalance ratio */ + domnnbr = grafptr->m.domnnbr; + sortnbr = grafptr->s.vertnbr - grafptr->vfixnbr; /* Only sort non-fixed vertices */ + if (memAllocGroup ((void **) (void *) + &doextab, (size_t) (domnnbr * sizeof (KgraphMapExDom)), + &sorttab, (size_t) (sortnbr * sizeof (KgraphMapExSort)), + &termtab, (size_t) (domnnbr * sizeof (KgraphMapExTerm)), + &treetab, (size_t) (domnnbr * sizeof (KgraphMapExTree) * 2), NULL) == NULL) { + errorPrint ("kgraphMapEx: out of memory"); + return (1); + } + + archptr = grafptr->m.archptr; + archDomFrst (archptr, &domndat); + wghtsum = (double) archDomWght (archptr, &domndat); + velosum = (double) grafptr->s.velosum; + + for (domnnum = 0, termnbr = 0, wghttmp = 0, flagval = 1; domnnum < domnnbr; domnnum ++) { + const ArchDom * restrict domnptr; + + domnptr = &grafptr->m.domntab[domnnum]; + if (archDomSize (archptr, domnptr) <= 1) { /* If domain is a terminal (even variable-sized) */ + Anum termnum; + + wghttmp += /* Accumulate subdomain loads in case of variable-sized architectures */ + doextab[domnnum].domnwght = archDomWght (archptr, domnptr); + doextab[domnnum].compload = 0; + doextab[domnnum].comploadmax = ((double) doextab[domnnum].domnwght * velosum * (1.0 + paraptr->kbalval)) / wghtsum; + + termnum = archDomNum (archptr, domnptr); + termtab[termnbr].termnum = termnum; /* Record domain in terminal domain array */ + termtab[termnbr].domnnum = domnnum; + termnbr ++; /* One more terminal domain */ + + if ((grafptr->comploadavg[domnnum] + grafptr->comploaddlt[domnnum]) > doextab[domnnum].comploadmax) + flagval = 0; /* Set flag if at least one domain is imbalanced */ + } + } + if (archVar (archptr)) { /* If architecture is variable-sized */ + Anum termnum; + + wghtsum = (double) wghttmp / wghtsum; /* Recompute real load sum */ + + for (termnum = 0; termnum < termnbr; termnum ++) { + Anum domnnum; + + domnnum = termtab[termnum].domnnum; + doextab[domnnum].comploadmax = ((double) doextab[domnnum].domnwght * velosum * (1.0 + paraptr->kbalval)) / wghtsum; + + if ((grafptr->comploadavg[domnnum] + grafptr->comploaddlt[domnnum]) > doextab[domnnum].comploadmax) + flagval = 0; /* Set flag if at least one domain is imbalanced */ + } + } + + if (flagval != 0) { /* If nothing to do */ + memFree (doextab); /* Free group leader */ + return (0); + } + + intSort2asc1 (termtab, termnbr); /* Sort terminal domains to allow for dichotomy */ + + treenbr = 0; /* Prepare to fill tree array; next slot to fill */ + kgraphMapExTree (archptr, termtab, termnbr, doextab, treetab, &treenbr, &domndat); /* Recursively fill tree array */ + + parttax = grafptr->m.parttax; + for (vertnum = grafptr->s.baseval, vertnnd = grafptr->s.vertnnd, sortnbr = 0; /* Get vertex weights */ + vertnum < vertnnd; vertnum ++) { + Gnum veloval; + + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + if ((pfixtax == NULL) || (pfixtax[vertnum] < 0)) { /* If vertex is not fixed */ + sorttab[sortnbr].veloval = veloval; /* Record it for sorting */ + sorttab[sortnbr].vertnum = vertnum; + sortnbr ++; + } + else + doextab[parttax[vertnum]].comploadmax -= veloval; /* Reduce available room in domain for non-fixed vertices */ + } +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (sortnbr != (grafptr->s.vertnbr - grafptr->vfixnbr)) { + errorPrint ("kgraphMapEx: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + if (velotax != NULL) /* If vertices are weighted, sort them in ascending order */ + intSort2asc1 (sorttab, sortnbr); + + for (sortnum = sortnbr - 1; sortnum >= 0; sortnum --) { /* For all sorted vertex indices, by descending weights */ + Gnum vertnum; + Gnum veloval; + Anum domnnum; + + vertnum = sorttab[sortnum].vertnum; + veloval = sorttab[sortnum].veloval; + domnnum = parttax[vertnum]; + + if ((doextab[domnnum].compload + veloval) > doextab[domnnum].comploadmax) { /* If leaving vertex in place would cause imbalance */ + domnnum = kgraphMapExFind (archptr, treetab, doextab, domnnum, veloval); /* Try to find better location for vertex load */ + if (parttax[vertnum] != domnnum) { /* If vertex moved to another part */ + parttax[vertnum] = domnnum; /* Set vertex to new part */ + flagval = 0; /* Record change */ + } + } + doextab[domnnum].compload += veloval; + } + + memFree (doextab); /* Free group leader */ + + if (flagval == 0) { /* If something changed */ + kgraphFron (grafptr); /* Recompute frontier */ + kgraphCost (grafptr); + } + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (grafptr) != 0) { + errorPrint ("kgraphMapEx: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + return (0); +} + +/* This routine fills the tree structure +** with the relevant node information. +** It returns: +** - void : in all cases. +*/ + +static +Anum +kgraphMapExTree ( +const Arch * restrict const archptr, +const KgraphMapExTerm * restrict const termtab, +const Anum termnbr, +KgraphMapExDom * restrict const doextab, /*+ Extended domain array, for adding link to tree +*/ +KgraphMapExTree * restrict const treetab, +Anum * restrict const treeptr, +const ArchDom * restrict const domnptr) /*+ Pointer to subdomain to consider for this node +*/ +{ + Anum treenum; + int o; + + if (archDomSize (archptr, domnptr) > 1) { /* If not variable-sized architecture and can bipartition */ + ArchDom domntab[2]; /* Temporary area to store subdomains */ + Anum sonstab[2]; + int i, j; + + o = archDomBipart (archptr, domnptr, &domntab[0], &domntab[1]); +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (o != 0) { + errorPrint ("kgraphMapExTree: internal error"); + return (-1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + sonstab[0] = kgraphMapExTree (archptr, termtab, termnbr, doextab, treetab, treeptr, &domntab[0]); + sonstab[1] = kgraphMapExTree (archptr, termtab, termnbr, doextab, treetab, treeptr, &domntab[1]); + if (sonstab[0] + sonstab[1] < -1) /* If both sub-branches do not exist */ + return (-1); /* Return that this branch does not exist */ + + treenum = (*treeptr) ++; /* Reserve slot for node */ + + treetab[treenum].fathnum = /* Assume node has no father (yet) */ + treetab[treenum].sonstab[1] = -1; /* Assume second node does not exist */ + for (i = j = 0; i < 2; i ++) { /* For both prospective sons */ + Anum sonsnum; + + sonsnum = sonstab[i]; + if (sonsnum == -1) /* If this son does not exist, skip it */ + continue; + + treetab[treenum].sonstab[j] = sonsnum; /* Link son to current node */ + treetab[sonsnum].fathnum = treenum; + j ++; /* One more son created */ + } + treetab[treenum].domndat = *domnptr; + } + else { /* If domain is terminal */ + Anum termmin; + Anum termmax; + Anum termnum; + Anum domnnum; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (archVar (archptr)) { + errorPrint ("kgraphMapExTree: not implemented"); + return (-1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + termnum = archDomNum (archptr, domnptr); /* Get number of terminal domain */ + for (termmin = 0, termmax = termnbr; (termmax - termmin) > 1; ) { + Anum termmed; + + termmed = (termmax + termmin) / 2; + if (termtab[termmed].termnum <= termnum) + termmin = termmed; + else + termmax = termmed; + } + if (termtab[termmin].termnum != termnum) /* If terminal not found */ + return (-1); /* This branch is dead */ + + treenum = (*treeptr) ++; /* Reserve slot for terminal */ + domnnum = termtab[termmin].domnnum; /* Get domain location */ + treetab[treenum].sonstab[0] = -1; /* Slot is terminal */ + treetab[treenum].sonstab[1] = domnnum; /* Record domain number of tree node */ + treetab[treenum].domndat = *domnptr; /* Record domain data */ + doextab[domnnum].treenum = treenum; /* Record entry point in tree structure */ + } + + return (treenum); +} + +/* This routine tries to find a destination +** target vertex that creates the least imbalance. +** It returns: +** - 0 : if a suitable terminal vertex has been found. +** - 1 : if process has to be continued.. +*/ + +static +Anum +kgraphMapExFind ( +const Arch * restrict const archptr, /*+ Target architecture +*/ +const KgraphMapExTree * restrict const treetab, /*+ Subdomain tree structure +*/ +const KgraphMapExDom * restrict const doextab, /*+ Extended domain array +*/ +const Anum domnnum, /*+ Initial domain number +*/ +const Gnum veloval) /*+ Weight of vertex to map +*/ +{ + KgraphMapExFind bestdat; + Anum treenum; + int o; + + bestdat.comploaddlt = (doextab[domnnum].compload + veloval - doextab[domnnum].comploadmax) / doextab[domnnum].domnwght; /* Compute weighted imbalance */ + bestdat.domnnum = domnnum; + + treenum = doextab[domnnum].treenum; /* Start from leaf of subdomain tree */ + do { /* Traverse nodes up to the root */ + Anum nodenum; /* Number of the son we come from */ + Anum othrnum; /* Number of the other son */ + + nodenum = treenum; /* Record position of current node */ + treenum = treetab[treenum].fathnum; /* Get father node */ + if (treenum == -1) /* If already reached root of tree */ + break; + + othrnum = treetab[treenum].sonstab[(treetab[treenum].sonstab[0] == nodenum) ? 1 : 0]; /* Don't consider the branch we come from */ + + if (othrnum == -1) /* If parent node has only one son */ + continue; /* Skip to upper level */ + + o = kgraphMapExFind2 (archptr, treetab, doextab, &bestdat, treenum, othrnum, veloval); + } + while (o != 0); /* As long as proper candidate not found */ + + return (bestdat.domnnum); /* Return best candidate found */ +} + +/* This routine tries to find a destination +** target vertex that creates the least imbalance. +** It returns: +** - 0 : if a suitable terminal vertex has been found. +** - 1 : if process has to be continued. +*/ + +static +int +kgraphMapExFind2 ( +const Arch * restrict const archptr, +const KgraphMapExTree * restrict const treetab, +const KgraphMapExDom * restrict const doextab, +KgraphMapExFind * restrict const bestptr, /*+ Pointer to structure that keeps best terminal found */ +const Anum treenum, +const Anum nodenum, +const Gnum veloval) +{ + Anum son0num; + Anum son1num; + + son0num = treetab[nodenum].sonstab[0]; + son1num = treetab[nodenum].sonstab[1]; + if (son0num != -1) { /* If node is not a terminal */ + int i; + int o; + + if (son1num == -1) /* If node has only one son */ + return (kgraphMapExFind2 (archptr, treetab, doextab, bestptr, treenum, son0num, veloval)); /* Process it directly */ + + i = (archDomDist (archptr, &treetab[treenum].domndat, &treetab[son0num].domndat) <= /* Get closest subdomain */ + archDomDist (archptr, &treetab[treenum].domndat, &treetab[son1num].domndat)) ? 0 : 1; + + o = kgraphMapExFind2 (archptr, treetab, doextab, bestptr, treenum, treetab[nodenum].sonstab[i], veloval); /* Process closest branch */ + if (o != 0) /* If didn't find suitable terminal in closest branch */ + o = kgraphMapExFind2 (archptr, treetab, doextab, bestptr, treenum, treetab[nodenum].sonstab[i ^ 1], veloval); /* Process farthest one */ + return (o); + } + else { /* If current node is terminal */ + Anum domnnum; + Gnum comploaddlt; + + domnnum = son1num; /* Second son records domain number */ + comploaddlt = (doextab[domnnum].compload + veloval - doextab[domnnum].comploadmax) / doextab[domnnum].domnwght; /* Compute weighted imbalance */ + + if (comploaddlt < bestptr->comploaddlt) { /* If found vertex that potentially improves balance */ + bestptr->comploaddlt = comploaddlt; + bestptr->domnnum = domnnum; + } + + return ((comploaddlt <= 0) ? 0 : 1); /* Return immediatly or go on whether found proper terminal to host vertex or not */ + } +} diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_ex.h b/scotch_6.0.3/src/libscotch/kgraph_map_ex.h new file mode 100644 index 00000000..ad0c47a5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_ex.h @@ -0,0 +1,117 @@ +/* Copyright 2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_ex.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the load balancing graph mapping **/ +/** routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 08 jun 2011 **/ +/** to 08 jun 2011 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct KgraphMapExParam_ { + double kbalval; /*+ Imbalance ratio +*/ +} KgraphMapExParam; + +/*+ This structure holds extended domain + information. sonstab[0] == -1 if node + is terminal. Else, sonstab[1] == -1 + means only one branch is considered + at this level. +*/ + +typedef struct KgraphMapExDom_ { + Anum treenum; /*+ Tree node index for this domain +*/ + Anum domnwght; /*+ Domain weight +*/ + Gnum compload; /*+ Current load in domain +*/ + Gnum comploadmax; /*+ Maximum load allowed in domain +*/ +} KgraphMapExDom; + +/*+ This structure records the best + candidate domain found to date. +*/ + +typedef struct KgraphMapExFind_ { + Gnum comploaddlt; /*+ Best imbalance +*/ + Anum domnnum; /*+ Domain number +*/ +} KgraphMapExFind; + +/*+ This structure allows one to + sort vertices by vertex weight. +*/ + +typedef struct KgraphMapExSort_ { + Gnum veloval; /*+ Vertex load +*/ + Gnum vertnum; /*+ Vertex number +*/ +} KgraphMapExSort; + +/*+ This structure allows one to sort + existing terminal domains by terminal + number. +*/ + +typedef struct KgraphMapExTerm_ { + Anum termnum; /*+ Domain terminal number +*/ + Anum domnnum; /*+ Domain index in domntab +*/ +} KgraphMapExTerm; + +/*+ This structure holds a recursive bi-mapping tree node. +*/ + +typedef struct KgraphMapExTree_ { + Anum fathnum; /*+ Index of father node; -1 if root +*/ + Anum sonstab[2]; /*+ Index of sons; [0] == -1 for terminal +*/ + ArchDom domndat; /*+ Subdomain data +*/ +} KgraphMapExTree; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_EX +#define static +#endif + +int kgraphMapEx (Kgraph * restrict const, const KgraphMapExParam * const); + +static Anum kgraphMapExTree (const Arch * restrict const, const KgraphMapExTerm * restrict const, const Anum, KgraphMapExDom * restrict const, KgraphMapExTree * restrict const, Anum * restrict const, const ArchDom * restrict const); +static Anum kgraphMapExFind (const Arch * restrict const, const KgraphMapExTree * restrict const, const KgraphMapExDom * restrict const, const Anum, const Gnum); +static int kgraphMapExFind2 (const Arch * restrict const, const KgraphMapExTree * restrict const, const KgraphMapExDom * restrict const, KgraphMapExFind * restrict const, const Anum, const Anum, const Gnum); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_fm.c b/scotch_6.0.3/src/libscotch/kgraph_map_fm.c new file mode 100644 index 00000000..2f7f9be2 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_fm.c @@ -0,0 +1,1861 @@ +/* Copyright 2004,2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_fm.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module refines a k-way mapping of **/ +/** the given mapping graph by applying a **/ +/** Fiduccia-Mattheyses-like gradient **/ +/** method. **/ +/** **/ +/** DATES : # Version 6.0 : from : 03 mar 2011 **/ +/** to 23 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_FM + +#define SCOTCH_TABLE_GAIN + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "fibo.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "parser.h" +#include "kgraph.h" +#include "kgraph_map_fm.h" +#include "kgraph_map_st.h" + +/* +** The static variables. +*/ + +static const Gnum kgraphloadone = 1; +static const Gnum kgraphnotfixed = -1; + +/*********************************/ +/* */ +/* Gain table handling routines. */ +/* */ +/*********************************/ + +/* This routine returns the vertex of best gain +** whose swap will keep the balance correct. +** It returns: +** - !NULL : pointer to the vertex. +** - NULL : if no more vertices available. +*/ + +#ifdef SCOTCH_TABLE_GAIN + +static +KgraphMapFmEdge * +kgraphMapFmTablGet ( +KgraphMapFmTabl * restrict const tablptr, /*+ Gain table +*/ +KgraphMapFmVertex * restrict const vexxtab, /*+ Extended vertex hash table array +*/ +const Gnum * restrict const comploaddlt, /*+ Current imbalance array +*/ +const Gnum * restrict const comploadmax, /*+ Maximum imbalance array +*/ +Gnum * restrict comploaddiff, +Gnum * restrict flagval) +{ + GainTabl * gaintab; + KgraphMapFmEdge * edxxptr; + KgraphMapFmEdge * edxxbest; + Gnum gainbest; + const GainEntr * restrict tablbest; + Gnum deltbest; + + gaintab = *tablptr; + tablbest = gaintab->tend; /* Assume no candidate vertex found yet */ + gainbest = GAINMAX; + edxxbest = NULL; + deltbest = GNUMMAX; + + for (edxxptr = (KgraphMapFmEdge *) gainTablFrst (gaintab); /* Select candidate edges */ + (edxxptr != NULL) && (edxxptr->gainlink.tabl < tablbest); + edxxptr = (KgraphMapFmEdge *) gainTablNext (gaintab, &edxxptr->gainlink)) { + Gnum vexxidx; + Gnum veloval; + Anum domnnumold; + Anum domnnumnew; + Gnum deltvalold; + Gnum deltvalnew; + Gnum deltnew; + Gnum commgain; + + vexxidx = edxxptr->vexxidx; + veloval = vexxtab[vexxidx].veloval; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[vexxidx].lockptr != NULL) { /* If vertex is locked */ + errorPrint ("kgraphMapFmTablGet: internal error (1)"); + return (NULL); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + domnnumold = vexxtab[vexxidx].domnnum; + domnnumnew = edxxptr->domnnum; + deltvalold = abs (comploaddlt[domnnumold] - veloval); + deltvalnew = abs (comploaddlt[domnnumnew] + veloval); + if (((deltvalold > comploadmax[domnnumold]) && (deltvalold >= abs (comploaddlt[domnnumold]))) || /* If vertex does not enforce or improve balance, skip it */ + ((deltvalnew > comploadmax[domnnumnew]) && (deltvalnew >= abs (comploaddlt[domnnumnew])))) { + if (edxxptr->cmigmask == ~0) { + edxxptr->cmigmask = 0; + kgraphMapFmTablDel (&gaintab, edxxptr); + kgraphMapFmTablAdd (&gaintab, edxxptr); + } + continue; + } + + deltnew = deltvalold - abs (comploaddlt[domnnumold]) + /* Compute difference in imbalance load sum */ + deltvalnew - abs (comploaddlt[domnnumnew]); + commgain = edxxptr->commgain + edxxptr->cmiggain; + if ((commgain < gainbest) || /* And if it gives better gain */ + ((commgain == gainbest) && /* Or if it gives better load */ + (deltnew < deltbest))) { + tablbest = edxxptr->gainlink.tabl; /* Select it */ + gainbest = commgain; + edxxbest = edxxptr; + deltbest = deltnew; + if ((abs (comploaddlt[domnnumold]) > comploadmax[domnnumold]) || + (abs (comploaddlt[domnnumnew]) > comploadmax[domnnumnew])) + *flagval = 1; + else + *flagval = 0; + } + } + + if (edxxbest != NULL) + *comploaddiff += deltbest; + + return (edxxbest); +} + +#else /* SCOTCH_TABLE_GAIN */ + +/* kgraphMapFmCmpFunc(a,b) must return a negative +** number if a is "better" than b. The smaller, the +** better. +*/ + +static +int +kgraphMapFmCmpFunc ( +const FiboNode * const data0ptr, /* TRICK: KgraphMapFmLink is FIRST in KgraphMapFmEdge */ +const FiboNode * const data1ptr) +{ + const KgraphMapFmEdge * const node0ptr = (KgraphMapFmEdge *) data0ptr; + const KgraphMapFmEdge * const node1ptr = (KgraphMapFmEdge *) data1ptr; + Gnum node0val; + Gnum node1val; + + node0val = node0ptr->commgain + node0ptr->cmiggain; + node1val = node1ptr->commgain + node1ptr->cmiggain; + + if (node0val < node1val) + return (-1); + if (node0val > node1val) + return (1); + return (0); +} + +static +KgraphMapFmEdge * +kgraphMapFmTablGet ( +KgraphMapFmTabl * restrict const tablptr, /*+ Gain table +*/ +KgraphMapFmVertex * restrict const vexxtab, /*+ Extended vertex hash table array +*/ +const Gnum * restrict const comploaddlt, /*+ Current imbalance array +*/ +const Gnum * restrict const comploadmax, /*+ Maximum imbalance array +*/ +Gnum * restrict comploaddiff, +Gnum * restrict flagval) +{ + FiboNode * remoptr; /* List of removed links */ + KgraphMapFmEdge * edxxptr; + Gnum deltnew; + FiboNode * linkptr; /* Pointer to current gain link */ + + edxxptr = NULL; + remoptr = NULL; + + while ((linkptr = fiboTreeMin (tablptr)) != NULL) { /* Select candidate vertices */ + Gnum vexxidx; + Gnum veloval; + Anum domnnumold; + Anum domnnumnew; + Gnum deltvalold; + Gnum deltvalnew; + + edxxptr = (KgraphMapFmEdge *) linkptr; + vexxidx = edxxptr->vexxidx; + veloval = vexxtab[vexxidx].veloval; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[vexxidx].lockptr != NULL) { /* If vertex is locked */ + errorPrint ("kgraphMapFmTablGet: internal error (2)"); + return (NULL); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + fiboTreeDel (tablptr, linkptr); /* Remove vertex link from table */ + linkptr->linkdat.prevptr = remoptr; /* Node has been removed but is not kept */ + remoptr = linkptr; /* It will be chained back afterwards */ + + domnnumold = vexxtab[vexxidx].domnnum; + domnnumnew = edxxptr->domnnum; + deltvalold = abs (comploaddlt[domnnumold] - veloval); + deltvalnew = abs (comploaddlt[domnnumnew] + veloval); + if (((deltvalold <= comploadmax[domnnumold]) || (deltvalold < abs (comploaddlt[domnnumold]))) && /* If vertex does enforce or improve balance, keep it */ + ((deltvalnew <= comploadmax[domnnumnew]) || (deltvalnew < abs (comploaddlt[domnnumnew])))) { + deltnew = deltvalold - abs (comploaddlt[domnnumold]) + /* Compute difference in imbalance load sum */ + deltvalnew - abs (comploaddlt[domnnumnew]); + if ((abs (comploaddlt[domnnumold]) > comploadmax[domnnumold]) || + (abs (comploaddlt[domnnumnew]) > comploadmax[domnnumnew])) + *flagval = 1; + break; + } + else { + if (edxxptr->cmigmask == ~0) { + edxxptr->cmigmask = 0; + kgraphMapFmTablDel (&gaintab, edxxptr); + kgraphMapFmTablAdd (&gaintab, edxxptr); + } + } + } + + while (remoptr != NULL) { /* Put back all temporarily removed nodes */ + FiboNode * tempptr; + + tempptr = remoptr; /* Get pointer to node */ + remoptr = remoptr->linkdat.prevptr; /* Find next node */ + fiboTreeAdd (tablptr, tempptr); /* Re-link node */ + } + + if (linkptr == NULL) + return (NULL); + + *comploaddiff += deltnew; + return (edxxptr); +} + +#endif /* SCOTCH_TABLE_GAIN */ + +/* This routine checks the consistency of +** the hash structures. +** It returns: +** - 0 : in case of success. +** - !0 : in case of error. +*/ + +#ifdef SCOTCH_DEBUG_KGRAPH3 + +static +int +kgraphMapFmCheck ( +KgraphMapFmTabl * restrict const tablptr, /*+ Gain table +*/ +const Kgraph * restrict const grafptr, +const KgraphMapFmVertex * restrict const vexxtab, +const KgraphMapFmEdge * const edxxtab, /*+ Extended edge array +*/ +const Gnum hashmsk, +const Gnum commload, +Gnum * const chektab) +{ + Gnum vexxidx; + Gnum edxxidx; + Gnum commloadtmp; + Anum domnnum; + + Anum * restrict const parttax = grafptr->m.parttax; + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const vmlotax = grafptr->r.vmlotax; + + Gnum * const edlosumtab = chektab; + Gnum * const edgenbrtab = chektab + grafptr->m.domnnbr; + Gnum * const commgaintab = chektab + (grafptr->m.domnnbr * 2); + + commloadtmp = 0; + for (vexxidx = 0; vexxidx <= hashmsk; vexxidx ++) { /* For all vertex slots */ + Gnum vertnum; + Gnum edgenum; + Anum domnorg; + Anum domnlst; /* Domain of last vertex for which a distance was computed */ + Anum distlst; /* Last distance computed */ + Gnum commloadloctmp; + Gnum edlosum; + Gnum edgenbr; + + commloadloctmp = 0; + vertnum = vexxtab[vexxidx].vertnum; + if ((vertnum == ~0)) /* If unallocated */ + continue; /* Skip to next slot */ + + domnorg = vexxtab[vexxidx].domnnum; + if ((domnorg < 0) || (domnorg >= grafptr->m.domnnbr)) { + errorPrint ("kgraphMapFmCheck: invalid vertex part value"); + return (1); + } + if (domnorg != parttax[vertnum]) { + errorPrint ("kgraphMapFmCheck: invalid extended vertex part value"); + return (1); + } + edxxidx = vexxtab[vexxidx].edxxidx; + if ((edxxidx >= 0) && + (edxxtab[edxxidx].vexxidx != vexxidx)) { + errorPrint ("kgraphMapFmCheck: invalid extended vertex pointer in extended edge"); + return (1); + } + + edlosum = + edgenbr = 0; + domnlst = -1; /* Invalid domnain to recompute distance */ + memSet (edlosumtab, 0, grafptr->m.domnnbr * 3 * sizeof(Gnum)); /* Reset edlosumtab, edgenbrtab and commgaintab */ + for (edgenum = verttax[vertnum]; /* For all neighbors */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Anum domnend; + Gnum edloval; + + vertend = edgetax[edgenum]; + domnend = parttax[vertend]; + edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; + + if (domnorg != domnend) { + Anum distval; + + distval = (domnend != domnlst) ? archDomDist (grafptr->m.archptr, &grafptr->m.domntab[domnorg], &grafptr->m.domntab[domnend]) : distlst; + distlst = distval; + domnlst = domnend; + + edlosumtab[domnend] += edloval; + edgenbrtab[domnend] ++; + + commloadloctmp += (Gnum) distval * edloval * grafptr->r.crloval; + + for (edxxidx = vexxtab[vexxidx].edxxidx; (edxxidx != -1) && (edxxtab[edxxidx].domnnum != domnend) ; + edxxidx = edxxtab[edxxidx].edxxidx) ; /* Search if edge slot exists */ + if (edxxidx == -1) { + Gnum vertndd; + Gnum vexxndd; + + vertndd = edgetax[edgenum]; + for (vexxndd = 0; (vexxtab[vexxndd].vertnum != vertndd) && (vexxndd <= hashmsk); vexxndd ++) ; /* For all vertex slots */ + errorPrint ("kgraphMapFmCheck: no link for migration of vertex %d to domain %d", vexxtab[vexxidx].vertnum, domnend); + return (1); + } + } + else { + edlosum += edloval; + edgenbr ++; + } + } + if (edlosum != vexxtab[vexxidx].edlosum) { + errorPrint ("kgraphMapFmCheck: invalid edge load sum for vertex %d", vexxtab[vexxidx].vertnum); + return (1); + } + if (edgenbr != vexxtab[vexxidx].edgenbr) { + errorPrint ("kgraphMapFmCheck: invalid edge number for vertex %d", vexxtab[vexxidx].vertnum); + return (1); + } + commloadtmp += commloadloctmp; + + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxxidx = edxxtab[edxxidx].edxxidx) { + Gnum domncur; + Gnum domnflg; + + domnflg = 0; + domncur = edxxtab[edxxidx].domnnum; + + commgaintab[domncur] = -commloadloctmp; + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Anum domnend; + Gnum edloval; + + vertend = edgetax[edgenum]; + domnend = parttax[vertend]; + edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; + + if (domnend == domncur) { + domnflg = 1; + continue; + } + + edloval *= grafptr->r.crloval; + commgaintab[domncur] += edloval /* Add edge contribution to target domain */ + * archDomDist (&grafptr->a, &grafptr->m.domntab[domncur], &grafptr->m.domntab[domnend]); + } + if (domnflg == 0) { + errorPrint ("kgraphMapFmCheck: extra link for migration of vertex %d to domain %d", vexxtab[vexxidx].vertnum, domncur); + return (1); + } + } + if ((vexxtab[vexxidx].domoptr != NULL) && + (vexxtab[vexxidx].cmigload != (archDomIncl (grafptr->m.archptr, &grafptr->m.domntab[domnorg], vexxtab[vexxidx].domoptr) == 1) ? 0 + : grafptr->r.cmloval * ((vmlotax != NULL) ? vmlotax[vertnum] : 1) + * archDomDist (grafptr->m.archptr, &grafptr->m.domntab[domnorg], vexxtab[vexxidx].domoptr))) { + errorPrint ("kgraphMapFmCheck: invalid migration communication load for extended vertex"); + return (1); + } + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxxidx = edxxtab[edxxidx].edxxidx) { /* For vertex links */ + if (edlosumtab[edxxtab[edxxidx].domnnum] != edxxtab[edxxidx].edlosum) { + errorPrint ("kgraphMapFmCheck: invalid extended edge edlosum value"); + return (1); + } + if (edgenbrtab[edxxtab[edxxidx].domnnum] != edxxtab[edxxidx].edgenbr) { + errorPrint ("kgraphMapFmCheck: invalid extended edge edgenbr value"); + return (1); + } + if (commgaintab[edxxtab[edxxidx].domnnum] != edxxtab[edxxidx].commgain) { + errorPrint ("kgraphMapFmCheck: invalid extended edge commgain value"); + return (1); + } + if ((vexxtab[vexxidx].domoptr != NULL) && + (edxxtab[edxxidx].cmiggain + vexxtab[vexxidx].cmigload != (archDomIncl (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxidx].domnnum], vexxtab[vexxidx].domoptr) == 1) ? 0 + : grafptr->r.cmloval * ((vmlotax != NULL) ? vmlotax[vertnum] : 1) + * archDomDist (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxidx].domnnum], vexxtab[vexxidx].domoptr))) { + errorPrint ("kgraphMapFmCheck: invalid migration communication gain for extended edge"); + return (1); + } + } + } + + if (grafptr->pfixtax != NULL) { /* We have fixed vertices */ + Anum domnlst; /* Domnain of last vertex for which a distance was computed */ + Anum distlst; /* Last distance computed */ + Gnum vertnum; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + if (grafptr->pfixtax[vertnum] != -1) { /* If vertex is fixed */ + Gnum domnorg; + Gnum edgenum; + + domnorg = parttax[vertnum]; + domnlst = -1; /* Invalid part to recompute distance */ + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Anum domnend; + Gnum edloval; + + vertend = edgetax[edgenum]; + domnend = parttax[vertend]; + edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; + edloval *= grafptr->r.crloval; + + if (domnorg != domnend) { + Anum distval; + + distval = (domnend != domnlst) ? archDomDist (grafptr->m.archptr, &grafptr->m.domntab[domnorg], &grafptr->m.domntab[domnend]) : distlst; + distlst = distval; + domnlst = domnend; + + commloadtmp += (Gnum) distval * edloval; + } + } + } + } + } + + if (commload != commloadtmp / 2) { + errorPrint ("kgraphMapFmCheck: invalid communication load"); + return (1); + } + + return (0); +} + +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + +/*****************************/ +/* */ +/* These routines handle the */ +/* insertion of vertices */ +/* into the gain arrays. */ +/* */ +/*****************************/ + +static +int +kgraphMapFmEdgeResize ( +KgraphMapFmVertex * restrict const vexxtab, /*+ Extended vertex hash table array +*/ +Gnum vexxidx, +KgraphMapFmEdge * restrict * const edxxtabptr, +Gnum * restrict const edxxsizptr, +Gnum const edxxnbr, +KgraphMapFmTabl * restrict const tablptr) +{ + KgraphMapFmEdge * restrict edxxtmp; + KgraphMapFmEdge * restrict edxxtab; + Gnum edxxsiz; + + edxxtab = *edxxtabptr; + edxxsiz = *edxxsizptr; + + edxxsiz *= 2; /* Compute new array size */ + *edxxsizptr = edxxsiz; /* Propagate back new size */ + + if ((edxxtmp = memRealloc (edxxtab, edxxsiz * sizeof (KgraphMapFmEdge))) == NULL) { + errorPrint ("kgraphMapFmEdgeResize: out of memory"); + return (1); + } + if (edxxtmp != edxxtab) { /* If array has been reallocated, re-link all edges */ + Gnum edxxidx; + + edxxtab = *edxxtabptr = edxxtmp; /* Point to new array location */ + + kgraphMapFmTablFree (tablptr); /* Free all edges in gain structure */ + + for (edxxidx = 0; edxxidx < edxxnbr; edxxidx ++) { + if ((vexxtab[edxxtab[edxxidx].vexxidx].lockptr == NULL) && /* Vertex is not locked */ + (edxxtab[edxxidx].vexxidx != vexxidx) && /* Edge of current vertex will be added later */ + (edxxtab[edxxidx].edxxidx != -2)) /* Skip deprecated extended edges */ + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxidx]); + } + } + + return (0); +} + +static +int +kgraphMapFmPartAdd2 ( +const Kgraph * restrict const grafptr, +KgraphMapFmVertex * restrict const vexxtab, /*+ Extended vertex hash table array +*/ +Gnum vexxidx, +KgraphMapFmEdge * restrict * const edxxtabptr, +Gnum * restrict const edxxsizptr, +Gnum * restrict const edxxnbrptr, +Anum domnnum, /*+ Vertex domain +*/ +Anum domnend, /*+ Domain of the extended edge to add +*/ +Gnum edloval, /*+ Load of the edge to domnend +*/ +KgraphMapFmTabl * restrict const tablptr) +{ + KgraphMapFmEdge * restrict edxxtab; + Gnum edxxidx; + Gnum edgenum; + Gnum edlosum; + Gnum edgenbr; + Gnum edxxtmp; + Gnum commgain; + + if (*edxxnbrptr >= *edxxsizptr) /* If new slot would not fit */ + kgraphMapFmEdgeResize (vexxtab, -1, edxxtabptr, edxxsizptr, *edxxnbrptr, tablptr); /* No vexxidx because vertex extended edges will be readd later */ + + edxxtab = *edxxtabptr; + edxxidx = (*edxxnbrptr) ++; /* Allocate new slot */ + + edxxtab[edxxidx].domnnum = domnend; /* Set extended edge data */ + edxxtab[edxxidx].distval = archDomDist (&grafptr->a, &grafptr->m.domntab[domnnum], &grafptr->m.domntab[domnend]); + edxxtab[edxxidx].edlosum = edloval; + edxxtab[edxxidx].edgenbr = 1; + edxxtab[edxxidx].vexxidx = vexxidx; + edxxtab[edxxidx].mswpnum = 0; + + commgain = 0; /* Compute commgain */ + for (edxxtmp = vexxtab[vexxidx].edxxidx; edxxtmp != -1; edxxtmp = edxxtab[edxxtmp].edxxidx) { + commgain += edxxtab[edxxtmp].edlosum * + (archDomDist (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxtmp].domnnum], &grafptr->m.domntab[domnend]) + - edxxtab[edxxtmp].distval); + } + commgain += (vexxtab[vexxidx].edlosum - edloval) * edxxtab[edxxidx].distval; + edxxtab[edxxidx].commgain = commgain * grafptr->r.crloval; + + edxxtab[edxxidx].edxxidx = vexxtab[vexxidx].edxxidx; /* Link edge to vertex */ + vexxtab[vexxidx].edxxidx = edxxidx; + + edxxtab[edxxidx].cmiggain = 0; /* Compute migration commgain */ + edxxtab[edxxidx].cmigmask = 0; + if (vexxtab[vexxidx].domoptr != NULL) { + Gnum migcoef; /* Equal to -migedloval if vertex was mapped in old mapping */ + + migcoef = grafptr->r.cmloval * ((grafptr->r.vmlotax != NULL) ? grafptr->r.vmlotax[vexxtab[vexxidx].vertnum] : 1); + + edxxtab[edxxidx].cmiggain = (archDomIncl (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxidx].domnnum], vexxtab[vexxidx].domoptr) == 1) ? 0 + : migcoef * archDomDist (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxidx].domnnum], vexxtab[vexxidx].domoptr); + edxxtab[edxxidx].cmiggain -= vexxtab[vexxidx].cmigload; + edxxtab[edxxidx].cmigmask = ~0; + } + + if (vexxtab[vexxidx].lockptr == NULL) /* If value has to be linked */ + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxidx]); + + return (0); +} + +/* This routine adds a vertex to hash table. +*/ + +static +int +kgraphMapFmPartAdd ( +const Kgraph * restrict const grafptr, +const Gnum vertnum, +const Gnum vexxidx, /* Hash value for insertion in vexxtab */ +KgraphMapFmVertex * restrict const vexxtab, +KgraphMapFmEdge ** edxxtabptr, +Gnum * restrict const edxxsizptr, +Gnum * restrict const edxxnbrptr, +KgraphMapFmTabl * restrict const tablptr) +{ + Gnum oldvertnum; /* Number of current vertex */ + KgraphMapFmEdge * restrict edxxtab; + Gnum edxxidx; + Gnum edgenum; + Gnum edlosum; + Gnum edgenbr; + Anum domnnum; + Gnum commload; /* Communication load for local domain */ + + const Anum * restrict const parttax = grafptr->m.parttax; + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[vexxidx].vertnum != ~0) { + errorPrint ("kgraphMapFmPartAdd: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + domnnum = parttax[vertnum]; + + vexxtab[vexxidx].vertnum = vertnum; + vexxtab[vexxidx].domnnum = domnnum; + vexxtab[vexxidx].veloval = (grafptr->s.velotax != NULL) ? grafptr->s.velotax[vertnum] : 1; /* Vertex will be linked since value is positive */ + vexxtab[vexxidx].mswpnum = 0; /* Implicitly set slot as used */ + vexxtab[vexxidx].edxxidx = -1; /* No target domains yet */ + vexxtab[vexxidx].lockptr = NULL; /* No locked yet */ + + oldvertnum = ((grafptr->s.vnumtax != NULL) && /* If there is ancestor graph vertex numbers */ + (grafptr->s.flagval & KGRAPHHASANCHORS) == 0) /* That are not the ones of the band graph */ + ? grafptr->s.vnumtax[vertnum] : vertnum; /* Get vertex number in original graph */ + + if ((grafptr->r.m.parttax != NULL) && /* If we are doing a repartitioning */ + (grafptr->r.m.parttax[oldvertnum] != -1)) /* And if vertex was mapped to an old domain */ + vexxtab[vexxidx].domoptr = mapDomain (&grafptr->r.m, oldvertnum); /* Domain in which the vertex was previously mapped */ + else + vexxtab[vexxidx].domoptr = NULL; + + edxxtab = *edxxtabptr; /* Compute and link edges */ + edgenbr = 0; + + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxxidx = edxxtab[edxxidx].edxxidx) { + Gnum domnend; + + domnend = edxxtab[edxxidx].domnnum; + edxxtab[edxxidx].edlosum = 0; + edxxtab[edxxidx].edgenbr = 0; + edxxtab[edxxidx].distval = archDomDist (&grafptr->a, &grafptr->m.domntab[domnnum], &grafptr->m.domntab[domnend]); + } + + commload = 0; /* Load associated with vertex edges */ + edlosum = 0; + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum edxxidx; + Gnum vertend; + Anum domnend; + Gnum edloval; + + vertend = edgetax[edgenum]; + domnend = parttax[vertend]; + + edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; /* Do not account for crloval yet */ + + if (domnend == domnnum) { /* If end vertex belongs to same domain */ + edlosum += edloval; /* Record local edge load sum */ + edgenbr ++; /* Record local edge */ + continue; /* Skip further processing */ + } + + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxxidx = edxxtab[edxxidx].edxxidx) { /* Search for edge */ + if (edxxtab[edxxidx].domnnum == domnend) /* If edge slot found */ + break; + } + + if (edxxidx == -1) { /* If edge slot not found */ + if (*edxxnbrptr >= *edxxsizptr) /* If new slot would not fit */ + kgraphMapFmEdgeResize (vexxtab, vexxidx, edxxtabptr, edxxsizptr, *edxxnbrptr, tablptr); + + edxxidx = (*edxxnbrptr) ++; /* Allocate new slot */ + edxxtab = *edxxtabptr; /* Update edxxtab */ + + edxxtab[edxxidx].commgain = 0; + edxxtab[edxxidx].cmiggain = 0; + edxxtab[edxxidx].cmigmask = (grafptr->r.m.parttax != NULL) ? ~0 : 0; + edxxtab[edxxidx].domnnum = domnend; + edxxtab[edxxidx].distval = archDomDist (&grafptr->a, &grafptr->m.domntab[domnnum], &grafptr->m.domntab[domnend]); + edxxtab[edxxidx].edlosum = 0; + edxxtab[edxxidx].edgenbr = 0; + edxxtab[edxxidx].vexxidx = vexxidx; + edxxtab[edxxidx].edxxidx = vexxtab[vexxidx].edxxidx; /* Link edge to vertex */ + vexxtab[vexxidx].edxxidx = edxxidx; + edxxtab[edxxidx].mswpnum = 0; + } + + commload += edloval * edxxtab[edxxidx].distval; + edxxtab[edxxidx].edlosum += edloval; + edxxtab[edxxidx].edgenbr ++; + } + commload *= grafptr->r.crloval; /* Multiply all local loads by crloval */ + vexxtab[vexxidx].edlosum = edlosum; + vexxtab[vexxidx].edgenbr = edgenbr; + + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxxidx = edxxtab[edxxidx].edxxidx) { + Gnum domncur; + Gnum edxxtmp; + Gnum commgain; + + domncur = edxxtab[edxxidx].domnnum; + + commgain = 0; + for (edxxtmp = vexxtab[vexxidx].edxxidx; edxxtmp != -1; edxxtmp = edxxtab[edxxtmp].edxxidx) { + Anum domnend; + + if (edxxtmp == edxxidx) + continue; + + domnend = edxxtab[edxxtmp].domnnum; + commgain += edxxtab[edxxtmp].edlosum * /* Add edge contribution to target domain */ + archDomDist (&grafptr->a, &grafptr->m.domntab[domncur], &grafptr->m.domntab[domnend]); + } + commgain += vexxtab[vexxidx].edlosum * edxxtab[edxxidx].distval; + edxxtab[edxxidx].commgain = commgain * grafptr->r.crloval - commload; + } + + vexxtab[vexxidx].cmigload = 0; + if (vexxtab[vexxidx].domoptr != NULL) { + Gnum migcoef; /* Equal to -migedloval if vertex was mapped in old mapping */ + + migcoef = grafptr->r.cmloval * ((grafptr->r.vmlotax != NULL) ? grafptr->r.vmlotax[vertnum] : 1); + + vexxtab[vexxidx].cmigload = (archDomIncl (&grafptr->a, &grafptr->m.domntab[domnnum], vexxtab[vexxidx].domoptr) == 1) ? 0 + : migcoef * archDomDist (&grafptr->a, &grafptr->m.domntab[domnnum], vexxtab[vexxidx].domoptr); + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxxidx = edxxtab[edxxidx].edxxidx) { + edxxtab[edxxidx].cmiggain = (archDomIncl (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxidx].domnnum], vexxtab[vexxidx].domoptr) == 1) ? 0 + : migcoef * archDomDist (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxidx].domnnum], vexxtab[vexxidx].domoptr); + edxxtab[edxxidx].cmiggain -= vexxtab[vexxidx].cmigload; + edxxtab[edxxidx].cmigmask = ~0; + } + } + + if (vexxtab[vexxidx].lockptr == NULL) { /* If value has to be (re)linked */ + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxxidx = edxxtab[edxxidx].edxxidx) /* Insert edges to neighbors in gain arrays */ + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxidx]); + } + + return (0); +} + +/* This routine doubles the size all of the arrays +** involved in handling the hash table and hash +** vertex arrays. +** It returns: +** - 0 : if resizing succeeded. +** - !0 : if out of memory. +*/ + +static +int +kgraphMapFmResize ( +KgraphMapFmVertex * restrict * vexxtabptr, /*+ Extended vertex array +*/ +Gnum * restrict const hashmaxptr, /*+ Size of vertex array +*/ +Gnum * const hashmskptr, /*+ Pointer to hash table mask +*/ +KgraphMapFmSave * restrict savetab, /*+ Move array +*/ +const Gnum savenbr, /*+ Number of moves recorded +*/ +KgraphMapFmTabl * const tablptr, /*+ Gain table +*/ +KgraphMapFmEdge * edxxtab, /*+ Extended edge array +*/ +KgraphMapFmVertex ** const lockptr) /*+ Pointer to locked list +*/ +{ + KgraphMapFmVertex * restrict vexxtab; /* Extended vertex array */ + KgraphMapFmSave * restrict saveold; /* Pointer to translated old save array */ + Gnum savenum; + Gnum hashold; /* Size of old hash table (half of new) */ + Gnum hashsiz; + Gnum hashmax; + Gnum hashmsk; + Gnum vexxidx; + + hashmax = *hashmaxptr << 1; /* Compute new sizes */ + hashold = *hashmaxptr << 2; + hashsiz = *hashmaxptr << 3; + hashmsk = hashsiz - 1; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (sizeof (KgraphMapFmVertex) < sizeof (KgraphMapFmSave)) { /* Should always be true */ + errorPrint ("kgraphMapFmResize: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + if ((vexxtab = memRealloc (*vexxtabptr, (size_t) hashsiz * sizeof (KgraphMapFmVertex))) == NULL) { + errorPrint ("kgraphMapFmResize: out of memory"); + return (1); + } + + for (savenum = savenbr - 1; savenum >= 0; savenum --) { /* Move save array, in reverse order */ + if (savetab[savenum].type == KGRAPHMAPPFMSAVEVEXX) + savetab[savenum].u.vexxdat.vexxidx = vexxtab[savetab[savenum].u.vexxdat.vexxidx].vertnum; /* Temporarily translate from hash index to number */ + else if ((savetab[savenum].type & KGRAPHMAPPFMSAVELINK) != 0) + savetab[savenum].u.linkdat.vexxidx = vexxtab[savetab[savenum].u.linkdat.vexxidx].vertnum; /* Temporarily translate from hash index to number */ + } + + *vexxtabptr = vexxtab; + *hashmaxptr = hashmax; + *hashmskptr = hashmsk; + + memSet (vexxtab + hashold, ~0, hashold * sizeof (KgraphMapFmVertex)); /* Set new slots to ~0 */ + + kgraphMapFmTablFree (tablptr); /* Reset gain table */ + *lockptr = (KgraphMapFmVertex *) -1; /* Rebuild lock list */ + + if (vexxtab[0].vertnum != ~0) { /* If vertex overflowing may have occured in old hash table */ + Gnum hashtmp; + Gnum hashnew; + + for (hashtmp = hashold - 1, hashnew = 0; /* Temporarily move vertices away from end of old table to prevent overflowing */ + vexxtab[hashtmp].vertnum != ~0; hashtmp --) { + while (vexxtab[++ hashnew].vertnum != ~0) ; /* Find an empty slot to receive moved vertex */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (hashnew >= hashtmp) { + errorPrint ("kgraphMapFmResize: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + vexxtab[hashnew] = vexxtab[hashtmp]; /* Move vertex from end of table */ + vexxtab[hashtmp].vertnum = ~0; /* Set old slot as free */ + } + } + + for (vexxidx = 0; vexxidx < hashold; vexxidx ++) { /* Re-compute position of vertices in new table */ + Gnum vertnum; + + vertnum = vexxtab[vexxidx].vertnum; + if (vertnum != ~0) { /* If hash slot used */ + Gnum hashnew; + Gnum edxxtmp; + + for (hashnew = (vertnum * KGRAPHMAPFMHASHPRIME) & hashmsk; ; hashnew = (hashnew + 1) & hashmsk) { + if (hashnew == vexxidx) /* If hash slot is the same */ + break; /* There is nothing to do */ + if (vexxtab[hashnew].vertnum == ~0) { /* If new slot is empty */ + vexxtab[hashnew] = vexxtab[vexxidx]; /* Copy data to new slot */ + vexxtab[vexxidx].mswpnum = ~0; /* TRICK: not tested at creation */ + vexxtab[vexxidx].vertnum = ~0; /* Make old slot empty */ + break; + } + } + if ((hashnew > vexxidx) && (hashnew < hashold)) /* If vertex was an overflowed vertex which will be replaced at end of old table */ + continue; /* It will be re-processed again and re-linked once for good at the end of the loop */ + + for (edxxtmp = vexxtab[hashnew].edxxidx; edxxtmp != -1; edxxtmp = edxxtab[edxxtmp].edxxidx) /* Insert edges to neighbors in gain arrays */ + edxxtab[edxxtmp].vexxidx = hashnew; + + edxxtmp = vexxtab[hashnew].edxxidx; /* vertices lock is done through their first links */ + if (vexxtab[hashnew].lockptr == NULL) { /* If vertex was linked, re-link its edges */ + for ( ; edxxtmp != -1; edxxtmp = edxxtab[edxxtmp].edxxidx) /* Insert edges to neighbors in gain arrays */ + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxtmp]); + } + else /* Re-lock vertices */ + kgraphMapFmLock (*lockptr, &vexxtab[hashnew]); + } + } + + for (savenum = 0; savenum < savenbr; savenum ++) { + if (savetab[savenum].type == KGRAPHMAPPFMSAVEVEXX) { + Gnum vertnum; + Gnum vexxidx; + + vertnum = savetab[savenum].u.vexxdat.vexxidx; /* Get vertex number */ + for (vexxidx = (vertnum * KGRAPHMAPFMHASHPRIME) & hashmsk; vexxtab[vexxidx].vertnum != vertnum; vexxidx = (vexxidx + 1) & hashmsk) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[vexxidx].vertnum == ~0) { + errorPrint ("kgraphMapFmResize: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + savetab[savenum].u.vexxdat.vexxidx = vexxidx; /* Set new hash table index */ + } + else if ((savetab[savenum].type & KGRAPHMAPPFMSAVELINK) != 0) { + Gnum vertnum; + Gnum vexxidx; + + vertnum = savetab[savenum].u.linkdat.vexxidx; /* Get vertex number */ + for (vexxidx = (vertnum * KGRAPHMAPFMHASHPRIME) & hashmsk; vexxtab[vexxidx].vertnum != vertnum; vexxidx = (vexxidx + 1) & hashmsk) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[vexxidx].vertnum == ~0) { + errorPrint ("kgraphMapFmResize: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + savetab[savenum].u.linkdat.vexxidx = vexxidx; /* Set new hash table index */ + } + } + + return (0); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the k-way partitioning. +** It returns: +** - 0 : if k-partition could be computed. +** - 1 : on error. +*/ + +int +kgraphMapFm ( +Kgraph * restrict const grafptr, /*+ Active graph +*/ +const KgraphMapFmParam * const paraptr) /*+ Method parameters +*/ +{ + KgraphMapFmSave * savetab; /* Pointer to move array */ + KgraphMapFmVertex * restrict vexxtab; /* Extended vertex hash table array */ + KgraphMapFmEdge * edxxtab; /* Edge extended array */ + Gnum edxxnbr; /* Current number of links in link array */ + Gnum edxxsiz; + Gnum edxxnum; + Gnum edxxcdx; /* Index for extended edge copy */ + Gnum edcunbr; /* Current number of unused extended edge slots */ + Gnum edxunbr; /* Number of unused extended edge slots */ + Gnum * comploadmax; /* Array of maximum imbalances */ + Gnum * comploaddlt; + Gnum commload; + Gnum cmigload; + KgraphMapFmTabl * restrict tablptr; /* Pointer to gain table for easy access */ + KgraphMapFmTabl tabldat; /* Gain table */ + KgraphMapFmVertex * lockptr; + Gnum fronnum; + Gnum fronnbr; + Gnum commloadbst; + Gnum cmigloadbst; + Gnum moveflag; /* Flag set if useful moves made */ + Gnum edcpflag; /* Extended edge array compacting flag */ + Gnum comploaddiff; + Gnum flagval; + Anum domnnum; + Gnum vexxidx; + Gnum passnbr; /* Maximum number of passes to go */ + Gnum movenbr; /* Number of uneffective moves done */ + Gnum savenbr; /* Number of recorded backtrack moves */ + Gnum savesiz; /* Size of save array */ + Gnum mswpnum; /* Current number of recording sweep */ + Gnum vertnum; + Gnum hashsiz; /* Size of hash table */ + Gnum hashmsk; /* Mask for access to hash table */ + Gnum hashnum; /* Hash value */ + Gnum hashmax; /* Maximum number of entries in vertex hash table */ + Gnum hashnbr; /* Current number of entries in vertex hash table */ +#ifdef SCOTCH_DEBUG_KGRAPH3 + Gnum * chektab; /* Extra memory needed for the check routine */ +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + + Anum * restrict const parttax = grafptr->m.parttax; + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + const Gnum * restrict const pfixtax = grafptr->pfixtax; + +#ifdef SCOTCH_DEBUG_KGRAPH3 /* Allocation of extra memory needed for the check routine */ + if ((chektab = memAlloc (grafptr->m.domnnbr * 3 * sizeof(Gnum))) == NULL) { + errorPrint ("kgraphMapFm: out of memory (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + tablptr = &tabldat; + + grafptr->kbalval = paraptr->deltval; /* Store last k-way imbalance ratio */ + kgraphCost (grafptr); + grafptr->commload *= grafptr->r.crloval; /* crloval must be 1 if we are not doing a repartitioning of a no-band graph */ + if (memAllocGroup ((void **) (void *) /* Allocation and initialization of imbalance arrays */ + &comploadmax, (size_t) (grafptr->m.domnnbr * sizeof (Gnum)), + &comploaddlt, (size_t) (grafptr->m.domnnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("kgraphMapFm: out of memory (2)"); + return (1); + } + for (domnnum = 0; domnnum < grafptr->m.domnnbr; domnnum ++) { + comploadmax[domnnum] = (Gnum) ((double) grafptr->comploadavg[domnnum] * paraptr->deltval); + comploaddlt[domnnum] = grafptr->comploaddlt[domnnum]; + } + + if (grafptr->fronnbr == 0) { /* If no current frontier */ + Anum domnnum; + + for (domnnum = 0; domnnum < grafptr->m.domnnbr; domnnum ++) { + if (abs (grafptr->comploaddlt[domnnum]) > comploadmax[domnnum]) + break; + } + if (domnnum == grafptr->m.domnnbr) { /* If balance is correct */ + memFree (comploadmax); /* Nothing to do */ + return (0); + } + else { /* Imbalance must be fought */ + const Strat * strat; + + strat = stratInit (&kgraphmapststratab, "r{sep=h{pass=10}}"); /* Use a standard algorithm */ + kgraphMapSt (grafptr, strat); /* Perform mapping */ + + if (grafptr->fronnbr == 0) { /* If new partition has no frontier */ + memFree (comploadmax); + return (0); /* This algorithm is still useless */ + } + + if (memReallocGroup ((void *) comploadmax, /* domnnbr has changed after mapping */ + &comploadmax, (size_t) (grafptr->m.domnnbr * sizeof (Gnum)), + &comploaddlt, (size_t) (grafptr->m.domnnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("kgraphMapFm: out of memory (3)"); + return (1); + } + + for (domnnum = 0; domnnum < grafptr->m.domnnbr; domnnum ++) { /* Else update compload{max,dlt} according to new partition */ + comploadmax[domnnum] = (Gnum) ((double) grafptr->comploadavg[domnnum] * paraptr->deltval); + comploaddlt[domnnum] = grafptr->comploaddlt[domnnum]; + } + } + } + +#ifdef SCOTCH_DEBUG_KGRAPH2 /* Allocation of extended vertex hash table and extended edge array */ + hashnbr = 2 * grafptr->fronnbr + 1; /* Ensure resizing will be performed, for maximum code coverage */ + savesiz = 2 * grafptr->fronnbr + 1; /* Ensure resizing will be performed, for maximum code coverage */ + edxxsiz = 2 * grafptr->fronnbr + 1; /* Ensure resizing will be performed, for maximum code coverage */ +#else /* SCOTCH_DEBUG_KGRAPH2 */ + hashnbr = 4 * (grafptr->fronnbr + paraptr->movenbr + grafptr->s.degrmax); + savesiz = 4 * (grafptr->fronnbr + paraptr->movenbr + grafptr->s.degrmax) * 2; + edxxsiz = 4 * (grafptr->fronnbr + paraptr->movenbr + grafptr->s.degrmax) * 4; +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + if (hashnbr > grafptr->s.vertnbr) + hashnbr = grafptr->s.vertnbr; + if (edxxsiz > grafptr->s.edgenbr) + edxxsiz = grafptr->s.edgenbr; + + for (hashsiz = 256; hashsiz < hashnbr; hashsiz <<= 1) ; /* Get upper power of two */ + hashmsk = hashsiz - 1; + hashmax = hashsiz >> 2; + + if (kgraphMapFmTablInit (tablptr) != 0) { + errorPrint ("kgraphMapFm: internal error (1)"); /* Unable to do proper initialization */ + kgraphMapFmTablExit (tablptr); + return (1); + } + else { + if (((vexxtab = memAlloc ((size_t) hashsiz * sizeof (KgraphMapFmVertex))) == NULL) || + ((savetab = memAlloc ((size_t) savesiz * sizeof (KgraphMapFmSave))) == NULL) || + ((edxxtab = memAlloc ((size_t) edxxsiz * sizeof (KgraphMapFmEdge))) == NULL)) { + errorPrint ("kgraphMapFm: out of memory (4)"); + kgraphMapFmTablExit (tablptr); + return (1); + } + } + memSet (vexxtab, ~0, hashsiz * sizeof (KgraphMapFmVertex)); /* Set all vertex numbers to ~0 */ + memSet (edxxtab, ~0, edxxsiz * sizeof (KgraphMapFmEdge)); /* Set all edge numbers to ~0 */ + + hashnbr = grafptr->fronnbr; + while (hashnbr >= hashmax) { + if (kgraphMapFmResize (&vexxtab, &hashmax, &hashmsk, savetab, 0, tablptr, edxxtab, &lockptr) != 0) { + errorPrint ("kgraphMapFm: out of memory (5)"); + memFree (vexxtab); /* Free group leader */ + kgraphMapFmTablExit (tablptr); + return (1); + } + } + + edxxnbr = 0; + for (fronnum = 0; fronnum < hashnbr; fronnum ++) { /* Set initial gains */ + Gnum vertnum; + + vertnum = grafptr->frontab[fronnum]; + if ((pfixtax == NULL) || (pfixtax[vertnum] == -1)) { /* Add only not fixed vertices */ + for (hashnum = (vertnum * KGRAPHMAPFMHASHPRIME) & hashmsk; vexxtab[hashnum].vertnum != ~0; hashnum = (hashnum + 1) & hashmsk) ; + + kgraphMapFmPartAdd (grafptr, vertnum, hashnum, vexxtab, &edxxtab, &edxxsiz, &edxxnbr, tablptr); + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[hashnum].edxxidx == -1) { /* If vertex does not have any neighbor */ + errorPrint ("kgraphMapFm: vertex does not belong to frontier"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + } +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (hashnbr >= hashmax) { /* Hash table too small (must not occur) */ + errorPrint ("kgraphMapFm: hash table to small"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + commloadbst = grafptr->commload; /* Start from initial situation */ + cmigloadbst = 0; /* Do not take initial migration cost situation into account */ + +#ifdef SCOTCH_DEBUG_KGRAPH3 + if (kgraphMapFmCheck (tablptr, grafptr, vexxtab, edxxtab, hashmsk, commloadbst, chektab) != 0) { + errorPrint ("kgraphMapFm: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + + passnbr = paraptr->passnbr; /* Set remaining number of passes */ + savenbr = 0; /* For empty backtrack of first pass */ + mswpnum = 0; /* Will be incremented afterwards */ + lockptr = (KgraphMapFmVertex *) -1; /* Locked list is empty */ + edxunbr = 0; + + do { /* As long as there are improvements */ + KgraphMapFmEdge * edxxptr; + Gnum oldsavenbr; + + oldsavenbr = savenbr; + + while (savenbr -- > 0) { /* Delete exceeding moves */ + /* Restore last correct state of the graph + * All unlocked vertices have all there valid extended edges in the table + * Any of the deprecated edges are in the table + * Any of locked vertices have extended edges in the table */ + Gnum vexxidx; + Gnum oldveloval; + Anum domnnum; + Anum domnorg; + Gnum edxxidx; + Gnum * edxiptr; + + switch (savetab[savenbr].type) { + case KGRAPHMAPPFMSAVEVEXX: + vexxidx = savetab[savenbr].u.vexxdat.vexxidx; + domnnum = savetab[savenbr].u.vexxdat.domnnum; + domnorg = vexxtab[vexxidx].domnnum; + oldveloval = vexxtab[vexxidx].veloval; + vexxtab[vexxidx].domnnum = domnnum; /* Restore vertex data */ + vexxtab[vexxidx].veloval = savetab[savenbr].u.vexxdat.veloval; + vexxtab[vexxidx].cmigload = savetab[savenbr].u.vexxdat.cmigload; + vexxtab[vexxidx].edlosum = savetab[savenbr].u.vexxdat.edlosum; + vexxtab[vexxidx].edgenbr = savetab[savenbr].u.vexxdat.edgenbr; + parttax[vexxtab[vexxidx].vertnum] = domnnum; + comploaddlt[domnorg] -= oldveloval; /* Update domain load delta */ + comploaddlt[domnnum] += oldveloval; + break; + + case KGRAPHMAPPFMSAVEEDXX: + edxxidx = savetab[savenbr].u.edxxdat.edxxidx; /* Restore extended edge data */ + edxxtab[edxxidx].domnnum = savetab[savenbr].u.edxxdat.domnnum; + edxxtab[edxxidx].commgain = savetab[savenbr].u.edxxdat.commgain; + edxxtab[edxxidx].cmiggain = savetab[savenbr].u.edxxdat.cmiggain; + edxxtab[edxxidx].cmigmask = (grafptr->r.m.parttax != NULL) ? ~0 : 0; + edxxtab[edxxidx].edlosum = savetab[savenbr].u.edxxdat.edlosum; + edxxtab[edxxidx].edgenbr = savetab[savenbr].u.edxxdat.edgenbr; + edxxtab[edxxidx].distval = savetab[savenbr].u.edxxdat.distval; + break; + + case KGRAPHMAPPFMSAVELINKDEL: + edxxidx = savetab[savenbr].u.linkdat.edxxidx; + vexxidx = savetab[savenbr].u.linkdat.vexxidx; + if (edxxtab[edxxidx].vexxidx != vexxidx) /* Restore correct vexxidx after resize */ + edxxtab[edxxidx].vexxidx = vexxidx; + edxxtab[edxxidx].edxxidx = vexxtab[vexxidx].edxxidx; /* Add it back to vertex list and set it as used */ + vexxtab[vexxidx].edxxidx = edxxidx; + edxunbr --; /* One more used edge slot */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (edxunbr < 0) { + errorPrint ("kgraphMapFm: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + if (vexxtab[vexxidx].lockptr == NULL) + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxidx]); /* Link it back */ + break; + + case KGRAPHMAPPFMSAVELINKADD: + edxxidx = savetab[savenbr].u.linkdat.edxxidx; + vexxidx = savetab[savenbr].u.linkdat.vexxidx; + if (edxxtab[edxxidx].vexxidx != vexxidx) /* Restore correct vexxidx after resize */ + edxxtab[edxxidx].vexxidx = vexxidx; + + if (vexxtab[vexxidx].lockptr == NULL) + kgraphMapFmTablDel (tablptr, &edxxtab[edxxidx]); /* Unlink it */ + + for (edxiptr = &vexxtab[vexxidx].edxxidx; (*edxiptr != edxxidx) && (*edxiptr != -1); edxiptr = &edxxtab[*edxiptr].edxxidx) ; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (*edxiptr == -1) { /* Since it has been added to the list, extended edge must be in it */ + errorPrint ("kgraphMapFm: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + *edxiptr = edxxtab[edxxidx].edxxidx; /* Remove it from the vertex list */ + edxxtab[edxxidx].edxxidx = -2; /* Set slot as unused */ + edxunbr ++; /* One more unused edge slot */ + break; + } + } + edcpflag = 0; /* Assume that extended edge array not need to be compacted */ + if (edxunbr > (edxxnbr / KGRAPHMAPFMEDXXCOMP)) { /* If more than 20% of edxxtab is unused, compact edxxtab */ + edcpflag = 1; + for (vexxidx = 0; vexxidx <= hashmsk; vexxidx ++) /* Extended edge list must be recomputed */ + vexxtab[vexxidx].edxxidx = -1; + edxxcdx = 0; + edcunbr = 0; + kgraphMapFmTablFree (tablptr); /* Free all edges in gain structure */ + for (edxxnum = 0; edxxnum < edxxnbr; edxxnum ++) { /* Remove unused slots of edxxtab */ + if (edxxtab[edxxnum].edxxidx == -2) { + if (edcunbr > 0) { + memmove (&edxxtab[edxxcdx], &edxxtab[edxxcdx + edcunbr], (edxxnum - edxxcdx - edcunbr) * sizeof (KgraphMapFmEdge)); /* Since there is overlapping, use memmove */ + edxxcdx = edxxnum - edcunbr; + } + else + edxxcdx = edxxnum; + edcunbr ++; + } + else { + vexxidx = edxxtab[edxxnum].vexxidx; + + edxxtab[edxxnum].edxxidx = vexxtab[vexxidx].edxxidx; /* Link edge to vertex */ + vexxtab[vexxidx].edxxidx = edxxnum - edcunbr; /* Set to new index */ + } + } + if ((edcunbr > 0) && (edxxtab[edxxnbr - 1].edxxidx != -2)) + memmove (&edxxtab[edxxcdx], &edxxtab[edxxcdx + edcunbr], (edxxnum - edxxcdx - edcunbr) * sizeof (KgraphMapFmEdge)); + edxxnbr -= edcunbr; + edxunbr = 0; + } + else { + while (oldsavenbr -- > 0) { /* Must be sure that all parttax is correct before recompute vertices gains */ + if (savetab[oldsavenbr].type == KGRAPHMAPPFMSAVEVEXX) { + Gnum vexxidx; + Gnum edxxtmp; + + vexxidx = savetab[oldsavenbr].u.vexxdat.vexxidx; + if (vexxtab[vexxidx].lockptr == NULL) { + for (edxxtmp = vexxtab[vexxidx].edxxidx; edxxtmp != -1; edxxtmp = edxxtab[edxxtmp].edxxidx) { /* Relink all vertex links */ + kgraphMapFmTablDel (tablptr, &edxxtab[edxxtmp]); + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxtmp]); + } + } + } + } + } + while (lockptr != (KgraphMapFmVertex *) -1) { /* Unlock locked vertices */ + KgraphMapFmVertex * vexxptr; + Gnum edxxtmp; + + vexxptr = lockptr; /* Get vertex associated with lock list */ + lockptr = kgraphMapFmLockNext (lockptr); /* Point to next vertex to unlock */ + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxptr->lockptr == NULL) { + errorPrint ("kgraphMapFm: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + vexxptr->lockptr = NULL; /* Set vertex as unlocked */ + + if (edcpflag == 0) /* It has not been done during edxxtab compacting */ + for (edxxtmp = vexxptr->edxxidx; edxxtmp != -1; edxxtmp = edxxtab[edxxtmp].edxxidx) /* Relink all vertex links */ + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxtmp]); + } + if (edcpflag == 1) + for (edxxnum = 0; edxxnum < edxxnbr; edxxnum ++) + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxnum]); /* Add all used links, all vertices will be unlocked */ + + commload = commloadbst; + cmigload = cmigloadbst; + mswpnum ++; /* Forget all recorded moves */ + +#ifdef SCOTCH_DEBUG_KGRAPH3 + if (kgraphMapFmCheck (tablptr, grafptr, vexxtab, edxxtab, hashmsk, commload, chektab) != 0) { + errorPrint ("kgraphMapFm: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + + moveflag = 0; /* No useful moves made */ + movenbr = 0; /* No ineffective moves recorded yet */ + savenbr = 0; /* Back up to beginning of table */ + comploaddiff = 0; + flagval = 0; + + while ((movenbr < paraptr->movenbr) && + ((edxxptr = (KgraphMapFmEdge *) kgraphMapFmTablGet (tablptr, vexxtab, comploaddlt, comploadmax, &comploaddiff, &flagval)) != NULL)) { + /* Move one vertex */ + Gnum vexxidx; + Gnum edxxtmp; + Gnum veloval; + Gnum edgenum; + Anum domnnum; + Gnum edlosum; + Gnum edgenbr; + Anum domnend; + Gnum edxxidx; + Gnum * edxpptr; + Gnum * vpexptr; + Gnum vexdflg; + + vexxidx = edxxptr->vexxidx; /* Get relevant information */ + vertnum = vexxtab[vexxidx].vertnum; + veloval = vexxtab[vexxidx].veloval; + domnnum = vexxtab[vexxidx].domnnum; + edlosum = vexxtab[vexxidx].edlosum; + edgenbr = vexxtab[vexxidx].edgenbr; + domnend = edxxptr->domnnum; + + /* Save moved vertex information */ + if (vexxtab[vexxidx].mswpnum != mswpnum) { /* If extended vertex data not yet recorded */ + vexxtab[vexxidx].mswpnum = mswpnum; + savetab[savenbr].type = KGRAPHMAPPFMSAVEVEXX; /* Save extended vertex data */ + savetab[savenbr].u.vexxdat.vexxidx = vexxidx; + savetab[savenbr].u.vexxdat.veloval = veloval; + savetab[savenbr].u.vexxdat.domnnum = domnnum; + savetab[savenbr].u.vexxdat.cmigload = vexxtab[vexxidx].cmigload; + savetab[savenbr].u.vexxdat.edlosum = edlosum; + savetab[savenbr].u.vexxdat.edgenbr = edgenbr; + savenbr ++; /* One more data recorded */ + } + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxxidx = edxxtab[edxxidx].edxxidx) { /* Save vertex links */ + if (edxxtab[edxxidx].mswpnum != mswpnum) { /* If extended edge data not yet recorded */ + edxxtab[edxxidx].mswpnum = mswpnum; + savetab[savenbr].type = KGRAPHMAPPFMSAVEEDXX; /* Save extended edge data */ + savetab[savenbr].u.edxxdat.edxxidx = edxxidx; + savetab[savenbr].u.edxxdat.domnnum = edxxtab[edxxidx].domnnum; + savetab[savenbr].u.edxxdat.commgain = edxxtab[edxxidx].commgain; + savetab[savenbr].u.edxxdat.cmiggain = edxxtab[edxxidx].cmiggain; + savetab[savenbr].u.edxxdat.edlosum = edxxtab[edxxidx].edlosum; + savetab[savenbr].u.edxxdat.edgenbr = edxxtab[edxxidx].edgenbr; + savetab[savenbr].u.edxxdat.distval = edxxtab[edxxidx].distval; + savenbr ++; /* One more data recorded */ + } + } + movenbr ++; /* One more move done */ + + commload += edxxptr->commgain; + cmigload += edxxptr->cmiggain; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[vexxidx].lockptr != NULL) { /* Vertex is locked */ + errorPrint ("kgraphMapFm: internal error (7)"); + return (1); + } + if (vexxtab[vexxidx].edxxidx == -1) { /* Vertex not in the frontier */ + errorPrint ("kgraphMapFm: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + kgraphMapFmLock (lockptr, &vexxtab[vexxidx]); /* Set part as having changed (lock vertex) */ + + for (edxxtmp = vexxtab[vexxidx].edxxidx; edxxtmp != -1; edxxtmp = edxxtab[edxxtmp].edxxidx) /* Unlink all vertex links from gain arrays */ + kgraphMapFmTablDel (tablptr, &edxxtab[edxxtmp]); + edxxtmp = vexxtab[vexxidx].edxxidx; /* Lock vertex through its first link */ + + /* Switch information with corresponding extended edge + * No add or del of extended edges needed. */ + parttax[vertnum] = domnend; /* Change vertex part */ + + comploaddlt[domnnum] -= veloval; /* Account for move */ + comploaddlt[domnend] += veloval; + + vexxtab[vexxidx].domnnum = domnend; /* Swap edges */ + edxxptr->domnnum = domnnum; + vexxtab[vexxidx].edlosum = edxxptr->edlosum; + edxxptr->edlosum = edlosum; + vexxtab[vexxidx].edgenbr = edxxptr->edgenbr; + edxxptr->edgenbr = edgenbr; + vexxtab[vexxidx].cmigload += edxxptr->cmiggain; + + + edxpptr = &vexxtab[vexxidx].edxxidx; + for (edxxidx = vexxtab[vexxidx].edxxidx; edxxidx != -1; edxpptr = &edxxtab[edxxidx].edxxidx, edxxidx = edxxtab[edxxidx].edxxidx) { /* Update vertex links */ + Gnum domncur; + + domncur = edxxtab[edxxidx].domnnum; + if (domncur == domnnum) { + vpexptr = edxpptr; + continue; + } + edxxtab[edxxidx].commgain -= edxxptr->commgain; + edxxtab[edxxidx].cmiggain -= edxxptr->cmiggain; + edxxtab[edxxidx].distval = archDomDist (&grafptr->a, &grafptr->m.domntab[domnend], &grafptr->m.domntab[domncur]); + } + edxxptr->commgain = - edxxptr->commgain; + edxxptr->cmiggain = - edxxptr->cmiggain; + + vexdflg = 0; + if (edgenbr == 0) { + Gnum edxxidx; + + edxxidx = *vpexptr; + savetab[savenbr].type = KGRAPHMAPPFMSAVELINKDEL; /* Save it */ + savetab[savenbr].u.linkdat.edxxidx = edxxidx; + savetab[savenbr].u.linkdat.vexxidx = vexxidx; + savenbr ++; /* One more data recorded */ + *vpexptr = edxxtab[edxxidx].edxxidx; /* Remove it from extended vertex list */ + edxxtab[edxxidx].edxxidx = -2; /* Set extended edge slot as unused */ + edxunbr ++; /* One more unused edge slot */ + } + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { /* (Re-)link neighbors */ + /* - Add the vertex in vexxtab if not yet inserted + * - Del the edge to the vertnum old domain if it was the only vertex + * linked to this domain. + * - Add and edge to the vertnum new domain if it was the first vertex + * linked to this domain. + * - Update commgain of other edges. + * - Relink extended edges + */ + Gnum edxxend; + Gnum vexxend; + Gnum edxoidx; /* Index of extended edge to old domain */ + Gnum * edxcptr; /* Pointer to index of current extended edge */ + Gnum * edxoptr; /* Pointer to index of extended edge to old domain */ + Gnum edxnidx; /* index of extended edge to new domain */ + Gnum vertend; /* Number of current end neighbor vertex */ + Gnum edxfidx; /* Index of first extended edge to update */ + Gnum edgeend; + Gnum edodnbr; + Gnum edndnbr; + Anum divoval; /* Distance between current neighbor domain and old domain */ + Anum divnval; /* Distance between current neighbor domain and new domain */ + Gnum edloval; + + vertend = edgetax[edgenum]; + edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; + + if (parttax[edgetax[edgenum]] == domnnum) + vexdflg = 1; + + if ((pfixtax != NULL) && (pfixtax[vertend] != -1)) /* Do not link fixed vertices */ + continue; + + if (savenbr >= (savesiz - (grafptr->m.domnnbr + 4) * 4)) { + KgraphMapFmSave * saveptr; /* Pointer to move array */ + + while (savenbr >= (savesiz - (grafptr->m.domnnbr + 4) * 4)) + savesiz += savesiz / 2; + + if ((saveptr = memRealloc (savetab, savesiz * sizeof (KgraphMapFmSave))) == NULL) { + errorPrint ("kgraphMapFm: out of memory (6)"); + memFree (savetab); /* Free group leader */ + return (1); + } + savetab = saveptr; + } + if (hashnbr >= hashmax) { /* If extended vertex table is already full */ + if (kgraphMapFmResize (&vexxtab, &hashmax, &hashmsk, savetab, savenbr, tablptr, edxxtab, &lockptr) != 0) { + errorPrint ("kgraphMapFm: out of memory (7)"); + memFree (vexxtab); /* Free group leader */ + kgraphMapFmTablExit (tablptr); + return (1); + } + } + for (vexxend = (vertend * KGRAPHMAPFMHASHPRIME) & hashmsk; /* Search for vertex or first free slot */ + (vexxtab[vexxend].vertnum != vertend) && (vexxtab[vexxend].vertnum != ~0); vexxend = (vexxend + 1) & hashmsk) ; + + if (vexxtab[vexxend].vertnum == ~0) { /* If neighbor vertex not yet inserted, create it */ + kgraphMapFmPartAdd (grafptr, vertend, vexxend, vexxtab, &edxxtab, &edxxsiz, &edxxnbr, tablptr); + hashnbr ++; /* One more vertex in hash table */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[vexxend].edxxidx == -1) { + errorPrint ("kgraphMapFm: internal error (9)"); + return (1); + } + if (edxxtab[vexxtab[vexxend].edxxidx].domnnum != domnend) { + errorPrint ("kgraphMapFm: internal error (10)"); + return (1); + } + if (edxxtab[vexxtab[vexxend].edxxidx].edxxidx != -1) { + errorPrint ("kgraphMapFm: internal error (11)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + vexxtab[vexxend].mswpnum = mswpnum; + savetab[savenbr].type = KGRAPHMAPPFMSAVEVEXX; /* Save extended vertex data */ + savetab[savenbr].u.vexxdat.vexxidx = vexxend; + savetab[savenbr].u.vexxdat.veloval = vexxtab[vexxend].veloval; + savetab[savenbr].u.vexxdat.domnnum = vexxtab[vexxend].domnnum; + savetab[savenbr].u.vexxdat.cmigload = vexxtab[vexxend].cmigload; + savetab[savenbr].u.vexxdat.edlosum = vexxtab[vexxend].edlosum + edloval; /* Save state before vertex move */ + savetab[savenbr].u.vexxdat.edgenbr = vexxtab[vexxend].edgenbr + 1; + savenbr ++; /* One more data saved */ + savetab[savenbr].type = KGRAPHMAPPFMSAVELINKADD; /* Save extended edge creation */ + savetab[savenbr].u.linkdat.edxxidx = vexxtab[vexxend].edxxidx; + savetab[savenbr].u.linkdat.vexxidx = vexxend; + savenbr ++; /* One more data recorded */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (savenbr > savesiz) { + errorPrint ("kgraphMapFm: save array error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + continue; + } + + if (vexxtab[vexxend].mswpnum != mswpnum) { /* If vertex data not yet recorded */ + vexxtab[vexxend].mswpnum = mswpnum; + savetab[savenbr].type = KGRAPHMAPPFMSAVEVEXX; /* Save extended vertex data */ + savetab[savenbr].u.vexxdat.vexxidx = vexxend; + savetab[savenbr].u.vexxdat.veloval = vexxtab[vexxend].veloval; + savetab[savenbr].u.vexxdat.domnnum = vexxtab[vexxend].domnnum; + savetab[savenbr].u.vexxdat.cmigload = vexxtab[vexxend].cmigload; + savetab[savenbr].u.vexxdat.edlosum = vexxtab[vexxend].edlosum; + savetab[savenbr].u.vexxdat.edgenbr = vexxtab[vexxend].edgenbr; + savenbr ++; /* One more data saved */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (savenbr > savesiz) { + errorPrint ("kgraphMapFm: save array error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + edxoidx = + edxnidx = -1; /* Assume there are no extended edges to domnnum or domnend */ + for (edxcptr = &vexxtab[vexxend].edxxidx, edxxidx = vexxtab[vexxend].edxxidx; edxxidx != -1; + edxcptr = &edxxtab[edxxidx].edxxidx, edxxidx = edxxtab[edxxidx].edxxidx) { /* Loop on domains */ + Gnum domncur; /* Save vertex links */ + + domncur = edxxtab[edxxidx].domnnum; + if (edxxtab[edxxidx].mswpnum != mswpnum) { /* If extended edge data not yet recorded */ + edxxtab[edxxidx].mswpnum = mswpnum; + savetab[savenbr].type = KGRAPHMAPPFMSAVEEDXX; /* Save extended edge data */ + savetab[savenbr].u.edxxdat.edxxidx = edxxidx; + savetab[savenbr].u.edxxdat.domnnum = domncur; + savetab[savenbr].u.edxxdat.commgain = edxxtab[edxxidx].commgain; + savetab[savenbr].u.edxxdat.cmiggain = edxxtab[edxxidx].cmiggain; + savetab[savenbr].u.edxxdat.edlosum = edxxtab[edxxidx].edlosum; + savetab[savenbr].u.edxxdat.edgenbr = edxxtab[edxxidx].edgenbr; + savetab[savenbr].u.edxxdat.distval = edxxtab[edxxidx].distval; + savenbr ++; /* One more data recorded */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (savenbr > savesiz) { + errorPrint ("kgraphMapFm: save array error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + if (domncur == domnnum) { + edxoidx = edxxidx; + edxoptr = edxcptr; + edxxtab[edxxidx].edlosum -= edloval; + edxxtab[edxxidx].edgenbr --; + divoval = edxxtab[edxxidx].distval; + } + else if (domncur == domnend) { + edxnidx = edxxidx; + edxxtab[edxxidx].edlosum += edloval; + edxxtab[edxxidx].edgenbr ++; + divnval = edxxtab[edxxidx].distval; + } + } +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((edxoidx == -1) && (vexxtab[vexxend].domnnum != domnnum)) { + errorPrint ("kgraphMapFm: internal error (12)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + if (vexxtab[vexxend].domnnum == domnend) { + vexxtab[vexxend].edlosum += edloval; + vexxtab[vexxend].edgenbr ++; + divnval = 0; + } + + if (vexxtab[vexxend].domnnum == domnnum) { /* Remove edge from neighbor domain */ + vexxtab[vexxend].edlosum -= edloval; + vexxtab[vexxend].edgenbr --; + divoval = 0; + } + else { + if (edxxtab[edxoidx].edgenbr == 0) { /* If it was the last edge in the end domain, save it */ + savetab[savenbr].type = KGRAPHMAPPFMSAVELINKDEL; + savetab[savenbr].u.linkdat.edxxidx = edxoidx; + savetab[savenbr].u.linkdat.vexxidx = vexxend; + savenbr ++; /* One more data recorded */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (savenbr > savesiz) { + errorPrint ("kgraphMapFm: save array error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + *edxoptr = edxxtab[edxoidx].edxxidx; /* Remove it from extended vertex list */ + if (vexxtab[vexxend].lockptr == NULL) /* If edge is of use (vertex not locked) */ + kgraphMapFmTablDel (tablptr, &edxxtab[edxoidx]); /* Remove it */ + edxxtab[edxoidx].edxxidx = -2; /* Set extended edge slot as unused */ + edxunbr ++; /* One more unused edge slot */ + } + } + + if ((edxnidx == -1) && (vexxtab[vexxend].domnnum != domnend)) { /* If was first vertex linked to this domain, add edge to new domain */ + Gnum edxxidx; + + kgraphMapFmPartAdd2 (grafptr, vexxtab, vexxend, &edxxtab, &edxxsiz, &edxxnbr, vexxtab[vexxend].domnnum, domnend, edloval, tablptr); /* Add new extended edge */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + for (edxxidx = vexxtab[vexxend].edxxidx; (edxxidx != -1) && (edxxtab[edxxidx].domnnum != domnend); edxxidx = edxxtab[edxxidx].edxxidx) ; + if (edxxidx == -1) { + errorPrint ("kgraphMapFm: internal error (13)"); + return (1); + } + if (edxxidx != edxxnbr - 1) { + errorPrint ("kgraphMapFm: internal error (14)"); + return (1); + } + if (edxxtab[edxxidx].domnnum != domnend) { + errorPrint ("kgraphMapFm: internal error (15)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + savetab[savenbr].type = KGRAPHMAPPFMSAVELINKADD; /* Save extended edge creation */ + savetab[savenbr].u.linkdat.edxxidx = edxxnbr - 1; + savetab[savenbr].u.linkdat.vexxidx = vexxend; + savenbr ++; /* One more data recorded */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (savenbr > savesiz) { + errorPrint ("kgraphMapFm: save array error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + divnval = edxxtab[edxxnbr - 1].distval; + edxfidx = edxxtab[edxxnbr - 1].edxxidx; /* Skip update of the newly added extended edge */ + } + else + edxfidx = vexxtab[vexxend].edxxidx; + + edloval *= grafptr->r.crloval; + for (edxxend = edxfidx; edxxend != -1; edxxend = edxxtab[edxxend].edxxidx) /* Update vertex links */ + edxxtab[edxxend].commgain -= edloval * (divnval - archDomDist (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxend].domnnum], &grafptr->m.domntab[domnend]) + - divoval + archDomDist (&grafptr->a, &grafptr->m.domntab[edxxtab[edxxend].domnnum], &grafptr->m.domntab[domnnum])); + if (vexxtab[vexxend].lockptr == NULL) { /* If vertex is not locked */ + for (edxxend = edxfidx; edxxend != -1; edxxend = edxxtab[edxxend].edxxidx) { /* Relink its extended edges */ + kgraphMapFmTablDel (tablptr, &edxxtab[edxxend]); /* Remove it and re-link it */ + kgraphMapFmTablAdd (tablptr, &edxxtab[edxxend]); + } + } + } + if (flagval == 1) { /* If move improves balance and we do not respect it */ + commloadbst = commload; /* This move was effective */ + cmigloadbst = cmigload; + moveflag = 1; + movenbr = + savenbr = 0; + flagval = 0; + comploaddiff = 0; + mswpnum ++; + } + else if ((commload + cmigload) < (commloadbst + cmigloadbst)) { /* If move improves the cost */ + commloadbst = commload; /* This move was effective */ + cmigloadbst = cmigload; + moveflag = 1; + movenbr = + savenbr = 0; + flagval = 0; + comploaddiff = 0; + mswpnum ++; + } + else if (((commload + cmigload) == (commloadbst + cmigloadbst)) && (comploaddiff < 0)) { /* If move improves balance and cut does not decrease */ + commloadbst = commload; /* This move was effective */ + cmigloadbst = cmigload; + moveflag = 1; + movenbr = + savenbr = 0; + flagval = 0; + comploaddiff = 0; + mswpnum ++; + } + else if (((commload + cmigload) == (commloadbst + cmigloadbst)) && (comploaddiff == 0)) { + commloadbst = commload; /* Forget backtracking */ + cmigloadbst = cmigload; + movenbr = + savenbr = 0; + flagval = 0; + mswpnum ++; + } +#ifdef SCOTCH_DEBUG_KGRAPH3 + if (kgraphMapFmCheck (tablptr, grafptr, vexxtab, edxxtab, hashmsk, commload, chektab) != 0) { + errorPrint ("kgraphMapFm: internal error (16)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + } +#ifdef SCOTCH_DEBUG_KGRAPH3 + if (kgraphMapFmCheck (tablptr, grafptr, vexxtab, edxxtab, hashmsk, commload, chektab) != 0) { + errorPrint ("kgraphMapFm: internal error (17)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + } while ((moveflag != 0) && /* As long as vertices are moved */ + (-- passnbr != 0)); /* And we are allowed to loop (TRICK for negative values) */ + +#ifdef SCOTCH_DEBUG_KGRAPH3 + if (kgraphMapFmCheck (tablptr, grafptr, vexxtab, edxxtab, hashmsk, commload, chektab) != 0) { + errorPrint ("kgraphMapFm: internal error (18)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + + while (savenbr -- > 0) { /* Delete exceeding moves */ + Gnum vexxidx; + Anum domnnum; + Gnum veloval; + + if (savetab[savenbr].type == KGRAPHMAPPFMSAVEVEXX) { + vexxidx = savetab[savenbr].u.vexxdat.vexxidx; + domnnum = savetab[savenbr].u.vexxdat.domnnum; + veloval = savetab[savenbr].u.vexxdat.veloval; + + comploaddlt[vexxtab[vexxidx].domnnum] -= veloval; + comploaddlt[domnnum] += veloval; + vexxtab[vexxidx].domnnum = domnnum; /* Restore vertex data */ + parttax[vexxtab[vexxidx].vertnum] = domnnum; + } + } + + commload = 0; + for (vexxidx = fronnbr = 0; /* Build new frontier, compute commload, update parttax */ + vexxidx <= hashmsk; vexxidx ++) { /* hashsiz no longer valid after resizing, so use hashmsk */ + Gnum vertnum; + Gnum edgenum; + Anum domnnum; + Anum domnlst; /* Domain of last vertex for which a distance was computed */ + Anum distlst; /* Last distance computed */ + Gnum commcut; + + vertnum = vexxtab[vexxidx].vertnum; /* Get vertex data from slot */ + if (vertnum != ~0) { + commcut = 0; + domnnum = parttax[vertnum]; + domnlst = -1; /* Invalid domnain to recompute distance */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (vexxtab[vexxidx].domnnum != parttax[vertnum]) { + errorPrint ("kgraphMapFm: internal error (19)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + for (edgenum = verttax[vertnum]; + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Gnum domnend; + + vertend = edgetax[edgenum]; + domnend = parttax[vertend]; + if (domnend != domnnum) { + Anum distval; + Gnum edloval; + + distval = (domnend != domnlst) ? archDomDist (grafptr->m.archptr, &grafptr->m.domntab[domnnum], &grafptr->m.domntab[domnend]) : distlst; + distlst = distval; + domnlst = domnend; + edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; + + commload += (Gnum) distval * edloval; + commcut = 1; + } + } + if (commcut != 0) + grafptr->frontab[fronnbr ++] = vertnum; + } + } + + if (grafptr->pfixtax != NULL) { /* We have fixed vertices */ + Gnum vertnum; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + if ((grafptr->pfixtax != NULL) && (grafptr->pfixtax[vertnum] != -1)) { /* If vertex is fixed */ + Gnum edgenum; + Anum domnnum; + Gnum commcut; + Anum domnlst; /* Domain of last vertex for which a distance was computed */ + Anum distlst; /* Last distance computed */ + + commcut = 0; + domnnum = parttax[vertnum]; + domnlst = -1; /* Invalid domnain to recompute distance */ + for (edgenum = verttax[vertnum]; /* For all neighbors */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Gnum domnend; + + vertend = edgetax[edgenum]; + domnend = parttax[vertend]; + if (domnend != domnnum) { + Anum distval; + Gnum edloval; + + distval = (domnend != domnlst) ? archDomDist (grafptr->m.archptr, &grafptr->m.domntab[domnnum], &grafptr->m.domntab[domnend]) : distlst; + distlst = distval; + domnlst = domnend; + edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; + + commload += (Gnum) distval * edloval; + commcut = 1; + } + } + if (commcut != 0) + grafptr->frontab[fronnbr ++] = vertnum; + } + } + } + grafptr->fronnbr = fronnbr; + grafptr->commload = commload / 2; + + for (domnnum = 0; domnnum < grafptr->m.domnnbr; domnnum ++) /* Update graph information */ + grafptr->comploaddlt[domnnum] = comploaddlt[domnnum]; + +#ifdef SCOTCH_DEBUG_KGRAPH3 + memFree (chektab); /* Free group leader */ +#endif /* SCOTCH_DEBUG_KGRAPH3 */ + memFree (comploadmax); /* Free group leader */ + memFree (vexxtab); + memFree (savetab); + memFree (edxxtab); + kgraphMapFmTablExit (tablptr); + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (grafptr) != 0) { + errorPrint ("kgraphMapFm: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + return (0); +} + + diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_fm.h b/scotch_6.0.3/src/libscotch/kgraph_map_fm.h new file mode 100644 index 00000000..2dbbfba4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_fm.h @@ -0,0 +1,212 @@ +/* Copyright 2004,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_fm.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the k-way Fiduccia-Mattheyses **/ +/** mapping algorithm. **/ +/** **/ +/** DATES : # Version 3.3 : from : 10 may 1999 **/ +/** to 20 jun 1999 **/ +/** # Version 3.4 : from : 27 sep 1999 **/ +/** to 13 nov 1999 **/ +/** # Version 5.0 : from : 11 oct 2006 **/ +/** to 12 oct 2006 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 19 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Prime number for hashing vertex numbers. +*/ + +#define KGRAPHMAPFMHASHPRIME 17 /*+ Prime number for hashing +*/ + +/*+ Ratio of unused slots before compacting extended edge array. +*/ + +#define KGRAPHMAPFMEDXXCOMP 5 /*+ Compact if edxunbr > (edxxnbr / KGRAPHMAPFMEDXXCOMP) */ + +/*+ Save type identifier +*/ + +#define KGRAPHMAPPFMSAVEVEXX 0 +#define KGRAPHMAPPFMSAVEEDXX 1 +#define KGRAPHMAPPFMSAVELINK 2 /* Bit value for KGRAPHMAPPFMSAVELINKADD and KGRAPHMAPPFMSAVELINKDEL */ +#define KGRAPHMAPPFMSAVELINKDEL 2 +#define KGRAPHMAPPFMSAVELINKADD 3 + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct KgraphMapFmParam_ { + INT movenbr; /*+ Maximum number of uneffective moves that can be done +*/ + INT passnbr; /*+ Number of passes to be performed (-1 : infinite) +*/ + double deltval; /*+ Maximum weight imbalance ratio +*/ +} KgraphMapFmParam; + +/*+ The extended edge structure. In fact, this + structure does not represent edges, but + possible moves in another domain. + For trick reasons, the gain table data + structure must be the first field of the + structure. +*/ + +#ifdef SCOTCH_TABLE_GAIN + +typedef GainTabl * KgraphMapFmTabl; +typedef GainLink KgraphMapFmLink; + +#else /* SCOTCH_TABLE_GAIN */ + +typedef FiboTree KgraphMapFmTabl; +typedef FiboNode KgraphMapFmLink; + +#endif /* SCOTCH_TABLE_GAIN */ + +typedef struct KgraphMapFmEdge_ { + KgraphMapFmLink gainlink; /*+ Gain link; TRICK: FIRST +*/ + Gnum commgain; /*+ Communication gain +*/ + Gnum cmiggain; /*+ Migration communication gain +*/ + Gnum cmigmask; /*+ Migration communication mask +*/ + Gnum edlosum; /*+ Sum of edge loads linking to the domain +*/ + Gnum edgenbr; /*+ Number of edges linking to the domain +*/ + Anum domnnum; /*+ Destination domain index +*/ + Anum distval; /*+ Distance between the two domains +*/ + Gnum vexxidx; /*+ Index of owner vertex in vertex array +*/ + Gnum edxxidx; /*+ Index of next edge in edge array +*/ + Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ +} KgraphMapFmEdge; + +/*+ The hash vertex structure. +*/ + +typedef struct KgraphMapFmVertex_ { + struct KgraphMapFmVertex_ * lockptr; /*+ Pointer to next vertex in lock list or NULL; FIRST +*/ + Gnum vertnum; /*+ Number of vertex +*/ + Gnum cmigload; /*+ Migration communication load +*/ + Gnum edlosum; /*+ Sum of edge loads linking to self domain +*/ + Gnum edgenbr; /*+ Number of edges linking to self domain +*/ + Anum domnnum; /*+ Domain number +*/ + ArchDom * domoptr; /*+ Domain in old mapping (for repartitioning) +*/ + Gnum veloval; /*+ Vertex load; negative when locked +*/ + Gnum edxxidx; /*+ Index of first element in edge array +*/ + Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ +} KgraphMapFmVertex; + +/*+ The move recording structures. +*/ + +typedef struct KgraphMapFmSave_ { + Gnum type; + union { + struct { + Gnum vexxidx; /*+ Index of vertex slot in hash table (vexxhab) +*/ + Gnum veloval; /*+ Vertex load +*/ + Anum domnnum; /*+ Original vertex domain +*/ + Gnum commload; /*+ Communication load for current domain +*/ + Gnum cmigload; /*+ Migration communication load +*/ + Gnum edlosum; /*+ Sum of edge loads linking to self domain +*/ + Gnum edgenbr; /*+ Number of edges linking to self domain +*/ + } vexxdat; + struct { + Gnum edxxidx; /*+ Index of edge in edge array +*/ + Anum domnnum; /*+ Destination domain index +*/ + Anum distval; /*+ Distance between the two domains +*/ + Gnum commgain; /*+ Communication gain +*/ + Gnum cmiggain; /*+ Migration communication gain +*/ + Gnum edlosum; /*+ Sum of edge loads linking to the domain +*/ + Gnum edgenbr; /*+ Number of edges linking to the domain +*/ + } edxxdat; + struct { + Gnum edxxidx; /*+ Index of extended vertex or edge +*/ + Gnum vexxidx; /*+ Index of vertex slot in hash table (vexxhab) +*/ + } linkdat; + } u; +} KgraphMapFmSave; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_FM +#define static +#endif + +int kgraphMapFm (Kgraph * restrict const, const KgraphMapFmParam * const); + +#undef static + +/* +** The macro definitions. +*/ + +#ifdef SCOTCH_TABLE_GAIN + +/*+ Gain table subbits. +*/ + +#define KGRAPHMAPFMSUBBITS 4 + +/*+ Service routines. +*/ + +#define kgraphMapFmTablInit(t) (((*(t)) = gainTablInit (GAINMAX, KGRAPHMAPFMSUBBITS)) == NULL) +#define kgraphMapFmTablFree(t) gainTablFree (*(t)) +#define kgraphMapFmTablExit(t) do { \ + if (*(t) != NULL) \ + gainTablExit (*(t)); \ + } while (0) +#define kgraphMapFmTablAdd(t,e) gainTablAdd ((*(t)), &(e)->gainlink, ((e)->commgain + (((e)->cmiggain) & ((e)->cmigmask))) * (e)->distval) +#define kgraphMapFmTablDel(t,e) gainTablDel ((*(t)), &(e)->gainlink) +#else /* SCOTCH_TABLE_GAIN */ + +/*+ Service routines. +*/ + +#define kgraphMapFmTablInit(t) (fiboTreeInit ((t), kgraphMapFmCmpFunc)) +#define kgraphMapFmTablFree(t) fiboTreeFree (t) +#define kgraphMapFmTablExit(t) fiboTreeExit (t) +#define kgraphMapFmTablAdd(t,e) fiboTreeAdd ((t), &(e)->gainlink) +#define kgraphMapFmTablDel(t,e) fiboTreeDel ((t), &(e)->gainlink) + +#endif /* SCOTCH_TABLE_GAIN */ + +#define kgraphMapFmLock(l,v) do { \ + (v)->lockptr = (KgraphMapFmVertex *) (l); \ + (l) = (v); \ + } while (0) +#define kgraphMapFmLockNext(v) ((KgraphMapFmVertex *) (v)->lockptr) diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_ml.c b/scotch_6.0.3/src/libscotch/kgraph_map_ml.c new file mode 100644 index 00000000..56e1e445 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_ml.c @@ -0,0 +1,430 @@ +/* Copyright 2010,2011,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_ml.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module maps an active graph **/ +/** to a specific architecture graph **/ +/** using a multi-level scheme. **/ +/** **/ +/** DATES : # Version 5.1 : from : 13 jul 2010 **/ +/** to 14 jul 2010 **/ +/** DATES : # Version 6.0 : from : 03 mar 2011 **/ +/** to 18 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_ML + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "graph_coarsen.h" +#include "kgraph.h" +#include "kgraph_map_ml.h" +#include "kgraph_map_st.h" + +/*********************************************/ +/* */ +/* The coarsening and uncoarsening routines. */ +/* */ +/*********************************************/ + +/* This routine builds a coarser graph from the +** graph that is given on input. The coarser +** graphs differ at this stage from classical +** active graphs as their internal gains are not +** yet computed. +** It returns: +** - 0 : if the coarse graph has been built. +** - 1 : if threshold reached or on error. +*/ + +static +int +kgraphMapMlCoarsen ( +Kgraph * restrict const finegrafptr, /*+ Finer graph +*/ +Kgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ +GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ +const KgraphMapMlParam * const paraptr) /*+ Method parameters +*/ +{ + GraphCoarsenMulti * restrict coarmulttab; + Gnum coarvertnum; /* Number of current multinode vertex */ + Gnum coarflagval; + + const Anum * restrict const finepfixtax = finegrafptr->pfixtax; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((finegrafptr->comploadavg == NULL) || (finegrafptr->comploaddlt == NULL)) { + errorPrint ("kgraphMapMlCoarsen: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + if (graphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, paraptr->coarnbr, paraptr->coarval, finegrafptr->r.m.parttax, finegrafptr->pfixtax, finegrafptr->vfixnbr, &coargrafptr->vfixnbr) != 0) + return (1); /* Return if coarsening failed */ + + finegrafptr->s.flagval &= ~KGRAPHFREECOMP; /* Now it's the coarse graph job to handle the load array */ + coargrafptr->s.flagval = (coargrafptr->s.flagval & ~KGRAPHFREEFRON) | KGRAPHFREECOMP; /* Share frontier array */ + coargrafptr->comploadavg = finegrafptr->comploadavg; /* By default, use fine target load arrays as coarse load arrays */ + coargrafptr->comploaddlt = finegrafptr->comploaddlt; + coargrafptr->frontab = finegrafptr->frontab; /* Share frontier array of finer graph as coarse frontier array */ + coargrafptr->a = finegrafptr->a; + coargrafptr->m.parttax = NULL; /* Do not allocate partition data yet */ + coargrafptr->m.domntab = finegrafptr->m.domntab; /* Get domain private array if any */ + coargrafptr->m.archptr = &coargrafptr->a; + coargrafptr->m.grafptr = &coargrafptr->s; + coargrafptr->m.flagval = finegrafptr->m.flagval & MAPPINGFREEDOMN; /* Get fine private domain array, if any */ + finegrafptr->m.flagval &= ~MAPPINGFREEDOMN; /* Now it's the coarse graph job to handle the domain array, if any */ + coargrafptr->m.domnorg = finegrafptr->m.domnorg; + coargrafptr->m.domnnbr = 0; /* Number of domains not known yet */ + coargrafptr->m.domnmax = finegrafptr->m.domnmax; /* Propagate relevant estimation */ + + coarmulttab = *coarmultptr; + + if (finegrafptr->r.m.parttax != NULL) { + const Gnum * restrict fineparotax; + const Gnum * restrict finevmlotax; + Gnum * coarparotab; + Gnum * coarvmlotab; + Gnum coarvertnbr; + + coarvertnbr = coargrafptr->s.vertnbr; + if ((coarparotab = (Anum *) memAlloc (coarvertnbr * sizeof (Anum))) == NULL) { + errorPrint ("kgraphMapMlCoarsen: out of memory (1)"); + return (1); + } + + if ((coarvmlotab = (Gnum *) memAlloc (coarvertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("kgraphMapMlCoarsen: out of memory (2)"); + memFree (coarparotab); + return (1); + } + + fineparotax = finegrafptr->r.m.parttax; + finevmlotax = finegrafptr->r.vmlotax; + for (coarvertnum = 0; coarvertnum < coarvertnbr; coarvertnum ++) { + Gnum finevertnum0; + Gnum finevertnum1; + + finevertnum0 = coarmulttab[coarvertnum].vertnum[0]; + finevertnum1 = coarmulttab[coarvertnum].vertnum[1]; + coarparotab[coarvertnum] = fineparotax[finevertnum0]; + coarvmlotab[coarvertnum] = (finevmlotax != NULL) + ? ((finevertnum0 == finevertnum1) ? 0 : finevmlotax[finevertnum1]) + finevmlotax[finevertnum0] + : ((finevertnum0 == finevertnum1) ? 1 : 2); +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((fineparotax[finevertnum1] != fineparotax[finevertnum0]) && /* If vertices were not in the same part */ + ((finegrafptr->pfixtax == NULL) || + ((finepfixtax[finevertnum1] == -1) && /* And both are not fixed */ + (finepfixtax[finevertnum0] == -1)))) { + errorPrint ("kgraphMapMlCoarsen: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + + coargrafptr->r.m.flagval = MAPPINGFREEPART; + coargrafptr->r.m.grafptr = &coargrafptr->s; + coargrafptr->r.m.archptr = finegrafptr->r.m.archptr; + coargrafptr->r.m.parttax = coarparotab - coargrafptr->s.baseval; /* Set coarse arrays */ + coargrafptr->r.m.domntab = finegrafptr->r.m.domntab; /* Clone old domain array */ + coargrafptr->r.m.domnnbr = finegrafptr->r.m.domnnbr; + coargrafptr->r.m.domnmax = finegrafptr->r.m.domnmax; + coargrafptr->r.vmlotax = coarvmlotab - coargrafptr->s.baseval; + coargrafptr->s.flagval |= KGRAPHFREEVMLO; + } + else { /* No old mapping */ + coargrafptr->r.m.flagval = MAPPINGNONE; + coargrafptr->r.m.parttax = NULL; + coargrafptr->r.vmlotax = NULL; + } + + if (finepfixtax != NULL) { /* If we have fixed vertices */ + Gnum coarvertnbr; + Anum * restrict coarpfixtab; + Gnum coarvfixnbr; + + coarvertnbr = coargrafptr->s.vertnbr; + if ((coarpfixtab = (Anum *) memAlloc (coarvertnbr * sizeof (Anum))) == NULL) { + errorPrint ("kgraphMapMlCoarsen: out of memory (3)"); + return (1); + } + + coarvfixnbr = coarvertnbr; /* Assume all vertices are fixed */ + for (coarvertnum = 0; coarvertnum < coarvertnbr; coarvertnum ++) { + Anum coarpfixval; + + coarpfixval = finepfixtax[coarmulttab[coarvertnum].vertnum[0]]; + coarvfixnbr += coarpfixval >> (sizeof (Anum) * 8 - 1); /* Accumulate -1's, that is, non-fixed vertices */ + + coarpfixtab[coarvertnum] = coarpfixval; +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (finepfixtax[coarmulttab[coarvertnum].vertnum[1]] != coarpfixval) { + errorPrint ("kgraphMapMlCoarsen: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + + coargrafptr->s.flagval |= KGRAPHFREEPFIX; + coargrafptr->pfixtax = coarpfixtab - coargrafptr->s.baseval; + coargrafptr->vfixnbr = coarvfixnbr; + } + else { + coargrafptr->pfixtax = NULL; + coargrafptr->vfixnbr = 0; + } + + coargrafptr->comploadrat = finegrafptr->comploadrat; + coargrafptr->r.cmloval = finegrafptr->r.cmloval; + coargrafptr->r.crloval = finegrafptr->r.crloval; + coargrafptr->kbalval = finegrafptr->kbalval; + coargrafptr->levlnum = finegrafptr->levlnum + 1; + + return (0); +} + +/* This routine propagates the partitioning of the +** coarser graph back to the finer graph, according +** to the multinode table of collapsed vertices. +** After the partitioning is propagated, it finishes +** to compute the parameters of the finer graph that +** were not computed at the coarsening stage. +** It returns: +** - 0 : if coarse graph data has been propagated to fine graph. +** - !0 : on error. +*/ + +static +int +kgraphMapMlUncoarsen ( +Kgraph * restrict const finegrafptr, /*+ Finer graph +*/ +Kgraph * restrict const coargrafptr, /*+ Coarser graph +*/ +const GraphCoarsenMulti * const coarmulttax) /*+ Pointer to multinode array +*/ +{ + const Anum * restrict coarparttax; /* Only known when coagrafptr is not NULL */ + Gnum coarvertnum; + Gnum * restrict coarfrontab; /* Coarse and fine frontiers arrays are merged */ + Gnum coarfronnum; + Gnum finefronnum; + Anum * restrict fineparttax; /* May not have been allocated yet */ + + const Gnum * restrict const fineverttax = finegrafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const finevendtax = finegrafptr->s.vendtax; + const Gnum * restrict const fineedgetax = finegrafptr->s.edgetax; + + if (coargrafptr == NULL) { /* If no coarse graph provided */ + if (mapAlloc (&finegrafptr->m) != 0) { /* Allocate partition array if needed */ + errorPrint ("kdgraphMapMlUncoarsen: cannot allocate mapping (1)"); + return (1); + } + kgraphFrst (finegrafptr); /* Assign all vertices to first subdomain */ + return (0); + } + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (((finegrafptr->m.flagval & MAPPINGFREEDOMN) != 0) && /* Fine graph should not have a private domain array because of coarsening */ + (finegrafptr->m.domntab != NULL)) { + errorPrint ("kdgraphMapMlUncoarsen: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + finegrafptr->m.domnnbr = coargrafptr->m.domnnbr; /* Propagate coarse domain array */ + finegrafptr->m.domnmax = coargrafptr->m.domnmax; + finegrafptr->m.domntab = coargrafptr->m.domntab; + finegrafptr->m.flagval |= MAPPINGFREEDOMN; + coargrafptr->m.domntab = NULL; /* No need to free coarse graph domain array as it has been transferred */ + if (mapAlloc (&finegrafptr->m) != 0) { /* Allocate partition array if needed */ + errorPrint ("kdgraphMapMlUncoarsen: cannot allocate mapping (2)"); + return (1); + } + + finegrafptr->s.flagval |= KGRAPHFREECOMP; + finegrafptr->comploadavg = coargrafptr->comploadavg; /* Propagate part load data in case it was changed at the coarser levels */ + finegrafptr->comploaddlt = coargrafptr->comploaddlt; + coargrafptr->comploadavg = NULL; /* No need to free coarse graph load array as it has been transferred */ + + fineparttax = finegrafptr->m.parttax; /* Fine part array is now allocated */ + coarparttax = coargrafptr->m.parttax; + coarfrontab = coargrafptr->frontab; + for (coarvertnum = coargrafptr->s.baseval; coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { + Gnum finevertnum0; /* First multinode vertex */ + Gnum finevertnum1; /* Second multinode vertex */ + Anum partval; + + finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; + finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; + partval = coarparttax[coarvertnum]; + + fineparttax[finevertnum0] = partval; + if (finevertnum0 != finevertnum1) + fineparttax[finevertnum1] = partval; + } + + finegrafptr->commload = coargrafptr->commload; + + for (coarfronnum = 0, finefronnum = coargrafptr->fronnbr; /* Re-cycle frontier array from coarse to fine graph */ + coarfronnum < coargrafptr->fronnbr; coarfronnum ++) { + Gnum coarvertnum; + Gnum finevertnum0; /* First multinode vertex */ + Gnum finevertnum1; /* Second multinode vertex */ + + coarvertnum = coarfrontab[coarfronnum]; + finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; + finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; + + if (finevertnum0 != finevertnum1) { /* If multinode si made of two distinct vertices */ + Gnum fineedgenum; + Gnum partval; + + partval = coarparttax[coarvertnum]; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + coarfrontab[coarfronnum] = ~0; +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + for (fineedgenum = fineverttax[finevertnum0]; + fineedgenum < finevendtax[finevertnum0]; fineedgenum ++) { + if (fineparttax[fineedgetax[fineedgenum]] != partval) { /* If first vertex belongs to frontier */ + coarfrontab[coarfronnum] = finevertnum0; /* Record it in lieu of the coarse frontier vertex */ + break; + } + } + if (fineedgenum >= finegrafptr->s.vendtax[finevertnum0]) { /* If first vertex not in frontier */ + coarfrontab[coarfronnum] = finevertnum1; /* Then second vertex must be in frontier */ + continue; /* Skip to next multinode */ + } + + for (fineedgenum = fineverttax[finevertnum1]; /* Check if second vertex also belongs to frontier */ + fineedgenum < finevendtax[finevertnum1]; fineedgenum ++) { + if (fineparttax[fineedgetax[fineedgenum]] != partval) { /* If second vertex belongs to frontier */ + coarfrontab[finefronnum ++] = finevertnum1; /* Record it at the end of the recycled frontier array */ + break; + } + } + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (coarfrontab[coarfronnum] == ~0) { + errorPrint ("kgraphMapMlUncoarsen: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + else /* If coarse vertex is single node */ + coarfrontab[coarfronnum] = finevertnum0; /* Then it belongs to the frontier */ + } + finegrafptr->fronnbr = finefronnum; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (finegrafptr) != 0) { + errorPrint ("kgraphMapMlUncoarsen: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + return (0); +} + +/* This routine performs the +** partitioning recursion. +** It returns: +** - 0 : if partitioning could be computed. +** - 1 : on error. +*/ + +static +int +kgraphMapMl2 ( +Kgraph * restrict const grafptr, /*+ Active graph +*/ +const KgraphMapMlParam * const paraptr) /*+ Method parameters +*/ +{ + Kgraph coargrafdat; + GraphCoarsenMulti * coarmultptr; + int o; + + if (kgraphMapMlCoarsen (grafptr, &coargrafdat, &coarmultptr, paraptr) == 0) { + if (((o = kgraphMapMl2 (&coargrafdat, paraptr)) == 0) && + ((o = kgraphMapMlUncoarsen (grafptr, &coargrafdat, coarmultptr)) == 0) && + ((o = kgraphMapSt (grafptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ + errorPrint ("kgraphMapMl2: cannot apply ascending strategy"); + kgraphExit (&coargrafdat); + } + else { /* Cannot coarsen due to lack of memory or error */ + if (((o = kgraphMapMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ + ((o = kgraphMapSt (grafptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ + errorPrint ("kgraphMapMl2: cannot apply low strategy"); + } + + return (o); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the multi-level mapping. +** It returns: +** - 0 : if mapping could be computed. +** - 1 : on error. +*/ + +int +kgraphMapMl ( +Kgraph * const grafptr, /*+ Active graph +*/ +const KgraphMapMlParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum levlnum; /* Save value for graph level */ + int o; + + levlnum = grafptr->levlnum; /* Save graph level */ + grafptr->levlnum = 0; /* Initialize coarsening level */ + o = kgraphMapMl2 (grafptr, paraptr); /* Perform multi-level mapping */ + grafptr->levlnum = levlnum; /* Restore graph level */ + + return (o); +} + diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_ml.h b/scotch_6.0.3/src/libscotch/kgraph_map_ml.h new file mode 100644 index 00000000..3f901c29 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_ml.h @@ -0,0 +1,78 @@ +/* Copyright 2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_ml.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the multi-level graph mapping **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 10 jul 2010 **/ +/** to 10 jul 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 01 jun 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct KgraphMapMlParam_ { + INT coarnbr; /*+ Minimum number of vertices +*/ + double coarval; /*+ Coarsening ratio +*/ + Strat * stratlow; /*+ Strategy at lowest level +*/ + Strat * stratasc; /*+ Strategy at ascending levels +*/ + int typeval; /*+ Not used +*/ +} KgraphMapMlParam; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_ML +#define static +#endif + +static int kgraphMapMlCoarsen (Kgraph * const, Kgraph * restrict const, GraphCoarsenMulti * restrict * const, const KgraphMapMlParam * const); +static int kgraphMapMlUncoarsen (Kgraph * restrict const, Kgraph * const, const GraphCoarsenMulti * const); + +int kgraphMapMl (Kgraph * restrict const, const KgraphMapMlParam * const); +static int kgraphMapMl2 (Kgraph * restrict const, const KgraphMapMlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_rb.c b/scotch_6.0.3/src/libscotch/kgraph_map_rb.c new file mode 100644 index 00000000..61764019 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_rb.c @@ -0,0 +1,739 @@ +/* Copyright 2004,2007,2008,2011,2013,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_rb.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module performs the Dual Recursive **/ +/** Bipartitioning mapping algorithm. **/ +/** It is now a branching routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 31 mar 1993 **/ +/** to 31 mar 1993 **/ +/** # Version 1.0 : from : 04 oct 1993 **/ +/** to 06 oct 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.3 : from : 09 apr 1994 **/ +/** to 11 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 17 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 18 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 19 oct 1995 **/ +/** # Version 3.1 : from : 30 oct 1995 **/ +/** to 14 jun 1996 **/ +/** # Version 3.2 : from : 23 aug 1996 **/ +/** to 07 sep 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 08 dec 1998 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 07 nov 2001 **/ +/** # Version 4.0 : from : 12 jan 2004 **/ +/** to 06 mar 2005 **/ +/** # Version 5.1 : from : 22 nov 2007 **/ +/** to 07 oct 2008 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 28 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_RB + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "arch_dist.h" +#include "mapping.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "kgraph.h" +#include "kgraph_map_rb.h" +#include "kgraph_map_rb_map.h" +#include "kgraph_map_rb_part.h" + +/********************************************/ +/* */ +/* This is the entry point for the Dual */ +/* Recursive Bipartitioning mapping method. */ +/* */ +/********************************************/ + +/* This routine runs the Dual Recursive +** Bipartitioning algorithm. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kgraphMapRb ( +Kgraph * const grafptr, +const KgraphMapRbParam * restrict const paraptr) +{ + KgraphMapRbData datadat; /* Data passed to each bipartitioning job */ + Graph indgrafdat; /* Induced graph without fixed vertices */ + Graph * restrict indgrafptr; /* Pointer to top-level graph without fixed vertices */ + KgraphMapRbVflo * restrict vflotab; /* Array of fixed vertex load slots */ + Anum vflonbr; /* Number of fixed vertex load slots */ + Gnum vertnum; + int o; + + Gnum * const frontab = grafptr->frontab; + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + + grafptr->kbalval = paraptr->kbalval; /* Store last k-way imbalance ratio */ + + datadat.grafptr = &grafptr->s; + datadat.mappptr = &grafptr->m; + + datadat.r.mappptr = (grafptr->r.m.parttax != NULL) ? &grafptr->r.m : NULL; + datadat.r.vmlotax = grafptr->r.vmlotax; + datadat.r.cmloval = grafptr->r.cmloval; + datadat.r.crloval = grafptr->r.crloval; + datadat.pfixtax = grafptr->pfixtax; + datadat.paraptr = paraptr; + datadat.comploadrat = grafptr->comploadrat; + datadat.comploadmin = (1.0 - paraptr->kbalval) * grafptr->comploadrat; /* Ratio can have been tilted when working on subgraph */ + datadat.comploadmax = (1.0 + paraptr->kbalval) * grafptr->comploadrat; + + if (grafptr->pfixtax == NULL) { + indgrafptr = &grafptr->s; /* Work on the original graph */ + vflonbr = 0; /* No fixed vertex load slots */ + vflotab = NULL; + } + else { + if (kgraphMapRbVfloBuild (grafptr->m.archptr, &grafptr->s, grafptr->vfixnbr, grafptr->pfixtax, + &indgrafdat, &vflonbr, &vflotab) != 0) { + errorPrint ("kgraphMapRb: cannot create induced graph"); + return (1); + } + indgrafptr = &indgrafdat; + } + + o = ((archPart (grafptr->m.archptr) != 0) ? kgraphMapRbPart : kgraphMapRbMap) (&datadat, indgrafptr, vflonbr, vflotab); /* Compute recursive bipartitioning */ + + if (grafptr->pfixtax != NULL) { /* If fixed vertices */ + memFree (vflotab); /* Not used any longer */ + + graphExit (&indgrafdat); + if (kgraphMapRbVfloMerge (&grafptr->m, grafptr->vfixnbr, grafptr->pfixtax, vflonbr) != 0) { + errorPrint ("kgraphMapRb: cannot merge fixed vertex domains"); + return (1); + } + } + + if (memReallocGroup (grafptr->comploadavg, /* Reallocate cost array according to potential new size */ + &grafptr->comploadavg, (size_t) (grafptr->m.domnmax * sizeof (Gnum)), /* TRICK: can send both compload arrays in one piece */ + &grafptr->comploaddlt, (size_t) (grafptr->m.domnmax * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("kgraphMapRb: out of memory (3)"); + return (1); + } + kgraphFron (grafptr); + kgraphCost (grafptr); /* Compute cost of full k-way partition */ + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (grafptr) != 0) { + errorPrint ("kgraphMapRb: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + return (o); +} + +/*******************************************/ +/* */ +/* These routines handle fixed vertex load */ +/* arrays and fixed vertices. */ +/* */ +/*******************************************/ + +/* If the given graph has fixed vertices, this +** routine builds simultaneously an induced subgraph +** from which such vertices have been removed, and +** a list of these fixed vertices. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kgraphMapRbVfloBuild ( +const Arch * restrict const archptr, /*+ Target architecture +*/ +const Graph * restrict const orggrafptr, /*+ Original graph with fixed vertices +*/ +const Gnum orgvfixnbr, /*+ Number of fixed vertices in graph +*/ +const Anum * restrict const orgpfixtax, /*+ Array of fixed vertex terminal domains +*/ +Graph * restrict const indgrafptr, /*+ Induced subgraph without fixed vertices +*/ +Anum * restrict const vflonbrptr, /*+ Pointer to number of fixed vertex slots +*/ +KgraphMapRbVflo * restrict * restrict const vflotabptr) /*+ Pointer to fixed vertex load array pointer +*/ +{ + ArchDom domndat; + Gnum orgvertnum; + GraphPart * restrict orgparttax; /* Part array for induced graph */ + KgraphMapRbVflo * restrict hashtab; /* Hash table for merging fixed vertices */ + Gnum hashnbr; /* Prospective number of cells in table */ + Gnum hashsiz; /* Size of hash table */ + Gnum hashnum; + Gnum hashmsk; /* Mask for access to hash table */ + Gnum velomsk; /* Zero if all fixed vertex loads are zero */ + Anum vflonbr; + + const Gnum * restrict const orgvelotax = orggrafptr->velotax; + + if (archVar (archptr) == 0) { /* If fixed size architecture */ + archDomFrst (archptr, &domndat); + hashnbr = archDomSize (archptr, &domndat); /* Get maximum size of distinct terminal domains */ + if (orgvfixnbr < hashnbr) + hashnbr = orgvfixnbr; + } + else + hashnbr = orgvfixnbr; + for (hashsiz = 0, hashmsk = hashnbr; hashmsk != 0; hashsiz ++, hashmsk >>= 1) ; /* Get upper power of two */ + hashsiz = 1 << (hashsiz + 2); /* Fill hash table at 25% maximum */ + hashmsk = hashsiz - 1; + + if (memAllocGroup ((void **) (void *) + &hashtab, (size_t) (hashsiz * sizeof (KgraphMapRbVflo)), /* Use fixed vertex load slots as hash slots */ + &orgparttax, (size_t) (orggrafptr->vertnbr * sizeof (GraphPart)), NULL) == NULL) { + errorPrint ("kgraphMapRbVfloBuild: out of memory"); + return (1); + } + orgparttax -= orggrafptr->baseval; + + memSet (hashtab, ~0, hashsiz * sizeof (KgraphMapRbVflo)); /* Set all vertex numbers to ~0 */ + + velomsk = 0; /* Assume all fixed vertex loads are zero */ + for (orgvertnum = orggrafptr->baseval; orgvertnum < orggrafptr->vertnnd; orgvertnum ++) { + Anum orgpfixval; + + orgpfixval = orgpfixtax[orgvertnum]; + if (orgpfixval >= 0) { /* If vertex is a fixed vertex */ + Gnum hashnum; + Gnum veloval; + + veloval = (orgvelotax == NULL) ? 1 : orgvelotax[orgvertnum]; /* Get fixed vertex load */ + velomsk |= veloval; /* See if all fixed vertex loads are zero */ + + for (hashnum = (orgpfixval * KGRAPHMAPRBVFLOHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + if (hashtab[hashnum].termnum == orgpfixval) { /* If hash slot found */ + hashtab[hashnum].veloval += veloval; /* Add contribution to slot */ + break; + } + if (hashtab[hashnum].termnum == ~0) { /* If hash slot empty */ + hashtab[hashnum].termnum = orgpfixval; /* Create slot */ + hashtab[hashnum].veloval = veloval; + break; + } + } + orgparttax[orgvertnum] = 1; /* Fixed vertex will not be kept in induced subgraph */ + } + else + orgparttax[orgvertnum] = 0; /* Keep non-fixed vertex in induced subgraph */ + } + + if (graphInducePart (orggrafptr, orgparttax, orggrafptr->vertnbr - orgvfixnbr, 0, indgrafptr) != 0) { /* Keep non-fixed vertices in induced graph */ + errorPrint ("kgraphMapRbVfloBuild: cannot build induced subgraph"); + memFree (hashtab); + return (1); + } + + if (velomsk == 0) { /* If all fixed vertex loads are zero */ + memFree (hashtab); /* No need to allocate a table */ + *vflonbrptr = 0; + *vflotabptr = NULL; + return (0); + } + + for (hashnum = vflonbr = 0; hashnum < hashsiz; hashnum ++) { /* Recycle hash table into fixed vertex load table */ + if (hashtab[hashnum].termnum != ~0) { + hashtab[vflonbr] = hashtab[hashnum]; + vflonbr ++; + } + } + + *vflonbrptr = vflonbr; + *vflotabptr = memRealloc (hashtab, vflonbr * sizeof (KgraphMapRbVflo)); + + return (0); +} + +/* This routine splits the fixed vertex load +** array in two parts, one for each of the two +** provided subdomains. +** It returns: +** - void : in all cases. +*/ + +void +kgraphMapRbVfloSplit ( +const Arch * restrict const archptr, /*+ Target architecture +*/ +const ArchDom * restrict const domnsubtab, /*+ Array of the two subdomains +*/ +const Anum vflonbr, /*+ Number of fixed vertex load slots +*/ +KgraphMapRbVflo * restrict const vflotab, /*+ Fixed vertex load array +*/ +Anum * restrict const vflonbrtab, /*+ Number of slots in each subdomain +*/ +Gnum * restrict const vflowgttab) /*+ Fixed vertex load in each subdomain +*/ +{ + KgraphMapRbVflo vflodat; /* Temporary swap area */ + ArchDom domndat; /* Terminal domain attached to fixed vertex */ + Gnum compload0; /* Load of slots in first subdomain */ + Gnum compload1; /* Load of slots in second subdomain */ + Gnum vflomax; + Gnum vflonum; + Gnum vflonnd; + + compload0 = + compload1 = 0; + + vflomax = vflonbr; + if (archVar (archptr) == 0) { + for (vflonum = 0, vflonnd = vflonbr - 1; vflonum < vflonnd; ) { + while (1) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + int o; + + o = +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + archDomTerm (archptr, &domndat, vflotab[vflonum].termnum); +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (o != 0) { + errorPrint ("kgraphMapRbVfloSplit: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + if (archDomIncl (archptr, &domnsubtab[0], &domndat) == 1) { /* If terminal vertex subdomain included in first subdomain */ + compload0 += vflotab[vflonum].veloval; /* Fixed vertex belongs to first subdomain */ + if (++ vflonum > vflonnd) /* If passed beyond the limit of the second subdomain */ + goto quit; + } + else { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (archDomIncl (archptr, &domnsubtab[1], &domndat) != 1) { /* If terminal vertex subdomain not included in second subdomain */ + errorPrint ("kgraphMapRbVfloSplit: internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + break; /* We have found a candidate for swapping */ + } + } + while (1) { + archDomTerm (archptr, &domndat, vflotab[vflonnd].termnum); + if (archDomIncl (archptr, &domnsubtab[1], &domndat) == 1) { /* If terminal vertex subdomain included in second subdomain */ + compload1 += vflotab[vflonnd].veloval; /* Fixed vertex belongs to second subdomain */ + if (-- vflonnd <= vflonum) { /* If matched the location of a slot that also belongs to second subdomain */ + compload1 += vflotab[vflonnd].veloval; /* Add load of reached slot to second subdomain */ + goto quit; + } + } + else { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (archDomIncl (archptr, &domnsubtab[0], &domndat) != 1) { /* If terminal vertex subdomain not included in first subdomain */ + errorPrint ("kgraphMapRbVfloSplit: internal error (3)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + break; /* We have found a candidate for swapping */ + } + } + + vflodat = vflotab[vflonum]; /* Swap slots */ + vflotab[vflonum] = vflotab[vflonnd]; + vflotab[vflonnd] = vflodat; + compload0 += vflotab[vflonum ++].veloval; + compload1 += vflotab[vflonnd --].veloval; + } + } + else { /* If variable-sized architecture, pseudo-terminals may not always be included */ + for (vflonum = 0, vflonnd = vflonbr - 1; vflonum <= vflonnd; ) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + int o; + + o = +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + archDomTerm (archptr, &domndat, vflotab[vflonum].termnum); +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (o != 0) { + errorPrint ("kgraphMapRbVfloSplit: internal error (4)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + if (archDomIncl (archptr, &domnsubtab[0], &domndat) == 1) { /* If vertex subdomain included in first subdomain */ + compload0 += vflotab[vflonum].veloval; /* Fixed vertex belongs to first subdomain */ + vflonum ++; + continue; /* Keep it in place */ + } + if (archDomIncl (archptr, &domnsubtab[1], &domndat) == 1) { /* If vertex subdomain included in second subdomain */ + compload1 += vflotab[vflonum].veloval; /* Fixed vertex belongs to second subdomain */ + + vflodat = vflotab[vflonum]; /* Swap slots */ + vflotab[vflonum] = vflotab[vflonnd]; + vflotab[vflonnd] = vflodat; + } + else { /* Fixed vertex is more generic than the two subdomains */ + vflomax --; /* One less slot to consider in the future */ + vflodat = vflotab[vflonum]; /* Swap slots */ + vflotab[vflonum] = vflotab[vflonnd]; + vflotab[vflonnd] = vflotab[vflomax]; + vflotab[vflomax] = vflodat; + } + vflonnd --; /* One less slot to consider */ + } + } + +quit: + vflonbrtab[0] = vflonum; + vflonbrtab[1] = vflomax - vflonum; + vflowgttab[0] = compload0; + vflowgttab[1] = compload1; +} + +/* This routine prolongs the given mapping +** with fixed vertices, by merging back with +** regular domains. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kgraphMapRbVfloMerge ( +Mapping * restrict const mappptr, /*+ Mapping to prolong +*/ +const Gnum vfixnbr, /*+ Number of fixed vertices in graph +*/ +const Anum * restrict const pfixtax, /*+ Array of fixed vertex terminal domains +*/ +const Anum vflonbr) /*+ Number of fixed vertex load slots +*/ +{ + ArchDom domndat; + Anum domnmax; + Anum domnnum; + Gnum vertnum; + Gnum vertnnd; + KgraphMapRbVfloHash * restrict hashtab; /* Hash table for merging fixed vertices */ + Gnum hashnbr; /* Prospective number of cells in table */ + Gnum hashsiz; /* Size of hash table */ + Gnum hashnum; + Gnum hashmsk; /* Mask for access to hash table */ + + const Arch * restrict const archptr = mappptr->archptr; + Anum * restrict const parttax = mappptr->parttax; + + hashnbr = mappptr->domnnbr + vflonbr; + for (hashsiz = 0, hashmsk = hashnbr; hashmsk != 0; hashsiz ++, hashmsk >>= 1) ; /* Get upper power of two */ + hashsiz = 1 << (hashsiz + 2); /* Fill hash table at 25% maximum */ + hashmsk = hashsiz - 1; + + if ((hashtab = memAlloc (hashsiz * sizeof (KgraphMapRbVfloHash))) == NULL) { /* Use fixed vertex load slots as hash slots */ + errorPrint ("kgraphMapRbVfloMerge: out of memory (1)"); + return (1); + } + memSet (hashtab, ~0, hashsiz * sizeof (KgraphMapRbVfloHash)); /* Set all vertex numbers to ~0 */ + + for (domnnum = 0; domnnum < mappptr->domnnbr; domnnum ++) { /* Load all existing domains into hash table */ + Anum termnum; + + termnum = archDomNum (archptr, &mappptr->domntab[domnnum]); + for (hashnum = (termnum * KGRAPHMAPRBVFLOHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + if (hashtab[hashnum].termnum == termnum) /* If domain found */ + break; + if (hashtab[hashnum].termnum == ~0) { /* If empty slot found */ + hashtab[hashnum].termnum = termnum; /* Fill it */ + hashtab[hashnum].domnnum = domnnum; + break; + } + } + } + + domnmax = mappptr->domnmax; + for (vertnum = mappptr->grafptr->baseval, vertnnd = mappptr->grafptr->vertnnd; vertnum < vertnnd; vertnum ++) { + Anum pfixval; + + pfixval = pfixtax[vertnum]; + if (pfixval < 0) { /* If vertex is not a fixed vertex */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mappptr->parttax[vertnum] < 0) { /* If vertex has not been mapped */ + errorPrint ("kgraphMapRbVfloMerge: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + continue; /* Skip to next vertex */ + } + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mappptr->parttax[vertnum] >= 0) { /* If fixed vertex has been mapped */ + errorPrint ("kgraphMapRbVfloMerge: internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + for (hashnum = (pfixval * KGRAPHMAPRBVFLOHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + if (hashtab[hashnum].termnum == pfixval) /* If hash slot found */ + break; + if (hashtab[hashnum].termnum == ~0) { /* If hash slot empty */ + if (domnnum >= mappptr->domnmax) { + if (mapResize (mappptr, mappptr->domnmax + (mappptr->domnmax >> 2) + 8) != 0) { /* Increase size by 25% */ + errorPrint ("kgraphMapRbVfloMerge: out of memory (2)"); + return (1); + } + } + archDomTerm (archptr, &mappptr->domntab[domnnum], pfixval); /* Add new domain to domain array */ + + hashtab[hashnum].termnum = pfixval; /* Create slot */ + hashtab[hashnum].domnnum = domnnum; + domnnum ++; /* One more domain created */ + break; + } + } + parttax[vertnum] = hashtab[hashnum].domnnum; /* Assign fixed vertex to existing domain */ + } + mappptr->domnnbr = domnnum; + + memFree (hashtab); + + return (0); +} + +/*****************************************/ +/* */ +/* This routine computes external gains. */ +/* */ +/*****************************************/ + +/* This routines computes the three kinds of +** external loads and gains that can be associated +** with a bipartitioning job: regular external +** gains arising from former bipartitions, fixed +** vertex gains and remapping gains. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kgraphMapRbBgraph ( +const KgraphMapRbData * restrict const dataptr, /*+ Global data +*/ +Bgraph * restrict const actgrafptr, /*+ Graph to build +*/ +const Graph * restrict const srcgrafptr, /*+ Source graph +*/ +const Mapping * restrict const srcmappptr, /*+ Current mapping +*/ +const ArchDom * restrict const domnsubtab, /*+ Array of the two subdomains +*/ +const Gnum * restrict const vflowgttab) /*+ Array of vertex weight biases +*/ +{ + Gnum actvertnum; /* Number of current active vertex */ + Gnum commloadextn0; /* External communication load */ + Gnum commgainextn0; /* External communication gain */ + Gnum * restrict veextax; /* External gain array */ + Gnum veexmsk; /* Flag set if external array useful */ + int flagval; + int o; + + const Arch * restrict const archptr = dataptr->mappptr->archptr; + const Gnum * restrict const orgverttax = dataptr->grafptr->verttax; + const Gnum * restrict const orgvendtax = dataptr->grafptr->vendtax; + const Gnum * restrict const orgvelotax = dataptr->grafptr->velotax; + const Gnum * restrict const orgedgetax = dataptr->grafptr->edgetax; + const Gnum * restrict const orgedlotax = dataptr->grafptr->edlotax; + const Mapping * restrict const oldmappptr = dataptr->r.mappptr; + const Gnum * restrict const orgvmlotax = dataptr->r.vmlotax; + const Anum * restrict const orgpfixtax = dataptr->pfixtax; + const Gnum * restrict const actverttax = srcgrafptr->verttax; /* Get pointers from source graph before bgraphInit() */ + const Gnum * restrict const actvendtax = srcgrafptr->vendtax; + const Gnum * restrict const actedgetax = srcgrafptr->edgetax; + const Gnum * restrict const actvnumtax = srcgrafptr->vnumtax; + + if (bgraphInit (actgrafptr, srcgrafptr, srcmappptr->archptr, domnsubtab, vflowgttab) != 0) { + errorPrint ("kgraphMapRbBgraph: cannot create bipartition graph"); + return (1); + } + + flagval = KGRAPHMAPRBVEEXNONE; /* Assume no processing */ + if ((! archPart (archptr)) && (actvnumtax != NULL)) + flagval |= KGRAPHMAPRBVEEXMAPP; + if (orgpfixtax != NULL) /* Fixed vertices always imply (actvnumtax != NULL) */ + flagval |= KGRAPHMAPRBVEEXVFIX; + if (dataptr->r.mappptr != NULL) + flagval |= KGRAPHMAPRBVEEXREMA; + + if (flagval == KGRAPHMAPRBVEEXNONE) /* If nothing to do */ + return (0); + + if ((veextax = (Gnum *) memAlloc (actgrafptr->s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("kgraphMapRbBgraph: out of memory"); + return (1); + } + veextax -= actgrafptr->s.baseval; + + o = 1; /* Assume failure */ + veexmsk = 0; /* No useful array entry yet */ + commloadextn0 = /* No external communication yet */ + commgainextn0 = 0; + for (actvertnum = actgrafptr->s.baseval; /* Compute external loads */ + actvertnum < actgrafptr->s.vertnnd; actvertnum ++) { + Gnum commloadextn; /* External communication load for current vertex */ + Gnum commgainextn; /* External communication gain for current vertex */ + Gnum orgvertnum; /* Number of current original vertex */ + + commloadextn = /* Assume no external loads */ + commgainextn = 0; + + if (actvnumtax == NULL) /* If active graph is not a subgraph */ + orgvertnum = actvertnum; /* Its number is that of original graph */ + else { /* Else we have external edges to process */ + orgvertnum = actvnumtax[actvertnum]; /* Get vertex number in original graph */ + + if ((flagval & KGRAPHMAPRBVEEXEDGE) != 0) { /* If edge-based gains have to be computed */ + Gnum orgedgenum; + Gnum orgedgennd; + Gnum actedgenum; + Gnum actedgennd; + + orgedgenum = orgverttax[orgvertnum]; + orgedgennd = orgvendtax[orgvertnum]; + actedgenum = actverttax[actvertnum]; + actedgennd = actvendtax[actvertnum]; + if ((orgedgennd - orgedgenum) != (actedgennd - actedgenum)) { /* If vertex has external edges */ + Gnum orgedloval; + Gnum actvertend; /* Next internal end vertex index to find in original edge array */ + + orgedloval = 1; /* Assume no edge loads */ + actvertend = (actedgenum >= actedgennd) ? ~0 : actvnumtax[actedgetax[actedgenum]]; + for ( ; orgedgenum < orgedgennd; orgedgenum ++) { + Gnum orgvertend; + + orgvertend = orgedgetax[orgedgenum]; + if (orgvertend == actvertend) { /* If internal edge found */ + actedgenum ++; /* Skip internal active edge */ + actvertend = (actedgenum >= actedgennd) ? ~0 : actvnumtax[actedgetax[actedgenum]]; /* Set next internal end vertex index to fetch */ + continue; /* Skip internal original edge */ + } + + if (orgedlotax != NULL) + orgedloval = orgedlotax[orgedgenum]; + + if (orgpfixtax != NULL) { + ArchDom domndat; + Anum pfixval; + + pfixval = orgpfixtax[orgvertend]; + if (pfixval >= 0) { /* If end vertex is fixed */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (dataptr->mappptr->parttax[orgvertend] != ~0) { /* If original vertex has a current part */ + errorPrint ("kgraphMapRbBgraph: internal error"); + goto fail; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + if (archDomTerm (archptr, &domndat, pfixval) != 0) { /* Get its domain */ + errorPrint ("kgraphMapRbBgraph: invalid fixed part array"); + goto fail; + } + + commloadextn += (archDomIncl (archptr, &domnsubtab[0], &domndat) != 0) + ? 0 : (orgedloval * archDomDist (archptr, &domnsubtab[0], &domndat)); + commgainextn += (archDomIncl (archptr, &domnsubtab[1], &domndat) != 0) + ? 0 : (orgedloval * archDomDist (archptr, &domnsubtab[1], &domndat)); + + continue; /* Process next edge */ + } + } + + if ((flagval & KGRAPHMAPRBVEEXMAPP) != 0) { /* If mapping */ + ArchDom * domnptr; + + domnptr = mapDomain (srcmappptr, orgvertend); + commloadextn += orgedloval * archDomDist (archptr, &domnsubtab[0], domnptr); + commgainextn += orgedloval * archDomDist (archptr, &domnsubtab[1], domnptr); + } + } + + commloadextn *= dataptr->r.crloval; /* Scale regular, non-remapping gains */ + commgainextn *= dataptr->r.crloval; + } + } + } + + if (oldmappptr != NULL) { /* If remapping gains have to be computed */ + ArchDom * domnptr; + Gnum edloval; + + edloval = dataptr->r.cmloval; + if (orgvmlotax != NULL) + edloval *= orgvmlotax[orgvertnum]; + + domnptr = mapDomain (oldmappptr, orgvertnum); + commloadextn += (archDomIncl (archptr, &domnsubtab[0], domnptr) != 0) + ? 0 : (edloval * archDomDist (archptr, &domnsubtab[0], domnptr)); + commgainextn += (archDomIncl (archptr, &domnsubtab[1], domnptr) != 0) + ? 0 : (edloval * archDomDist (archptr, &domnsubtab[1], domnptr)); + } + + commgainextn -= commloadextn; /* Compute vertex gain */ + commloadextn0 += commloadextn; /* Account for external edges */ + commgainextn0 += commgainextn; + + veextax[actvertnum] = commgainextn; /* Record external gain value */ + veexmsk |= commgainextn; /* Accumulate non-zero values */ + } + o = 0; /* Computations succeeded */ + +fail: + if ((o != 0) || (veexmsk == 0)) { /* If external gain array is useless */ + memFree (veextax + actgrafptr->s.baseval); /* Forget about it */ + return (o); /* Return error code */ + } + + actgrafptr->s.flagval |= BGRAPHFREEVEEX; /* Keep external gain array */ + actgrafptr->veextax = veextax; + + actgrafptr->commload = commloadextn0; /* Account for external gains in future computations */ + actgrafptr->commgainextn = commgainextn0; + actgrafptr->commloadextn0 = commloadextn0; + actgrafptr->commgainextn0 = commgainextn0; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (bgraphCheck (actgrafptr) != 0) { + errorPrint ("kgraphMapRbBgraph: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_rb.h b/scotch_6.0.3/src/libscotch/kgraph_map_rb.h new file mode 100644 index 00000000..8bb10e29 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_rb.h @@ -0,0 +1,167 @@ +/* Copyright 2004,2007,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_rb.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the Dual Recursive Bipartitioning **/ +/** mapping algorithm. **/ +/** **/ +/** DATES : # Version 0.0 : from : 23 mar 1993 **/ +/** to 12 may 1993 **/ +/** # Version 1.3 : from : 06 apr 1994 **/ +/** to 09 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 04 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 15 nov 1995 **/ +/** to 15 nov 1995 **/ +/** # Version 3.2 : from : 01 oct 1996 **/ +/** to 10 jun 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 17 may 1999 **/ +/** # Version 3.4 : from : 12 sep 2001 **/ +/** to 06 nov 2001 **/ +/** # Version 4.0 : from : 29 nov 2003 **/ +/** to 05 may 2006 **/ +/** # Version 5.1 : from : 07 oct 2008 **/ +/** to 28 mar 2011 **/ +/** # Version 6.0 : from : 07 aug 2014 **/ +/** to 24 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Prime number for hashing terminal domain numbers. +*/ + +#define KGRAPHMAPRBVFLOHASHPRIME 17 /*+ Prime number for hashing +*/ + +/*+ Kinds of external edge processing. +*/ + +#define KGRAPHMAPRBVEEXNONE 0x0000 /* No options set */ + +#define KGRAPHMAPRBVEEXMAPP 0x0001 /* Graph mapping */ +#define KGRAPHMAPRBVEEXVFIX 0x0002 /* Fixed vertices */ +#define KGRAPHMAPRBVEEXREMA 0x0004 /* Remapping */ + +#define KGRAPHMAPRBVEEXEDGE (KGRAPHMAPRBVEEXMAPP | KGRAPHMAPRBVEEXVFIX) +#define KGRAPHMAPRBVEEXVERT (KGRAPHMAPRBVEEXREMA) + +/* +** The type and structure definitions. +*/ + +/*+ Job selection policy types. +*/ + +typedef enum KgraphMapRbPolicy_ { + KGRAPHMAPRBPOLIRANDOM = 0, /*+ Random job selection policy +*/ + KGRAPHMAPRBPOLILEVEL, /*+ Select job with highest level +*/ + KGRAPHMAPRBPOLISIZE, /*+ Select job with largest size +*/ + KGRAPHMAPRBPOLINEIGHBOR, /*+ Priority level computed with respect to neighbors +*/ + KGRAPHMAPRBPOLINGLEVEL, /*+ Select job with most neighbors of higher level +*/ + KGRAPHMAPRBPOLINGSIZE, /*+ Select job with most neighbors of smaller size +*/ + KGRAPHMAPRBPOLIOLD /*+ Select job in old style (version 2.x) +*/ +} KgraphMapRbPolicy; + +/*+ Method parameters. +*/ + +typedef struct KgraphMapRbParam_ { + int flagjobtie; /*+ Flag set of job pools are tied +*/ + int flagmaptie; /*+ Flag set if mappings are tied +*/ + KgraphMapRbPolicy polival; /*+ Job selection policy +*/ + Strat * strat; /*+ Bipartitioning strategy used +*/ + double kbalval; /*+ K-way imbalance ratio +*/ +} KgraphMapRbParam; + +/*+ This structure holds the data passed to each bipartitioning job. +*/ + +typedef struct KgraphMapRbData_ { + const Graph * grafptr; /*+ Pointer to top-level graph, possibly with fixed vertices +*/ + Mapping * mappptr; /*+ Mapping to compute +*/ + struct { /*+ Remapping structure +*/ + const Mapping * mappptr; /*+ Old mapping (for remapping only) +*/ + const Gnum * vmlotax; /*+ Array of vertex migration costs +*/ + Gnum cmloval; /*+ Migration edge load for remapping +*/ + Gnum crloval; /*+ Regular edge load for mapping +*/ + } r; + const Anum * pfixtax; /*+ Fixed vertex partition array +*/ + const KgraphMapRbParam * paraptr; /*+ Pointer to mapping parameter structure +*/ + double comploadrat; /*+ Ideal load balance per weight unit +*/ + double comploadmin; /*+ Minimum vertex load per target load +*/ + double comploadmax; /*+ Maximum vertex load per target load +*/ +} KgraphMapRbData; + +/*+ Fixed vertex load type. An array of such + cells stores the loads of strictly positive + fixed vertices (zero ones are discarded) that + must be assigned to some subdomain of the + current domain to be bipartitioned. +*/ + +typedef struct KgraphMapRbVflo_ { + Anum termnum; /*+ Terminal domain number +*/ + Gnum veloval; /*+ Vertex load +*/ +} KgraphMapRbVflo; + +/*+ Hash structure for merging fixed vertex + domains with non-fixed vertex domains. +*/ + +typedef struct KgraphMapRbVfloHash_ { + Anum termnum; /*+ Terminal domain number +*/ + Anum domnnum; /*+ Domain number in domain array +*/ +} KgraphMapRbVfloHash; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_RB +#define static +#endif + +int kgraphMapRb (Kgraph * const, const KgraphMapRbParam * const); + +int kgraphMapRbVfloBuild (const Arch * restrict const, const Graph * restrict const, const Gnum, const Anum * restrict const, Graph * restrict const, Anum * restrict const, KgraphMapRbVflo * restrict * restrict const); +void kgraphMapRbVfloSplit (const Arch * restrict const, const ArchDom * restrict const, const Anum, KgraphMapRbVflo * restrict const, Anum * restrict const, Gnum * restrict const); +int kgraphMapRbVfloMerge (Mapping * restrict const, const Gnum, const Anum * restrict const, const Anum); + +int kgraphMapRbBgraph (const KgraphMapRbData * restrict const, Bgraph * restrict const, const Graph * restrict const, const Mapping * restrict const, const ArchDom * restrict const, const Gnum * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_rb_map.c b/scotch_6.0.3/src/libscotch/kgraph_map_rb_map.c new file mode 100644 index 00000000..7882a917 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_rb_map.c @@ -0,0 +1,1058 @@ +/* Copyright 2004,2007-2009,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_rb_map.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module performs the Dual Recursive **/ +/** Bipartitioning mapping algorithm. **/ +/** **/ +/** DATES : # Version 0.0 : from : 31 mar 1993 **/ +/** to 31 mar 1993 **/ +/** # Version 1.0 : from : 04 oct 1993 **/ +/** to 06 oct 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.3 : from : 09 apr 1994 **/ +/** to 11 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 17 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 18 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 19 oct 1995 **/ +/** # Version 3.1 : from : 30 oct 1995 **/ +/** to 14 jun 1996 **/ +/** # Version 3.2 : from : 23 aug 1996 **/ +/** to 07 sep 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 08 dec 1998 **/ +/** # Version 3.4 : from : 01 jun 2001 **/ +/** to 07 nov 2001 **/ +/** # Version 4.0 : from : 12 jan 2004 **/ +/** to 06 mar 2005 **/ +/** # Version 5.1 : from : 22 nov 2007 **/ +/** to 04 feb 2009 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 29 aug 2014 **/ +/** **/ +/** NOTES : # This code is a complete rewrite of **/ +/** the original code of kgraphMapRb(), **/ +/** hence the kept history. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_RB_MAP + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "kgraph.h" +#include "kgraph_map_rb.h" +#include "kgraph_map_rb_map.h" + +/* +** The static variables. +*/ + +static KgraphMapRbMapPoolLink kgraphmaprbmappooldummy; /* Dummy links for pool routines; TRICK */ + +/************************************/ +/* */ +/* These routines handle job pools. */ +/* */ +/************************************/ + +/* This routine initializes the job pool +** structures. +** It returns: +** - 0 : in case of success. +** - !0 : on error. +*/ + +static +int +kgraphMapRbMapPoolInit ( +KgraphMapRbMapPoolData * restrict const poolptr, +const KgraphMapRbData * restrict const dataptr) +{ + int flagval; + + Mapping * restrict const mappptr = dataptr->mappptr; + + flagval = 0; + if (archVar (mappptr->archptr) != 0) + flagval |= KGRAPHMAPRBMAPARCHVAR; + if (archPart (mappptr->archptr) != 0) { + flagval |= KGRAPHMAPRBMAPARCHCMPLT; + poolptr->polival = KGRAPHMAPRBPOLILEVEL; /* A simple policy will do */ + poolptr->grafptr = NULL; /* We don't need top level graph data */ + } + else { + poolptr->polival = dataptr->paraptr->polival; /* Enforce original policy */ + poolptr->grafptr = dataptr->grafptr; /* We will need top-level graph data */ + } + poolptr->pfixtax = dataptr->pfixtax; + + poolptr->linktab[0].prev = /* Initialize doubly linked list as empty, pointing to the dummy element */ + poolptr->linktab[0].next = + poolptr->linktab[1].prev = + poolptr->linktab[1].next = &kgraphmaprbmappooldummy; + poolptr->pooltab[0] = &poolptr->linktab[0]; + poolptr->pooltab[1] = (dataptr->paraptr->flagjobtie != 0) ? &poolptr->linktab[0] : &poolptr->linktab[1]; + + if ((poolptr->jobtab = (KgraphMapRbMapJob *) memAlloc (mappptr->domnmax * sizeof (KgraphMapRbMapJob))) == NULL) { + errorPrint ("kgraphMapRbMapPoolInit: out of memory (2)"); + return (1); + } + poolptr->jobtab[0].poolflag = 0; /* In case kgraphMapRbPoolExit() is called just afterwards on single-domain mapping */ + + poolptr->mappptr = mappptr; + + poolptr->domntab[0] = mappptr->domntab; /* Use original domain array */ + if (dataptr->paraptr->flagmaptie != 0) { /* If mappings are tied, use same domain array */ + poolptr->domntab[1] = mappptr->domntab; + flagval |= KGRAPHMAPRBMAPPARTHALF; /* Updates will only involve half of the vertices */ + } + else { + if ((poolptr->domntab[1] = (ArchDom *) memAlloc (mappptr->domnmax * sizeof (ArchDom))) == NULL) { + errorPrint ("kgraphMapRbMapPoolInit: out of memory (3)"); + memFree (poolptr->jobtab); + return (1); + } + } + + poolptr->flagval = flagval; + + return (0); +} + +/* This routine frees all of the internal arrays +** involved in the DRB algorithms. Great care +** should be taken that this routine always +** succeeds, whatever part of the algorithm it +** is called from. +** It returns: +** - VOID : in all cases. +*/ + +static +void +kgraphMapRbMapPoolExit ( +KgraphMapRbMapPoolData * restrict const poolptr) +{ + Anum domnnbr; + Anum jobnum; + + Mapping * restrict const mappptr = poolptr->mappptr; + + domnnbr = mappptr->domnnbr; + + for (jobnum = 0; jobnum < domnnbr; jobnum ++) { /* For all potential jobs in both pools */ + if (poolptr->jobtab[jobnum].poolflag != 0) { /* If job slot is active */ + graphExit (&poolptr->jobtab[jobnum].grafdat); /* Free job graph, if not clone of original graph */ + } + } + + if (mappptr->domntab != poolptr->domntab[1]) { /* If current mapping domain array is not original domain array */ + if ((mappptr->flagval & MAPPINGFREEDOMN) != 0) /* If mapping domain array was privately owned, free it */ + memFree (mappptr->domntab); + mappptr->flagval |= MAPPINGFREEDOMN; /* Keep current domain array as private mapping domain array */ + mappptr->domntab = poolptr->domntab[1]; + } + + memFree (poolptr->jobtab); +} + +/* This routine swaps the internal arrays +** involved in the DRB algorithms. +** It returns: +** - VOID : in all cases. +*/ + +static +void +kgraphMapRbMapPoolSwap ( +KgraphMapRbMapPoolData * restrict const poolptr) +{ + KgraphMapRbMapPoolLink * linktmp; + ArchDom * domntmp; + + linktmp = poolptr->pooltab[0]; + poolptr->pooltab[0] = poolptr->pooltab[1]; + poolptr->pooltab[1] = linktmp; + + domntmp = poolptr->domntab[0]; + poolptr->domntab[0] = poolptr->domntab[1]; + poolptr->domntab[1] = domntmp; +} + +/* This routine doubles the size all of the arrays +** involved in handling the target architecture, +** to make room for new domains of variable-sized +** architectures. +** It returns: +** - 0 : if resize succeeded. +** - !0 : if out of memory. +*/ + +static +int +kgraphMapRbMapPoolResize ( +KgraphMapRbMapPoolData * restrict const poolptr) +{ + KgraphMapRbMapJob * restrict jobtab; /* Pointer to (new) job array */ + Anum domnnbr; /* Current (max) number of domains */ + Anum domnmax; /* New maximum number of domains */ + int i; + + domnnbr = poolptr->mappptr->domnmax; /* Current max size */ + domnmax = domnnbr + (domnnbr >> 2) + 8; /* Increase size by 25% */ + + if ((jobtab = (KgraphMapRbMapJob *) memRealloc (poolptr->jobtab, domnmax * sizeof (KgraphMapRbMapJob))) == NULL) { + errorPrint ("kgraphMapRbMapPoolResize: out of memory (1)"); + return (1); + } + if (jobtab != poolptr->jobtab) { /* If job array moved */ + KgraphMapRbMapJob * joboldtab; /* Pointer to start of old job array */ + KgraphMapRbMapJob * joboldtnd; /* Pointer to end of old job array */ + Anum jobnum; /* Temporary job index */ + intptr_t jobdlt; /* Address delta value */ + + joboldtab = poolptr->jobtab; + joboldtnd = joboldtab + domnnbr; + jobdlt = (byte *) jobtab - (byte *) joboldtab; /* Compute delta between new and old addresses */ + + for (jobnum = 0; jobnum < domnnbr; jobnum ++) { + if ((jobtab[jobnum].poollink.prev >= (KgraphMapRbMapPoolLink *) joboldtab) && /* If old pointers within bounds of old array, adjust them */ + (jobtab[jobnum].poollink.prev < (KgraphMapRbMapPoolLink *) joboldtnd)) + jobtab[jobnum].poollink.prev = (KgraphMapRbMapPoolLink *) ((byte *) jobtab[jobnum].poollink.prev + jobdlt); + if ((jobtab[jobnum].poollink.next >= (KgraphMapRbMapPoolLink *) joboldtab) && + (jobtab[jobnum].poollink.next < (KgraphMapRbMapPoolLink *) joboldtnd)) + jobtab[jobnum].poollink.next = (KgraphMapRbMapPoolLink *) ((byte *) jobtab[jobnum].poollink.next + jobdlt); + } + if (poolptr->linktab[0].next != &kgraphmaprbmappooldummy) /* Update first pool pointer */ + poolptr->linktab[0].next = (KgraphMapRbMapPoolLink *) ((byte *) poolptr->linktab[0].next + jobdlt); + if (poolptr->pooltab[0] != poolptr->pooltab[1]) { /* If job pools not tied */ + if (poolptr->linktab[1].next != &kgraphmaprbmappooldummy) /* Update second pool pointer */ + poolptr->linktab[1].next = (KgraphMapRbMapPoolLink *) ((byte *) poolptr->linktab[1].next + jobdlt); + } + + poolptr->jobtab = jobtab; /* Set new memory location of job array */ + } + + i = (poolptr->domntab[1] == poolptr->mappptr->domntab) ? 1 : 0; /* Find which domain array is that of the mapping */ + if (mapResize (poolptr->mappptr, domnmax) != 0) { + errorPrint ("kgraphMapRbMapPoolResize: out of memory (2)"); + return (1); + } + if (poolptr->domntab[1] != poolptr->domntab[0]) { /* If two domain arrays present */ + ArchDom * domntab; + + if ((domntab = (ArchDom *) memRealloc (poolptr->domntab[i ^ 1], domnmax * sizeof (ArchDom))) == NULL) { /* Reallocate other domain array */ + errorPrint ("kgraphMapRbMapPoolResize: out of memory (3)"); + return (1); + } + poolptr->domntab[i ^ 1] = domntab; /* Set (possibly new) memory location of other domain array */ + } + else + poolptr->domntab[i ^ 1] = poolptr->mappptr->domntab; /* Both domain arrays point to the same (new) location */ + poolptr->domntab[i] = poolptr->mappptr->domntab; /* Set (possibly new) memory location of mapping domain array */ + + return (0); +} + +/**********************************************/ +/* */ +/* These routines handle bipartitioning jobs. */ +/* */ +/**********************************************/ + + +/* This routine adds a job to pool 1 of the +** given pool data structure. +** It returns: +** - VOID : in all cases. +*/ + +static +void +kgraphMapRbMapPoolAdd ( +KgraphMapRbMapPoolLink * restrict const linkptr, +KgraphMapRbMapJob * const jobptr) +{ + jobptr->poollink.prev = linkptr; /* Link job in pool: TRICK */ + jobptr->poollink.next = linkptr->next; + jobptr->poolflag = 1; /* Job is in pool */ + jobptr->poolptr = linkptr; /* Point to the pool */ + linkptr->next->prev = &jobptr->poollink; + linkptr->next = &jobptr->poollink; +} + +/* This routine gets the best job available from +** the given pool, according to the given policy. +** It returns: +** - !NULL : pointer to the job. +** - NULL : if the pool is empty. +*/ + +static +KgraphMapRbMapJob * +kgraphMapRbMapPoolGet ( +KgraphMapRbMapPoolData * const poolptr) +{ + KgraphMapRbMapJob * jobbest; /* Best job found */ + KgraphMapRbMapJob * jobptr; + + jobbest = (KgraphMapRbMapJob *) poolptr->pooltab[0]->next; /* Get first job in pool */ + for (jobptr = jobbest; /* For all jobs in pool */ + jobptr != (KgraphMapRbMapJob *) (void *) &kgraphmaprbmappooldummy; + jobptr = (KgraphMapRbMapJob *) jobptr->poollink.next) { + if (jobptr->priolvl > jobbest->priolvl) /* If the current job has stronger priority */ + jobbest = jobptr; /* Select it as the best job */ + } + + if (jobbest != (KgraphMapRbMapJob *) (void *) &kgraphmaprbmappooldummy) { /* If job found */ + jobbest->poollink.next->prev = jobbest->poollink.prev; /* Remove it from pool */ + jobbest->poollink.prev->next = jobbest->poollink.next; /* But do not mark it unused */ + } + else /* Dummy job means no job found */ + jobbest = NULL; + + return (jobbest); +} + +/* This routine adds a job to the given pool +** as the first bipartitioning job. +** It returns: +** - VOID : in all cases. +*/ + +static +void +kgraphMapRbMapPoolFrst ( +KgraphMapRbMapPoolData * const poolptr, +KgraphMapRbMapJob * const jobptr) /* Job to be added */ +{ + switch (poolptr->polival) { /* Set job priority value */ + case KGRAPHMAPRBPOLIRANDOM : + jobptr->prioval = + jobptr->priolvl = intRandVal (INTVALMAX); + break; + case KGRAPHMAPRBPOLILEVEL : + case KGRAPHMAPRBPOLINGLEVEL : + jobptr->prioval = jobptr->grafdat.vertnbr; + jobptr->priolvl = 0; + break; + case KGRAPHMAPRBPOLISIZE : + case KGRAPHMAPRBPOLINGSIZE : + jobptr->prioval = + jobptr->priolvl = jobptr->grafdat.vertnbr; + break; +#ifdef SCOTCH_DEBUG_KGRAPH2 + default : + errorPrint ("kgraphMapRbMapPoolFrst: unknown job selection policy"); + jobptr->prioval = 0; + jobptr->priolvl = 0; + return; +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + + kgraphMapRbMapPoolAdd (poolptr->pooltab[0], jobptr); /* Add job to pool */ +} + +/* This routine updates the given job +** table with both of the given subjob +** data. +** This routine can be called only if +** the parent jobs of the vertices to +** be updated still exist. +** It returns: +** - VOID : in all cases. +*/ + +static +void +kgraphMapRbMapPoolUpdt1 ( +KgraphMapRbMapPoolData * const poolptr, +const KgraphMapRbMapJob * const joboldptr, /* Job to be removed */ +const GraphPart * const parttax, +KgraphMapRbMapJob * const jobnewptr, /* Its only active subjob */ +const GraphPart partval) +{ + Gnum prioval; + Gnum priolvl; + + priolvl = 0; /* Prepare for neighbor updating methods */ + + switch (poolptr->polival) { /* Set job priority value */ + case KGRAPHMAPRBPOLIRANDOM : + prioval = + priolvl = intRandVal (INTVALMAX); + break; + case KGRAPHMAPRBPOLILEVEL : + priolvl = joboldptr->priolvl + 1; + case KGRAPHMAPRBPOLINGLEVEL : + prioval = joboldptr->prioval - 1; + break; + case KGRAPHMAPRBPOLISIZE : + priolvl = jobnewptr->grafdat.vertnbr; + case KGRAPHMAPRBPOLINGSIZE : + prioval = jobnewptr->grafdat.vertnbr; + break; +#ifdef SCOTCH_DEBUG_KGRAPH2 + default : + errorPrint ("kgraphMapRbMapPoolUpdt1: unknown job selection policy"); + jobnewptr->prioval = 0; + jobnewptr->priolvl = 0; + return; +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + + jobnewptr->prioval = prioval; + + if (poolptr->polival >= KGRAPHMAPRBPOLINEIGHBOR) { /* If neighbors have to be updated */ + Gnum prioold; + + KgraphMapRbMapJob * restrict const jobtab = poolptr->jobtab; + const Anum * restrict const mapparttax = poolptr->mappptr->parttax; /* Based pointer to mapping part array */ + const Anum * restrict const toppfixtax = poolptr->pfixtax; + const Gnum * restrict const topverttax = poolptr->grafptr->verttax; /* Point to top-level graph arrays */ + const Gnum * restrict const topvendtax = poolptr->grafptr->vendtax; + const Gnum * restrict const topedgetax = poolptr->grafptr->edgetax; + + prioold = joboldptr->prioval; + + if (joboldptr->grafdat.vertnbr < poolptr->grafptr->vertnbr) { /* If subgraph is not top graph, change priority of neighboring jobs of old job */ + Gnum jobvertnnd; + Gnum jobvertnum; + + const Gnum * restrict const jobverttax = joboldptr->grafdat.verttax; + const Gnum * restrict const jobvendtax = joboldptr->grafdat.vendtax; + const Gnum * restrict const jobvnumtax = joboldptr->grafdat.vnumtax; + + jobnewptr->poolflag = 0; /* TRICK: avoid new job being considered for update */ + + for (jobvertnum = joboldptr->grafdat.baseval, jobvertnnd = joboldptr->grafdat.vertnnd; + jobvertnum < jobvertnnd; jobvertnum ++) { + Gnum topvertnum; + Gnum topedgenum; + + if (parttax[jobvertnum] == partval) /* If vertex belongs to part which is still alive */ + continue; /* Do not consider update part as removed */ + + topvertnum = jobvnumtax[jobvertnum]; /* If graph is smaller than top graph, then vnumtax must exist */ + + if ((topvendtax[topvertnum] - topverttax[topvertnum]) == /* If vertex is internal, skip it */ + (jobvendtax[jobvertnum] - jobverttax[jobvertnum])) + continue; + + for (topedgenum = topverttax[topvertnum]; topedgenum < topvendtax[topvertnum]; topedgenum ++) { + KgraphMapRbMapJob * restrict jobnghbptr; /* (Old ?) job of neighbor vertex */ + Gnum topvertend; + + topvertend = topedgetax[topedgenum]; + if ((toppfixtax != NULL) && (toppfixtax[topvertend] >= 0)) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[topvertend] != ~0) { + errorPrint ("kgraphMapRbMapPoolUpdt1: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + continue; + } + + jobnghbptr = &jobtab[mapparttax[topvertend]]; /* Get pointer to neighboring job */ + + if ((jobnghbptr->poolflag != 0) && /* If neighbor is active */ + (jobnghbptr->prioval <= prioold)) /* And had not already a stronger priority */ + jobnghbptr->priolvl ++; /* Update neighbor priority */ + } + } + + jobnewptr->poolflag = 1; /* TRICK: new job is active again */ + } + + if (jobnewptr->grafdat.vertnbr < poolptr->grafptr->vertnbr) { /* If subgraph is not top graph, update priority of neighbors of new job only */ + Gnum jobvertnnd; + Gnum jobvertnum; + + const Gnum * restrict const jobverttax = jobnewptr->grafdat.verttax; + const Gnum * restrict const jobvendtax = jobnewptr->grafdat.vendtax; + const Gnum * restrict const jobvnumtax = jobnewptr->grafdat.vnumtax; + + for (jobvertnum = jobnewptr->grafdat.baseval, jobvertnnd = jobnewptr->grafdat.vertnnd; + jobvertnum < jobvertnnd; jobvertnum ++) { + Gnum topvertnum; + Gnum topedgenum; + + topvertnum = jobvnumtax[jobvertnum]; /* For subjobs jobvnumtax always exists */ + + if ((topvendtax[topvertnum] - topverttax[topvertnum]) == /* If vertex is internal, skip it */ + (jobvendtax[jobvertnum] - jobverttax[jobvertnum])) + continue; + + for (topedgenum = topverttax[topvertnum]; topedgenum < topvendtax[topvertnum]; topedgenum ++) { + KgraphMapRbMapJob * restrict jobnghbptr; /* (Old ?) job of neighbor vertex */ + Gnum topvertend; + + topvertend = topedgetax[topedgenum]; + if ((toppfixtax != NULL) && (toppfixtax[topvertend] >= 0)) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[topvertend] != ~0) { + errorPrint ("kgraphMapRbMapPoolUpdt1: internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + continue; + } + + jobnghbptr = &jobtab[mapparttax[topvertend]]; /* Get pointer to neighboring job */ + if (jobnghbptr == jobnewptr) /* If it is the current job, do not consider the edge */ + continue; + + if ((jobnghbptr->poolflag == 0) || /* If neighbor is not active */ + (prioval > jobnghbptr->prioval)) /* Or if we have higher priority */ + priolvl ++; /* Increase our priority */ + else if ((prioval < jobnghbptr->prioval) && /* Else if neighbor has higher one */ + (prioold >= jobnghbptr->prioval)) /* Which it did not already have */ + jobnghbptr->priolvl ++; /* Update neighbor priority */ + } + } + } + } + + jobnewptr->priolvl = priolvl; + + kgraphMapRbMapPoolAdd (poolptr->pooltab[1], jobnewptr); /* Add job to pool */ +} + +static +void +kgraphMapRbMapPoolUpdt2 ( +KgraphMapRbMapPoolData * const poolptr, +const KgraphMapRbMapJob * const joboldptr, /* Job to be removed */ +const GraphPart * const parttax, +KgraphMapRbMapJob * const jobnewptr0, /* Its two subjobs */ +KgraphMapRbMapJob * const jobnewptr1) +{ + KgraphMapRbMapJob * restrict jobnewtab[2]; + int i; + + jobnewtab[0] = jobnewptr0; + jobnewtab[1] = jobnewptr1; + + for (i = 1; i >= 0; i --) { + KgraphMapRbMapJob * jobnewptr; + Gnum prioval; + Gnum priolvl; + + jobnewptr = jobnewtab[i]; /* Get concerned subjob */ + + priolvl = 0; /* Prepare for neighbor updating methods */ + + switch (poolptr->polival) { /* Set job priority value */ + case KGRAPHMAPRBPOLIRANDOM : + prioval = + priolvl = intRandVal (INTVALMAX); + break; + case KGRAPHMAPRBPOLILEVEL : + priolvl = joboldptr->priolvl + 1; + case KGRAPHMAPRBPOLINGLEVEL : + prioval = joboldptr->prioval - 1; + break; + case KGRAPHMAPRBPOLISIZE : + priolvl = jobnewptr->grafdat.vertnbr; + case KGRAPHMAPRBPOLINGSIZE : + prioval = jobnewptr->grafdat.vertnbr; + break; +#ifdef SCOTCH_DEBUG_KGRAPH2 + default : + errorPrint ("kgraphMapRbMapPoolUpdt2: unknown job selection policy"); + jobnewptr->prioval = 0; + jobnewptr->priolvl = 0; + return; +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + } + + jobnewptr0->prioval = prioval + 1; /* TRICK: when processing subdomain 1, subdomain 0 has higher priority value */ + jobnewptr->prioval = prioval; /* Then in its turn subdomain 0 will have its proper priority value */ + + if (poolptr->polival >= KGRAPHMAPRBPOLINEIGHBOR) { /* If neighbors have to be updated */ + Gnum jobvertnnd; + Gnum jobvertnum; + Gnum prioold; + + KgraphMapRbMapJob * restrict const jobtab = poolptr->jobtab; + const Anum * restrict const mapparttax = poolptr->mappptr->parttax; /* Based pointer to mapping part array */ + const Anum * restrict const toppfixtax = poolptr->pfixtax; + const Gnum * restrict const topverttax = poolptr->grafptr->verttax; /* Point to top-level graph arrays */ + const Gnum * restrict const topvendtax = poolptr->grafptr->vendtax; + const Gnum * restrict const topedgetax = poolptr->grafptr->edgetax; + const Gnum * restrict const jobverttax = jobnewptr->grafdat.verttax; + const Gnum * restrict const jobvendtax = jobnewptr->grafdat.vendtax; + const Gnum * restrict const jobvnumtax = jobnewptr->grafdat.vnumtax; + + prioold = joboldptr->prioval; + + for (jobvertnum = jobnewptr->grafdat.baseval, jobvertnnd = jobnewptr->grafdat.vertnnd; + jobvertnum < jobvertnnd; jobvertnum ++) { + Gnum topvertnum; + Gnum topedgenum; + + topvertnum = jobvnumtax[jobvertnum]; /* For subjobs jobvnumtax always exists */ + + if ((topvendtax[topvertnum] - topverttax[topvertnum]) == /* If vertex is internal, skip it */ + (jobvendtax[jobvertnum] - jobverttax[jobvertnum])) + continue; + + for (topedgenum = topverttax[topvertnum]; topedgenum < topvendtax[topvertnum]; topedgenum ++) { + KgraphMapRbMapJob * jobnghbptr; /* (Old ?) job of neighbor vertex */ + Gnum topvertend; + + topvertend = topedgetax[topedgenum]; + if ((toppfixtax != NULL) && (toppfixtax[topvertend] >= 0)) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[topvertend] != ~0) { + errorPrint ("kgraphMapRbMapPoolUpdt2: internal error"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + continue; + } + + jobnghbptr = &jobtab[mapparttax[topvertend]]; /* Get pointer to neighboring job */ + + if ((jobnghbptr->poolflag != 0) && /* If neighbor is in active job */ + (jobnghbptr->prioval > prioval) && /* Which gained priority over us */ + (jobnghbptr->prioval <= prioold)) { + jobnghbptr->priolvl ++; /* Update neighbor priority */ + } + if ((jobnghbptr->poolflag == 0) || /* If neighbor is fully known */ + (jobnghbptr->prioval < prioval)) /* Or has smaller priority value */ + priolvl ++; /* Then we should be processed */ + } + } + } + + jobnewptr->priolvl = priolvl; /* Set new priority */ + kgraphMapRbMapPoolAdd (poolptr->pooltab[1], jobnewptr); /* Add job to pool */ + } +} + +/* +** This routine removes the influence of the +** given job from its neighbor jobs. +** It returns: +** - VOID : in all cases. +*/ + +static +void +kgraphMapRbMapPoolRemv ( +KgraphMapRbMapPoolData * const poolptr, +const KgraphMapRbMapJob * const joboldptr) /* Job to be removed */ +{ + KgraphMapRbMapJob * restrict jobtab; + const Anum * restrict mapparttax; /* Based pointer to mapping part array */ + const Gnum * restrict jobvnumtax; + const Gnum * restrict jobverttax; + const Gnum * restrict jobvendtax; + const Gnum * restrict topverttax; + const Gnum * restrict topvendtax; + const Gnum * restrict topedgetax; + + if (poolptr->polival >= KGRAPHMAPRBPOLINEIGHBOR) { /* If neighbors have to be modified */ + Gnum jobvertnnd; + Gnum jobvertnum; + Gnum prioold; + + KgraphMapRbMapJob * restrict const jobtab = poolptr->jobtab; + const Anum * restrict const mapparttax = poolptr->mappptr->parttax; /* Based pointer to mapping part array */ + const Anum * restrict const toppfixtax = poolptr->pfixtax; + const Gnum * restrict const topverttax = poolptr->grafptr->verttax; /* Point to top-level graph arrays */ + const Gnum * restrict const topvendtax = poolptr->grafptr->vendtax; + const Gnum * restrict const topedgetax = poolptr->grafptr->edgetax; + const Gnum * restrict const jobverttax = joboldptr->grafdat.verttax; + const Gnum * restrict const jobvendtax = joboldptr->grafdat.vendtax; + const Gnum * restrict const jobvnumtax = joboldptr->grafdat.vnumtax; + + prioold = joboldptr->prioval; + + for (jobvertnum = joboldptr->grafdat.baseval, jobvertnnd = joboldptr->grafdat.vertnnd; + jobvertnum < jobvertnnd; jobvertnum ++) { + Gnum topvertnum; /* Source graph vertex number */ + Gnum topedgenum; /* Source graph edge number */ + + topvertnum = (jobvnumtax == NULL) ? jobvertnum : jobvnumtax[jobvertnum]; + + if ((topvendtax[topvertnum] - topverttax[topvertnum]) == /* If vertex is internal, skip it */ + (jobvendtax[jobvertnum] - jobverttax[jobvertnum])) + continue; + + for (topedgenum = topverttax[topvertnum]; topedgenum < topvendtax[topvertnum]; topedgenum ++) { + KgraphMapRbMapJob * jobnghbptr; /* (Old ?) job of neighbor vertex */ + Gnum topvertend; + + topvertend = topedgetax[topedgenum]; + if ((toppfixtax != NULL) && (toppfixtax[topvertend] >= 0)) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[topvertend] != ~0) { + errorPrint ("kgraphMapRbMapPoolRemv: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + continue; + } + + jobnghbptr = &jobtab[mapparttax[topvertend]]; /* Get pointer to neighboring job */ + + if ((jobnghbptr->poolflag != 0) && /* If neighbor job is active */ + (jobnghbptr->prioval <= prioold)) /* And had not already a stronger priority */ + jobnghbptr->priolvl ++; /* Increase its priority since we are now inactive */ + } + } + } +} + +/**********************************************/ +/* */ +/* These routines handle the pool part array. */ +/* */ +/**********************************************/ + +static +void +kgraphMapRbMapPartBoth ( +KgraphMapRbMapPoolData * restrict const poolptr, +const Bgraph * restrict const actgrafptr, +const Anum * restrict const jobsubnum) +{ + Gnum actvertnum; + const GraphPart * restrict actparttax; + Anum * restrict mapparttax; + Anum mappartval1; + Anum mappartdlt; + + actparttax = actgrafptr->parttax; + mapparttax = poolptr->mappptr->parttax; + mappartval1 = jobsubnum[1]; + mappartdlt = jobsubnum[0] - jobsubnum[1]; + + if (actgrafptr->s.vnumtax != NULL) { + const Gnum * restrict actvnumtax; + + actvnumtax = actgrafptr->s.vnumtax; + for (actvertnum = actgrafptr->s.baseval; actvertnum < actgrafptr->s.vertnnd; actvertnum ++) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[actvnumtax[actvertnum]] == ~0) { + errorPrint ("kgraphMapRbMapPartBoth: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + mapparttax[actvnumtax[actvertnum]] = mappartval1 + ((((Anum) actparttax[actvertnum]) - 1) & mappartdlt); + } + } + else { + for (actvertnum = actgrafptr->s.baseval; actvertnum < actgrafptr->s.vertnnd; actvertnum ++) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[actvertnum] == ~0) { + errorPrint ("kgraphMapRbMapPartBoth: internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + mapparttax[actvertnum] = mappartval1 + ((((Anum) actparttax[actvertnum]) - 1) & mappartdlt); + } + } +} + +static +void +kgraphMapRbMapPartOne ( +KgraphMapRbMapPoolData * restrict const poolptr, +const Bgraph * restrict const actgrafptr, +const Anum jobsubnum1) +{ + Gnum actvertnum; + const GraphPart * restrict actparttax; + Anum * restrict mapparttax; + + actparttax = actgrafptr->parttax; + mapparttax = poolptr->mappptr->parttax; + + if (actgrafptr->s.vnumtax != NULL) { + const Gnum * restrict actvnumtax; + + actvnumtax = actgrafptr->s.vnumtax; + for (actvertnum = actgrafptr->s.baseval; actvertnum < actgrafptr->s.vertnnd; actvertnum ++) { + if (actparttax[actvertnum] == 1) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[actvnumtax[actvertnum]] == ~0) { + errorPrint ("kgraphMapRbMapPartOne: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + mapparttax[actvnumtax[actvertnum]] = jobsubnum1; + } + } + } + else { + for (actvertnum = actgrafptr->s.baseval; actvertnum < actgrafptr->s.vertnnd; actvertnum ++) { + if (actparttax[actvertnum] == 1) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[actvertnum] == ~0) { + errorPrint ("kgraphMapRbMapPartOne: internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + mapparttax[actvertnum] = jobsubnum1; + } + } + } +} + +/********************************************/ +/* */ +/* This is the entry point for the Dual */ +/* Recursive Bipartitioning mapping method. */ +/* */ +/********************************************/ + +/* This routine runs the Dual Recursive +** Bipartitioning algorithm. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kgraphMapRbMap ( +const KgraphMapRbData * restrict const dataptr, /*+ Global mapping data +*/ +const Graph * restrict const grafptr, /*+ Graph to map, without fixed vertices +*/ +const Anum vflonbr, /*+ Number of fixed vertex load slots +*/ +KgraphMapRbVflo * restrict const vflotab) /*+ Array of fixed vertex load slots +*/ +{ + KgraphMapRbMapPoolData pooldat; /* Data for handling jobs and job pools */ + ArchDom domnsubtab[2]; /* Subdomains of current job domain */ + KgraphMapRbMapJob joborgdat; /* Aera to save original job data */ + Anum jobsubnum[2]; /* Number of subjob slots in job array */ + Gnum jobsubsiz[2]; /* Sizes of subjobs */ + Bgraph actgrafdat; /* Bipartition graph */ + double comploadmin; /* Minimum vertex load per target load */ + double comploadmax; /* Maximum vertex load per target load */ + int i; + + Mapping * restrict const mappptr = dataptr->mappptr; + + mapFrst (mappptr); /* Initialize mapping */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (dataptr->pfixtax != NULL) { /* In debug mode, fixed vertex parts are set to ~0 */ + Gnum vertnnd; + Gnum vertnum; + + Anum * restrict const parttax = mappptr->parttax; + const Anum * restrict const pfixtax = dataptr->pfixtax; + + for (vertnum = dataptr->grafptr->baseval, vertnnd = dataptr->grafptr->vertnnd; vertnum < vertnnd; vertnum ++) { + if (pfixtax[vertnum] >= 0) + parttax[vertnum] = ~0; + } + } + mappptr->domnmax = 1; /* Force resizing of job arrays, for debugging */ +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + if (kgraphMapRbMapPoolInit (&pooldat, dataptr) != 0) /* Initialize pool data; done first for kgraphMapRbMapPoolExit() to succeed afterwards */ + return (1); + + if ((((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) == 0) && (archDomSize (mappptr->archptr, &mappptr->domnorg) <= 1)) || /* If single-vertex domain */ + (((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) != 0) && (grafptr->vertnbr <= 1))) { /* Or if variable-sized architecture with single vertex graph */ + kgraphMapRbMapPoolExit (&pooldat); + return (0); /* Job already done */ + } + + pooldat.jobtab[0].domnorg = mappptr->domnorg; /* Build first job */ + pooldat.jobtab[0].grafdat = *grafptr; /* Clone induced graph as first job graph */ + pooldat.jobtab[0].grafdat.flagval &= ~GRAPHFREETABS; /* Do not free its arrays on exit */ + pooldat.jobtab[0].vflonbr = vflonbr; /* Record initial list of fixed load slots */ + pooldat.jobtab[0].vflotab = vflotab; + kgraphMapRbMapPoolFrst (&pooldat, &pooldat.jobtab[0]); /* Add initial job */ + + comploadmin = (1.0 - dataptr->paraptr->kbalval) * dataptr->comploadrat; /* Ratio can have been tilted when working on subgraph */ + comploadmax = (1.0 + dataptr->paraptr->kbalval) * dataptr->comploadrat; + + while (! kgraphMapRbMapPoolEmpty (&pooldat)) { /* For all non-empty pools */ + KgraphMapRbMapJob * joborgptr; /* Pointer to current job */ + + while ((joborgptr = kgraphMapRbMapPoolGet (&pooldat)) != NULL) { /* For all jobs in pool */ + Gnum vflonbrtab[2]; + Gnum vflowgttab[2]; + int partval; + + jobsubnum[0] = joborgptr - pooldat.jobtab; /* Get current (and first son) job slot number before possible move of pointers */ + joborgdat = *joborgptr; /* Save current job data (clone graph) */ + + if (archDomBipart (mappptr->archptr, &joborgdat.domnorg, &domnsubtab[0], &domnsubtab[1]) != 0) { + errorPrint ("kgraphMapRbMap: cannot bipartition domain"); + kgraphMapRbMapPoolExit (&pooldat); /* Copied graph will be freed as not yet removed */ + return (1); + } + + kgraphMapRbVfloSplit (mappptr->archptr, domnsubtab, /* Split fixed vertex load slots, if any */ + joborgdat.vflonbr, joborgdat.vflotab, vflonbrtab, vflowgttab); + if (kgraphMapRbBgraph (dataptr, &actgrafdat, &joborgdat.grafdat, pooldat.mappptr, domnsubtab, vflowgttab) != 0) { /* Create bipartition graph */ + errorPrint ("kgraphMapRbMap: cannot create bipartition graph"); + kgraphMapRbMapPoolExit (&pooldat); /* Copied graph will be freed as not yet removed */ + return (1); + } + + actgrafdat.s.flagval |= (joborgdat.grafdat.flagval & GRAPHFREETABS); /* Bipartition graph is responsible for freeing the cloned graph data fields */ + joborgptr->poolflag = 0; /* Original slot is now considered unused so that cloned graph data will not be freed twice */ + + if ((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) == 0) { /* If not variable-sized, impose constraints on bipartition */ + double comploadavg; + + comploadavg = (double) actgrafdat.s.velosum / (double) archDomWght (mappptr->archptr, &joborgdat.domnorg); + actgrafdat.compload0min = actgrafdat.compload0avg - + (Gnum) MIN ((comploadmax - comploadavg) * (double) actgrafdat.domnwght[0], + (comploadavg - comploadmin) * (double) actgrafdat.domnwght[1]); + actgrafdat.compload0max = actgrafdat.compload0avg + + (Gnum) MIN ((comploadavg - comploadmin) * (double) actgrafdat.domnwght[0], + (comploadmax - comploadavg) * (double) actgrafdat.domnwght[1]); + } + + if (bgraphBipartSt (&actgrafdat, dataptr->paraptr->strat) != 0) { /* Perform bipartitioning */ + errorPrint ("kgraphMapRbMap: cannot bipartition job"); + bgraphExit (&actgrafdat); + kgraphMapRbMapPoolExit (&pooldat); + return (1); + } + + if ((partval = 1, actgrafdat.compsize0 == 0) || /* If no bipartition found */ + (partval = 0, actgrafdat.compsize0 == actgrafdat.s.vertnbr)) { + if (((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) != 0) || /* If architecture is variable-sized */ + (archDomSize (mappptr->archptr, &domnsubtab[partval]) <= 1)) { /* Or if domain is terminal */ + pooldat.domntab[0][jobsubnum[0]] = joborgdat.domnorg; /* Update domain in next pool */ + kgraphMapRbMapPoolRemv (&pooldat, &joborgdat); /* Remove job from pool as long as graph exists */ + bgraphExit (&actgrafdat); /* Free bipartitioning data as well as current graph */ + continue; /* Process next job in current pool */ + } + else { /* Re-use job slot and graph for further bipartitioning */ + pooldat.domntab[0][jobsubnum[0]] = /* Update domain in next pool */ + joborgptr->domnorg = domnsubtab[partval]; /* New job takes same graph and non-empty subdomain */ + joborgptr->vflonbr = vflonbrtab[partval]; + joborgptr->vflotab = joborgdat.vflotab + (partval * vflonbrtab[0]); /* Point to proper sub-array */ + kgraphMapRbMapPoolUpdt1 (&pooldat, &joborgdat, actgrafdat.parttax, joborgptr, partval); /* Add job to pool */ + actgrafdat.s.flagval &= ~GRAPHFREETABS; /* Since graph will be re-used, never free its internal arrays */ + bgraphExit (&actgrafdat); /* Free bipartitioning data */ + continue; /* Process next job in current pool */ + } + } + + if ((pooldat.mappptr->domnnbr == pooldat.mappptr->domnmax) && /* If all job slots busy and if cannot resize */ + (kgraphMapRbMapPoolResize (&pooldat) != 0)) { + errorPrint ("kgraphMapRbMap: cannot resize structures"); + kgraphMapRbMapPoolExit (&pooldat); + return (1); + } + + jobsubnum[1] = pooldat.mappptr->domnnbr ++; /* Get slot number of new subdomain */ + jobsubsiz[1] = actgrafdat.s.vertnbr - actgrafdat.compsize0; + jobsubsiz[0] = actgrafdat.compsize0; + + pooldat.jobtab[jobsubnum[1]].poolflag = 0; /* Assume that new job is inactive in case of premature freeing */ + pooldat.domntab[1][jobsubnum[1]] = joborgdat.domnorg; /* Copy original domain to new subdomain as old mapping shares parttax with new */ + pooldat.domntab[0][jobsubnum[0]] = domnsubtab[0]; /* Set subdomains of second mapping before relinking subjobs in pool */ + pooldat.domntab[0][jobsubnum[1]] = domnsubtab[1]; + + if ((pooldat.flagval & KGRAPHMAPRBMAPPARTHALF) != 0) /* If can only update second half */ + kgraphMapRbMapPartOne (&pooldat, &actgrafdat, jobsubnum[1]); + else + kgraphMapRbMapPartBoth (&pooldat, &actgrafdat, jobsubnum); + + for (i = 1; i >= 0; i --) { /* For both subdomains */ + KgraphMapRbMapJob * jobsubptr; + + jobsubptr = &pooldat.jobtab[jobsubnum[i]]; /* Point to subdomain job slot */ + jobsubptr->poollink.prev = /* Prevent Valgrind from yelling in kgraphMapRbMapPoolResize() */ + jobsubptr->poollink.next = NULL; + jobsubptr->prioval = /* Prevent Valgrind from yelling in kgraphMapRbMapPoolRemv()/Updt1()/Updt2() */ + jobsubptr->priolvl = 0; + + if ((((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) == 0) && (archDomSize (mappptr->archptr, &domnsubtab[i]) <= 1)) || /* If single-vertex domain */ + (((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) != 0) && (jobsubsiz[i] <= 1))) { /* Or if variable-sized architecture with single vertex graph */ + jobsubsiz[i] = 0; /* Cancel subjob */ + continue; + } + + partval = i; /* At least this subjob works */ + + if (graphInducePart (&actgrafdat.s, actgrafdat.parttax, jobsubsiz[i], (GraphPart) i, &jobsubptr->grafdat) != 0) { + errorPrint ("kgraphMapRbMap: cannot create induced subgraph"); + bgraphExit (&actgrafdat); + kgraphMapRbMapPoolExit (&pooldat); + return (1); + } + jobsubptr->poolflag = 1; /* So that graph is freed in case of error on other part */ + jobsubptr->domnorg = domnsubtab[i]; + jobsubptr->vflonbr = vflonbrtab[i]; + jobsubptr->vflotab = joborgdat.vflotab + (i * vflonbrtab[0]); /* Point to proper sub-array */ + } + + if ((jobsubsiz[0] | jobsubsiz[1]) == 0) /* If both subjobs do not need further processing */ + kgraphMapRbMapPoolRemv (&pooldat, &joborgdat); + else if (jobsubsiz[1 - partval] == 0) /* If one of the subjobs only needs further processing */ + kgraphMapRbMapPoolUpdt1 (&pooldat, &joborgdat, actgrafdat.parttax, &pooldat.jobtab[jobsubnum[partval]], (GraphPart) partval); + else + kgraphMapRbMapPoolUpdt2 (&pooldat, &joborgdat, actgrafdat.parttax, &pooldat.jobtab[jobsubnum[0]], &pooldat.jobtab[jobsubnum[1]]); + + bgraphExit (&actgrafdat); /* Free bipartition graph data */ + } + + kgraphMapRbMapPoolSwap (&pooldat); /* Swap current and next levels */ + } + + kgraphMapRbMapPoolExit (&pooldat); /* Free internal structures and propagate back new partition */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_rb_map.h b/scotch_6.0.3/src/libscotch/kgraph_map_rb_map.h new file mode 100644 index 00000000..c3db4425 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_rb_map.h @@ -0,0 +1,148 @@ +/* Copyright 2004,2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_rb_map.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the Dual Recursive Bipartitioning **/ +/** mapping algorithm. **/ +/** **/ +/** DATES : # Version 0.0 : from : 23 mar 1993 **/ +/** to 12 may 1993 **/ +/** # Version 1.3 : from : 06 apr 1994 **/ +/** to 09 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 04 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 30 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 28 sep 1995 **/ +/** # Version 3.1 : from : 15 nov 1995 **/ +/** to 15 nov 1995 **/ +/** # Version 3.2 : from : 01 oct 1996 **/ +/** to 10 jun 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 17 may 1999 **/ +/** # Version 3.4 : from : 12 sep 2001 **/ +/** to 06 nov 2001 **/ +/** # Version 4.0 : from : 29 nov 2003 **/ +/** to 05 may 2006 **/ +/** # Version 5.1 : from : 30 sep 2008 **/ +/** to 04 nov 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 28 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Dual recursive bipartitioning option flags. +*/ + +#define KGRAPHMAPRBMAPARCHVAR 0x0001 /* Variable-sized architecture */ +#define KGRAPHMAPRBMAPARCHCMPLT 0x0002 /* Complete-graph architecture */ +#define KGRAPHMAPRBMAPPARTHALF 0x0004 /* Only update half of part array as mappings are tied */ + +/* +** The type and structure definitions. +*/ + +/*+ Job pool structures. +*/ + +typedef struct KgraphMapRbMapPoolLink_ { + struct KgraphMapRbMapPoolLink_ * prev; /*+ Pointer to previous link +*/ + struct KgraphMapRbMapPoolLink_ * next; /*+ Pointer to next link +*/ +} KgraphMapRbMapPoolLink; + +/*+ This structure defines a job to be + performed with respect to a partial + mapping of a source graph. +*/ + +typedef struct KgraphMapRbMapJob_ { + KgraphMapRbMapPoolLink poollink; /*+ Link to job pool; TRICK: FIRST +*/ + KgraphMapRbMapPoolLink * poolptr; /*+ Pointer to last/current job pool +*/ + int poolflag; /*+ Flag set if job in pool +*/ + Gnum prioval; /*+ Job priority value by policy +*/ + Gnum priolvl; /*+ Priority level computed for this job +*/ + ArchDom domnorg; /*+ Domain to which the vertices belong +*/ + Graph grafdat; /*+ Job graph data (may be clone of another) +*/ + Anum vflonbr; /*+ Number of fixed vertex load slots +*/ + KgraphMapRbVflo * vflotab; /*+ Partial array of fixed vertex load slots +*/ +} KgraphMapRbMapJob; + +/*+ This structure defines the working data, + for easier parameter passing. +*/ + +typedef struct KgraphMapRbMapPoolData_ { + int flagval; /*+ Pool flag value +*/ + KgraphMapRbPolicy polival; /*+ Job selection policy +*/ + const Graph * grafptr; /*+ Pointer to top graph +*/ + const Anum * pfixtax; /*+ Pointer to fixed part array +*/ + KgraphMapRbMapPoolLink linktab[2]; /*+ Lists of jobs in pools +*/ + KgraphMapRbMapPoolLink * pooltab[2]; /*+ Pointer to pools (same if tied) +*/ + ArchDom * domntab[2]; /*+ Pointer to domain arrays (same if tied) +*/ + KgraphMapRbMapJob * jobtab; /*+ Job table +*/ + Mapping * mappptr; /*+ Pointer to original mapping: current state +*/ +} KgraphMapRbMapPoolData; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_RB_MAP +#define static +#endif + +static int kgraphMapRbMapPoolInit (KgraphMapRbMapPoolData * restrict const, const KgraphMapRbData * restrict const); +static void kgraphMapRbMapPoolExit (KgraphMapRbMapPoolData * restrict const poolptr); +static void kgraphMapRbMapPoolAdd (KgraphMapRbMapPoolLink * restrict const, KgraphMapRbMapJob * const); +static KgraphMapRbMapJob * kgraphMapRbMapPoolGet (KgraphMapRbMapPoolData * restrict const); +static void kgraphMapRbMapPoolFrst (KgraphMapRbMapPoolData * const, KgraphMapRbMapJob * const); +static void kgraphMapRbMapPoolUpdt1 (KgraphMapRbMapPoolData * const, const KgraphMapRbMapJob * const, const GraphPart * const, KgraphMapRbMapJob * const, const GraphPart); +static void kgraphMapRbMapPoolUpdt2 (KgraphMapRbMapPoolData * const, const KgraphMapRbMapJob * const, const GraphPart * const, KgraphMapRbMapJob * const, KgraphMapRbMapJob * const); + +int kgraphMapRbMap (const KgraphMapRbData * restrict const, const Graph * restrict const, const Anum, KgraphMapRbVflo * restrict const); + +static int kgraphMapRbMapPoolResize (KgraphMapRbMapPoolData * restrict const); + +#undef static + +/* +** The macro definitions. +*/ + +#define kgraphMapRbMapPoolEmpty(poolptr) ((poolptr)->pooltab[0]->next == &kgraphmaprbmappooldummy) diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_rb_part.c b/scotch_6.0.3/src/libscotch/kgraph_map_rb_part.c new file mode 100644 index 00000000..077a3b05 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_rb_part.c @@ -0,0 +1,339 @@ +/* Copyright 2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_rb_part.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module performs the Dual Recursive **/ +/** Bipartitioning mapping algorithm for **/ +/** (eventually weighted) complete graph **/ +/** target architectures. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 sep 2008 **/ +/** to 31 aug 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 16 sep 2014 **/ +/** **/ +/** NOTES : # This is a rewrite of kgraphMapRb() **/ +/** for complete-graph target topologies. **/ +/** Its advantage over kgraphMapRbMap() **/ +/** is that no job arrays are allocated, **/ +/** which can save space for instance for **/ +/** using the variable-sized complete **/ +/** graph architecture. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_RB_PART + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "kgraph.h" +#include "kgraph_map_rb.h" +#include "kgraph_map_rb_part.h" + +/********************************************/ +/* */ +/* This is the entry point for the Dual */ +/* Recursive Bipartitioning mapping method. */ +/* */ +/********************************************/ + +/* This routine updates partial mappings +** according to the result of the recursive +** bipartitioning process. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +void +kgraphMapRbPart3 ( +const Graph * restrict const srcgrafptr, /* Graph to induce and bipartition */ +const GraphPart * restrict const srcparttax, /* Part array of original graph */ +const GraphPart indpartval, /* Part of graph to consider */ +const int domnnum, /* Index of domain onto which map the part */ +Mapping * restrict const mappptr) /* Final mapping */ +{ + Gnum vertnum; + + const Gnum * restrict const srcvnumtax = srcgrafptr->vnumtax; + Anum * restrict const mapparttax = mappptr->parttax; + + if (srcparttax == NULL) { /* If graph is full graph */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (domnnum != 0) { + errorPrint ("kgraphMapRbPart3: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + if (srcvnumtax == NULL) /* If full graph doesn't have fixed vertices */ + memSet (mapparttax + srcgrafptr->baseval, 0, srcgrafptr->vertnbr * sizeof (Anum)); + else { + Gnum vertnnd; + + for (vertnum = srcgrafptr->baseval, vertnnd = srcgrafptr->vertnnd; + vertnum < vertnnd; vertnum ++) { +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[srcvnumtax[vertnum]] == ~0) { + errorPrint ("kgraphMapRbPart3: internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + mapparttax[srcvnumtax[vertnum]] = domnnum; + } + } + } + else { /* Graph to consider is a subgraph of the original graph */ + if (srcvnumtax == NULL) { /* If original graph is not itself a subgraph */ + Gnum vertnnd; + + for (vertnum = srcgrafptr->baseval, vertnnd = srcgrafptr->vertnnd; + vertnum < vertnnd; vertnum ++) { + if (srcparttax[vertnum] == indpartval) { /* If vertex belongs to the right part */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[vertnum] == ~0) { + errorPrint ("kgraphMapRbPart3: internal error (3)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + mapparttax[vertnum] = domnnum; + } + } + } + else { + Gnum vertnnd; + + for (vertnum = srcgrafptr->baseval, vertnnd = srcgrafptr->vertnnd; + vertnum < vertnnd; vertnum ++) { + if (srcparttax[vertnum] == indpartval) { /* If vertex belongs to the right part */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (mapparttax[srcvnumtax[vertnum]] == ~0) { + errorPrint ("kgraphMapRbPart3: internal error (4)"); + return; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + mapparttax[srcvnumtax[vertnum]] = domnnum; + } + } + } + } +} + +/* This routine is the core of the degenerated, +** graph partitioning version of the Dual Recursive +** Bipartitioning algorithm. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +int +kgraphMapRbPart2 ( +const KgraphMapRbData * restrict const dataptr, /*+ Global mapping data +*/ +const Graph * restrict const srcgrafptr, /*+ Graph to induce and bipartition +*/ +const GraphPart * restrict const srcparttax, /*+ Part array of original graph to consider +*/ +const GraphPart indpartval, /*+ Part of graph to consider +*/ +const Gnum indvertnbr, /*+ Number of vertices in part or in graph +*/ +const Anum domnnum, /*+ Index of domain onto which to map the part +*/ +const Anum vflonbr, /*+ Number of fixed vertex load slots +*/ +KgraphMapRbVflo * restrict const vflotab) /*+ Array of fixed vertex load slots +*/ +{ + Graph indgrafdat; + const Graph * indgrafptr; + Bgraph actgrafdat; + Anum domnsubidx; + Anum domnsubdlt; + ArchDom domnsubtab[2]; /* Target subdomains */ + Anum domnidxtab[2]; /* Index of subdomains in mapping */ + Gnum vertnbrtab[2]; /* Number of vertices in subgraphs */ + Anum vflonbrtab[2]; /* Number of fixed vertex slots in subdomains */ + Gnum vflowgttab[2]; /* Weights of fixed vertex slots in subdomains */ + Mapping * restrict mappptr; + int avarval; /* Flag set if variable-sized */ + int i; + int o; + + mappptr = dataptr->mappptr; + avarval = archVar (mappptr->archptr); + o = (avarval && /* If architecture is variable-sized */ + (indvertnbr <= 1)) /* And source subgraph of minimal size */ + ? 1 /* Then do not bipartition target more */ + : archDomBipart (mappptr->archptr, &mappptr->domntab[domnnum], &domnsubtab[0], &domnsubtab[1]); + + switch (o) { + case 1 : /* If target domain is terminal */ + kgraphMapRbPart3 (srcgrafptr, srcparttax, indpartval, domnnum, mappptr); /* Update mapping and return */ + return (0); + case 2 : /* On error */ + errorPrint ("kgraphMapRbPart2: cannot bipartition domain"); + return (1); + } + + indgrafptr = srcgrafptr; /* Assume we will work on the original graph */ + if ((srcparttax != NULL) && /* If not the case, build induced subgraph */ + (indvertnbr < srcgrafptr->vertnbr)) { + indgrafptr = &indgrafdat; + if (graphInducePart (srcgrafptr, srcparttax, indvertnbr, indpartval, &indgrafdat) != 0) { + errorPrint ("kgraphMapRbPart2: cannot induce graph"); + return (1); + } + } + + kgraphMapRbVfloSplit (mappptr->archptr, domnsubtab, vflonbr, vflotab, vflonbrtab, vflowgttab); + + if (kgraphMapRbBgraph (dataptr, &actgrafdat, indgrafptr, mappptr, domnsubtab, vflowgttab) != 0) { /* Create active graph */ + errorPrint ("kgraphMapRbPart2: cannot create bipartition graph"); + return (1); + } + + if (! avarval) { /* If not variable-sized, impose constraints on bipartition */ + double comploadavg; + + comploadavg = (double) (actgrafdat.s.velosum + vflowgttab[0] + vflowgttab[1]) / + (double) archDomWght (mappptr->archptr, &mappptr->domntab[domnnum]); + actgrafdat.compload0min = actgrafdat.compload0avg - + (Gnum) MIN ((dataptr->comploadmax - comploadavg) * (double) actgrafdat.domnwght[0], + (comploadavg - dataptr->comploadmin) * (double) actgrafdat.domnwght[1]); + actgrafdat.compload0max = actgrafdat.compload0avg + + (Gnum) MIN ((comploadavg - dataptr->comploadmin) * (double) actgrafdat.domnwght[0], + (dataptr->comploadmax - comploadavg) * (double) actgrafdat.domnwght[1]); + } + + if (bgraphBipartSt (&actgrafdat, dataptr->paraptr->strat) != 0) { /* Perform bipartitioning */ + errorPrint ("kgraphMapRbPart2: cannot bipartition graph"); + bgraphExit (&actgrafdat); + return (1); + } + memFree (actgrafdat.frontab); /* Frontier array of bipartitioning graph is no longer necessary */ + actgrafdat.s.flagval &= ~BGRAPHFREEFRON; + + if (archVar (mappptr->archptr)) { /* If architecture is variable-sized */ + if ((actgrafdat.compsize0 == 0) || /* If bipartition failed */ + (actgrafdat.compsize0 == actgrafdat.s.vertnbr)) { + bgraphExit (&actgrafdat); /* Free bipartition graph (that is, parttax) */ + if (indgrafptr == &indgrafdat) /* If an induced subgraph had been created */ + graphExit (&indgrafdat); /* Free it */ + kgraphMapRbPart3 (srcgrafptr, srcparttax, indpartval, domnnum, mappptr); /* Update mapping with original domain */ + return (0); + } + } + + domnsubdlt = mappptr->domnnbr - domnnum; /* Increment in domain number */ + domnsubidx = domnnum - domnsubdlt; /* Place where to insert subdomain */ + mappptr->domnnbr --; /* One less subdomain as for now */ + vertnbrtab[0] = actgrafdat.compsize0; + vertnbrtab[1] = actgrafdat.s.vertnbr - actgrafdat.compsize0; + + o = 0; + for (i = 1; i >= 0; i --) { /* For all subparts */ + if (vertnbrtab[i] <= 0) /* If subpart is empty, skip it */ + continue; + + mappptr->domnnbr ++; /* One more subdomain to account for */ + if (mappptr->domnnbr > mappptr->domnmax) { + if ((o = mapResize (mappptr, mappptr->domnmax + (mappptr->domnmax >> 2) + 8)) != 0) { /* Increase size by 25% */ + errorPrint ("kgraphMapRbPart: cannot resize structures"); + break; + } + } + domnsubidx += domnsubdlt; /* Compute location of subdomain */ + domnidxtab[i] = domnsubidx; /* Record it before recursion */ + mappptr->domntab[domnsubidx] = domnsubtab[i]; /* Write it at this (new) place */ + } + + if (o == 0) { + for (i = 1; i >= 0; i --) { /* For all subparts */ + if (vertnbrtab[i] <= 0) /* If subpart is empty, skip it */ + continue; + + if ((o = kgraphMapRbPart2 (dataptr, indgrafptr, actgrafdat.parttax, (GraphPart) i, vertnbrtab[i], + domnidxtab[i], vflonbrtab[i], vflotab + (i * vflonbrtab[0]))) != 0) + return (1); /* If problem in recursion, stop */ + } + } + + bgraphExit (&actgrafdat); /* Free bipartition graph (that is, parttax) */ + if (indgrafptr == &indgrafdat) /* If an induced subgraph had been created */ + graphExit (&indgrafdat); /* Free it */ + + return (o); +} + +/* This routine is the entry point for +** the degenerated, graph partitioning +** version, of the Dual Recursive +** Bipartitioning algorithm. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kgraphMapRbPart ( +const KgraphMapRbData * restrict const dataptr, /*+ Global mapping data +*/ +const Graph * restrict const grafptr, /*+ Graph to map, without fixed vertices +*/ +const Anum vflonbr, /*+ Number of fixed vertex load slots +*/ +KgraphMapRbVflo * restrict const vflotab) /*+ Array of fixed vertex load slots +*/ +{ + Mapping * restrict const mappptr = dataptr->mappptr; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (dataptr->pfixtax != NULL) { /* In debug mode, fixed vertex parts are set to ~0 */ + Gnum vertnum; + + for (vertnum = dataptr->grafptr->baseval; vertnum < dataptr->grafptr->vertnnd; vertnum ++) + mappptr->parttax[vertnum] = (dataptr->pfixtax[vertnum] >= 0) ? ~0 : 0; + } + else + memSet (mappptr->parttax + dataptr->grafptr->baseval, 0, dataptr->grafptr->vertnbr * sizeof (Anum)); +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + + mappptr->domntab[0] = mappptr->domnorg; /* Initialize mapping */ + mappptr->domnnbr = 1; + return (kgraphMapRbPart2 (dataptr, grafptr, NULL, 0, grafptr->vertnbr, 0, vflonbr, vflotab)); +} diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_rb_part.h b/scotch_6.0.3/src/libscotch/kgraph_map_rb_part.h new file mode 100644 index 00000000..e0e34bf5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_rb_part.h @@ -0,0 +1,60 @@ +/* Copyright 2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_rb_part.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the Dual Recursive Bipartitioning **/ +/** mapping algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 22 sep 2008 **/ +/** to 14 apr 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 10 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_RB_PART +#define static +#endif + +int kgraphMapRbPart (const KgraphMapRbData * restrict const, const Graph * restrict const, const Anum, KgraphMapRbVflo * restrict); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_st.c b/scotch_6.0.3/src/libscotch/kgraph_map_st.c new file mode 100644 index 00000000..de7b09da --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_st.c @@ -0,0 +1,394 @@ +/* Copyright 2004,2007,2009-2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_st.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the strategy and **/ +/** method tables for the multi-way static **/ +/** mapping routines. **/ +/** **/ +/** DATES : # Version 3.2 : from : 15 oct 1996 **/ +/** to 26 may 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 17 may 1999 **/ +/** # Version 3.4 : from : 12 sep 2001 **/ +/** to 12 sep 2001 **/ +/** # Version 4.0 : from : 12 jan 2004 **/ +/** to 05 jan 2005 **/ +/** # Version 5.1 : from : 04 oct 2009 **/ +/** to 29 mar 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_MAP_ST + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "gain.h" +#include "fibo.h" +#include "graph.h" +#include "arch.h" +#include "graph_coarsen.h" +#include "mapping.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "kgraph.h" +#include "kgraph_map_bd.h" +#include "kgraph_map_cp.h" +#include "kgraph_map_df.h" +#include "kgraph_map_ex.h" +#include "kgraph_map_fm.h" +#include "kgraph_map_ml.h" +#include "kgraph_map_rb.h" +#include "kgraph_map_st.h" + +/* +** The static and global variables. +*/ + +static Kgraph kgraphdummy; /*+ Dummy active graph for offset computations +*/ + +static union { + KgraphMapBdParam param; + StratNodeMethodData padding; +} kgraphmapstdefaultbd = { { 3, &stratdummy, &stratdummy } }; + +static union { + StratNodeMethodData padding; +} kgraphmapstdefaultcp; + +static union { + KgraphMapDfParam param; + StratNodeMethodData padding; +} kgraphmapstdefaultdf = { { 40, 1.0F, 0.0F } }; + +static union { + KgraphMapExParam param; + StratNodeMethodData padding; +} kgraphmapstdefaultex = { { 0.05 } }; + +static union { + KgraphMapFmParam param; + StratNodeMethodData padding; +} kgraphmapstdefaultfm = { { 200, ~0, 0.05 } }; + +static union { + KgraphMapMlParam param; + StratNodeMethodData padding; +} kgraphmapstdefaultml = { { 100, 0.8, &stratdummy, &stratdummy, 0 } }; + +static union { + KgraphMapRbParam param; + StratNodeMethodData padding; +} kgraphmapstdefaultrb = { { 1, 1, KGRAPHMAPRBPOLINGSIZE, &stratdummy, 0.05 } }; + +static StratMethodTab kgraphmapstmethtab[] = { /* Mapping methods array */ + { KGRAPHMAPSTMETHBD, "b", kgraphMapBd, &kgraphmapstdefaultbd }, + { KGRAPHMAPSTMETHCP, "c", kgraphMapCp, &kgraphmapstdefaultcp }, + { KGRAPHMAPSTMETHDF, "d", kgraphMapDf, &kgraphmapstdefaultdf }, + { KGRAPHMAPSTMETHEX, "x", kgraphMapEx, &kgraphmapstdefaultex }, + { KGRAPHMAPSTMETHFM, "f", kgraphMapFm, &kgraphmapstdefaultfm }, + { KGRAPHMAPSTMETHML, "m", kgraphMapMl, &kgraphmapstdefaultml }, + { KGRAPHMAPSTMETHRB, "r", kgraphMapRb, &kgraphmapstdefaultrb }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab kgraphmapstparatab[] = { /* Method parameter list */ + { KGRAPHMAPSTMETHBD, STRATPARAMINT, "width", + (byte *) &kgraphmapstdefaultbd.param, + (byte *) &kgraphmapstdefaultbd.param.distmax, + NULL }, + { KGRAPHMAPSTMETHBD, STRATPARAMSTRAT, "bnd", + (byte *) &kgraphmapstdefaultbd.param, + (byte *) &kgraphmapstdefaultbd.param.stratbnd, + (void *) &kgraphmapststratab }, + { KGRAPHMAPSTMETHBD, STRATPARAMSTRAT, "org", + (byte *) &kgraphmapstdefaultbd.param, + (byte *) &kgraphmapstdefaultbd.param.stratorg, + (void *) &kgraphmapststratab }, + { KGRAPHMAPSTMETHDF, STRATPARAMINT, "pass", + (byte *) &kgraphmapstdefaultdf.param, + (byte *) &kgraphmapstdefaultdf.param.passnbr, + NULL }, + { KGRAPHMAPSTMETHDF, STRATPARAMDOUBLE, "dif", + (byte *) &kgraphmapstdefaultdf.param, + (byte *) &kgraphmapstdefaultdf.param.cdifval, + NULL }, + { KGRAPHMAPSTMETHDF, STRATPARAMDOUBLE, "rem", + (byte *) &kgraphmapstdefaultdf.param, + (byte *) &kgraphmapstdefaultdf.param.cremval, + NULL }, + { KGRAPHMAPSTMETHEX, STRATPARAMDOUBLE, "bal", + (byte *) &kgraphmapstdefaultex.param, + (byte *) &kgraphmapstdefaultex.param.kbalval, + (void *) &kgraphmapststratab }, + { KGRAPHMAPSTMETHFM, STRATPARAMINT, "move", + (byte *) &kgraphmapstdefaultfm.param, + (byte *) &kgraphmapstdefaultfm.param.movenbr, + NULL }, + { KGRAPHMAPSTMETHFM, STRATPARAMINT, "pass", + (byte *) &kgraphmapstdefaultfm.param, + (byte *) &kgraphmapstdefaultfm.param.passnbr, + NULL }, + { KGRAPHMAPSTMETHFM, STRATPARAMDOUBLE, "bal", + (byte *) &kgraphmapstdefaultfm.param, + (byte *) &kgraphmapstdefaultfm.param.deltval, + NULL }, + { KGRAPHMAPSTMETHML, STRATPARAMSTRAT, "asc", + (byte *) &kgraphmapstdefaultml.param, + (byte *) &kgraphmapstdefaultml.param.stratasc, + (void *) &kgraphmapststratab }, + { KGRAPHMAPSTMETHML, STRATPARAMSTRAT, "low", + (byte *) &kgraphmapstdefaultml.param, + (byte *) &kgraphmapstdefaultml.param.stratlow, + (void *) &kgraphmapststratab }, + { KGRAPHMAPSTMETHML, STRATPARAMINT, "vert", + (byte *) &kgraphmapstdefaultml.param, + (byte *) &kgraphmapstdefaultml.param.coarnbr, + NULL }, + { KGRAPHMAPSTMETHML, STRATPARAMDOUBLE, "rat", + (byte *) &kgraphmapstdefaultml.param, + (byte *) &kgraphmapstdefaultml.param.coarval, + NULL }, + { KGRAPHMAPSTMETHML, STRATPARAMCASE, "type", + (byte *) &kgraphmapstdefaultml.param, + (byte *) &kgraphmapstdefaultml.param.typeval, + (void *) "hscd" }, + { KGRAPHMAPSTMETHRB, STRATPARAMCASE, "job", + (byte *) &kgraphmapstdefaultrb.param, + (byte *) &kgraphmapstdefaultrb.param.flagjobtie, + (void *) "ut" }, + { KGRAPHMAPSTMETHRB, STRATPARAMDOUBLE, "bal", + (byte *) &kgraphmapstdefaultrb.param, + (byte *) &kgraphmapstdefaultrb.param.kbalval, + NULL }, + { KGRAPHMAPSTMETHRB, STRATPARAMCASE, "map", + (byte *) &kgraphmapstdefaultrb.param, + (byte *) &kgraphmapstdefaultrb.param.flagmaptie, + (void *) "ut" }, + { KGRAPHMAPSTMETHRB, STRATPARAMCASE, "poli", + (byte *) &kgraphmapstdefaultrb.param, + (byte *) &kgraphmapstdefaultrb.param.polival, + (void *) "rls LS" }, + { KGRAPHMAPSTMETHRB, STRATPARAMSTRAT, "sep", + (byte *) &kgraphmapstdefaultrb.param, + (byte *) &kgraphmapstdefaultrb.param.strat, + (void *) &bgraphbipartststratab }, + { KGRAPHMAPSTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab kgraphmapstcondtab[] = { /* Graph condition parameter table */ + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &kgraphdummy, + (byte *) &kgraphdummy.s.velosum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &kgraphdummy, + (byte *) &kgraphdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &kgraphdummy, + (byte *) &kgraphdummy.s.edgenbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vert", + (byte *) &kgraphdummy, + (byte *) &kgraphdummy.s.vertnbr, + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab kgraphmapststratab = { /* Strategy tables for graph mapping methods */ + kgraphmapstmethtab, + kgraphmapstparatab, + kgraphmapstcondtab }; + +/****************************************/ +/* */ +/* This is the generic mapping routine. */ +/* */ +/****************************************/ + +/* This routine computes the given +** mapping according to the given +** strategy. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +kgraphMapSt ( +Kgraph * restrict const grafptr, /*+ Mapping graph +*/ +const Strat * restrict const strat) /*+ Mapping strategy +*/ +{ + StratTest val; /* Result of condition evaluation */ + KgraphStore savetab[2]; /* Results of the two strategies */ + Gnum comploaddltasu[2]; /* Absolute sum of computation load delta */ + ArchDom domnfrst; /* Largest domain in the architecture */ + Anum partnbr; /* Number of processors in the target topology */ + Anum partnum; + int o; + int o2; + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (sizeof (Gnum) != sizeof (INT)) { + errorPrint ("kgraphMapSt: invalid type specification for parser variables"); + return (1); + } + if ((sizeof (KgraphMapRbParam) > sizeof (StratNodeMethodData))) { + errorPrint ("kgraphMapSt: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ +#ifdef SCOTCH_DEBUG_KGRAPH1 + if ((strat->tabl != &kgraphmapststratab) && + (strat != &stratdummy)) { + errorPrint ("kgraphMapSt: invalid parameter (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_KGRAPH1 */ + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + o = kgraphMapSt (grafptr, strat->data.concat.strat[0]); /* Apply first strategy */ + if (o == 0) /* If it worked all right */ + o |= kgraphMapSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ + break; + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + if ((val.typetest != STRATTESTVAL) || + (val.typenode != STRATPARAMLOG)) { + errorPrint ("kgraphMapSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_KGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = kgraphMapSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = kgraphMapSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + break; + case STRATNODESELECT : + archDomFrst (&grafptr->a, &domnfrst); /* Get architecture domain */ + partnbr = archDomSize (&grafptr->a, &domnfrst); /* Get architecture size */ + + if (((kgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ + ((kgraphStoreInit (grafptr, &savetab[1])) != 0)) { + errorPrint ("kgraphMapSt: out of memory"); + kgraphStoreExit (&savetab[0]); + return (1); + } + + kgraphStoreSave (grafptr, &savetab[1]); /* Save initial partition */ + o = kgraphMapSt (grafptr, strat->data.select.strat[0]); /* Apply first strategy */ + kgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ + kgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial partition */ + o2 = kgraphMapSt (grafptr, strat->data.select.strat[1]); /* Apply second strategy */ + + if ((o == 0) || (o2 == 0)) { /* If at least one method has computed a partition */ + Gnum comploadadlt; + int b0; + int b1; + + comploaddltasu[0] = + comploaddltasu[1] = 0; + b0 = o; /* Assume that balance is invalid if partitioning has failed */ + b1 = o2; + for (partnum = 0; partnum < partnbr; partnum ++) { + comploadadlt = abs (savetab[0].comploaddlt[partnum]); + if (comploadadlt > ((Gnum) ((double) savetab[0].comploadavg[partnum] * savetab[0].kbalval))) + b0 |= 1; + comploaddltasu[0] += comploadadlt; + comploadadlt = abs (grafptr->comploaddlt[partnum]); + if (comploadadlt > ((Gnum) ((double) grafptr->comploadavg[partnum] * grafptr->kbalval))) + b1 |= 1; + comploaddltasu[1] += comploadadlt; + } + do { /* Do we want to restore partition 0? */ + if (b0 > b1) + break; + if (b0 == b1) { /* If both are valid or invalid */ + if (b0 == 0) { /* If both are valid */ + if ( (savetab[0].commload > grafptr->commload) || /* Compare on cut */ + ((savetab[0].commload == grafptr->commload) && + (comploaddltasu[0] > comploaddltasu[1]))) + break; + } + else { /* If both are invalid */ + if ( (comploaddltasu[0] > comploaddltasu[1]) || /* Compare on imbalance */ + ((comploaddltasu[0] == comploaddltasu[1]) && + (savetab[0].commload > grafptr->commload))) + break; + } + } + + kgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ + } while (0); + } + if (o2 < o) /* o = min(o,o2): if one parts, then part */ + o = o2; /* Else if one stops, then stop, else error */ + + kgraphStoreExit (&savetab[0]); /* Free both save areas */ + kgraphStoreExit (&savetab[1]); + break; +#ifdef SCOTCH_DEBUG_KGRAPH1 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_KGRAPH1 */ + default : +#endif /* SCOTCH_DEBUG_KGRAPH1 */ + return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_KGRAPH1 + default : + errorPrint ("kgraphMapSt: invalid parameter (2)"); + return (1); +#endif /* SCOTCH_DEBUG_KGRAPH1 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/kgraph_map_st.h b/scotch_6.0.3/src/libscotch/kgraph_map_st.h new file mode 100644 index 00000000..c8dca4c9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_map_st.h @@ -0,0 +1,90 @@ +/* Copyright 2004,2007,2010-2012 IPB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_map_st.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the strategy and method **/ +/** tables and the generic entry point for **/ +/** the graph multipartitioning methods. **/ +/** **/ +/** DATES : # Version 3.2 : from : 15 oct 1996 **/ +/** to 29 sep 1997 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 09 dec 1998 **/ +/** # Version 4.0 : from : 12 jan 2004 **/ +/** to 12 jan 2004 **/ +/** # Version 5.1 : from : 13 jul 2010 **/ +/** to 13 jul 2010 **/ +/** # Version 6.0 : from : 08 jun 2011 **/ +/** to 16 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum KgraphMapStMethodType_ { + KGRAPHMAPSTMETHBD = 0, /*+ Band (strategy) +*/ + KGRAPHMAPSTMETHCP, /*+ Old mapping copy +*/ + KGRAPHMAPSTMETHDF, /*+ Diffusion +*/ + KGRAPHMAPSTMETHEX, /*+ Exactifier +*/ + KGRAPHMAPSTMETHFM, /*+ Fiduccia-Mattheyses +*/ + KGRAPHMAPSTMETHML, /*+ Multi-level (strategy) +*/ + KGRAPHMAPSTMETHRB, /*+ Dual Recursive Bipartitioning +*/ + KGRAPHMAPSTMETHNBR /*+ Number of methods +*/ +} KgraphMapStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab kgraphmapststratab; + +/* +** The function prototypes. +*/ + +#ifndef KGRAPH_MAP_ST +#define static +#endif + +int kgraphMapSt (Kgraph * restrict const, const Strat * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/kgraph_store.c b/scotch_6.0.3/src/libscotch/kgraph_store.c new file mode 100644 index 00000000..e209cf08 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/kgraph_store.c @@ -0,0 +1,167 @@ +/* Copyright 2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : kgraph_store.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the save data **/ +/** structure handling routines for k-par- **/ +/** tition graphs. **/ +/** **/ +/** DATES : # Version 6.0 : from : 16 aug 2011 **/ +/** to 16 aug 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define KGRAPH_STORE + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "kgraph.h" + +/**********************************/ +/* */ +/* Store graph handling routines. */ +/* */ +/**********************************/ + +/* This routine builds a save structure +** for the given active graph. +** It returns: +** - 0 : if allocation succeeded. +** - !0 : on error. +*/ + +int +kgraphStoreInit ( +const Kgraph * const grafptr, +KgraphStore * const storptr) +{ + ArchDom domnfrst; /* Largest domain in the architecture */ + + archDomFrst (&grafptr->a, &domnfrst); /* Get architecture domain */ + storptr->partnbr = (Gnum) archDomSize (&grafptr->a, &domnfrst); /* Get architecture size */ + + if (memAllocGroup ((void **) (void *) /* Allocate save structure */ + &storptr->parttab, (size_t) (grafptr->s.vertnbr * sizeof (Anum)), + &storptr->domntab, (size_t) (grafptr->m.domnmax * sizeof (ArchDom)), + &storptr->frontab, (size_t) (grafptr->s.vertnbr * sizeof (Gnum)), + &storptr->comploadavg, (size_t) (storptr->partnbr * sizeof (Gnum)), + &storptr->comploaddlt, (size_t) (storptr->partnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("kgraphStoreInit out of memory (1)"); + return (1); + } + + return (0); +} + +/* This routine frees a save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +kgraphStoreExit ( +KgraphStore * const storptr) +{ + memFree (storptr->parttab); /* Free group leader */ +#ifdef SCOTCH_DEBUG_KGRAPH2 + storptr->parttab = NULL; + storptr->domntab = NULL; + storptr->frontab = NULL; + storptr->comploadavg = NULL; + storptr->comploaddlt = NULL; +#endif /* SCOTCH_DEBUG_KGRAPH2 */ +} + +/* This routine saves partition data from the +** given active graph to the given save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +kgraphStoreSave ( +const Kgraph * const grafptr, +KgraphStore * const storptr) +{ + storptr->mflaval = grafptr->commload; + storptr->domnnbr = grafptr->m.domnnbr; + storptr->fronnbr = grafptr->fronnbr; + storptr->kbalval = grafptr->kbalval; + storptr->commload = grafptr->commload; + + memCpy (storptr->parttab, grafptr->m.parttax + grafptr->s.baseval, grafptr->s.vertnbr * sizeof (Anum)); + memCpy (storptr->domntab, grafptr->m.domntab, grafptr->m.domnnbr * sizeof (ArchDom)); + memCpy (storptr->frontab, grafptr->frontab, storptr->fronnbr * sizeof (Gnum)); + memCpy (storptr->comploadavg, grafptr->comploadavg, storptr->partnbr * sizeof (Gnum)); + memCpy (storptr->comploaddlt, grafptr->comploaddlt, storptr->partnbr * sizeof (Gnum)); +} + +/* This routine updates partition data of the +** given active graph, using the given save graph. +** It returns: +** - VOID : in all cases. +*/ + +void +kgraphStoreUpdt ( +Kgraph * const grafptr, +const KgraphStore * const storptr) +{ + grafptr->commload = storptr->mflaval; + grafptr->m.domnnbr = storptr->domnnbr; + grafptr->fronnbr = storptr->fronnbr; + grafptr->kbalval = storptr->kbalval; + grafptr->commload = storptr->commload; + + memCpy (grafptr->m.parttax + grafptr->s.baseval, storptr->parttab, grafptr->s.vertnbr * sizeof (Anum)); + memCpy (grafptr->m.domntab, storptr->domntab, grafptr->m.domnnbr * sizeof (ArchDom)); + memCpy (grafptr->frontab, storptr->frontab, storptr->fronnbr * sizeof (Gnum)); + memCpy (grafptr->comploadavg, storptr->comploadavg, storptr->partnbr * sizeof (Gnum)); + memCpy (grafptr->comploaddlt, storptr->comploaddlt, storptr->partnbr * sizeof (Gnum)); + +#ifdef SCOTCH_DEBUG_KGRAPH2 + if (kgraphCheck (grafptr) != 0) + errorPrint ("kgraphStoreUpdt: inconsistent graph data"); +#endif /* SCOTCH_DEBUG_KGRAPH2 */ +} diff --git a/scotch_6.0.3/src/libscotch/last_resort/parser_ll.c b/scotch_6.0.3/src/libscotch/last_resort/parser_ll.c new file mode 100644 index 00000000..cf8c5ddc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/last_resort/parser_ll.c @@ -0,0 +1,2077 @@ +#line 2 "lex.yy.c" + +#line 4 "lex.yy.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer scotchyy_create_buffer +#define yy_delete_buffer scotchyy_delete_buffer +#define yy_flex_debug scotchyy_flex_debug +#define yy_init_buffer scotchyy_init_buffer +#define yy_flush_buffer scotchyy_flush_buffer +#define yy_load_buffer_state scotchyy_load_buffer_state +#define yy_switch_to_buffer scotchyy_switch_to_buffer +#define yyin scotchyyin +#define yyleng scotchyyleng +#define yylex scotchyylex +#define yylineno scotchyylineno +#define yyout scotchyyout +#define yyrestart scotchyyrestart +#define yytext scotchyytext +#define yywrap scotchyywrap +#define yyalloc scotchyyalloc +#define yyrealloc scotchyyrealloc +#define yyfree scotchyyfree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 37 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE scotchyyrestart(scotchyyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t scotchyyleng; + +extern FILE *scotchyyin, *scotchyyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up scotchyytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up scotchyytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via scotchyyrestart()), so that the user can continue scanning by + * just pointing scotchyyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when scotchyytext is formed. */ +static char yy_hold_char; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t scotchyyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow scotchyywrap()'s to do buffer switches + * instead of setting up a fresh scotchyyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void scotchyyrestart (FILE *input_file ); +void scotchyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE scotchyy_create_buffer (FILE *file,int size ); +void scotchyy_delete_buffer (YY_BUFFER_STATE b ); +void scotchyy_flush_buffer (YY_BUFFER_STATE b ); +void scotchyypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void scotchyypop_buffer_state (void ); + +static void scotchyyensure_buffer_stack (void ); +static void scotchyy_load_buffer_state (void ); +static void scotchyy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER scotchyy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE scotchyy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE scotchyy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE scotchyy_scan_bytes (yyconst char *bytes,yy_size_t len ); + +void *scotchyyalloc (yy_size_t ); +void *scotchyyrealloc (void *,yy_size_t ); +void scotchyyfree (void * ); + +#define yy_new_buffer scotchyy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + scotchyyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + scotchyy_create_buffer(scotchyyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + scotchyyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + scotchyy_create_buffer(scotchyyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +typedef unsigned char YY_CHAR; + +FILE *scotchyyin = (FILE *) 0, *scotchyyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int scotchyylineno; + +int scotchyylineno = 1; + +extern char *scotchyytext; +#define yytext_ptr scotchyytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up scotchyytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + scotchyyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 13 +#define YY_END_OF_BUFFER 14 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[53] = + { 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 14, 12, 11, 11, + 1, 2, 3, 4, 5, 12, 8, 10, 11, 2, + 0, 4, 0, 0, 5, 0, 0, 7, 0, 8, + 0, 10, 4, 0, 4, 6, 0, 6, 9, 0, + 9, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 5, 1, 5, 6, 1, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, + 1, 1, 1, 1, 8, 8, 8, 8, 9, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 1, 1, 1, 1, 1, 8, 8, 8, 8, + + 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[10] = + { 0, + 1, 2, 2, 1, 1, 1, 3, 3, 3 + } ; + +static yyconst flex_int16_t yy_base[58] = + { 0, + 0, 2, 0, 0, 2, 0, 5, 0, 57, 56, + 55, 54, 56, 55, 8, 0, 58, 65, 0, 0, + 65, 0, 65, 12, 16, 53, 20, 0, 0, 0, + 49, 0, 25, 48, 0, 28, 50, 65, 39, 0, + 31, 0, 32, 36, 33, 35, 30, 27, 38, 24, + 21, 65, 47, 22, 17, 50, 3 + } ; + +static yyconst flex_int16_t yy_def[58] = + { 0, + 53, 53, 2, 3, 2, 5, 5, 7, 2, 2, + 2, 2, 2, 2, 2, 15, 52, 52, 54, 54, + 52, 55, 52, 52, 52, 56, 52, 57, 54, 55, + 52, 24, 52, 52, 25, 52, 56, 52, 52, 27, + 52, 57, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 0, 52, 52, 52, 52, 52 + } ; + +static yyconst flex_int16_t yy_nxt[75] = + { 0, + 52, 19, 20, 19, 20, 42, 21, 21, 21, 22, + 22, 23, 23, 23, 27, 28, 28, 31, 32, 30, + 33, 34, 35, 29, 36, 39, 40, 51, 41, 44, + 51, 45, 47, 48, 48, 50, 48, 51, 43, 45, + 33, 46, 45, 36, 49, 49, 41, 18, 18, 18, + 37, 37, 37, 38, 46, 43, 38, 52, 26, 26, + 25, 25, 24, 24, 17, 52, 52, 52, 52, 52, + 52, 52, 52, 52 + } ; + +static yyconst flex_int16_t yy_chk[75] = + { 0, + 0, 1, 1, 2, 2, 57, 3, 3, 3, 5, + 5, 7, 7, 7, 15, 15, 15, 24, 24, 55, + 24, 25, 25, 54, 25, 27, 27, 51, 27, 33, + 50, 33, 36, 48, 36, 41, 47, 41, 43, 45, + 43, 46, 44, 46, 49, 39, 49, 53, 53, 53, + 56, 56, 56, 37, 34, 31, 26, 17, 14, 13, + 12, 11, 10, 9, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int scotchyy_flex_debug; +int scotchyy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *scotchyytext; +#line 1 "parser_ll.l" +#line 2 "parser_ll.l" +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parser_ll.l **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the lexical parser **/ +/** which processes strategy strings. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 nov 1995 **/ +/** to 23 aug 1996 **/ +/** # Version 3.2 : from : 24 sep 1996 **/ +/** to 05 jun 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 11 sep 2001 **/ +/** # Version 4.0 : from : 20 dec 2001 **/ +/** to 23 dec 2001 **/ +/** # Version 5.1 : from : 09 jun 2009 **/ +/** to 24 jul 2011 **/ +/** **/ +/** NOTES : # In order for flex to read its input **/ +/** with getc() instead of fread, we set **/ +/** YY_ALWAYS_INTERACTIVE to 1. This may **/ +/** not always work with future releases. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define PARSER_LL + +#include "module.h" +#include "common.h" + +#undef INTEGER /* In case someone defined them */ +#undef DOUBLE + +#include "parser.h" +#include "parser_ll.h" +#include "parser_yy.h" +#include "parser_ly.h" /*+ Definitions produced by yacc +*/ + +/* Assume no interactive parsing. */ + +#ifdef X_OSDOS /* Available only with MKS LEX */ +#ifdef YY_INTERACTIVE +#undef YY_INTERACTIVE +#endif /* YY_INTERACTIVE */ +#define YY_INTERACTIVE 0 +#endif /* X_OSDOS */ + +#ifdef FLEX_SCANNER +#define YY_ALWAYS_INTERACTIVE 1 /* Set the parser as interactive and read one char at a time */ +#define YY_INPUT(buf,result,max_size) { int c = stratParserInput (); result = (c == 0) ? YY_NULL : ((buf)[0] = c, 1); } +#else /* FLEX_SCANNER */ +#undef getc /* Redirect I/O functions */ +#define getc yygetc +#undef yygetc +#define yygetc(stream) stratParserInput () +#endif /* FLEX_SCANNER */ + +#define YY_NO_UNPUT /* No prototype for yyunput as not defined */ +#define YY_SKIP_YYWRAP /* No prototype for scotchyywrap as defined as macro */ +#define scotchyywrap() (1) /* Always return end-of-file on end-of-string */ + +/* +** The static variables. +*/ + +static const char * stratparserstringptr; /* Pointer to the string to parse */ + + + + + + + + +#line 611 "lex.yy.c" + +#define INITIAL 0 +#define lstrat 1 +#define lparam 2 +#define lparamcase 3 +#define lparamdouble 4 +#define lparamint 5 +#define lparamstring 6 +#define ltest 7 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int scotchyylex_destroy (void ); + +int scotchyyget_debug (void ); + +void scotchyyset_debug (int debug_flag ); + +YY_EXTRA_TYPE scotchyyget_extra (void ); + +void scotchyyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *scotchyyget_in (void ); + +void scotchyyset_in (FILE * in_str ); + +FILE *scotchyyget_out (void ); + +void scotchyyset_out (FILE * out_str ); + +yy_size_t scotchyyget_leng (void ); + +char *scotchyyget_text (void ); + +int scotchyyget_lineno (void ); + +void scotchyyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int scotchyywrap (void ); +#else +extern int scotchyywrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( scotchyytext, scotchyyleng, 1, scotchyyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( scotchyyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( scotchyyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, scotchyyin))==0 && ferror(scotchyyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(scotchyyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int scotchyylex (void); + +#define YY_DECL int scotchyylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after scotchyytext and scotchyyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 121 "parser_ll.l" + +#line 802 "lex.yy.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! scotchyyin ) + scotchyyin = stdin; + + if ( ! scotchyyout ) + scotchyyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + scotchyyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + scotchyy_create_buffer(scotchyyin,YY_BUF_SIZE ); + } + + scotchyy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of scotchyytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 65 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 122 "parser_ll.l" +{ + strncpy (yylval.STRING, scotchyytext, PARSERSTRINGLEN); + yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; + return (METHODNAME); + } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 128 "parser_ll.l" +{ + strncpy (yylval.STRING, scotchyytext, PARSERSTRINGLEN); + yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; + return (PARAMNAME); + } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 134 "parser_ll.l" +{ + yylval.CASEVAL = scotchyytext[0]; + return (VALCASE); + } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 139 "parser_ll.l" +{ + yylval.DOUBLE = atof (scotchyytext); + return (VALDOUBLE); + } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 144 "parser_ll.l" +{ + yylval.INTEGER = (INT) atol (scotchyytext); + return (VALINT); + } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 148 "parser_ll.l" +{ + yylval.INTEGER = (INT) atof (scotchyytext); /* FLOAT is put after so that INTEGER can be matched */ + return (VALINT); + } + YY_BREAK +case 7: +/* rule 7 can match eol */ +YY_RULE_SETUP +#line 153 "parser_ll.l" +{ + scotchyytext[scotchyyleng - 1] = '\0'; /* Remove the heading and trailing \" */ + strncpy (yylval.STRING, scotchyytext + 1, PARSERSTRINGLEN); + yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; + return (VALSTRING); + } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 160 "parser_ll.l" +{ + yylval.INTEGER = (INT) atol (scotchyytext); + return (VALINT); + } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 164 "parser_ll.l" +{ + yylval.DOUBLE = atof (scotchyytext); + return (VALDOUBLE); + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 168 "parser_ll.l" +{ + strncpy (yylval.STRING, scotchyytext, PARSERSTRINGLEN); + yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; + return (PARAMNAME); + } + YY_BREAK +case 11: +/* rule 11 can match eol */ +YY_RULE_SETUP +#line 174 "parser_ll.l" +; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 175 "parser_ll.l" +return (scotchyytext[0]); + YY_BREAK +case 13: +YY_RULE_SETUP +#line 177 "parser_ll.l" +ECHO; + YY_BREAK +#line 987 "lex.yy.c" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(lstrat): +case YY_STATE_EOF(lparam): +case YY_STATE_EOF(lparamcase): +case YY_STATE_EOF(lparamdouble): +case YY_STATE_EOF(lparamint): +case YY_STATE_EOF(lparamstring): +case YY_STATE_EOF(ltest): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed scotchyyin at a new source and called + * scotchyylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = scotchyyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( scotchyywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * scotchyytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of scotchyylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + scotchyyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + scotchyyrestart(scotchyyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) scotchyyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 52); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up scotchyytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register yy_size_t number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + scotchyyrestart(scotchyyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( scotchyywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve scotchyytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void scotchyyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + scotchyyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + scotchyy_create_buffer(scotchyyin,YY_BUF_SIZE ); + } + + scotchyy_init_buffer(YY_CURRENT_BUFFER,input_file ); + scotchyy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void scotchyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * scotchyypop_buffer_state(); + * scotchyypush_buffer_state(new_buffer); + */ + scotchyyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + scotchyy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (scotchyywrap()) processing, but the only time this flag + * is looked at is after scotchyywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void scotchyy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + scotchyyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE scotchyy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) scotchyyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in scotchyy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) scotchyyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in scotchyy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + scotchyy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with scotchyy_create_buffer() + * + */ + void scotchyy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + scotchyyfree((void *) b->yy_ch_buf ); + + scotchyyfree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a scotchyyrestart() or at EOF. + */ + static void scotchyy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + scotchyy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then scotchyy_init_buffer was _probably_ + * called from scotchyyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void scotchyy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + scotchyy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void scotchyypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + scotchyyensure_buffer_stack(); + + /* This block is copied from scotchyy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from scotchyy_switch_to_buffer. */ + scotchyy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void scotchyypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + scotchyy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + scotchyy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void scotchyyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)scotchyyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in scotchyyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)scotchyyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in scotchyyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE scotchyy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) scotchyyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in scotchyy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + scotchyy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to scotchyylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * scotchyy_scan_bytes() instead. + */ +YY_BUFFER_STATE scotchyy_scan_string (yyconst char * yystr ) +{ + + return scotchyy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to scotchyylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE scotchyy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) scotchyyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in scotchyy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = scotchyy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in scotchyy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up scotchyytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + scotchyytext[scotchyyleng] = (yy_hold_char); \ + (yy_c_buf_p) = scotchyytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + scotchyyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int scotchyyget_lineno (void) +{ + + return scotchyylineno; +} + +/** Get the input stream. + * + */ +FILE *scotchyyget_in (void) +{ + return scotchyyin; +} + +/** Get the output stream. + * + */ +FILE *scotchyyget_out (void) +{ + return scotchyyout; +} + +/** Get the length of the current token. + * + */ +yy_size_t scotchyyget_leng (void) +{ + return scotchyyleng; +} + +/** Get the current token. + * + */ + +char *scotchyyget_text (void) +{ + return scotchyytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void scotchyyset_lineno (int line_number ) +{ + + scotchyylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see scotchyy_switch_to_buffer + */ +void scotchyyset_in (FILE * in_str ) +{ + scotchyyin = in_str ; +} + +void scotchyyset_out (FILE * out_str ) +{ + scotchyyout = out_str ; +} + +int scotchyyget_debug (void) +{ + return scotchyy_flex_debug; +} + +void scotchyyset_debug (int bdebug ) +{ + scotchyy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from scotchyylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + scotchyyin = stdin; + scotchyyout = stdout; +#else + scotchyyin = (FILE *) 0; + scotchyyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * scotchyylex_init() + */ + return 0; +} + +/* scotchyylex_destroy is for both reentrant and non-reentrant scanners. */ +int scotchyylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + scotchyy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + scotchyypop_buffer_state(); + } + + /* Destroy the stack itself. */ + scotchyyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * scotchyylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *scotchyyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *scotchyyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void scotchyyfree (void * ptr ) +{ + free( (char *) ptr ); /* see scotchyyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 177 "parser_ll.l" + + + +/*******************************************/ +/* */ +/* These routines handle data input to the */ +/* lexical analyzer. */ +/* */ +/*******************************************/ + +/* This routine initializes the +** lexical analyzer. +** It returns: +** - VOID : in all cases. +*/ + +void +stratParserInit ( +const char * const string) /*+ Strategy string to parse +*/ +{ +#ifdef FLEX_SCANNER + scotchyyrestart (scotchyyin); /* (Re-)initialize the parser */ +#endif /* FLEX_SCANNER */ + + stratParserSelect (VALSTRAT); /* Begin with a strategy */ + stratparserstringptr = string; /* Point to beginning of string */ +} + +/* This routine reads a single character +** from the input string. +** It returns: +** - 0 : if end of string reached. +** - !0 : character from string. +*/ + +static +int +stratParserInput () +{ + if (*stratparserstringptr == '\0') /* If end-of-string reached */ + return (0); /* Return end-of-file token */ + else /* Else return the character */ + return ((int) (unsigned char) *stratparserstringptr ++); +} + +/* This routine returns the pointer to the +** remaining part of the string. +*/ + +const char * +stratParserRemain () +{ + return (stratparserstringptr); +} + +/* This routine selects the sub-parser +** to parse the input. +** It returns: +** - VOID : in all cases. +*/ + +void +stratParserSelect ( +unsigned int type) +{ + switch (type) { + case VALCASE : + BEGIN lparamcase; + break; + case VALDOUBLE : + BEGIN lparamdouble; + break; + case VALINT : + BEGIN lparamint; + break; + case VALSTRING : + BEGIN lparamstring; + break; + case VALPARAM : + BEGIN lparam; + break; + case VALSTRAT : + BEGIN lstrat; + break; + case VALTEST : + BEGIN ltest; + break; + } +} + diff --git a/scotch_6.0.3/src/libscotch/last_resort/parser_ly.h b/scotch_6.0.3/src/libscotch/last_resort/parser_ly.h new file mode 100644 index 00000000..5866be52 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/last_resort/parser_ly.h @@ -0,0 +1,101 @@ +/* A Bison parser, made by GNU Bison 3.0.2. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_SCOTCHYY_Y_TAB_H_INCLUDED +# define YY_SCOTCHYY_Y_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int scotchyydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + METHODNAME = 258, + PARAMNAME = 259, + VALCASE = 260, + VALDOUBLE = 261, + VALINT = 262, + VALSTRING = 263, + VALSTRAT = 264, + VALPARAM = 265, + VALTEST = 266 + }; +#endif +/* Tokens. */ +#define METHODNAME 258 +#define PARAMNAME 259 +#define VALCASE 260 +#define VALDOUBLE 261 +#define VALINT 262 +#define VALSTRING 263 +#define VALSTRAT 264 +#define VALPARAM 265 +#define VALTEST 266 + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE YYSTYPE; +union YYSTYPE +{ +#line 92 "parser_yy.y" /* yacc.c:1909 */ + + char CASEVAL; /* Case value */ + StratTest * TEST; /* Test type */ + StratTestType TESTOP; /* Relational type */ + double DOUBLE; /* Double-precision */ + INT INTEGER; /* Integer */ + char STRING[PARSERSTRINGLEN]; /* Character string */ + struct { + const StratTab * tabl; /* Current tables */ + Strat * strat; /* Current method */ + StratParamTab * param; /* Current parameter */ + } SAVE; /* Parameter type */ + Strat * STRAT; /* Strategy tree */ + +#line 91 "y.tab.h" /* yacc.c:1909 */ +}; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE scotchyylval; + +int scotchyyparse (void); + +#endif /* !YY_SCOTCHYY_Y_TAB_H_INCLUDED */ diff --git a/scotch_6.0.3/src/libscotch/last_resort/parser_yy.c b/scotch_6.0.3/src/libscotch/last_resort/parser_yy.c new file mode 100644 index 00000000..85df1829 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/last_resort/parser_yy.c @@ -0,0 +1,2415 @@ +/* A Bison parser, made by GNU Bison 3.0.2. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + +/* Substitute the variable and function names. */ +#define yyparse scotchyyparse +#define yylex scotchyylex +#define yyerror scotchyyerror +#define yydebug scotchyydebug +#define yynerrs scotchyynerrs + +#define yylval scotchyylval +#define yychar scotchyychar + +/* Copy the first part of user declarations. */ +#line 1 "parser_yy.y" /* yacc.c:339 */ + +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parser_yy.y **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the syntactic parser **/ +/** which processes strategy strings. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 nov 1995 **/ +/** to 13 jun 1996 **/ +/** # Version 3.2 : from : 24 sep 1996 **/ +/** to 27 feb 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 20 dec 2001 **/ +/** to 11 jun 2004 **/ +/** # Version 5.1 : from : 30 oct 2007 **/ +/** to 24 jul 2011 **/ +/** # Version 6.0 : from : 30 sep 2014 **/ +/** to 30 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define PARSER_YY + +#include "module.h" +#include "common.h" + +#undef INTEGER /* In case someone defined them */ +#undef DOUBLE + +#include "parser.h" +#include "parser_ll.h" +#include "parser_yy.h" + +/* #define SCOTCH_DEBUG_PARSER3 */ +#ifdef SCOTCH_DEBUG_PARSER3 +extern int yydebug; +#define YYDEBUG 1 +#endif /* SCOTCH_DEBUG_PARSER3 */ + +/* +** The static and global definitions. +** See also at the end of this file. +*/ + +static const StratTab * parserstrattab; /* Pointer to parsing tables */ +static Strat * parserstratcurr = NULL; /* Pointer to current strategy node */ +static StratParamTab * parserparamcurr = NULL; /* Pointer to current parameter */ + +extern unsigned int parsermethtokentab[]; /* Pre-definition for stupid compilers */ + + +#line 165 "y.tab.c" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "y.tab.h". */ +#ifndef YY_SCOTCHYY_Y_TAB_H_INCLUDED +# define YY_SCOTCHYY_Y_TAB_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int scotchyydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + METHODNAME = 258, + PARAMNAME = 259, + VALCASE = 260, + VALDOUBLE = 261, + VALINT = 262, + VALSTRING = 263, + VALSTRAT = 264, + VALPARAM = 265, + VALTEST = 266 + }; +#endif +/* Tokens. */ +#define METHODNAME 258 +#define PARAMNAME 259 +#define VALCASE 260 +#define VALDOUBLE 261 +#define VALINT 262 +#define VALSTRING 263 +#define VALSTRAT 264 +#define VALPARAM 265 +#define VALTEST 266 + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE YYSTYPE; +union YYSTYPE +{ +#line 92 "parser_yy.y" /* yacc.c:355 */ + + char CASEVAL; /* Case value */ + StratTest * TEST; /* Test type */ + StratTestType TESTOP; /* Relational type */ + double DOUBLE; /* Double-precision */ + INT INTEGER; /* Integer */ + char STRING[PARSERSTRINGLEN]; /* Character string */ + struct { + const StratTab * tabl; /* Current tables */ + Strat * strat; /* Current method */ + StratParamTab * param; /* Current parameter */ + } SAVE; /* Parameter type */ + Strat * STRAT; /* Strategy tree */ + +#line 242 "y.tab.c" /* yacc.c:355 */ +}; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE scotchyylval; + +int scotchyyparse (void); + +#endif /* !YY_SCOTCHYY_Y_TAB_H_INCLUDED */ + +/* Copy the second part of user declarations. */ + +#line 257 "y.tab.c" /* yacc.c:358 */ + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 13 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 93 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 31 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 37 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 65 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 93 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 266 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 24, 2, 2, 2, 30, 23, 2, + 17, 18, 29, 27, 21, 28, 2, 13, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 16, 15, + 25, 22, 26, 14, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 19, 12, 20, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 132, 132, 138, 156, 159, 161, 176, 194, 198, + 202, 198, 226, 229, 234, 239, 243, 247, 246, 308, + 312, 308, 316, 319, 320, 324, 323, 362, 397, 412, + 427, 444, 444, 468, 476, 479, 497, 500, 518, 521, + 537, 541, 544, 563, 567, 571, 577, 593, 596, 600, + 606, 622, 625, 631, 647, 650, 656, 660, 661, 664, + 679, 696, 737, 741, 744, 748 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "METHODNAME", "PARAMNAME", "VALCASE", + "VALDOUBLE", "VALINT", "VALSTRING", "VALSTRAT", "VALPARAM", "VALTEST", + "'|'", "'/'", "'?'", "';'", "':'", "'('", "')'", "'{'", "'}'", "','", + "'='", "'&'", "'!'", "'<'", "'>'", "'+'", "'-'", "'*'", "'%'", "$accept", + "STRAT", "STRATSELECT", "STRATEMPTY", "STRATCONCAT", "STRATTEST", "$@1", + "$@2", "STRATTESTELSE", "STRATGROUP", "STRATMETHOD", "$@3", + "METHODPARAM", "$@4", "$@5", "PARAMLIST", "PARAMPARAM", "@6", "PARAMVAL", + "@7", "TEST", "TESTOR", "TESTAND", "TESTNOT", "TESTREL", "TESTRELOP", + "TESTEXPR1", "TESTEXPR1OP", "TESTEXPR2", "TESTEXPR2OP", "TESTEXPR3", + "TESTEXPR3OP", "TESTEXPR4", "TESTVAL", "TESTVAR", "VALSDOUBLE", + "VALSINT", YY_NULLPTR +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 124, 47, 63, 59, 58, 40, 41, 123, + 125, 44, 61, 38, 33, 60, 62, 43, 45, 42, + 37 +}; +# endif + +#define YYPACT_NINF -33 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-33))) + +#define YYTABLE_NINF -32 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + 5, -33, 5, 10, 7, -33, 5, -33, 4, -33, + -33, 19, 40, -33, 5, -33, 27, -33, 20, -33, + -33, -33, -33, -33, 27, 27, -33, -33, -33, 28, + 3, -33, -33, 47, -1, 33, 13, -33, -33, -33, + -33, -33, 44, 41, 39, -33, 42, 27, 27, -33, + -33, -33, 43, 43, -33, -33, -33, 43, -33, 43, + -33, 55, -33, -33, -33, 5, 3, -33, 43, -4, + 33, 13, -33, 46, 44, 57, -9, 14, 8, -33, + -33, 5, 63, -33, -33, -33, -33, 5, -33, -33, + 7, -33, 7 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 6, 17, 6, 0, 2, 4, 5, 8, 0, 12, + 16, 22, 0, 1, 6, 7, 0, 18, 0, 15, + 3, 61, 63, 65, 0, 0, 48, 49, 10, 34, + 36, 38, 41, 0, 0, 47, 51, 54, 57, 58, + 59, 60, 0, 0, 0, 39, 0, 0, 0, 44, + 43, 45, 0, 0, 62, 64, 52, 0, 55, 0, + 25, 20, 24, 40, 56, 6, 35, 37, 0, 42, + 46, 50, 53, 0, 0, 0, 14, 0, 0, 23, + 21, 6, 0, 33, 27, 30, 26, 6, 28, 29, + 13, 11, 32 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -33, -33, -2, 66, -33, 75, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, 9, -33, -33, -33, + -33, 58, 37, -21, -33, -33, -22, -32, 34, -33, + 29, -33, 30, -33, -33, 12, 15 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 3, 4, 5, 6, 7, 8, 46, 82, 9, + 10, 11, 17, 18, 75, 61, 62, 73, 86, 87, + 28, 29, 30, 31, 32, 52, 33, 34, 35, 57, + 36, 59, 37, 38, 39, 40, 41 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int8 yytable[] = +{ + 12, 53, 44, 14, 45, 54, 55, 81, 1, 83, + 13, -31, 53, 84, 22, 23, 85, 16, -9, 14, + -31, -31, 2, 26, 27, -31, 48, 67, -31, -31, + 69, 21, 64, 22, 23, 26, 27, 53, -19, 42, + 47, 26, 27, 58, 24, 53, 77, 21, 60, 22, + 23, 25, 14, 47, 26, 27, 65, 64, 19, 63, + 68, 49, 56, 76, 50, 51, 26, 27, 78, 49, + 26, 27, 50, 51, 26, 27, 74, 80, 91, 90, + 20, 15, 43, 79, 66, 92, 71, 70, 0, 72, + 88, 0, 0, 89 +}; + +static const yytype_int8 yycheck[] = +{ + 2, 33, 24, 12, 25, 6, 7, 16, 3, 1, + 0, 3, 44, 5, 6, 7, 8, 13, 13, 12, + 12, 13, 17, 27, 28, 17, 23, 48, 20, 21, + 52, 4, 18, 6, 7, 27, 28, 69, 19, 19, + 12, 27, 28, 30, 17, 77, 68, 4, 4, 6, + 7, 24, 12, 12, 27, 28, 14, 18, 18, 18, + 17, 22, 29, 65, 25, 26, 27, 28, 22, 22, + 27, 28, 25, 26, 27, 28, 21, 20, 15, 81, + 14, 6, 24, 74, 47, 87, 57, 53, -1, 59, + 78, -1, -1, 78 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 17, 32, 33, 34, 35, 36, 37, 40, + 41, 42, 33, 0, 12, 36, 13, 43, 44, 18, + 34, 4, 6, 7, 17, 24, 27, 28, 51, 52, + 53, 54, 55, 57, 58, 59, 61, 63, 64, 65, + 66, 67, 19, 52, 57, 54, 38, 12, 23, 22, + 25, 26, 56, 58, 6, 7, 29, 60, 30, 62, + 4, 46, 47, 18, 18, 14, 53, 54, 17, 57, + 59, 61, 63, 48, 21, 45, 33, 57, 22, 47, + 20, 16, 39, 1, 5, 8, 49, 50, 66, 67, + 33, 15, 33 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 31, 32, 33, 33, 34, 34, 35, 35, 37, + 38, 36, 36, 39, 39, 40, 40, 42, 41, 44, + 45, 43, 43, 46, 46, 48, 47, 49, 49, 49, + 49, 50, 49, 49, 51, 52, 52, 53, 53, 54, + 54, 54, 55, 56, 56, 56, 57, 57, 58, 58, + 59, 59, 60, 61, 61, 62, 63, 63, 63, 64, + 64, 65, 66, 66, 67, 67 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 3, 1, 1, 0, 2, 1, 0, + 0, 8, 1, 2, 0, 3, 1, 0, 3, 0, + 0, 5, 0, 3, 1, 0, 4, 1, 1, 1, + 1, 0, 2, 1, 1, 3, 1, 3, 1, 2, + 3, 1, 3, 1, 1, 1, 3, 1, 1, 1, + 3, 1, 1, 3, 1, 1, 3, 1, 1, 1, + 1, 1, 2, 1, 2, 1 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +{ + YYUSE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 133 "parser_yy.y" /* yacc.c:1646 */ + { + parserstratcurr = ((yyvsp[0].STRAT)); /* Save pointer to root of tree */ + } +#line 1406 "y.tab.c" /* yacc.c:1646 */ + break; + + case 3: +#line 139 "parser_yy.y" /* yacc.c:1646 */ + { + Strat * strat; + + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (2)"); + stratExit ((yyvsp[-2].STRAT)); + stratExit ((yyvsp[0].STRAT)); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODESELECT; + strat->data.select.strat[0] = ((yyvsp[-2].STRAT)); + strat->data.select.strat[1] = ((yyvsp[0].STRAT)); + + ((yyval.STRAT)) = strat; + } +#line 1428 "y.tab.c" /* yacc.c:1646 */ + break; + + case 6: +#line 161 "parser_yy.y" /* yacc.c:1646 */ + { + Strat * strat; + + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (3)"); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODEEMPTY; + + ((yyval.STRAT)) = strat; + } +#line 1446 "y.tab.c" /* yacc.c:1646 */ + break; + + case 7: +#line 177 "parser_yy.y" /* yacc.c:1646 */ + { + Strat * strat; + + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (4)"); + stratExit ((yyvsp[-1].STRAT)); + stratExit ((yyvsp[0].STRAT)); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODECONCAT; + strat->data.concat.strat[0] = ((yyvsp[-1].STRAT)); + strat->data.concat.strat[1] = ((yyvsp[0].STRAT)); + + ((yyval.STRAT)) = strat; + } +#line 1468 "y.tab.c" /* yacc.c:1646 */ + break; + + case 9: +#line 198 "parser_yy.y" /* yacc.c:1646 */ + { + stratParserSelect (VALTEST); /* Parse parameter tokens */ + } +#line 1476 "y.tab.c" /* yacc.c:1646 */ + break; + + case 10: +#line 202 "parser_yy.y" /* yacc.c:1646 */ + { + stratParserSelect (VALSTRAT); /* Parse strategy tokens */ + } +#line 1484 "y.tab.c" /* yacc.c:1646 */ + break; + + case 11: +#line 206 "parser_yy.y" /* yacc.c:1646 */ + { + Strat * strat; + + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (1)"); + stratExit ((yyvsp[-2].STRAT)); + if (((yyvsp[-1].STRAT)) != NULL) + stratExit ((yyvsp[-1].STRAT)); + stratTestExit ((yyvsp[-5].TEST)); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODECOND; + strat->data.cond.test = ((yyvsp[-5].TEST)); + strat->data.cond.strat[0] = ((yyvsp[-2].STRAT)); + strat->data.cond.strat[1] = ((yyvsp[-1].STRAT)); + + ((yyval.STRAT)) = strat; + } +#line 1509 "y.tab.c" /* yacc.c:1646 */ + break; + + case 13: +#line 230 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.STRAT)) = ((yyvsp[0].STRAT)); + } +#line 1517 "y.tab.c" /* yacc.c:1646 */ + break; + + case 14: +#line 234 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.STRAT)) = NULL; + } +#line 1525 "y.tab.c" /* yacc.c:1646 */ + break; + + case 15: +#line 240 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.STRAT)) = ((yyvsp[-1].STRAT)); + } +#line 1533 "y.tab.c" /* yacc.c:1646 */ + break; + + case 17: +#line 247 "parser_yy.y" /* yacc.c:1646 */ + { + Strat * strat; + int meth; + int methlen; + StratMethodTab * methtab; + int i, j; + + meth = + methlen = 0; /* No method recognized yet */ + methtab = parserstrattab->methtab; /* Point to the method table */ + for (i = 0; methtab[i].name != NULL; i ++) { + if ((strncasecmp (((yyvsp[0].STRING)), /* Find longest matching code name */ + methtab[i].name, + j = strlen (methtab[i].name)) == 0) && + (j > methlen)) { + meth = methtab[i].meth; + methlen = j; + } + } + if (methlen == 0) { /* If method name not known */ + errorPrint ("stratParserParse: invalid method name \"%s\", before \"%s\"", + ((yyvsp[0].STRING)), stratParserRemain ()); + YYABORT; + } + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (5)"); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODEMETHOD; + strat->data.method.meth = meth; /* Set method type */ + if (methtab[meth].data != NULL) /* If default values exist */ + memcpy (&strat->data.method.data, /* Set values to default */ + methtab[meth].data, + sizeof (StratNodeMethodData)); + + parserstratcurr = strat; /* Structure available for parameter processing */ + } +#line 1577 "y.tab.c" /* yacc.c:1646 */ + break; + + case 18: +#line 287 "parser_yy.y" /* yacc.c:1646 */ + { + StratParamTab * paratab; + int i; + + paratab = parserstrattab->paratab; /* Point to the parameter table */ + for (i = 0; paratab[i].name != NULL; i ++) { + if ((paratab[i].meth == parserstratcurr->data.method.meth) && /* If a strategy parameter found for this method */ + (paratab[i].type == STRATPARAMSTRAT)) { + if (*((Strat **) ((byte *) &parserstratcurr->data.method.data + /* And this parameter has not been set */ + (paratab[i].dataofft - paratab[i].database))) == NULL) + errorPrintW ("stratParserParse: strategy parameter \"%s\" of method \"%s\" not set, before \"%s\"", + paratab[i].name, parserstrattab->methtab[parserstratcurr->data.method.meth].name, stratParserRemain ()); + } + } + + ((yyval.STRAT)) = parserstratcurr; /* Return current structure */ + parserstratcurr = NULL; /* No current structure */ + } +#line 1600 "y.tab.c" /* yacc.c:1646 */ + break; + + case 19: +#line 308 "parser_yy.y" /* yacc.c:1646 */ + { + stratParserSelect (VALPARAM); /* Parse parameter tokens */ + } +#line 1608 "y.tab.c" /* yacc.c:1646 */ + break; + + case 20: +#line 312 "parser_yy.y" /* yacc.c:1646 */ + { + stratParserSelect (VALSTRAT); /* Parse strategy tokens */ + } +#line 1616 "y.tab.c" /* yacc.c:1646 */ + break; + + case 25: +#line 324 "parser_yy.y" /* yacc.c:1646 */ + { + int para; + int paralen; + StratParamTab * paratab; + int i, j; + + para = + paralen = 0; /* No parameter recognized yet */ + paratab = parserstrattab->paratab; /* Point to the parameter table */ + for (i = 0; paratab[i].name != NULL; i ++) { + if ((paratab[i].meth == parserstratcurr->data.method.meth) && + (strncasecmp (((yyvsp[0].STRING)), /* Find longest matching parameter name */ + paratab[i].name, + j = strlen (paratab[i].name)) == 0) && + (j > paralen)) { + para = i; + paralen = j; + } + } + if (paralen == 0) { + errorPrint ("stratParserParse: invalid method parameter name \"%s\", before \"%s\"", + ((yyvsp[0].STRING)), stratParserRemain ()); + YYABORT; + } + + ((yyval.SAVE)).tabl = parserstrattab; /* Save current strategy tables */ + parserparamcurr = ¶tab[para]; /* Save current parameter value */ + stratParserSelect (parsermethtokentab[parserparamcurr->type & ~STRATPARAMDEPRECATED]); /* Get non-deprecated type */ + if (parserparamcurr->type == STRATPARAMSTRAT) /* If parameter is a strategy */ + parserstrattab = (StratTab *) parserparamcurr->datasltr; /* Use new strategy tables */ + } +#line 1652 "y.tab.c" /* yacc.c:1646 */ + break; + + case 26: +#line 356 "parser_yy.y" /* yacc.c:1646 */ + { + stratParserSelect (VALPARAM); /* Go-on reading parameters */ + parserstrattab = ((yyvsp[-2].SAVE)).tabl; /* Restore current strategy tables */ + } +#line 1661 "y.tab.c" /* yacc.c:1646 */ + break; + + case 27: +#line 363 "parser_yy.y" /* yacc.c:1646 */ + { + char c; /* Character read */ + char * p; /* Pointer to selector string */ + int i; /* Index in selector string */ + + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ + c = ((yyvsp[0].CASEVAL)); /* First, use char as is */ + for (p = (char *) parserparamcurr->datasltr, i = 0; + (*p != '\0') && (*p != c); + p ++, i ++) ; + if (*p == '\0') { /* Char was not found */ + c = tolower (c); /* Convert char to lower case */ + for (p = (char *) parserparamcurr->datasltr, i = 0; + (*p != '\0') && (*p != c); + p ++, i ++) ; + if (*p == '\0') { + errorPrint ("stratParserParse: invalid method parameter switch \"%s=%c\", before \"%s\"", + parserparamcurr->name, ((yyvsp[0].CASEVAL)), stratParserRemain ()); + YYABORT; + } + } + +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (int)) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (1)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + *((int *) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database))) = i; + } + } +#line 1700 "y.tab.c" /* yacc.c:1646 */ + break; + + case 28: +#line 398 "parser_yy.y" /* yacc.c:1646 */ + { + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (double)) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (2)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + *((double *) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database))) = ((yyvsp[0].DOUBLE)); + } + } +#line 1719 "y.tab.c" /* yacc.c:1646 */ + break; + + case 29: +#line 413 "parser_yy.y" /* yacc.c:1646 */ + { + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (INT)) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (3)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + *((INT *) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database))) = (INT) ((yyvsp[0].INTEGER)); + } + } +#line 1738 "y.tab.c" /* yacc.c:1646 */ + break; + + case 30: +#line 428 "parser_yy.y" /* yacc.c:1646 */ + { + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + strlen ((yyvsp[0].STRING)) + 1) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (4)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + strcpy ((char *) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database)), + ((yyvsp[0].STRING))); + } + } +#line 1758 "y.tab.c" /* yacc.c:1646 */ + break; + + case 31: +#line 444 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.SAVE)).strat = parserstratcurr; + ((yyval.SAVE)).param = parserparamcurr; + parserstratcurr = NULL; + parserparamcurr = NULL; + } +#line 1769 "y.tab.c" /* yacc.c:1646 */ + break; + + case 32: +#line 451 "parser_yy.y" /* yacc.c:1646 */ + { + parserstratcurr = ((yyvsp[-1].SAVE)).strat; /* Restore current method */ + parserparamcurr = ((yyvsp[-1].SAVE)).param; /* Restore current parameter */ + + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (Strat *)) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (5)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + *((Strat **) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database))) = ((yyvsp[0].STRAT)); + } + } +#line 1791 "y.tab.c" /* yacc.c:1646 */ + break; + + case 33: +#line 469 "parser_yy.y" /* yacc.c:1646 */ + { + errorPrint ("stratParserParse: invalid value for parameter \"%s\" of method \"%s\", before \"%s\"", + parserparamcurr->name, parserstratcurr->tabl->methtab[parserstratcurr->data.method.meth].name, stratParserRemain ()); + YYABORT; + } +#line 1801 "y.tab.c" /* yacc.c:1646 */ + break; + + case 35: +#line 480 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (6)"); + stratTestExit ((yyvsp[-2].TEST)); + stratTestExit ((yyvsp[0].TEST)); + YYABORT; + } + + test->typetest = STRATTESTOR; + test->typenode = STRATPARAMLOG; + test->data.test[0] = ((yyvsp[-2].TEST)); + test->data.test[1] = ((yyvsp[0].TEST)); + + ((yyval.TEST)) = test; + } +#line 1823 "y.tab.c" /* yacc.c:1646 */ + break; + + case 37: +#line 501 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (7)"); + stratTestExit ((yyvsp[-2].TEST)); + stratTestExit ((yyvsp[0].TEST)); + YYABORT; + } + + test->typetest = STRATTESTAND; + test->typenode = STRATPARAMLOG; + test->data.test[0] = ((yyvsp[-2].TEST)); + test->data.test[1] = ((yyvsp[0].TEST)); + + ((yyval.TEST)) = test; + } +#line 1845 "y.tab.c" /* yacc.c:1646 */ + break; + + case 39: +#line 522 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (8)"); + stratTestExit ((yyvsp[0].TEST)); + YYABORT; + } + + test->typetest = STRATTESTNOT; + test->typenode = STRATPARAMLOG; + test->data.test[0] = ((yyvsp[0].TEST)); + + ((yyval.TEST)) = test; + } +#line 1865 "y.tab.c" /* yacc.c:1646 */ + break; + + case 40: +#line 538 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TEST)) = ((yyvsp[-1].TEST)); + } +#line 1873 "y.tab.c" /* yacc.c:1646 */ + break; + + case 42: +#line 545 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (9)"); + stratTestExit ((yyvsp[-2].TEST)); + stratTestExit ((yyvsp[0].TEST)); + YYABORT; + } + test->typetest = ((yyvsp[-1].TESTOP)); + test->typenode = STRATPARAMLOG; + test->data.test[0] = ((yyvsp[-2].TEST)); + test->data.test[1] = ((yyvsp[0].TEST)); + + ((yyval.TEST)) = test; + } +#line 1894 "y.tab.c" /* yacc.c:1646 */ + break; + + case 43: +#line 564 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TESTOP)) = STRATTESTLT; + } +#line 1902 "y.tab.c" /* yacc.c:1646 */ + break; + + case 44: +#line 568 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TESTOP)) = STRATTESTEQ; + } +#line 1910 "y.tab.c" /* yacc.c:1646 */ + break; + + case 45: +#line 572 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TESTOP)) = STRATTESTGT; + } +#line 1918 "y.tab.c" /* yacc.c:1646 */ + break; + + case 46: +#line 578 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (10)"); + stratTestExit ((yyvsp[-2].TEST)); + stratTestExit ((yyvsp[0].TEST)); + YYABORT; + } + test->typetest = ((yyvsp[-1].TESTOP)); + test->data.test[0] = ((yyvsp[-2].TEST)); + test->data.test[1] = ((yyvsp[0].TEST)); + + ((yyval.TEST)) = test; + } +#line 1938 "y.tab.c" /* yacc.c:1646 */ + break; + + case 48: +#line 597 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TESTOP)) = STRATTESTADD; + } +#line 1946 "y.tab.c" /* yacc.c:1646 */ + break; + + case 49: +#line 601 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TESTOP)) = STRATTESTSUB; + } +#line 1954 "y.tab.c" /* yacc.c:1646 */ + break; + + case 50: +#line 607 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + stratTestExit ((yyvsp[-2].TEST)); + stratTestExit ((yyvsp[0].TEST)); + errorPrint ("stratParserParse: out of memory (11)"); + YYABORT; + } + test->typetest = ((yyvsp[-1].TESTOP)); + test->data.test[0] = ((yyvsp[-2].TEST)); + test->data.test[1] = ((yyvsp[0].TEST)); + + ((yyval.TEST)) = test; + } +#line 1974 "y.tab.c" /* yacc.c:1646 */ + break; + + case 52: +#line 626 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TESTOP)) = STRATTESTMUL; + } +#line 1982 "y.tab.c" /* yacc.c:1646 */ + break; + + case 53: +#line 632 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (12)"); + stratTestExit ((yyvsp[-2].TEST)); + stratTestExit ((yyvsp[0].TEST)); + YYABORT; + } + test->typetest = ((yyvsp[-1].TESTOP)); + test->data.test[0] = ((yyvsp[-2].TEST)); + test->data.test[1] = ((yyvsp[0].TEST)); + + ((yyval.TEST)) = test; + } +#line 2002 "y.tab.c" /* yacc.c:1646 */ + break; + + case 55: +#line 651 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TESTOP)) = STRATTESTMOD; + } +#line 2010 "y.tab.c" /* yacc.c:1646 */ + break; + + case 56: +#line 657 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.TEST)) = ((yyvsp[-1].TEST)); + } +#line 2018 "y.tab.c" /* yacc.c:1646 */ + break; + + case 59: +#line 665 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (13)"); + YYABORT; + } + + test->typetest = STRATTESTVAL; + test->typenode = STRATPARAMDOUBLE; + test->data.val.valdbl = ((yyvsp[0].DOUBLE)); + + ((yyval.TEST)) = test; + } +#line 2037 "y.tab.c" /* yacc.c:1646 */ + break; + + case 60: +#line 680 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (14)"); + YYABORT; + } + + test->typetest = STRATTESTVAL; + test->typenode = STRATPARAMINT; + test->data.val.valint = ((yyvsp[0].INTEGER)); + + ((yyval.TEST)) = test; + } +#line 2056 "y.tab.c" /* yacc.c:1646 */ + break; + + case 61: +#line 697 "parser_yy.y" /* yacc.c:1646 */ + { + StratTest * test; + StratParamTab * condtab; + int para; + int paralen; + int i, j; + + para = + paralen = 0; /* No parameter recognized yet */ + condtab = parserstrattab->condtab; /* Point to parameter table */ + for (i = 0; condtab[i].name != NULL; i ++) { + if ((strncasecmp (((yyvsp[0].STRING)), /* Find longest matching parameter name */ + condtab[i].name, + j = strlen (condtab[i].name)) == 0) && + (j > paralen)) { + para = i; + paralen = j; + } + } + if (paralen == 0) { + errorPrint ("stratParserParse: invalid graph parameter name \"%s\", before \"%s\"", + ((yyvsp[0].STRING)), stratParserRemain ()); + YYABORT; + } + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (15)"); + YYABORT; + } + + test->typetest = STRATTESTVAR; + test->typenode = condtab[para].type; + test->data.var.datatab = parserstrattab; + test->data.var.datadisp = condtab[para].dataofft - + condtab[para].database; + + ((yyval.TEST)) = test; + } +#line 2099 "y.tab.c" /* yacc.c:1646 */ + break; + + case 62: +#line 738 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.DOUBLE)) = (((yyvsp[-1].TESTOP)) == STRATTESTSUB) ? - ((yyvsp[0].DOUBLE)) : ((yyvsp[0].DOUBLE)); + } +#line 2107 "y.tab.c" /* yacc.c:1646 */ + break; + + case 64: +#line 745 "parser_yy.y" /* yacc.c:1646 */ + { + ((yyval.INTEGER)) = (((yyvsp[-1].TESTOP)) == STRATTESTSUB) ? - ((yyvsp[0].INTEGER)) : ((yyvsp[0].INTEGER)); + } +#line 2115 "y.tab.c" /* yacc.c:1646 */ + break; + + +#line 2119 "y.tab.c" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} +#line 751 "parser_yy.y" /* yacc.c:1906 */ + + +/* +** The static and global definitions (bis). +** These are put at the end of the file because +** the token values that they use are not yet +** defined in the first section of the file. +*/ + +unsigned int parsermethtokentab[] = { /* Table for parameter/token type conversion */ + VALCASE, + VALDOUBLE, + VALINT, + -1, /* No logical parameters */ + VALSTRAT, + VALSTRING, + -1 /* One more value to detect array overflow */ + }; + +/************************************/ +/* */ +/* These routines drive the parser. */ +/* */ +/************************************/ + +/* This routine is the entry point for +** the strategy parser. +** It returns: +** - !NULL : pointer to the strategy. +** - NULL : on error. +*/ + +Strat * +stratParserParse ( +const StratTab * const strattab, /*+ Pointer to parsing tables +*/ +const char * const string) /*+ Strategy string to parse +*/ +{ + yyclearin; /* Reset the parser state */ + +#ifdef SCOTCH_DEBUG_PARSER3 + yydebug = 1; /* Set debugging if needed */ +#endif /* SCOTCH_DEBUG_PARSER3 */ + + stratParserInit (string); /* Initialize the lexical parser */ + parserstrattab = strattab; /* Point to the parsing tables */ + parserstratcurr = NULL; /* Clear up the temporary strategy pointer */ + + if (stratParserParse2 () != 0) { /* Parse the strategy string */ + if (parserstratcurr != NULL) + stratExit (parserstratcurr); + return (NULL); + } + + return (parserstratcurr); /* Return strategy pointer */ +} + +/* This routine displays the parser error message. +** It returns: +** - 1 : in all cases. +*/ + +static +int +stratParserError ( +const char * const errstr) +{ + errorPrint ("stratParserParse: invalid strategy string, before \"%s\"", stratParserRemain ()); + return (1); +} diff --git a/scotch_6.0.3/src/libscotch/library.h b/scotch_6.0.3/src/libscotch/library.h new file mode 100644 index 00000000..b8066f03 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library.h @@ -0,0 +1,293 @@ +/* Copyright 2004,2007-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Jun-Ho HER (v6.0) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : Declaration file for the LibScotch **/ +/** static mapping and sparse matrix block **/ +/** ordering library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 07 sep 1996 **/ +/** to 22 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 31 may 1999 **/ +/** # Version 3.4 : from : 10 oct 1999 **/ +/** to 15 nov 2001 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 20 dec 2005 **/ +/** # Version 5.0 : from : 26 apr 2006 **/ +/** to : 20 feb 2008 **/ +/** # Version 5.1 : from : 30 nov 2007 **/ +/** to : 07 aug 2011 **/ +/** # Version 6.0 : from : 12 sep 2008 **/ +/** to 28 sep 2014 **/ +/** **/ +/************************************************************/ + +#ifndef SCOTCH_H +#define SCOTCH_H + +/* +** The type and structure definitions. +*/ + +/*+ Version flags. +*/ + +#define SCOTCH_VERSION DUMMYVERSION +#define SCOTCH_RELEASE DUMMYRELEASE +#define SCOTCH_PATCHLEVEL DUMMYPATCHLEVEL + +/*+ Integer type. +*/ + +typedef DUMMYIDX SCOTCH_Idx; + +typedef DUMMYINT SCOTCH_Num; + +#define SCOTCH_NUMMAX DUMMYMAXINT +#define SCOTCH_NUMSTRING DUMMYNUMSTRING + +/*+ Coarsening flags +*/ + +#define SCOTCH_COARSENNONE 0x0000 +#define SCOTCH_COARSENFOLD 0x0100 +#define SCOTCH_COARSENFOLDDUP 0x0300 +#define SCOTCH_COARSENNOMERGE 0x4000 + +/*+ Strategy string parametrization values +*/ + +#define SCOTCH_STRATDEFAULT 0x0000 +#define SCOTCH_STRATQUALITY 0x0001 +#define SCOTCH_STRATSPEED 0x0002 +#define SCOTCH_STRATBALANCE 0x0004 +#define SCOTCH_STRATSAFETY 0x0008 +#define SCOTCH_STRATSCALABILITY 0x0010 +#define SCOTCH_STRATRECURSIVE 0x0100 +#define SCOTCH_STRATREMAP 0x0200 +#define SCOTCH_STRATLEVELMAX 0x1000 +#define SCOTCH_STRATLEVELMIN 0x2000 +#define SCOTCH_STRATLEAFSIMPLE 0x4000 +#define SCOTCH_STRATSEPASIMPLE 0x8000 + +/*+ Opaque objects. The dummy sizes of these +objects, computed at compile-time by program +"dummysizes", are given as double values for +proper padding +*/ + +typedef struct { + double dummy[DUMMYSIZEARCH]; +} SCOTCH_Arch; + +typedef struct { + double dummy[DUMMYSIZEGEOM]; +} SCOTCH_Geom; + +typedef struct { + double dummy[DUMMYSIZEGRAPH]; +} SCOTCH_Graph; + +typedef struct { + double dummy[DUMMYSIZEMESH]; +} SCOTCH_Mesh; + +typedef struct { + double dummy[DUMMYSIZEMAP]; +} SCOTCH_Mapping; + +typedef struct { + double dummy[DUMMYSIZEORDER]; +} SCOTCH_Ordering; + +typedef struct { + double dummy[DUMMYSIZESTRAT]; +} SCOTCH_Strat; + +/* +** The function prototypes. +*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +SCOTCH_Arch * SCOTCH_archAlloc (void); +int SCOTCH_archInit (SCOTCH_Arch * const); +void SCOTCH_archExit (SCOTCH_Arch * const); +int SCOTCH_archLoad (SCOTCH_Arch * const, FILE * const); +int SCOTCH_archSave (const SCOTCH_Arch * const, FILE * const); +int SCOTCH_archBuild (SCOTCH_Arch * const, const SCOTCH_Graph * const, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Strat * const); +char * SCOTCH_archName (const SCOTCH_Arch * const); +SCOTCH_Num SCOTCH_archSize (const SCOTCH_Arch * const); +int SCOTCH_archVar (const SCOTCH_Arch * const); +int SCOTCH_archCmplt (SCOTCH_Arch * const, const SCOTCH_Num); +int SCOTCH_archCmpltw (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num * const); +int SCOTCH_archHcub (SCOTCH_Arch * const, const SCOTCH_Num); +int SCOTCH_archMesh2 (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num); +int SCOTCH_archMesh3 (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num); +int SCOTCH_archTleaf (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const); +int SCOTCH_archTorus2 (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num); +int SCOTCH_archTorus3 (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num); +int SCOTCH_archVcmplt (SCOTCH_Arch * const); +int SCOTCH_archVhcub (SCOTCH_Arch * const); + +void SCOTCH_errorProg (const char * const); +void SCOTCH_errorPrint (const char * const, ...); +void SCOTCH_errorPrintW (const char * const, ...); + +SCOTCH_Geom * SCOTCH_geomAlloc (void); +int SCOTCH_geomInit (SCOTCH_Geom * const); +void SCOTCH_geomExit (SCOTCH_Geom * const); +void SCOTCH_geomData (const SCOTCH_Geom * const, SCOTCH_Num * const, double ** const); + +SCOTCH_Graph * SCOTCH_graphAlloc (void); +int SCOTCH_graphInit (SCOTCH_Graph * const); +void SCOTCH_graphExit (SCOTCH_Graph * const); +void SCOTCH_graphFree (SCOTCH_Graph * const); +int SCOTCH_graphLoad (SCOTCH_Graph * const, FILE * const, const SCOTCH_Num, const SCOTCH_Num); +int SCOTCH_graphSave (const SCOTCH_Graph * const, FILE * const); +int SCOTCH_graphBuild (SCOTCH_Graph * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const); +int SCOTCH_graphCoarsen (const SCOTCH_Graph * const, SCOTCH_Graph * const, SCOTCH_Num * const, const SCOTCH_Num, const double); +int SCOTCH_graphColor (const SCOTCH_Graph * const, SCOTCH_Num * const, SCOTCH_Num * const, const SCOTCH_Num); +SCOTCH_Num SCOTCH_graphBase (SCOTCH_Graph * const, const SCOTCH_Num baseval); +int SCOTCH_graphCheck (const SCOTCH_Graph * const); +void SCOTCH_graphSize (const SCOTCH_Graph * const, SCOTCH_Num * const, SCOTCH_Num * const); +void SCOTCH_graphData (const SCOTCH_Graph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const); +void SCOTCH_graphStat (const SCOTCH_Graph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const); +int SCOTCH_graphGeomLoadChac (SCOTCH_Graph * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); +int SCOTCH_graphGeomLoadHabo (SCOTCH_Graph * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); +int SCOTCH_graphGeomLoadMmkt (SCOTCH_Graph * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); +int SCOTCH_graphGeomLoadScot (SCOTCH_Graph * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); +int SCOTCH_graphGeomSaveChac (const SCOTCH_Graph * const, const SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); +int SCOTCH_graphGeomSaveMmkt (const SCOTCH_Graph * const, const SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); +int SCOTCH_graphGeomSaveScot (const SCOTCH_Graph * const, const SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); + +int SCOTCH_graphMapInit (const SCOTCH_Graph * const, SCOTCH_Mapping * const, const SCOTCH_Arch * const, SCOTCH_Num * const); +void SCOTCH_graphMapExit (const SCOTCH_Graph * const, SCOTCH_Mapping * const); +int SCOTCH_graphMapLoad (const SCOTCH_Graph * const, const SCOTCH_Mapping * const, FILE * const); +int SCOTCH_graphTabLoad (const SCOTCH_Graph * const, SCOTCH_Num * const, FILE * const); +int SCOTCH_graphMapSave (const SCOTCH_Graph * const, const SCOTCH_Mapping * const, FILE * const); +int SCOTCH_graphMapView (const SCOTCH_Graph * const, const SCOTCH_Mapping * const, FILE * const); +int SCOTCH_graphRemapView (const SCOTCH_Graph * const, const SCOTCH_Mapping * const, const SCOTCH_Mapping * const, const double, SCOTCH_Num *, FILE * const); +int SCOTCH_graphRemapViewRaw (const SCOTCH_Graph * const, const SCOTCH_Mapping * const, const SCOTCH_Mapping * const, const double, SCOTCH_Num *, FILE * const); +int SCOTCH_graphMapCompute (SCOTCH_Graph * const, SCOTCH_Mapping * const, SCOTCH_Strat * const); +int SCOTCH_graphMapFixedCompute (SCOTCH_Graph * const, SCOTCH_Mapping * const, SCOTCH_Strat * const); +int SCOTCH_graphRemapCompute (SCOTCH_Graph * const, SCOTCH_Mapping * const, SCOTCH_Mapping * const, const double, const SCOTCH_Num *, SCOTCH_Strat * const); +int SCOTCH_graphRemapFixedCompute (SCOTCH_Graph * const, SCOTCH_Mapping * const, SCOTCH_Mapping * const, const double, const SCOTCH_Num *, SCOTCH_Strat * const); +int SCOTCH_graphMap (SCOTCH_Graph * const, const SCOTCH_Arch * const, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_graphMapFixed (SCOTCH_Graph * const, const SCOTCH_Arch * const, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_graphRemap (SCOTCH_Graph * const, const SCOTCH_Arch * const, SCOTCH_Num *, const double, const SCOTCH_Num *, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_graphRemapFixed (SCOTCH_Graph * const, const SCOTCH_Arch * const, SCOTCH_Num *, const double, const SCOTCH_Num *, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_graphPart (SCOTCH_Graph * const, const SCOTCH_Num, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_graphPartFixed (SCOTCH_Graph * const, const SCOTCH_Num, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_graphPartOvl (SCOTCH_Graph * const, const SCOTCH_Num, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_graphRepart (SCOTCH_Graph * const, const SCOTCH_Num, SCOTCH_Num * const, const double, const SCOTCH_Num *, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_graphRepartFixed (SCOTCH_Graph * const, const SCOTCH_Num, SCOTCH_Num * const, const double, const SCOTCH_Num *, SCOTCH_Strat * const, SCOTCH_Num * const); + +int SCOTCH_graphOrderInit (const SCOTCH_Graph * const, SCOTCH_Ordering * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void SCOTCH_graphOrderExit (const SCOTCH_Graph * const, SCOTCH_Ordering * const); +int SCOTCH_graphOrderLoad (const SCOTCH_Graph * const, SCOTCH_Ordering * const, FILE * const); +int SCOTCH_graphOrderSave (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, FILE * const); +int SCOTCH_graphOrderSaveMap (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, FILE * const); +int SCOTCH_graphOrderSaveTree (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, FILE * const); +int SCOTCH_graphOrderCompute (SCOTCH_Graph * const, SCOTCH_Ordering * const, SCOTCH_Strat * const); +int SCOTCH_graphOrderComputeList (SCOTCH_Graph * const, SCOTCH_Ordering * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const); +int SCOTCH_graphOrderFactor (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, SCOTCH_Graph * const); +int SCOTCH_graphOrderView (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, FILE * const); +int SCOTCH_graphOrder (SCOTCH_Graph * const, SCOTCH_Strat * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +int SCOTCH_graphOrderList (SCOTCH_Graph * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +int SCOTCH_graphOrderCheck (const SCOTCH_Graph * const, const SCOTCH_Ordering * const); + +SCOTCH_Mapping * SCOTCH_mapAlloc (void); + +void SCOTCH_memFree (void * const); +SCOTCH_Idx SCOTCH_memCur (void); +SCOTCH_Idx SCOTCH_memMax (void); + +int SCOTCH_meshInit (SCOTCH_Mesh * const); +void SCOTCH_meshExit (SCOTCH_Mesh * const); +int SCOTCH_meshLoad (SCOTCH_Mesh * const, FILE * const, const SCOTCH_Num); +int SCOTCH_meshSave (const SCOTCH_Mesh * const, FILE * const); +int SCOTCH_meshBuild (SCOTCH_Mesh * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num * const); +int SCOTCH_meshCheck (const SCOTCH_Mesh * const); +void SCOTCH_meshSize (const SCOTCH_Mesh * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void SCOTCH_meshData (const SCOTCH_Mesh * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num * const); +void SCOTCH_meshStat (const SCOTCH_Mesh * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const); +int SCOTCH_meshGraph (const SCOTCH_Mesh * const, SCOTCH_Graph * const); +int SCOTCH_meshGeomLoadHabo (SCOTCH_Mesh * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); +int SCOTCH_meshGeomLoadScot (SCOTCH_Mesh * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); +int SCOTCH_meshGeomSaveScot (const SCOTCH_Mesh * const, const SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); + +int SCOTCH_meshOrderInit (const SCOTCH_Mesh * const, SCOTCH_Ordering * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void SCOTCH_meshOrderExit (const SCOTCH_Mesh * const, SCOTCH_Ordering * const); +int SCOTCH_meshOrderSave (const SCOTCH_Mesh * const, const SCOTCH_Ordering * const, FILE * const); +int SCOTCH_meshOrderSaveMap (const SCOTCH_Mesh * const, const SCOTCH_Ordering * const, FILE * const); +int SCOTCH_meshOrderSaveTree (const SCOTCH_Mesh * const, const SCOTCH_Ordering * const, FILE * const); +int SCOTCH_meshOrderCompute (SCOTCH_Mesh * const, SCOTCH_Ordering * const, SCOTCH_Strat * const); +int SCOTCH_meshOrderComputeList (SCOTCH_Mesh * const, SCOTCH_Ordering * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const); +int SCOTCH_meshOrder (SCOTCH_Mesh * const, SCOTCH_Strat * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +int SCOTCH_meshOrderList (SCOTCH_Mesh * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +int SCOTCH_meshOrderCheck (const SCOTCH_Mesh * const, const SCOTCH_Ordering * const); + +int SCOTCH_numSizeof (void); + +SCOTCH_Ordering * SCOTCH_orderAlloc (void); + +void SCOTCH_randomReset (void); +void SCOTCH_randomSeed (SCOTCH_Num); + +SCOTCH_Strat * SCOTCH_stratAlloc (void); +int SCOTCH_stratInit (SCOTCH_Strat * const); +void SCOTCH_stratExit (SCOTCH_Strat * const); +void SCOTCH_stratFree (SCOTCH_Strat * const); +int SCOTCH_stratSave (const SCOTCH_Strat * const, FILE * const); +int SCOTCH_stratGraphBipart (SCOTCH_Strat * const, const char * const); +int SCOTCH_stratGraphMap (SCOTCH_Strat * const, const char * const); +int SCOTCH_stratGraphMapBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const double); +int SCOTCH_stratGraphClusterBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const double, const double); +int SCOTCH_stratGraphPartOvl (SCOTCH_Strat * const, const char * const); +int SCOTCH_stratGraphPartOvlBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const double); +int SCOTCH_stratGraphOrder (SCOTCH_Strat * const, const char * const); +int SCOTCH_stratGraphOrderBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const double); +int SCOTCH_stratMeshOrder (SCOTCH_Strat * const, const char * const); +int SCOTCH_stratMeshOrderBuild (SCOTCH_Strat * const, const SCOTCH_Num, const double); + +void SCOTCH_version (int * const, int * const, int * const); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SCOTCH_H */ diff --git a/scotch_6.0.3/src/libscotch/library_arch.c b/scotch_6.0.3/src/libscotch/library_arch.c new file mode 100644 index 00000000..d3a83d5b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_arch.c @@ -0,0 +1,580 @@ +/* Copyright 2004,2007,2009-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_arch.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module is the API for the target **/ +/** architecture handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 18 aug 1998 **/ +/** to : 18 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 29 mar 1999 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to : 01 nov 2001 **/ +/** # Version 4.0 : from : 13 jan 2004 **/ +/** to : 13 jan 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to : 12 sep 2007 **/ +/** # Version 5.1 : from : 05 jun 2009 **/ +/** to : 13 feb 2011 **/ +/** # Version 6.0 : from : 14 fev 2011 **/ +/** to 19 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "arch_cmplt.h" +#include "arch_cmpltw.h" +#include "arch_hcub.h" +#include "arch_mesh.h" +#include "arch_tleaf.h" +#include "arch_torus.h" +#include "arch_vcmplt.h" +#include "arch_vhcub.h" +#include "scotch.h" + +/***************************************/ +/* */ +/* These routines are the C API for */ +/* the architecture handling routines. */ +/* */ +/***************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** target architecture. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Arch * +SCOTCH_archAlloc () +{ + return ((SCOTCH_Arch *) memAlloc (sizeof (SCOTCH_Arch))); +} + +/*+ This routine initializes the opaque +*** architecture structure used to handle +*** target architectures in the Scotch library. +*** It returns: +*** - 0 : if the initialization succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_archInit ( +SCOTCH_Arch * const archptr) +{ + if (sizeof (SCOTCH_Num) != sizeof (Anum)) { + errorPrint ("SCOTCH_archInit: internal error (1)"); + return (1); + } + if (sizeof (SCOTCH_Arch) < sizeof (Arch)) { + errorPrint ("SCOTCH_archInit: internal error (2)"); + return (1); + } + + return (archInit ((Arch *) archptr)); +} + +/*+ This routine frees the contents of the +*** given opaque architecture structure. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_archExit ( +SCOTCH_Arch * const archptr) +{ + archExit ((Arch *) archptr); +} + +/*+ This routine loads the given opaque +*** architecture structure with the data of +*** the given stream. +*** It returns: +*** - 0 : if the loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_archLoad ( +SCOTCH_Arch * const archptr, +FILE * const stream) +{ + return (archLoad ((Arch *) archptr, stream)); +} + +/*+ This routine saves the given opaque +*** architecture structure to the given +*** stream. +*** It returns: +*** - 0 : if the saving succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_archSave ( +const SCOTCH_Arch * const archptr, +FILE * const stream) +{ + return (archSave ((Arch *) archptr, stream)); +} + +/*+ This routine returns the name of the +*** given target architecture. +*** It returns: +*** - !NULL : pointer to the name of the +*** target architecture. ++*/ + +char * +SCOTCH_archName ( +const SCOTCH_Arch * const archptr) +{ + return (archName ((const Arch * const) archptr)); +} + +/*+ This routine returns the size of the +*** given target architecture. +*** It returns: +*** - !0 : size of the target architecture. ++*/ + +SCOTCH_Num +SCOTCH_archSize ( +const SCOTCH_Arch * const archptr) +{ + ArchDom domdat; + + archDomFrst ((Arch *) archptr, &domdat); /* Get first domain */ + return (archDomSize ((Arch *) archptr, &domdat)); /* Return domain size */ +} + +/*+ This routine tells if the given architecture +*** is a variable-sized architecture or not. +*** It returns: +*** - 0 : if the architecture is not variable-sized. +*** - 1 : if the architecture is variable-sized. ++*/ + +int +SCOTCH_archVar ( +const SCOTCH_Arch * const archptr) +{ + return ((archVar ((Arch *) archptr) != 0) ? 1 : 0); +} + +/*+ These routines fill the contents of the given +*** opaque target structure so as to yield target +*** architectures of the given types. +*** It returns: +*** - 0 : if the computation succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_archCmplt ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num numnbr) +{ + Arch * tgtarchptr; + ArchCmplt * tgtarchdatptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archCmplt: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchCmplt *) (void *) (&tgtarchptr->data); + + tgtarchptr->class = archClass ("cmplt"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + tgtarchdatptr->numnbr = (Anum) numnbr; + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archCmpltw ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num vertnbr, +const SCOTCH_Num * const velotab) +{ + Arch * tgtarchptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archCmpltw: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchptr->class = archClass ("cmpltw"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + + return (archCmpltwArchBuild ((ArchCmpltw *) (void *) (&tgtarchptr->data), vertnbr, velotab)); +} + +/* +** +*/ + +int +SCOTCH_archHcub ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num dimmax) /*+ Number of dimensions +*/ +{ + Arch * tgtarchptr; + ArchHcub * tgtarchdatptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archHcub: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchHcub *) (void *) (&tgtarchptr->data); + + tgtarchptr->class = archClass ("hcub"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + tgtarchdatptr->dimmax = (Anum) dimmax; + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archMesh2 ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num dimxval, +const SCOTCH_Num dimyval) +{ + Arch * tgtarchptr; + ArchMesh2 * tgtarchdatptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archMesh2: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchMesh2 *) (void *) (&tgtarchptr->data); + + tgtarchptr->class = archClass ("mesh2D"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + tgtarchdatptr->c[0] = (Anum) dimxval; + tgtarchdatptr->c[1] = (Anum) dimyval; + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archMesh3 ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num dimxval, +const SCOTCH_Num dimyval, +const SCOTCH_Num dimzval) +{ + Arch * tgtarchptr; + ArchMesh3 * tgtarchdatptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archMesh3: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchMesh3 *) (void *) (&tgtarchptr->data); + + tgtarchptr->class = archClass ("mesh3D"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + tgtarchdatptr->c[0] = (Anum) dimxval; + tgtarchdatptr->c[1] = (Anum) dimyval; + tgtarchdatptr->c[2] = (Anum) dimzval; + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archTleaf ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num levlnbr, /*+ Number of levels in architecture +*/ +const SCOTCH_Num * const sizetab, /*+ Size array, by increasing level number +*/ +const SCOTCH_Num * const linktab) /*+ Link cost array, by increasing level number +*/ +{ + Anum levlnum; + Anum sizeval; + Arch * tgtarchptr; + ArchTleaf * tgtarchdatptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archTleaf: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchTleaf *) (void *) (&tgtarchptr->data); + tgtarchptr->class = archClass ("tleaf"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + + if ((tgtarchdatptr->sizetab = memAlloc ((levlnbr * 2 + 1) * sizeof (Anum))) == NULL) { /* TRICK: One more slot for linktab[-1] */ + errorPrint ("SCOTCH_archTleaf: out of memory"); + return (1); + } + tgtarchdatptr->levlnbr = (Anum) levlnbr; + tgtarchdatptr->linktab = tgtarchdatptr->sizetab + tgtarchdatptr->levlnbr + 1; + tgtarchdatptr->linktab[-1] = 0; /* TRICK: Dummy slot for for level-0 communication */ + tgtarchdatptr->permtab = NULL; /* Assume no permutation array */ + + for (levlnum = 0, sizeval = 1; levlnum < tgtarchdatptr->levlnbr; levlnum ++) { + tgtarchdatptr->sizetab[levlnum] = sizetab[levlnum]; + tgtarchdatptr->linktab[levlnum] = linktab[levlnum]; + sizeval *= tgtarchdatptr->sizetab[levlnum]; + } + tgtarchdatptr->termnbr = sizeval; + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archLtleaf ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num levlnbr, /*+ Number of levels in architecture +*/ +const SCOTCH_Num * const sizetab, /*+ Size array, by increasing level number +*/ +const SCOTCH_Num * const linktab, /*+ Link cost array, by increasing level number +*/ +const SCOTCH_Num permnbr, /*+ Number of permutation indices +*/ +const SCOTCH_Num * const permtab) /*+ Permutation array +*/ +{ + Anum levlnum; + Anum permnum; + Anum sizeval; + Arch * tgtarchptr; + ArchTleaf * tgtarchdatptr; + + if (SCOTCH_archTleaf (archptr, levlnbr, sizetab, linktab) != 0) /* Build tree part */ + return (1); + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchTleaf *) (void *) (&tgtarchptr->data); + tgtarchptr->class = archClass ("ltleaf"); /* Override class */ + + if ((tgtarchdatptr->permtab = memAlloc (permnbr * 2 * sizeof (Anum))) == NULL) { /* TRICK: space for peritab too */ + errorPrint ("SCOTCH_archLtleaf: out of memory"); + return (1); + } + tgtarchdatptr->permnbr = (Anum) permnbr; + tgtarchdatptr->peritab = tgtarchdatptr->permtab + permnbr; + + for (permnum = 0; permnum < tgtarchdatptr->permnbr; permnum ++) + tgtarchdatptr->permtab[permnum] = permtab[permnum]; + for (permnum = 0; permnum < tgtarchdatptr->permnbr; permnum ++) /* Build inverse permutation */ + tgtarchdatptr->peritab[tgtarchdatptr->permtab[permnum]] = permnum; + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archTorus2 ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num dimxval, +const SCOTCH_Num dimyval) +{ + Arch * tgtarchptr; + ArchTorusX * tgtarchdatptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archTorus2: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchTorusX *) (void *) (&tgtarchptr->data); + + tgtarchptr->class = archClass ("torus2D"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + tgtarchdatptr->dimmax = 2; + tgtarchdatptr->c[0] = (Anum) dimxval; + tgtarchdatptr->c[1] = (Anum) dimyval; + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archTorus3 ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num dimxval, +const SCOTCH_Num dimyval, +const SCOTCH_Num dimzval) +{ + Arch * tgtarchptr; + ArchTorusX * tgtarchdatptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archTorus3: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchTorusX *) (void *) (&tgtarchptr->data); + + tgtarchptr->class = archClass ("torus3D"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + tgtarchdatptr->dimmax = 3; + tgtarchdatptr->c[0] = (Anum) dimxval; + tgtarchdatptr->c[1] = (Anum) dimyval; + tgtarchdatptr->c[2] = (Anum) dimzval; + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archTorusX ( +SCOTCH_Arch * const archptr, +const SCOTCH_Num dimnbr, /*+ Number of dimensions in architecture +*/ +const SCOTCH_Num * const dimtab) /*+ Array of dimensions +*/ +{ + Arch * tgtarchptr; + ArchTorusX * tgtarchdatptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archTorusX: internal error"); + return (1); + } + if (dimnbr > ARCHTORUSDIMMAX) { + errorPrint ("SCOTCH_archTorusX: too many dimensions"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + tgtarchdatptr = (ArchTorusX *) (void *) (&tgtarchptr->data); + + tgtarchptr->class = archClass ("torusXD"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + tgtarchdatptr->dimmax = dimnbr; + memCpy (tgtarchdatptr->c, dimtab, dimnbr * sizeof (SCOTCH_Num)); /* Copy dimension array */ + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archVcmplt ( +SCOTCH_Arch * const archptr) +{ + Arch * tgtarchptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archVcmplt: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + + tgtarchptr->class = archClass ("varcmplt"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + + return (0); +} + +/* +** +*/ + +int +SCOTCH_archVhcub ( +SCOTCH_Arch * const archptr) +{ + Arch * tgtarchptr; + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_archVhcub: internal error"); + return (1); + } + + tgtarchptr = (Arch *) archptr; + + tgtarchptr->class = archClass ("varhcub"); + tgtarchptr->flagval = tgtarchptr->class->flagval; /* Copy architecture flag */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_arch_build.c b/scotch_6.0.3/src/libscotch/library_arch_build.c new file mode 100644 index 00000000..51894235 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_arch_build.c @@ -0,0 +1,146 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_arch_build.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the target **/ +/** architecture building routine of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.3 : from : 02 oct 1998 **/ +/** to 29 mar 1999 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 08 mar 2005 **/ +/** to 17 mar 2005 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "arch_build.h" +#include "mapping.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the C API for */ +/* the architecture building routine. */ +/* */ +/**************************************/ + +/*+ This routine parses the given +*** bipartitioning strategy. +*** It returns: +*** - 0 : if string successfully scanned. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratGraphBipart ( +SCOTCH_Strat * const stratptr, +const char * const string) +{ + if (*((Strat **) stratptr) != NULL) + stratExit (*((Strat **) stratptr)); + + if ((*((Strat **) stratptr) = stratInit (&bgraphbipartststratab, string)) == NULL) { + errorPrint ("SCOTCH_stratBipart: error in bipartitioning strategy"); + return (1); + } + + return (0); +} + +/*+ This routine fills the contents of the given +*** opaque target structure with the data provided +*** by the user. The source graph provided on input +*** is turned into a decomposition-defined target +*** architecture. +*** It returns: +*** - 0 : if the computation succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_archBuild ( +SCOTCH_Arch * const archptr, /*+ Target architecture to build +*/ +const SCOTCH_Graph * const grafptr, /*+ Graph to turn into architecture +*/ +const SCOTCH_Num listnbr, /*+ Number of elements in sublist +*/ +const SCOTCH_Num * const listptr, /*+ Pointer to sublist +*/ +const SCOTCH_Strat * const stratptr) /*+ Bipartitoning strategy +*/ +{ + Strat * bipstratptr; + VertList graflistdat; + VertList * graflistptr; + int o; + + if ((sizeof (SCOTCH_Num) != sizeof (Gnum)) || + (sizeof (SCOTCH_Num) != sizeof (Anum))) { + errorPrint ("SCOTCH_archBuild: internal error (1)"); + return (1); + } + + if (*((Strat **) stratptr) == NULL) /* Set default mapping strategy if necessary */ + *((Strat **) stratptr) = stratInit (&bgraphbipartststratab, "(m{vert=50,low=h{pass=10},asc=f{move=100,bal=0.1}}f{move=100,bal=0.05})(/((load0=load)|(load0=0))?x;)"); + bipstratptr = *((Strat **) stratptr); + if (bipstratptr->tabl != &bgraphbipartststratab) { + errorPrint ("SCOTCH_archBuild: not a bipartitioning strategy"); + return (1); + } + + if ((listnbr == ((Graph *) grafptr)->vertnbr) || (listnbr == 0) || (listptr == NULL)) + graflistptr = NULL; + else { + graflistptr = &graflistdat; + graflistdat.vnumnbr = (Gnum) listnbr; + graflistdat.vnumtab = (Gnum *) listptr; + } + + o = archBuild ((Arch * const) archptr, (const Graph * const) grafptr, graflistptr, bipstratptr); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/library_arch_build_f.c b/scotch_6.0.3/src/libscotch/library_arch_build_f.c new file mode 100644 index 00000000..265ad3a9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_arch_build_f.c @@ -0,0 +1,106 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_arch_build_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the target architecture building **/ +/** routine of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 17 mar 2005 **/ +/** to 17 mar 2005 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/****************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the target architecture building */ +/* routines. */ +/* */ +/****************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATGRAPHBIPART, scotchfstratgraphbipart, ( \ +SCOTCH_Strat * const stratptr, \ +const char * const string, \ +int * const revaptr, \ +const int strnbr), \ +(stratptr, string, revaptr, strnbr)) +{ + char * restrict strtab; /* Pointer to null-terminated string */ + + if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ + errorPrint ("SCOTCHFSTRATGRAPHBIPART: out of memory (1)"); + *revaptr = 1; + } + memCpy (strtab, string, strnbr); /* Copy string contents */ + strtab[strnbr] = '\0'; /* Terminate string */ + + *revaptr = SCOTCH_stratGraphBipart (stratptr, strtab); /* Call original routine */ + + memFree (strtab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHBUILD, scotchfarchbuild, ( \ +SCOTCH_Arch * const archptr, \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const listnbr, \ +const SCOTCH_Num * const listptr, \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(archptr, grafptr, listnbr, listptr, stratptr, revaptr)) +{ + *revaptr = SCOTCH_archBuild (archptr, grafptr, *listnbr, listptr, stratptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_arch_f.c b/scotch_6.0.3/src/libscotch/library_arch_f.c new file mode 100644 index 00000000..61ddb224 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_arch_f.c @@ -0,0 +1,357 @@ +/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_arch_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.4 : from : 02 dec 1999 **/ +/** to 15 nov 2001 **/ +/** # Version 4.0 : from : 13 jan 2004 **/ +/** to 13 jan 2004 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 13 feb 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the Fortran */ +/* API for the architecture handling */ +/* routines. */ +/* */ +/*************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHINIT, scotchfarchinit, ( \ +SCOTCH_Arch * const archptr, \ +int * const revaptr), \ +(archptr, revaptr)) +{ + *revaptr = SCOTCH_archInit (archptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHEXIT, scotchfarchexit, ( \ +SCOTCH_Arch * const archptr), \ +(archptr)) +{ + SCOTCH_archExit (archptr); +} + +/* When an input stream is built from the given +** file handle, it is set as unbuffered, so as to +** allow for multiple stream reads from the same +** file handle. If it were buffered, too many +** input characters would be read on the first +** block read. +*/ + +FORTRAN ( \ +SCOTCHFARCHLOAD, scotchfarchload, ( \ +SCOTCH_Arch * const archptr, \ +int * const fileptr, \ +int * const revaptr), \ +(archptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFARCHLOAD: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFARCHLOAD: cannot open input stream"); + close (filenum); + *revaptr = 1; + return; + } + setbuf (stream, NULL); /* Do not buffer on input */ + + o = SCOTCH_archLoad (archptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHSAVE, scotchfarchsave, ( \ +const SCOTCH_Arch * const archptr, \ +int * const fileptr, \ +int * const revaptr), \ +(archptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFARCHSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFARCHSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_archSave (archptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHNAME, scotchfarchname, ( \ +const SCOTCH_Arch * const archptr, \ +char * const chartab, \ +int * const charptr), \ +(archptr, chartab, charptr)) +{ + char * nameptr; /* Name string */ + + nameptr = SCOTCH_archName (archptr); /* Get architecture name */ + strncpy (chartab, nameptr, *charptr); /* Copy architecture name */ +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHSIZE, scotchfarchsize, ( \ +const SCOTCH_Arch * const archptr, \ +int * const sizeptr), \ +(archptr, sizeptr)) +{ + *sizeptr = SCOTCH_archSize (archptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHVAR, scotchfarchvar, ( \ +const SCOTCH_Arch * const archptr, \ +int * const flagptr), \ +(archptr, flagptr)) +{ + *flagptr = SCOTCH_archVar (archptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHCMPLT, scotchfarchcmplt, ( \ +SCOTCH_Arch * const archptr, \ +const SCOTCH_Num * const archnbr, \ +int * const revaptr), \ +(archptr, archnbr, revaptr)) +{ + *revaptr = SCOTCH_archCmplt (archptr, *archnbr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHCMPLTW, scotchfarchcmpltw, ( \ +SCOTCH_Arch * const archptr, \ +const SCOTCH_Num * const vertnbr, \ +const SCOTCH_Num * const velotab, \ +int * const revaptr), \ +(archptr, vertnbr, velotab, revaptr)) +{ + *revaptr = SCOTCH_archCmpltw (archptr, *vertnbr, velotab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHHCUB, scotchfarchhcub, ( \ +SCOTCH_Arch * const archptr, \ +const SCOTCH_Num * const dimmax, \ +int * const revaptr), \ +(archptr, dimmax, revaptr)) +{ + *revaptr = SCOTCH_archHcub (archptr, *dimmax); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHMESH2, scotchfarchmesh2, ( \ +SCOTCH_Arch * const archptr, \ +const SCOTCH_Num * const dimxval, \ +const SCOTCH_Num * const dimyval, \ +int * const revaptr), \ +(archptr, dimxval, dimyval, revaptr)) +{ + *revaptr = SCOTCH_archMesh2 (archptr, *dimxval, *dimyval); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHMESH3, scotchfarchmesh3, ( \ +SCOTCH_Arch * const archptr, \ +const SCOTCH_Num * const dimxval, \ +const SCOTCH_Num * const dimyval, \ +const SCOTCH_Num * const dimzval, \ +int * const revaptr), \ +(archptr, dimxval, dimyval, dimzval, revaptr)) +{ + *revaptr = SCOTCH_archMesh3 (archptr, *dimxval, *dimyval, *dimzval); +} + + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHTLEAF, scotchfarchtleaf, ( \ +SCOTCH_Arch * const archptr, \ +const SCOTCH_Num * const levlnbr, \ +const SCOTCH_Num * const sizetab, \ +const SCOTCH_Num * const linktab, \ +int * const revaptr), \ +(archptr, levlnbr, sizetab, linktab, revaptr)) +{ + *revaptr = SCOTCH_archTleaf (archptr, *levlnbr, sizetab, linktab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHTORUS2, scotchfarchtorus2, ( \ +SCOTCH_Arch * const archptr, \ +const SCOTCH_Num * const dimxval, \ +const SCOTCH_Num * const dimyval, \ +int * const revaptr), \ +(archptr, dimxval, dimyval, revaptr)) +{ + *revaptr = SCOTCH_archTorus2 (archptr, *dimxval, *dimyval); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHTORUS3, scotchfarchtorus3, ( \ +SCOTCH_Arch * const archptr, \ +const SCOTCH_Num * const dimxval, \ +const SCOTCH_Num * const dimyval, \ +const SCOTCH_Num * const dimzval, \ +int * const revaptr), \ +(archptr, dimxval, dimyval, dimzval, revaptr)) +{ + *revaptr = SCOTCH_archTorus3 (archptr, *dimxval, *dimyval, *dimzval); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHVCMPLT, scotchfarchvcmplt, ( \ +SCOTCH_Arch * const archptr, \ +int * const revaptr), \ +(archptr, revaptr)) +{ + *revaptr = SCOTCH_archVcmplt (archptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFARCHVHCUB, scotchfarchvhcub, ( \ +SCOTCH_Arch * const archptr, \ +int * const revaptr), \ +(archptr, revaptr)) +{ + *revaptr = SCOTCH_archVhcub (archptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_common_f.c b/scotch_6.0.3/src/libscotch/library_common_f.c new file mode 100644 index 00000000..79967225 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_common_f.c @@ -0,0 +1,87 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_common_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the some miscellaneous routines **/ +/** provided by the common files of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 14 jun 2012 **/ +/** to 14 jun 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for some miscellaneous routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMEMCUR, scotchfmemcur, ( \ +SCOTCH_Idx * const memoptr), \ +(memoptr)) +{ + *memoptr = SCOTCH_memCur (); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMEMMAX, scotchfmemmax, ( \ +SCOTCH_Idx * const memoptr), \ +(memoptr)) +{ + *memoptr = SCOTCH_memMax (); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph.c b/scotch_6.0.3/src/libscotch/library_dgraph.c new file mode 100644 index 00000000..1e7fffa6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph.c @@ -0,0 +1,242 @@ +/* Copyright 2007,2009,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 26 apr 2006 **/ +/** to 14 apr 2008 **/ +/** # Version 5.1 : from : 26 mar 2009 **/ +/** to 17 nov 2010 **/ +/** # Version 6.0 : from : 27 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" /* For graphPtscotch() */ +#include "dgraph.h" +#include "ptscotch.h" + +/****************************************/ +/* */ +/* These routines are the C API for the */ +/* distributed graph handling routines. */ +/* */ +/****************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** distributed graph structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Dgraph * +SCOTCH_dgraphAlloc () +{ + return ((SCOTCH_Dgraph *) memAlloc (sizeof (SCOTCH_Dgraph))); +} + +/*+ This routine initializes the opaque +*** distributed graph structure used to +*** handle distributed graphs in the +*** Scotch library. +*** It returns: +*** - 0 : if the initialization succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphInit ( +SCOTCH_Dgraph * const grafptr, +MPI_Comm proccomm) /* Communicator to be used for all communications */ +{ +#ifdef SCOTCH_PTHREAD + int thrdlvlval; +#endif /* SCOTCH_PTHREAD */ + +#ifdef SCOTCH_PTHREAD + MPI_Query_thread (&thrdlvlval); + if (thrdlvlval < MPI_THREAD_MULTIPLE) { + errorPrint ("SCOTCH_dgraphInit: Scotch compiled with SCOTCH_PTHREAD and program not launched with MPI_THREAD_MULTIPLE"); + return (1); + } +#endif /* SCOTCH_PTHREAD */ + + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_dgraphInit: internal error (1)"); + return (1); + } + if (sizeof (SCOTCH_Dgraph) < sizeof (Dgraph)) { + errorPrint ("SCOTCH_dgraphInit: internal error (2)"); + return (1); + } + + return (dgraphInit ((Dgraph *) grafptr, proccomm)); +} + +/*+ This routine frees the contents of the +*** given opaque graph structure. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_dgraphExit ( +SCOTCH_Dgraph * const grafptr) +{ + dgraphExit ((Dgraph *) grafptr); +} + +/*+ This routine frees the contents of the +*** given opaque graph structure but does +*** not free its private data. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_dgraphFree ( +SCOTCH_Dgraph * const grafptr) +{ + dgraphFree ((Dgraph *) grafptr); +} + +/*+ This routine accesses graph size data. +*** NULL pointers on input indicate unwanted +*** data. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_dgraphSize ( +const SCOTCH_Dgraph * const grafptr, +SCOTCH_Num * const vertglbnbr, +SCOTCH_Num * const vertlocnbr, +SCOTCH_Num * const edgeglbnbr, +SCOTCH_Num * const edgelocnbr) +{ + const Dgraph * srcgrafptr; + + srcgrafptr = (Dgraph *) grafptr; + + if (vertglbnbr != NULL) + *vertglbnbr = (SCOTCH_Num) (srcgrafptr->vertglbnbr); + if (vertlocnbr != NULL) + *vertlocnbr = (SCOTCH_Num) (srcgrafptr->vertlocnbr); + if (edgeglbnbr != NULL) + *edgeglbnbr = (SCOTCH_Num) srcgrafptr->edgeglbnbr; + if (edgelocnbr != NULL) + *edgelocnbr = (SCOTCH_Num) srcgrafptr->edgelocnbr; +} + +/*+ This routine accesses all of the graph data. +*** NULL pointers on input indicate unwanted +*** data. NULL pointers on output indicate +*** unexisting arrays. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_dgraphData ( +const SCOTCH_Dgraph * const grafptr, /* Graph structure to read */ +SCOTCH_Num * const baseptr, /* Base value */ +SCOTCH_Num * const vertglbptr, /* Number of global vertices */ +SCOTCH_Num * const vertlocptr, /* Number of local vertices */ +SCOTCH_Num * const vertlocptz, /* Maximum number of local vertices */ +SCOTCH_Num * const vertgstptr, /* Number of local + ghost vertices */ +SCOTCH_Num ** const vertloctab, /* Vertex array [vertnbr+1] */ +SCOTCH_Num ** const vendloctab, /* Vertex array [vertnbr] */ +SCOTCH_Num ** const veloloctab, /* Vertex load array */ +SCOTCH_Num ** const vlblloctab, /* Vertex label array */ +SCOTCH_Num * const edgeglbptr, /* Number of global edges (arcs) */ +SCOTCH_Num * const edgelocptr, /* Number of local edges (arcs) */ +SCOTCH_Num * const edgelocptz, /* Size of local edge array */ +SCOTCH_Num ** const edgeloctab, /* Local edge array [edgelocsiz] */ +SCOTCH_Num ** const edgegsttab, /* Ghost edge array [edgelocsiz] */ +SCOTCH_Num ** const edloloctab, /* Edge load array [edgelocsiz] */ +MPI_Comm * const comm) /* MPI Communicator */ +{ + const Dgraph * srcgrafptr; /* Pointer to source graph structure */ + + srcgrafptr = (const Dgraph *) grafptr; + + if (baseptr != NULL) + *baseptr = srcgrafptr->baseval; + if (vertglbptr != NULL) + *vertglbptr = srcgrafptr->vertglbnbr; + if (vertlocptr != NULL) + *vertlocptr = srcgrafptr->vertlocnbr; + if (vertlocptz != NULL) + *vertlocptz = srcgrafptr->procvrttab[srcgrafptr->proclocnum + 1] - srcgrafptr->procvrttab[srcgrafptr->proclocnum]; + if (vertgstptr != NULL) + *vertgstptr = ((srcgrafptr->flagval & DGRAPHHASEDGEGST) != 0) ? srcgrafptr->vertgstnbr : -1; + if (vertloctab != NULL) + *vertloctab = srcgrafptr->vertloctax + srcgrafptr->baseval; + if (vendloctab != NULL) + *vendloctab = srcgrafptr->vendloctax + srcgrafptr->baseval; + if (veloloctab != NULL) + *veloloctab = (srcgrafptr->veloloctax != NULL) ? srcgrafptr->veloloctax + srcgrafptr->baseval : NULL; + if (vlblloctab != NULL) + *vlblloctab = (srcgrafptr->vlblloctax != NULL) ? srcgrafptr->vlblloctax + srcgrafptr->baseval : NULL; + if (edgeglbptr != NULL) + *edgeglbptr = srcgrafptr->edgeglbnbr; + if (edgelocptr != NULL) + *edgelocptr = srcgrafptr->edgelocnbr; + if (edgelocptz != NULL) + *edgelocptz = srcgrafptr->edgelocsiz; + if (edgeloctab != NULL) + *edgeloctab = srcgrafptr->edgeloctax + srcgrafptr->baseval; + if (edgegsttab != NULL) + *edgegsttab = (srcgrafptr->edgegsttax != NULL) ? srcgrafptr->edgegsttax + srcgrafptr->baseval : NULL; + if (edloloctab != NULL) + *edloloctab = (srcgrafptr->edloloctax != NULL) ? srcgrafptr->edloloctax + srcgrafptr->baseval : NULL; + if (comm != NULL) + *comm = srcgrafptr->proccomm; +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_band.c b/scotch_6.0.3/src/libscotch/library_dgraph_band.c new file mode 100644 index 00000000..9572dd9a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_band.c @@ -0,0 +1,360 @@ +/* Copyright 2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_band.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted band graph building routine of **/ +/** the libScotch library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 28 oct 2011 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_halo.h" +#include "ptscotch.h" + +#define DGRAPHBANDGROWNAME dgraphBand +#include "dgraph_band_grow.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the mapping routines. */ +/* */ +/************************************/ + +/*+ This routine builds a distributed +*** band graph, without anchors, from the +*** given distributed graph. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphBand ( +SCOTCH_Dgraph * const orggrafptr, +const SCOTCH_Num fronlocnbr, +SCOTCH_Num * const fronloctab, +const SCOTCH_Num distval, +SCOTCH_Dgraph * const bndgrafptr) +{ + MPI_Comm bandproccomm; + Gnum bandvertlocnnd; /* End of local band vertex array */ + Gnum bandvertlocnbr; /* Number of local band vertices */ + Gnum bandvertlvlnum; /* Index of first band vertex belonging to last level */ + Gnum * restrict bandvertloctax; + Gnum bandvertlocadj; /* Ajust value for local-to-global band vertex indices */ + Gnum bandvertlocnum; + Gnum * restrict bandveloloctax; + Gnum bandvelolocnbr; + Gnum bandvelolocsum; + Gnum * restrict bandedgeloctax; + Gnum bandedgelocnum; + Gnum bandedgelocsiz; /* Number of local edges in band graph */ + Gnum * restrict bandedloloctax; + Gnum bandedlolocsiz; /* Size of local band edge load array */ + Gnum bandvnumgstsiz; + Gnum * restrict bandvnumgsttax; /* Indices of selected band vertices in band graph */ + Gnum * restrict bandvlblloctax; + Gnum banddegrlocmax; + Gnum degrval; + Gnum veloval; + Gnum vertlocadj; + const Gnum * restrict edgegsttax; + SCOTCH_Num * fronloctax; + Gnum fronlocnum; + int cheklocval; + int chekglbval; + int procngbnum; + + Dgraph * restrict const grafptr = (Dgraph *) orggrafptr; + Dgraph * restrict const bandgrafptr = (Dgraph *) bndgrafptr; + const Gnum * restrict const vertloctax = grafptr->vertloctax; + const Gnum * restrict const vendloctax = grafptr->vendloctax; + const Gnum * restrict const vlblloctax = grafptr->vlblloctax; + const Gnum * restrict const veloloctax = grafptr->veloloctax; + const Gnum * restrict const edloloctax = grafptr->edloloctax; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + int o; + + MPI_Comm_compare (((Dgraph * restrict const) orggrafptr)->proccomm, + ((Dgraph * restrict const) bndgrafptr)->proccomm, &o); + if ((o != MPI_IDENT) && (o != MPI_CONGRUENT)) { + errorPrint ("SCOTCH_dgraphBand: communicators are not congruent"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("SCOTCH_dgraphBand: cannot compute ghost edge array"); + return (1); + } + + cheklocval = 0; + bandvnumgstsiz = MAX ((grafptr->vertgstnbr * sizeof (Gnum)), (grafptr->procglbnbr * sizeof (int))); /* TRICK: re-use array for further error collective communications */ + if ((bandvnumgsttax = memAlloc (bandvnumgstsiz)) == NULL) { + errorPrint ("SCOTCH_dgraphBand: out of memory (1)"); + cheklocval = 1; + } +#ifdef SCOTCH_DEBUG_DGRAPH1 /* This communication cannot be covered by a useful one */ + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphBand: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_DGRAPH1 */ + chekglbval = cheklocval; +#endif /* SCOTCH_DEBUG_DGRAPH1 */ + if (chekglbval != 0) + return (1); + + memSet (bandvnumgsttax, ~0, grafptr->vertgstnbr * sizeof (Gnum)); /* Reset part array */ + bandvnumgsttax -= grafptr->baseval; + + if ((((grafptr->flagval & DGRAPHCOMMPTOP) != 0) ? dgraphBandPtop : dgraphBandColl) + (grafptr, fronlocnbr, fronloctab, distval, bandvnumgsttax, &bandvertlvlnum, &bandvertlocnbr, &bandedgelocsiz) != 0) + return (1); + + bandvelolocnbr = (veloloctax != NULL) ? bandvertlocnbr : 0; + bandedlolocsiz = (edloloctax != NULL) ? bandedgelocsiz : 0; + + bandgrafptr->flagval |= (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* Arrays created by the routine itself */ + bandgrafptr->baseval = grafptr->baseval; + + cheklocval = 0; + if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ + &bandgrafptr->procdsptab, (size_t) ((grafptr->procglbnbr + 1) * sizeof (Gnum)), + &bandgrafptr->proccnttab, (size_t) (grafptr->procglbnbr * sizeof (Gnum)), + &bandgrafptr->procngbtab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &bandgrafptr->procrcvtab, (size_t) (grafptr->procglbnbr * sizeof (int)), + &bandgrafptr->procsndtab, (size_t) (grafptr->procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("SCOTCH_dgraphBand: out of memory (2)"); + cheklocval = 1; + } + else if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ + &bandgrafptr->vertloctax, (size_t) ((bandvertlocnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ + &bandvlblloctax, (size_t) (bandvertlocnbr * sizeof (Gnum)), + &bandveloloctax, (size_t) (bandvelolocnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("SCOTCH_dgraphBand: out of memory (3)"); + cheklocval = 1; + } + else if (bandgrafptr->vertloctax -= bandgrafptr->baseval, + bandvlblloctax -= bandgrafptr->baseval, + bandveloloctax = (veloloctax != NULL) ? (bandveloloctax - bandgrafptr->baseval) : NULL, + (memAllocGroup ((void **) (void *) + &bandedgeloctax, (size_t) (bandedgelocsiz * sizeof (Gnum)), + &bandedloloctax, (size_t) (bandedlolocsiz * sizeof (Gnum)), NULL) == NULL)) { + errorPrint ("SCOTCH_dgraphBand: out of memory (4)"); + cheklocval = 1; + } + else { + bandedgeloctax -= bandgrafptr->baseval; + bandedloloctax = (edloloctax != NULL) ? (bandedloloctax - bandgrafptr->baseval) : NULL; + } + + if (cheklocval != 0) { /* In case of memory error */ + bandgrafptr->procdsptab[0] = -1; + if (MPI_Allgather (&bandgrafptr->procdsptab[0], 1, GNUM_MPI, /* Send received data to dummy array */ + bandvnumgsttax + bandgrafptr->baseval, 1, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphBand: communication error (2)"); + return (1); + } + dgraphExit (bandgrafptr); + memFree (bandvnumgsttax + bandgrafptr->baseval); + return (1); + } + else { + bandgrafptr->procdsptab[0] = bandvertlocnbr; + if (MPI_Allgather (&bandgrafptr->procdsptab[0], 1, GNUM_MPI, + &bandgrafptr->procdsptab[1], 1, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphBand: communication error (3)"); + return (1); + } + } + bandgrafptr->procdsptab[0] = bandgrafptr->baseval; /* Build vertex-to-process array */ +#ifdef SCOTCH_DEBUG_DGRAPH2 + memSet (bandvlblloctax + bandgrafptr->baseval, ~0, (bandvertlocnbr * sizeof (Gnum))); +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + for (procngbnum = 1; procngbnum <= grafptr->procglbnbr; procngbnum ++) { /* Process potential error flags from other processes */ + if (bandgrafptr->procdsptab[procngbnum] < 0) { /* If error notified by another process */ + dgraphExit (bandgrafptr); + memFree (bandvnumgsttax + bandgrafptr->baseval); + return (1); + } + bandgrafptr->procdsptab[procngbnum] += bandgrafptr->procdsptab[procngbnum - 1]; + bandgrafptr->proccnttab[procngbnum - 1] = bandgrafptr->procdsptab[procngbnum] - bandgrafptr->procdsptab[procngbnum - 1]; + } + + fronloctax = fronloctab - bandgrafptr->baseval; + for (vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval, + bandvertlocnum = bandgrafptr->baseval, + bandvertlocnnd = bandvertlocnbr + bandgrafptr->baseval, + bandvertlocadj = bandgrafptr->procdsptab[grafptr->proclocnum] - bandgrafptr->baseval; + bandvertlocnum < bandvertlocnnd; bandvertlocnum ++) { /* Turn all kept graph vertices into band graph vertices */ + Gnum vertlocnum; + + vertlocnum = fronloctax[bandvertlocnum]; + bandvlblloctax[bandvertlocnum] = (vlblloctax == NULL) ? (vertlocnum + vertlocadj) : vlblloctax[vertlocnum]; + bandvnumgsttax[vertlocnum] += bandvertlocadj; /* Turn local indices in band graph into global indices */ + } + + if (dgraphHaloSync (grafptr, (byte *) (bandvnumgsttax + bandgrafptr->baseval), GNUM_MPI) != 0) { /* Share global indexing of halo vertices */ + errorPrint ("SCOTCH_dgraphBand: cannot perform halo exchange"); + return (1); + } + + edgegsttax = grafptr->edgegsttax; + + veloval = 1; + bandvertloctax = bandgrafptr->vertloctax; + bandvelolocsum = 0; + banddegrlocmax = 0; + for (bandvertlocnum = bandedgelocnum = bandgrafptr->baseval; /* Build global vertex array of band graph */ + bandvertlocnum < bandvertlvlnum; bandvertlocnum ++) { /* For all vertices save for the last level */ + Gnum vertlocnum; + Gnum edgelocnum; + Gnum degrval; + + vertlocnum = bandvlblloctax[bandvertlocnum] - vertlocadj; + bandvertloctax[bandvertlocnum] = bandedgelocnum; + if (veloloctax != NULL) { + veloval = veloloctax[vertlocnum]; + bandvelolocsum += veloval; + bandveloloctax[bandvertlocnum] = veloval; + } + + degrval = vendloctax[vertlocnum] - vertloctax[vertlocnum]; + if (banddegrlocmax < degrval) + banddegrlocmax = degrval; + + for (edgelocnum = vertloctax[vertlocnum]; /* For all original edges */ + edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (bandvnumgsttax[edgegsttax[edgelocnum]] == ~0) { /* All ends should belong to the band graph too */ + errorPrint ("SCOTCH_dgraphBand: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + bandedgeloctax[bandedgelocnum ++] = bandvnumgsttax[edgegsttax[edgelocnum]]; + } + } + for ( ; bandvertlocnum < bandvertlocnnd; bandvertlocnum ++) { /* For all vertices that belong to the last level */ + Gnum vertlocnum; + Gnum edgelocnum; + Gnum degrval; + + vertlocnum = bandvlblloctax[bandvertlocnum] - vertlocadj; + bandvertloctax[bandvertlocnum] = bandedgelocnum; + if (veloloctax != NULL) { + veloval = veloloctax[vertlocnum]; + bandvelolocsum += veloval; + bandveloloctax[bandvertlocnum] = veloval; + } + + for (edgelocnum = vertloctax[vertlocnum]; /* For all original edges */ + edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { + Gnum bandvertlocend; + + bandvertlocend = bandvnumgsttax[edgegsttax[edgelocnum]]; + if (bandvertlocend != ~0) { /* If end vertex belongs to band graph */ + if (bandedloloctax != NULL) /* If graph has edge weights, copy load */ + bandedloloctax[bandedgelocnum] = edloloctax[edgelocnum]; + bandedgeloctax[bandedgelocnum ++] = bandvertlocend; + } + } + + degrval = bandedgelocnum - bandvertloctax[bandvertlocnum]; + if (banddegrlocmax < degrval) + banddegrlocmax = degrval; + } + bandvertloctax[bandvertlocnnd] = bandedgelocnum; /* Set end of vertex array */ + + memFree (bandvnumgsttax + bandgrafptr->baseval); /* Free useless space */ + + if (bandedloloctax != NULL) { /* If graph has edge weights */ + Gnum edgelocnum; + Gnum edgelocnnd; + + for (bandvertlocnum = bandgrafptr->baseval; /* For all vertices that do not belong to the last level */ + bandvertlocnum < bandvertlvlnum; bandvertlocnum ++) { + Gnum vertlocnum; + Gnum bandedgelocnum; + + vertlocnum = bandvlblloctax[bandvertlocnum] - vertlocadj; + bandedgelocnum = bandvertloctax[bandvertlocnum]; + memCpy (bandedloloctax + bandedgelocnum, /* Copy edge load array */ + &edloloctax[vertloctax[vertlocnum]], + (bandvertloctax[bandvertlocnum + 1] - bandedgelocnum) * sizeof (Gnum)); + } /* Vertices of last level have been processed before */ + } + + bandgrafptr->procvrttab = bandgrafptr->procdsptab; /* Graph does not have holes */ + bandgrafptr->vertlocnbr = bandvertlocnbr; + bandgrafptr->vertlocnnd = bandvertlocnbr + bandgrafptr->baseval; + bandgrafptr->vendloctax = bandvertloctax + 1; /* Band graph is compact */ + bandgrafptr->veloloctax = bandveloloctax; + bandgrafptr->velolocsum = bandvelolocsum; + bandgrafptr->vlblloctax = bandvlblloctax; + bandgrafptr->edgeloctax = bandedgeloctax; + bandgrafptr->edloloctax = bandedloloctax; + bandgrafptr->edgelocnbr = bandedgelocnum - bandgrafptr->baseval; + bandgrafptr->edgelocsiz = bandedgelocsiz; + bandgrafptr->degrglbmax = banddegrlocmax; /* Local maximum degree will be turned into global maximum degree */ + if (dgraphBuild4 (bandgrafptr) != 0) { + errorPrint ("SCOTCH_dgraphBand: cannot build band graph"); + return (1); + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphCheck (bandgrafptr) != 0) { + errorPrint ("SCOTCH_dgraphBand: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_band_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_band_f.c new file mode 100644 index 00000000..489d3b03 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_band_f.c @@ -0,0 +1,80 @@ +/* Copyright 2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_band_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed graph handling routines **/ +/** of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 03 nov 2011 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph handling */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHBAND, scotchfdgraphband, ( \ +SCOTCH_Dgraph * const srcgrafptr, \ +const SCOTCH_Num fronlocnbr, \ +SCOTCH_Num * const fronloctab, \ +const SCOTCH_Num distval, \ +SCOTCH_Dgraph * const bndgrafptr, \ +int * const revaptr), \ +(srcgrafptr, fronlocnbr, fronloctab, distval, bndgrafptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphBand (srcgrafptr, fronlocnbr, fronloctab, distval, bndgrafptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_build.c b/scotch_6.0.3/src/libscotch/library_dgraph_build.c new file mode 100644 index 00000000..6f0bfb15 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_build.c @@ -0,0 +1,125 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_build.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 23 feb 2007 **/ +/** to 18 jul 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "ptscotch.h" + +/****************************************/ +/* */ +/* These routines are the C API for the */ +/* distributed graph handling routines. */ +/* */ +/****************************************/ + +/*+ This routine fills the contents of the given +*** opaque distributed graph structure with the +*** data provided by the user. The base value +*** allows the user to set the graph base to 0 or 1. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphBuild ( +SCOTCH_Dgraph * const grafptr, /* Distributed graph structure to fill */ +const Gnum baseval, /* Base for indexing */ +const Gnum vertlocnbr, /* Number of local vertices */ +const Gnum vertlocmax, /* Maximum number of local vertices */ +Gnum * const vertloctab, /* Local vertex begin array */ +Gnum * const vendloctab, /* Local vertex end array */ +Gnum * const veloloctab, /* Local vertex load array (if any) */ +Gnum * const vlblloctab, /* Local vertex label array (if any) */ +const Gnum edgelocnbr, /* Number of local edges */ +const Gnum edgelocsiz, /* Size of local edge array */ +Gnum * const edgeloctab, /* Local edge array */ +Gnum * const edgegsttab, /* Ghost edge array (if any); not const */ +Gnum * const edloloctab) /* Local edge load array (if any) */ +{ + Dgraph * srcgrafptr; /* Pointer to source graph structure */ + Gnum * vertloctax; + Gnum * vendloctax; + Gnum * veloloctax; + Gnum * vlblloctax; + Gnum * edgeloctax; + Gnum * edgegsttax; + Gnum * edloloctax; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Dgraph) < sizeof (Dgraph)) { + errorPrint ("SCOTCH_dgraphBuild: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + if ((baseval < 0) || (baseval > 1)) { + errorPrint ("SCOTCH_dgraphBuild: invalid base parameter"); + return (1); + } + + srcgrafptr = (Dgraph *) grafptr; /* Use structure as source graph */ + + vertloctax = (Gnum *) vertloctab - baseval; + vendloctax = ((vendloctab == NULL) || (vendloctab == vertloctab + 1)) ? vertloctax + 1 : (Gnum *) vendloctab - baseval; + veloloctax = ((veloloctab == NULL) || (veloloctab == vertloctab)) ? NULL : (Gnum *) veloloctab - baseval; + vlblloctax = ((vlblloctab == NULL) || (vlblloctab == vertloctab)) ? NULL : (Gnum *) vlblloctab - baseval; + edgeloctax = (Gnum *) edgeloctab - baseval; + edgegsttax = ((edgegsttab == NULL) || (edgegsttab == edgeloctab)) ? NULL : (Gnum *) edgegsttab - baseval; + edloloctax = ((edloloctab == NULL) || (edloloctab == edgeloctab)) ? NULL : (Gnum *) edloloctab - baseval; + + return (dgraphBuild (srcgrafptr, baseval, + vertlocnbr, vertlocmax, vertloctax, vendloctax, veloloctax, NULL, vlblloctax, + edgelocnbr, edgelocsiz, edgeloctax, edgegsttax, edloloctax)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_build_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_build_f.c new file mode 100644 index 00000000..f2e4629c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_build_f.c @@ -0,0 +1,95 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_build_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 24 feb 2007 **/ +/** to 18 jul 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/********************************************/ +/* */ +/* These routines are the Fortran API for */ +/* the distributed graph handling routines. */ +/* */ +/********************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHBUILD, scotchfdgraphbuild, ( \ +SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Num * const baseptr, \ +const SCOTCH_Num * const vertlocptr, \ +const SCOTCH_Num * const vertlocmpt, \ +SCOTCH_Num * const vertloctab, \ +SCOTCH_Num * const vendloctab, \ +SCOTCH_Num * const veloloctab, \ +SCOTCH_Num * const vlblloctab, \ +const SCOTCH_Num * const edgelocptr, \ +const SCOTCH_Num * const edgelocptz, \ +SCOTCH_Num * const edgeloctab, \ +SCOTCH_Num * const edgegsttab, \ +SCOTCH_Num * const edloloctab, \ +int * const revaptr), \ +(grafptr, baseptr, vertlocptr, vertlocmpt, \ + vertloctab, vendloctab, veloloctab, \ + vlblloctab, edgelocptr, edgelocptz, \ + edgeloctab, edgegsttab, edloloctab, \ + revaptr)) +{ + *revaptr = SCOTCH_dgraphBuild (grafptr, *baseptr, *vertlocptr, *vertlocmpt, vertloctab, + vendloctab, veloloctab, vlblloctab, + *edgelocptr, *edgelocptz, edgeloctab, edgegsttab, edloloctab); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_build_grid3d.c b/scotch_6.0.3/src/libscotch/library_dgraph_build_grid3d.c new file mode 100644 index 00000000..2e096e39 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_build_grid3d.c @@ -0,0 +1,84 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_build_grid3d.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : These lines are the distributed source **/ +/** graph building routines for 3D grid **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 5.0 : from : 21 jul 2005 **/ +/** to : 10 sep 2007 **/ +/** # Version 5.1 : from : 05 jun 2010 **/ +/** to : 06 jun 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/*+ This routine builds a distributed +*** 3D grid or torus graph structure. +*** It returns: +*** - 0 : if the creation succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphBuildGrid3D ( +SCOTCH_Dgraph * const grafptr, +const SCOTCH_Num baseval, /* Base value */ +const SCOTCH_Num dimx, /* First dimension */ +const SCOTCH_Num dimy, /* Second dimension */ +const SCOTCH_Num dimz, /* Third dimension */ +const SCOTCH_Num incrval, /* Increment value */ +const int flagval) /* Flag value */ +{ + return (dgraphBuildGrid3D ((Dgraph *) grafptr, baseval, dimx, dimy, dimz, incrval, flagval)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_build_grid3d_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_build_grid3d_f.c new file mode 100644 index 00000000..24974e7d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_build_grid3d_f.c @@ -0,0 +1,86 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_build_grid3d_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 feb 2007 **/ +/** to 16 feb 2007 **/ +/** # Version 5.1 : from : 06 jun 2010 **/ +/** to 06 jun 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph handling */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHBUILDGRID3D, scotchfdgraphbuildgrid3d, ( \ +SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Num * const baseptr, \ +const SCOTCH_Num * const dimxptr, \ +const SCOTCH_Num * const dimyptr, \ +const SCOTCH_Num * const dimzptr, \ +const SCOTCH_Num * const incrptr, \ +const int * const flagptr, \ +int * const revaptr), \ +(grafptr, baseptr, dimxptr, dimyptr, dimzptr, incrptr, flagptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphBuildGrid3D (grafptr, *baseptr, *dimxptr, *dimyptr, *dimzptr, *incrptr, *flagptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_check.c b/scotch_6.0.3/src/libscotch/library_dgraph_check.c new file mode 100644 index 00000000..76e334c0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_check.c @@ -0,0 +1,80 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the source **/ +/** graph handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 26 aug 2006 **/ +/** to 26 aug 2006 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the distributed graph handling */ +/* routines. */ +/* */ +/************************************/ + +/*+ This routine checks the consistency +*** of the given graph. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphCheck ( +const SCOTCH_Dgraph * const grafptr) +{ + return (dgraphCheck ((const Dgraph * const) grafptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_check_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_check_f.c new file mode 100644 index 00000000..f39b7f0d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_check_f.c @@ -0,0 +1,78 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_check_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 26 aug 2006 **/ +/** to 26 aug 2006 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph handling */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHCHECK, scotchfdgraphcheck, ( \ +const SCOTCH_Dgraph * const grafptr, \ +int * const revaptr), \ +(grafptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphCheck (grafptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_coarsen.c b/scotch_6.0.3/src/libscotch/library_dgraph_coarsen.c new file mode 100644 index 00000000..de0c7b0d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_coarsen.c @@ -0,0 +1,127 @@ +/* Copyright 2011,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_coarsen.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the **/ +/** distributed graph coarsening routine of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 07 aug 2011 **/ +/** to 07 aug 2011 **/ +/** # Version 6.0 : from : 11 sep 2012 **/ +/** to 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* This routine is the C API for */ +/* the distributed graph coarsening */ +/* routine. */ +/* */ +/************************************/ + +/*+ This routine creates a distributed coarse graph +*** from the given fine graph, unless the coarse graph +*** is smaller than some threshold size or the +*** coarsening ratio is above some other threshold. +*** If the coarse graph is created, a coarse-to-fine +*** vertex array is created, that contains a pair of +*** fine indices for each coarse index. It is the +*** user's responsibility to free this array when it +*** is no longer needed. +*** It returns: +*** - 0 : if the graph has been coarsened. +*** - 1 : if the graph could not be coarsened. +*** - 2 : if folded graph not present +*** - 3 : on error. ++*/ + +int +SCOTCH_dgraphCoarsen ( +SCOTCH_Dgraph * restrict const finegrafptr, /* Fine graph structure to fill */ +const SCOTCH_Num coarnbr, /* Minimum number of coarse vertices */ +const double coarrat, /* Maximum contraction ratio */ +const SCOTCH_Num flagval, /* Flag value */ +SCOTCH_Dgraph * restrict const coargrafptr, /* Coarse graph */ +SCOTCH_Num * restrict const multloctab) /* Pointer to multinode array */ +{ + DgraphCoarsenMulti * restrict multlocptr; +#ifdef SCOTCH_DEBUG_LIBRARY1 + int o; + + MPI_Comm_compare (((Dgraph * restrict const) coargrafptr)->proccomm, + ((Dgraph * restrict const) finegrafptr)->proccomm, &o); + if ((o != MPI_IDENT) && (o != MPI_CONGRUENT)) { + errorPrint ("SCOTCH_dgraphCoarsen: communicators are not congruent"); + return (3); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + intRandInit (); /* Check that random number generator is initialized */ + + multlocptr = (DgraphCoarsenMulti * restrict) multloctab; /* User-provided multinode array */ + switch (dgraphCoarsen ((Dgraph * restrict const) finegrafptr, (Dgraph * restrict const) coargrafptr, + &multlocptr, 5, coarnbr, coarrat, (int) flagval)) { + case 1 : + return (1); + case 2 : + return (3); + } + + if (multlocptr != (DgraphCoarsenMulti * restrict) multloctab) { /* If folding occurred */ + if (multlocptr == NULL) + return (2); + + memCpy (multloctab, multlocptr, /* Update array with folded multinode data */ + ((Dgraph * restrict const) coargrafptr)->vertlocnbr * sizeof (DgraphCoarsenMulti)); + memFree (multlocptr); /* Free allocated folded multinode array */ + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_coarsen_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_coarsen_f.c new file mode 100644 index 00000000..6e3ef25a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_coarsen_f.c @@ -0,0 +1,82 @@ +/* Copyright 2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_coarsen_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed graph coarsening routine of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 07 aug 2011 **/ +/** to 07 aug 2011 **/ +/** # Version 6.0 : from : 12 sep 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHCOARSEN, scotchfdgraphcoarsen, ( \ +SCOTCH_Dgraph * const finegrafptr, \ +const SCOTCH_Num * const coarnbrptr, \ +double * const coarratptr, \ +const SCOTCH_Num * const flagvalptr, \ +SCOTCH_Dgraph * const coargrafptr, \ +SCOTCH_Num * const multloctab, \ +int * const revaptr), \ +(finegrafptr, coarnbrptr, coarratptr, flagvalptr, coargrafptr, multloctab, revaptr)) +{ + *revaptr = SCOTCH_dgraphCoarsen (finegrafptr, *coarnbrptr, *coarratptr, *flagvalptr, coargrafptr, multloctab); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_f.c new file mode 100644 index 00000000..e0515b47 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_f.c @@ -0,0 +1,165 @@ +/* Copyright 2007-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 04 sep 2006 **/ +/** to 05 aug 2007 **/ +/** # Version 5.1 : from : 27 jul 2008 **/ +/** to 15 apr 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHINIT, scotchfdgraphinit, ( \ +SCOTCH_Dgraph * const grafptr, \ +const MPI_Fint * const commptr, \ +int * const revaptr), \ +(grafptr, commptr, revaptr)) +{ + MPI_Comm commdat; + + commdat = MPI_Comm_f2c (*commptr); + *revaptr = SCOTCH_dgraphInit (grafptr, commdat); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHEXIT, scotchfdgraphexit, ( \ +SCOTCH_Dgraph * const grafptr), \ +(grafptr)) +{ + SCOTCH_dgraphExit (grafptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHSIZE, scotchfdgraphsize, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Num * const vertglbptr, \ +SCOTCH_Num * const vertlocptr, \ +SCOTCH_Num * const edgeglbptr, \ +SCOTCH_Num * const edgelocptr), \ +(grafptr, vertglbptr, vertlocptr, edgeglbptr, edgelocptr)) +{ + SCOTCH_dgraphSize (grafptr, vertglbptr, vertlocptr, edgeglbptr, edgelocptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHDATA, scotchfdgraphdata, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Num * const indxptr, \ +SCOTCH_Num * const baseptr, \ +SCOTCH_Num * const vertglbptr, \ +SCOTCH_Num * const vertlocptr, \ +SCOTCH_Num * const vertlocptz, \ +SCOTCH_Num * const vertgstptr, \ +SCOTCH_Idx * const vertlocidx, \ +SCOTCH_Idx * const vendlocidx, \ +SCOTCH_Idx * const velolocidx, \ +SCOTCH_Idx * const vlbllocidx, \ +SCOTCH_Num * const edgeglbptr, \ +SCOTCH_Num * const edgelocptr, \ +SCOTCH_Num * const edgelocptz, \ +SCOTCH_Idx * const edgelocidx, \ +SCOTCH_Idx * const edgegstidx, \ +SCOTCH_Idx * const edlolocidx, \ +MPI_Fint * const commptr), \ +(grafptr, indxptr, baseptr, \ + vertglbptr, vertlocptr, vertlocptz, \ + vertgstptr, vertlocidx, vendlocidx, \ + velolocidx, vlbllocidx, edgeglbptr, \ + edgelocptr, edgelocptz, edgelocidx, \ + edgegstidx, edlolocidx, commptr)) +{ + SCOTCH_Num * vertloctab; /* Pointer to graph arrays */ + SCOTCH_Num * vendloctab; + SCOTCH_Num * veloloctab; + SCOTCH_Num * vlblloctab; + SCOTCH_Num * edgeloctab; + SCOTCH_Num * edgegsttab; + SCOTCH_Num * edloloctab; + MPI_Comm commdat; + + SCOTCH_dgraphData (grafptr, baseptr, vertglbptr, vertlocptr, vertlocptz, vertgstptr, + &vertloctab, &vendloctab, &veloloctab, &vlblloctab, + edgeglbptr, edgelocptr, edgelocptz, + &edgeloctab, &edgegsttab, &edloloctab, &commdat); + *vertlocidx = (vertloctab - indxptr) + 1; /* Add 1 since Fortran indices start at 1 */ + *vendlocidx = (vendloctab - indxptr) + 1; + *velolocidx = (veloloctab != NULL) ? (veloloctab - indxptr) + 1 : *vertlocidx; + *vlbllocidx = (vlblloctab != NULL) ? (vlblloctab - indxptr) + 1 : *vertlocidx; + *edgelocidx = (edgeloctab - indxptr) + 1; + *edgegstidx = (edgegsttab != NULL) ? (edgegsttab - indxptr) + 1 : *vertlocidx; + *edlolocidx = (edloloctab != NULL) ? (edloloctab - indxptr) + 1 : *vertlocidx; + *commptr = MPI_Comm_c2f (commdat); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_gather.c b/scotch_6.0.3/src/libscotch/library_dgraph_gather.c new file mode 100644 index 00000000..4f70425d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_gather.c @@ -0,0 +1,125 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_gather.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 12 jul 2007 **/ +/** to 17 jul 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/*+ This routine gathers the data of a +*** distributed graph on a centralized graph. +*** It returns: +*** - 0 : if the centralization succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphGather ( +const SCOTCH_Dgraph * const dgrfptr, +SCOTCH_Graph * const cgrfptr) +{ + Dgraph * restrict srcdgrfptr; + Gnum reduloctab[3]; + Gnum reduglbtab[3]; + + srcdgrfptr = (Dgraph *) dgrfptr; + + if ((cgrfptr != NULL) && (((void *) cgrfptr) != ((void *) dgrfptr))) { /* If centralized graph provided */ + reduloctab[0] = 1; /* Process is a potential root */ + reduloctab[1] = (Gnum) srcdgrfptr->proclocnum; + } + else { /* Process is not a root */ + reduloctab[0] = 0; + reduloctab[1] = 0; + } + + if (srcdgrfptr->edloloctax == NULL) /* Compute sum of edge loads for access to low-level routines */ + reduloctab[2] = srcdgrfptr->edgelocnbr; + else { + Gnum vertlocnum; + Gnum edlolocsum; + + for (vertlocnum = srcdgrfptr->baseval, edlolocsum = 0; + vertlocnum < srcdgrfptr->vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + Gnum edgelocnnd; + + for (edgelocnum = srcdgrfptr->vertloctax[vertlocnum], + edgelocnnd = srcdgrfptr->vendloctax[vertlocnum]; + edgelocnum < edgelocnnd; edgelocnum ++) + edlolocsum += srcdgrfptr->edloloctax[edgelocnum]; + } + reduloctab[2] = edlolocsum; + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_SUM, srcdgrfptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphGather: communication error"); + return (1); + } + if (reduglbtab[0] == 1) /* If only one single root */ + return (dgraphGatherAll2 (srcdgrfptr, (Graph *) cgrfptr, reduglbtab[2], (int) reduglbtab[1])); + else if (reduglbtab[0] == srcdgrfptr->procglbnbr) /* If all processes are roots */ + return (dgraphGatherAll2 (srcdgrfptr, (Graph *) cgrfptr, reduglbtab[2], -1)); + + errorPrint ("SCOTCH_dgraphGather: invalid number of roots"); + return (1); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_gather_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_gather_f.c new file mode 100644 index 00000000..f5091470 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_gather_f.c @@ -0,0 +1,79 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_gather_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 12 jul 2007 **/ +/** to 12 jul 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph handling */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHGATHER, scotchfdgraphgather, ( \ +SCOTCH_Dgraph * const dgrfptr, \ +SCOTCH_Graph * const cgrfptr, \ +int * const revaptr), \ +(dgrfptr, cgrfptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphGather (dgrfptr, cgrfptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_grow.c b/scotch_6.0.3/src/libscotch/library_dgraph_grow.c new file mode 100644 index 00000000..9fb64be9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_grow.c @@ -0,0 +1,118 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_grow.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted graph growing routine of **/ +/** the libScotch library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 26 sep 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dgraph_halo.h" +#include "ptscotch.h" + +/**********************************/ +/* */ +/* Distance computation routines. */ +/* */ +/**********************************/ + +#define DGRAPHBANDGROWNAME dgraphGrow +#define DGRAPHBANDGROWEDGE(n) /* No need to count edges */ +#define DGRAPHBANDGROWENQ1 /* Color array already set */ +#define DGRAPHBANDGROWENQ2 vnumgsttax[vertlocnum] /* Set vertex color */ +#define DGRAPHBANDGROWENQ3 vsnddattab[nsndidxnum ++] = vnumgsttax[vertlocnum] /* Send color value */ +#define DGRAPHBANDGROWENQ4 vrcvdatptr[vertrcvnum + 1] /* Get and set color */ +#define DGRAPHBANDGROWSMUL(n) ((n) * 2) /* Add space for color value */ +#include "dgraph_band_grow.h" +#include "dgraph_band_grow.c" +#undef DGRAPHBANDGROWNAME +#undef DGRAPHBANDGROWEDGE +#undef DGRAPHBANDGROWENQ1 +#undef DGRAPHBANDGROWENQ2 +#undef DGRAPHBANDGROWENQ3 +#undef DGRAPHBANDGROWENQ4 +#undef DGRAPHBANDGROWSMUL + +/*********************************/ +/* */ +/* This routine is the C API for */ +/* the graph growing routine. */ +/* */ +/*********************************/ + +/*+ This routine grows areas from a given +*** set of seeds of some color. Several +*** seeds can have the same color. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphGrow ( +SCOTCH_Dgraph * const orggrafptr, +const SCOTCH_Num seedlocnbr, +SCOTCH_Num * const seedloctab, +const SCOTCH_Num distval, +SCOTCH_Num * const partgsttab) +{ + Gnum bandvertlocnbr; /* Not used */ + Gnum bandvertlvlnum; /* Not used */ + Gnum bandedgelocsiz; /* Not used */ + + Dgraph * restrict const grafptr = (Dgraph *) orggrafptr; + + if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("SCOTCH_dgraphGrow: cannot compute ghost edge array"); + return (1); + } + + return ((((grafptr->flagval & DGRAPHCOMMPTOP) != 0) ? dgraphGrowPtop : dgraphGrowColl) + (grafptr, seedlocnbr, seedloctab, distval, partgsttab - grafptr->baseval, &bandvertlvlnum, &bandvertlocnbr, &bandedgelocsiz)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_halo.c b/scotch_6.0.3/src/libscotch/library_dgraph_halo.c new file mode 100644 index 00000000..98ced5a0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_halo.c @@ -0,0 +1,175 @@ +/* Copyright 2007,2009,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_halo.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 jul 2007 **/ +/** to 02 aug 2007 **/ +/** # Version 5.1 : from : 02 jul 2008 **/ +/** to 17 nov 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" +#include "dgraph_halo.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/*+ This routine requests the computation +*** of the ghost edge array. +*** It returns: +*** - 0 : if the computation succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphGhst ( +SCOTCH_Dgraph * const grafptr) +{ + return (dgraphGhst ((Dgraph *) grafptr)); +} + +/*+ This routine requests the computation of the +*** ghost edge array in replacement of the global +*** edge array. +*** It returns: +*** - 0 : if the computation succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphGhstReplace ( +SCOTCH_Dgraph * const grafptr) +{ + Dgraph * restrict srcgrafptr; /* Pointer to scotch graph */ + DgraphFlag srcflagval; /* Graph properties */ + int o; + + srcgrafptr = (Dgraph *) grafptr; + srcflagval = srcgrafptr->flagval; + srcgrafptr->flagval |= DGRAPHFREETABS; /* If edge array was not allocated internally, assume it was */ + + o = dgraphGhstReplace (srcgrafptr); + + srcgrafptr->flagval = (srcgrafptr->flagval & ~DGRAPHFREETABS) | srcflagval; /* Restore original allocation flag */ + + return (o); +} + +/*+ This routine spreads local information +*** borne by local vertices across the ghost +*** vertices of the neighboring processes. +*** It returns: +*** - 0 : if the exchange succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphHalo ( +SCOTCH_Dgraph * const grafptr, +void * const datatab, +const MPI_Datatype typeval) +{ + return (dgraphHaloSync ((Dgraph *) grafptr, (byte *) datatab, typeval)); +} + +/*+ This routine spreads local information +*** borne by local vertices across the ghost +*** vertices of the neighboring processes, in +*** an asynchronous way. +*** It returns: +*** - 0 : if the exchange succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphHaloAsync ( +SCOTCH_Dgraph * const grafptr, +void * const datatab, +const MPI_Datatype typeval, +SCOTCH_DgraphHaloReq * const requptr) +{ + dgraphHaloAsync ((Dgraph *) grafptr, (byte *) datatab, typeval, (DgraphHaloRequest *) requptr); + return (0); +} + +/*+ This routine waits for the termination of +*** an asynchronous halo request. +*** It returns: +*** - 0 : if the exchange succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphHaloWait ( +SCOTCH_DgraphHaloReq * const requptr) +{ + return (dgraphHaloWait ((DgraphHaloRequest *) requptr)); +} + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** halo request structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_DgraphHaloReq * +SCOTCH_dgraphHaloReqAlloc () +{ + return ((SCOTCH_DgraphHaloReq *) memAlloc (sizeof (SCOTCH_DgraphHaloReq))); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_halo_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_halo_f.c new file mode 100644 index 00000000..b06b55de --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_halo_f.c @@ -0,0 +1,130 @@ +/* Copyright 2007,2009,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_halo_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 jul 2007 **/ +/** to 02 aug 2007 **/ +/** # Version 5.1 : from : 09 may 2009 **/ +/** to 10 may 2009 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph handling */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHGHST, scotchfdgraphghst, ( \ +SCOTCH_Dgraph * const grafptr, \ +int * const revaptr), \ +(grafptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphGhst (grafptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHHALO, scotchfdgraphhalo, ( \ +SCOTCH_Dgraph * const grafptr, \ +void * const datatab, \ +MPI_Fint * const typeptr, \ +int * const revaptr), \ +(grafptr, datatab, typeptr, revaptr)) +{ + MPI_Datatype typeval; + + typeval = MPI_Type_f2c (*typeptr); + *revaptr = SCOTCH_dgraphHalo (grafptr, datatab, typeval); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHHALOASYNC, scotchfdgraphhaloasync, ( \ +SCOTCH_Dgraph * const grafptr, \ +void * const datatab, \ +MPI_Fint * const typeptr, \ +SCOTCH_DgraphHaloReq * const requptr, \ +int * const revaptr), \ +(grafptr, datatab, typeptr, requptr, revaptr)) +{ + MPI_Datatype typeval; + + typeval = MPI_Type_f2c (*typeptr); + *revaptr = SCOTCH_dgraphHaloAsync (grafptr, datatab, typeval, requptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHHALOWAIT, scotchfdgraphhalowait, ( \ +SCOTCH_DgraphHaloReq * const requptr, \ +int * const revaptr), \ +(requptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphHaloWait (requptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_induce.c b/scotch_6.0.3/src/libscotch/library_dgraph_induce.c new file mode 100644 index 00000000..17a2da4c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_induce.c @@ -0,0 +1,168 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_induce.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the **/ +/** distributed graph induction routine of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 30 aug 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/** NOTES : # This code is directly derived from **/ +/** the code of dgraphInducePart() and **/ +/** of its subroutines. The only change **/ +/** is that it uses Gnum's instead of **/ +/** GraphPart's as part values. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "ptscotch.h" + +/***********************************/ +/* */ +/* This routine is the C API for */ +/* the distributed graph induction */ +/* routine. */ +/* */ +/***********************************/ + +/*+ This routine creates a distributed induced graph +*** from the given graph, according to the partition +*** map that is passed to the routine. +*** It returns: +*** - 0 : if the induced graph has been created. +*** - !0 : on error. ++*/ + +typedef struct _SCOTCHDgraphInducePartData_ { + const Gnum * orgpartloctax; /* In the public interface, parts are represented as Gnum's */ + Gnum indpartval; +} _SCOTCHDgraphInducePartData; + +static +Gnum +_SCOTCHdgraphInducePart2 ( +Dgraph * restrict const indgrafptr, +Dgraph * restrict const orggrafptr, +const void * restrict const orgdataptr, +Gnum * restrict const orgindxgsttax) +{ + Gnum orgvertlocnnd; + Gnum orgvertlocnum; + Gnum indvertlocnum; + Gnum indvertglbnum; + Gnum indedgelocmax; + + const Gnum * restrict const orgvertloctax = orggrafptr->vertloctax; + const Gnum * restrict const orgvendloctax = orggrafptr->vendloctax; + const Gnum * restrict const orgpartloctax = ((const _SCOTCHDgraphInducePartData * restrict const) orgdataptr)->orgpartloctax; + const Gnum indpartval = ((const _SCOTCHDgraphInducePartData * restrict const) orgdataptr)->indpartval; + Gnum * restrict const indvnumloctax = indgrafptr->vnumloctax; + + for (orgvertlocnum = indvertlocnum = orggrafptr->baseval, indvertglbnum = indgrafptr->procvrttab[indgrafptr->proclocnum], /* Fill index array while recomputing tighter upper bound on arcs */ + orgvertlocnnd = orggrafptr->vertlocnnd, indedgelocmax = 0; + orgvertlocnum < orgvertlocnnd; orgvertlocnum ++) { + if (orgpartloctax[orgvertlocnum] == indpartval) { + orgindxgsttax[orgvertlocnum] = indvertglbnum; /* Mark selected vertices */ + indvnumloctax[indvertlocnum] = orgvertlocnum; + indedgelocmax += orgvendloctax[orgvertlocnum] - orgvertloctax[orgvertlocnum]; + indvertlocnum ++, indvertglbnum ++; + } + else + orgindxgsttax[orgvertlocnum] = ~0; + } +#ifdef SCOTCH_DEBUG_DGRAPH2 + if ((indvertlocnum - orggrafptr->baseval) != indgrafptr->vertlocnbr) { + errorPrint ("dgraphInducePart2: inconsistent data"); + dgraphExit (indgrafptr); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + return (indedgelocmax); +} + +int +SCOTCH_dgraphInducePart ( +SCOTCH_Dgraph * const orggrafptr, /* Original graph */ +const SCOTCH_Num * const orgpartloctab, /* Partition array */ +const SCOTCH_Num indpartval, /* Part value of induced subgraph */ +const SCOTCH_Num indvertlocnbr, /* Number of local vertices in part */ +SCOTCH_Dgraph * const indgrafptr) /* Induced subgraph */ +{ + _SCOTCHDgraphInducePartData orgdatadat; + Gnum indvertloctmp; + int o; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + MPI_Comm_compare (((Dgraph * restrict const) orggrafptr)->proccomm, + ((Dgraph * restrict const) indgrafptr)->proccomm, &o); + if ((o != MPI_IDENT) && (o != MPI_CONGRUENT)) { + errorPrint ("SCOTCH_dgraphInducePart: communicators are not congruent"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + if (indvertlocnbr < 0) { /* If number of kept vertices is not known, compute it */ + Gnum orgvertlocnum; + Gnum orgvertlocnbr; + + for (orgvertlocnum = indvertloctmp = 0, orgvertlocnbr = ((Dgraph * restrict const) orggrafptr)->vertlocnbr; + orgvertlocnum < orgvertlocnbr; orgvertlocnum ++) { + if (orgpartloctab[orgvertlocnum] == indpartval) + indvertloctmp ++; + } + } + else + indvertloctmp = indvertlocnbr; + + orgdatadat.orgpartloctax = orgpartloctab - ((Dgraph *) orggrafptr)->baseval; + orgdatadat.indpartval = indpartval; + + o = dgraphInduce2 ((Dgraph *) orggrafptr, _SCOTCHdgraphInducePart2, &orgdatadat, indvertloctmp, NULL, (Dgraph *) indgrafptr); + ((Dgraph *) indgrafptr)->vnumloctax = NULL; /* Do not impact subsequent inductions */ + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_induce_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_induce_f.c new file mode 100644 index 00000000..4f332922 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_induce_f.c @@ -0,0 +1,80 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_induce_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 30 aug 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph handling */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHINDUCEPART, scotchfdgraphinducepart, ( \ +SCOTCH_Dgraph * const orggrafptr, \ +SCOTCH_Num * const orgpartloctab, \ +SCOTCH_Num * const indpartval, \ +SCOTCH_Num * const indvertlocnbr, \ +SCOTCH_Dgraph * const indgrafptr, \ +int * const revaptr), \ +(orggrafptr, orgpartloctab, indpartval, indvertlocnbr, indgrafptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphInducePart (orggrafptr, orgpartloctab, *indpartval, *indvertlocnbr, indgrafptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_io_load.c b/scotch_6.0.3/src/libscotch/library_dgraph_io_load.c new file mode 100644 index 00000000..b3c8aecd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_io_load.c @@ -0,0 +1,103 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_io_load.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted source graph loading routine of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 13 may 2007 **/ +/** to 13 may 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" +#include "ptscotch.h" + +/****************************************/ +/* */ +/* These routines are the C API for the */ +/* distributed graph handling routines. */ +/* */ +/****************************************/ + +/*+ This routine loads the given opaque graph +*** structure with the data of the given stream. +*** The base value allows the user to set the +*** graph base to 0 or 1, or to the base value +*** of the stream if the base value is equal +*** to -1. On input, vertex loads are discarded if +*** flagval is 1, edge loads are discarded if flagval +*** is 2, and both if flagval is set to 3. +*** It returns: +*** - 0 : if the loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphLoad ( +SCOTCH_Dgraph * const grafptr, +FILE * const stream, +const SCOTCH_Num baseval, +const SCOTCH_Num flagval) +{ + GraphFlag srcgrafflag; /* Graph flags */ + + if ((baseval < -1) || (baseval > 1)) { + errorPrint ("SCOTCH_dgraphLoad: invalid base parameter"); + return (1); + } + if ((flagval < 0) || (flagval > 3)) { + errorPrint ("SCOTCH_dgraphLoad: invalid flag parameter"); + return (1); + } + + srcgrafflag = (((flagval & 1) != 0) ? GRAPHIONOLOADVERT : 0) + + (((flagval & 2) != 0) ? GRAPHIONOLOADEDGE : 0); + + return (dgraphLoad ((Dgraph * const) grafptr, stream, (Gnum) baseval, srcgrafflag)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_io_load_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_io_load_f.c new file mode 100644 index 00000000..8a21446c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_io_load_f.c @@ -0,0 +1,113 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_io_load_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 13 may 2007 **/ +/** to 13 may 2007 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph handling routines. */ +/* */ +/**************************************/ + +/* When an input stream is built from the given +** file handle, it is set as unbuffered, so as to +** allow for multiple stream reads from the same +** file handle. If it were buffered, too many +** input characters would be read on the first +** block read. +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHLOAD, scotchfdgraphload, ( \ +SCOTCH_Dgraph * const grafptr, \ +int * const fileptr, \ +const SCOTCH_Num * const baseptr, \ +const SCOTCH_Num * const flagptr, \ +int * const revaptr), \ +(grafptr, fileptr, baseptr, flagptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if (*fileptr == -1) /* If process does not want to open a stream */ + stream = NULL; + else { + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFDGRAPHLOAD: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFDGRAPHLOAD: cannot open input stream"); + close (filenum); + *revaptr = 1; + return; + } + setbuf (stream, NULL); /* Do not buffer on input */ + } + + errorPrint ("SCOTCHFDGRAPHLOAD: not implemented"); + o = SCOTCH_dgraphLoad (grafptr, stream, *baseptr, *flagptr); + + if (stream != NULL) /* If process has an open stream */ + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_io_save.c b/scotch_6.0.3/src/libscotch/library_dgraph_io_save.c new file mode 100644 index 00000000..6e507dfb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_io_save.c @@ -0,0 +1,82 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_io_save.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted source graph saving routine of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 may 2007 **/ +/** to 16 may 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" +#include "ptscotch.h" + +/****************************************/ +/* */ +/* These routines are the C API for the */ +/* distributed graph handling routines. */ +/* */ +/****************************************/ + +/*+ This routine saves the contents of the given +*** opaque distributed graph structure to the +*** given streams. +*** It returns: +*** - 0 : if the saving succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphSave ( +SCOTCH_Dgraph * const grafptr, +FILE * const stream) +{ + return (dgraphSave ((Dgraph * const) grafptr, stream)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_io_save_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_io_save_f.c new file mode 100644 index 00000000..cc642499 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_io_save_f.c @@ -0,0 +1,101 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_io_save_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 may 2007 **/ +/** to 16 may 2007 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHSAVE, scotchfdgraphsave, ( \ +SCOTCH_Dgraph * const grafptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFDGRAPHSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFDGRAPHSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_dgraphSave (grafptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_map.c b/scotch_6.0.3/src/libscotch/library_dgraph_map.c new file mode 100644 index 00000000..4a6de033 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_map.c @@ -0,0 +1,422 @@ +/* Copyright 2008-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_map.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted graph mapping routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 12 jun 2008 **/ +/** to 31 aug 2011 **/ +/** # Version 6.0 : from : 14 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "dgraph.h" +#include "arch.h" +#include "dmapping.h" +#include "kdgraph.h" +#include "kdgraph_map_st.h" +#include "library_dmapping.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the parallel mapping routines. */ +/* */ +/************************************/ + +/*+ This routine initializes an API opaque +*** mapping with respect to the given source +*** graph and the locations of output parameters. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphMapInit ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ +SCOTCH_Dmapping * const mappptr, /*+ Mapping structure to initialize +*/ +const SCOTCH_Arch * const archptr, /*+ Target architecture used to map +*/ +SCOTCH_Num * const termloctab) /*+ Mapping array +*/ +{ + LibDmapping * restrict srcmappptr; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Dmapping) < sizeof (LibDmapping)) { + errorPrint ("SCOTCH_dgraphMapInit: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + srcmappptr = (LibDmapping *) mappptr; + srcmappptr->termloctab = ((termloctab == NULL) || ((void *) termloctab == (void *) grafptr)) ? NULL : termloctab; + return (dmapInit (&srcmappptr->m, (Arch *) archptr)); +} + +/*+ This routine frees an API mapping. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_dgraphMapExit ( +const SCOTCH_Dgraph * const grafptr, +SCOTCH_Dmapping * const mappptr) +{ + dmapExit (&((LibDmapping *) mappptr)->m); +} + +/*+ This routine saves the contents of +*** the given mapping to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphMapSave ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Dmapping * const mappptr, /*+ Mapping to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (dmapSave (&((LibDmapping *) mappptr)->m, (Dgraph *) grafptr, stream)); +} + +/*+ This routine computes a mapping +*** of the API mapping structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphMapCompute ( +SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ +SCOTCH_Dmapping * const mappptr, /*+ Mapping to compute +*/ +SCOTCH_Strat * const stratptr) /*+ Mapping strategy +*/ +{ + Kdgraph mapgrafdat; /* Effective mapping graph */ + Kdmapping mapmappdat; /* Initial mapping domain */ + const Strat * mapstratptr; /* Pointer to mapping strategy */ + LibDmapping * restrict srcmappptr; + Dgraph * srcgrafptr; + int o; + + srcgrafptr = (Dgraph *) grafptr; + srcmappptr = (LibDmapping *) mappptr; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphCheck (srcgrafptr) != 0) { + errorPrint ("SCOTCH_dgraphMapCompute: invalid input graph"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (*((Strat **) stratptr) == NULL) { /* Set default mapping strategy if necessary */ + ArchDom archdomnorg; + + archDomFrst (&srcmappptr->m.archdat, &archdomnorg); + if (archVar (&srcmappptr->m.archdat)) + SCOTCH_stratDgraphClusterBuild (stratptr, 0, srcgrafptr->procglbnbr, 1, 1.0, 0.05); + else + SCOTCH_stratDgraphMapBuild (stratptr, 0, srcgrafptr->procglbnbr, archDomSize (&srcmappptr->m.archdat, &archdomnorg), 0.05); + } + mapstratptr = *((Strat **) stratptr); + if (mapstratptr->tabl != &kdgraphmapststratab) { + errorPrint ("SCOTCH_dgraphMapCompute: not a parallel graph mapping strategy"); + return (1); + } + + intRandInit (); /* Check that random number generator is initialized */ + + if (kdgraphInit (&mapgrafdat, srcgrafptr, &srcmappptr->m) != 0) + return (1); + mapmappdat.mappptr = &srcmappptr->m; + + if (((o = kdgraphMapSt (&mapgrafdat, &mapmappdat, mapstratptr)) == 0) && /* Perform mapping */ + (srcmappptr->termloctab != NULL)) + o = dmapTerm (&srcmappptr->m, &mapgrafdat.s, srcmappptr->termloctab); /* Use "&mapgrafdat.s" to take advantage of ghost arrays */ + kdgraphExit (&mapgrafdat); + + return (o); +} + +/*+ This routine computes a mapping of the +*** given graph structure onto the given +*** target architecture with respect to the +*** given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphMap ( +SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Arch * const archptr, /*+ Target architecture +*/ +SCOTCH_Strat * const stratptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const termloctab) /*+ Mapping array +*/ +{ + SCOTCH_Dmapping mappdat; + int o; + + SCOTCH_dgraphMapInit (grafptr, &mappdat, archptr, termloctab); + o = SCOTCH_dgraphMapCompute (grafptr, &mappdat, stratptr); + SCOTCH_dgraphMapExit (grafptr, &mappdat); + + return (o); +} + +/*+ This routine computes a partition of +*** the given graph structure with respect +*** to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphPart ( +SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Num partnbr, /*+ Number of parts +*/ +SCOTCH_Strat * const stratptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const termloctab) /*+ Mapping array +*/ +{ + SCOTCH_Arch archdat; + int o; + + SCOTCH_archInit (&archdat); + SCOTCH_archCmplt (&archdat, partnbr); + o = SCOTCH_dgraphMap (grafptr, &archdat, stratptr, termloctab); + SCOTCH_archExit (&archdat); + + return (o); +} + +/*+ This routine parses the given +*** mapping strategy. +*** It returns: +*** - 0 : if string successfully scanned. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratDgraphMap ( +SCOTCH_Strat * const stratptr, +const char * const string) +{ + if (*((Strat **) stratptr) != NULL) + stratExit (*((Strat **) stratptr)); + + if ((*((Strat **) stratptr) = stratInit (&kdgraphmapststratab, string)) == NULL) { + errorPrint ("SCOTCH_stratDgraphMap: error in parallel mapping strategy"); + return (1); + } + + return (0); +} + +/*+ This routine provides predefined +*** mapping strategies. +*** It returns: +*** - 0 : if string successfully initialized. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratDgraphMapBuild ( +SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ +const SCOTCH_Num flagval, /*+ Desired characteristics +*/ +const SCOTCH_Num procnbr, /*+ Number of processes for running +*/ +const SCOTCH_Num partnbr, /*+ Number of expected parts +*/ +const double kbalval) /*+ Desired imbalance ratio +*/ +{ + char bufftab[8192]; /* Should be enough */ + char bbaltab[32]; + char kbaltab[32]; + char verttab[32]; + Gnum vertnbr; + char * difpptr; + char * difsptr; + char * exapptr; + char * exasptr; + char * muceptr; + + sprintf (kbaltab, "%lf", kbalval); + sprintf (bbaltab, "%lf", kbalval); + + vertnbr = MAX (2000 * procnbr, 10000); + vertnbr = MIN (vertnbr, 100000); + sprintf (verttab, GNUMSTRING, vertnbr); + + strcpy (bufftab, "r{bal=,sep=m{vert=,asc=b{bnd=,org=},low=q{strat=(m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})},seq=q{strat=(m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})}},seq=r{bal=,poli=S,sep=(m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})}}"); + stringSubst (bufftab, "", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" + : "m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}}|"); + + if ((flagval & SCOTCH_STRATSCALABILITY) != 0) + muceptr = "/(edge<10000000)?q{strat=f};"; /* Multi-centralization */ + else + muceptr = "q{strat=f}"; + + if ((flagval & SCOTCH_STRATBALANCE) != 0) { + exapptr = "x{bal=0}"; + exasptr = "f{bal=0}"; + } + else { + exapptr = "x{bal=}"; /* Parallel exactifier */ + exasptr = ""; + } + + if ((flagval & SCOTCH_STRATSAFETY) != 0) { + difpptr = ""; + difsptr = ""; + } + else { + difpptr = "(d{pass=40}|)"; + difsptr = "(d{pass=40}|)"; + } + + stringSubst (bufftab, "", muceptr); + stringSubst (bufftab, "", exapptr); + stringSubst (bufftab, "", exasptr); + stringSubst (bufftab, "", difpptr); + stringSubst (bufftab, "", difsptr); + stringSubst (bufftab, "", bbaltab); + stringSubst (bufftab, "", kbaltab); + stringSubst (bufftab, "", verttab); + + if (SCOTCH_stratDgraphMap (stratptr, bufftab) != 0) { + errorPrint ("SCOTCH_stratDgraphMapBuild: error in parallel mapping strategy"); + return (1); + } + + return (0); +} + +/*+ This routine provides predefined +*** clustering strategies. +*** It returns: +*** - 0 : if string successfully initialized. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratDgraphClusterBuild ( +SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ +const SCOTCH_Num flagval, /*+ Desired characteristics +*/ +const SCOTCH_Num procnbr, /*+ Number of processes for running +*/ +const SCOTCH_Num pwgtval, /*+ Threshold part load +*/ +const double densval, /*+ Threshold density value +*/ +const double bbalval) /*+ Maximum imbalance ratio +*/ +{ + char bufftab[8192]; /* Should be enough */ + char bbaltab[32]; + char denstab[32]; + char pwgttab[32]; + char verttab[32]; + Gnum vertnbr; + char * difpptr; + char * difsptr; + char * exapptr; + char * exasptr; + char * muceptr; + + sprintf (bbaltab, "%lf", bbalval); + sprintf (denstab, "%lf", densval); + sprintf (pwgttab, GNUMSTRING, pwgtval); + + vertnbr = MAX (2000 * procnbr, 10000); + vertnbr = MIN (vertnbr, 100000); + sprintf (verttab, GNUMSTRING, vertnbr); + + strcpy (bufftab, "r{sep=/((load>)&!(edge>vert**(vert-1)))?m{vert=,asc=b{bnd=,org=},low=q{strat=(m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})},seq=q{strat=/((load>)&!(edge>vert**(vert-1)))?(m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}});}};,seq=r{sep=/((load>)&!(edge>vert**(vert-1)))?(m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}});}}"); + stringSubst (bufftab, "", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" + : "m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}}|"); + + if ((flagval & SCOTCH_STRATSCALABILITY) != 0) + muceptr = "/(edge<10000000)?q{strat=f};"; /* Multi-centralization */ + else + muceptr = "q{strat=f}"; + + if ((flagval & SCOTCH_STRATBALANCE) != 0) { + exapptr = "x{bal=0}"; + exasptr = "f{bal=0}"; + } + else { + exapptr = "x{bal=}"; /* Parallel exactifier */ + exasptr = ""; + } + + if ((flagval & SCOTCH_STRATSAFETY) != 0) { + difpptr = ""; + difsptr = ""; + } + else { + difpptr = "(d{pass=40}|)"; + difsptr = "(d{pass=40}|)"; + } + + stringSubst (bufftab, "", muceptr); + stringSubst (bufftab, "", exapptr); + stringSubst (bufftab, "", exasptr); + stringSubst (bufftab, "", difpptr); + stringSubst (bufftab, "", difsptr); + stringSubst (bufftab, "", bbaltab); + stringSubst (bufftab, "", denstab); + stringSubst (bufftab, "", pwgttab); + stringSubst (bufftab, "", verttab); + + if (SCOTCH_stratDgraphMap (stratptr, bufftab) != 0) { + errorPrint ("SCOTCH_stratDgraphClusterBuild: error in parallel mapping strategy"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_map_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_map_f.c new file mode 100644 index 00000000..cc979de9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_map_f.c @@ -0,0 +1,237 @@ +/* Copyright 2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_map_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** parallel mapping routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 28 jun 2008 **/ +/** to 31 aug 2011 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the parallel mapping routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHMAPINIT, scotchfdgraphmapinit, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Dmapping * const mapptr, \ +const SCOTCH_Arch * const archptr, \ +SCOTCH_Num * const termloctab, \ +int * const revaptr), \ +(grafptr, mapptr, archptr, termloctab, revaptr)) +{ + *revaptr = SCOTCH_dgraphMapInit (grafptr, mapptr, archptr, termloctab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHMAPEXIT, scotchfdgraphmapexit, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Dmapping * const mapptr), \ +(grafptr, mapptr)) +{ + SCOTCH_dgraphMapExit (grafptr, mapptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHMAPSAVE, scotchfdgraphmapsave, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Dmapping * const mapptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, mapptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFDGRAPHMAPSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFDGRAPHMAPSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_dgraphMapSave (grafptr, mapptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHMAPCOMPUTE, scotchfdgraphmapcompute, ( \ +SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Dmapping * const mapptr, \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(grafptr, mapptr, stratptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphMapCompute (grafptr, mapptr, stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHMAP, scotchfdgraphmap, ( \ +SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Arch * const archptr, \ +SCOTCH_Strat * const stratptr, \ +SCOTCH_Num * const termloctab, \ +int * const revaptr), \ +(grafptr, archptr, stratptr, termloctab, revaptr)) +{ + *revaptr = SCOTCH_dgraphMap (grafptr, archptr, stratptr, termloctab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHPART, scotchfdgraphpart, ( \ +SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Num * const partptr, \ +SCOTCH_Strat * const stratptr, \ +SCOTCH_Num * const termloctab, \ +int * const revaptr), \ +(grafptr, partptr, stratptr, termloctab, revaptr)) +{ + *revaptr = SCOTCH_dgraphPart (grafptr, *partptr, stratptr, termloctab); +} + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFSTRATDGRAPHMAP, scotchfstratdgraphmap, ( \ +SCOTCH_Strat * const stratptr, \ +const char * const string, \ +int * const revaptr, \ +const int strnbr), \ +(stratptr, string, revaptr, strnbr)) +{ + char * restrict strtab; /* Pointer to null-terminated string */ + + if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ + errorPrint ("SCOTCHFSTRATDGRAPHMAP: out of memory (1)"); + *revaptr = 1; + } + memCpy (strtab, string, strnbr); /* Copy string contents */ + strtab[strnbr] = '\0'; /* Terminate string */ + + *revaptr = SCOTCH_stratDgraphMap (stratptr, strtab); /* Call original routine */ + + memFree (strtab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATDGRAPHMAPBUILD, scotchfstratdgraphmapbuild, ( \ +SCOTCH_Strat * const stratptr, \ +const SCOTCH_Num * const flagval, \ +const SCOTCH_Num * const procnbr, \ +const SCOTCH_Num * const partnbr, \ +const double * const kbalval, \ +int * const revaptr), \ +(stratptr, flagval, procnbr, partnbr, kbalval, revaptr)) +{ + *revaptr = SCOTCH_stratDgraphMapBuild (stratptr, *flagval, *procnbr, *partnbr, *kbalval); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATDGRAPHCLUSTERBUILD, scotchfstratdgraphclusterbuild, ( \ +SCOTCH_Strat * const stratptr, \ +const SCOTCH_Num * const flagval, \ +const SCOTCH_Num * const procnbr, \ +const SCOTCH_Num * const pwgtval, \ +const double * const densval, \ +const double * const bbalval, \ +int * const revaptr), \ +(stratptr, flagval, procnbr, pwgtval, densval, bbalval, revaptr)) +{ + *revaptr = SCOTCH_stratDgraphClusterBuild (stratptr, *flagval, *procnbr, *pwgtval, *densval, *bbalval); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_map_view.c b/scotch_6.0.3/src/libscotch/library_dgraph_map_view.c new file mode 100644 index 00000000..fdc44131 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_map_view.c @@ -0,0 +1,385 @@ +/* Copyright 2008-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_map_view.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted mapping routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 26 jul 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY +#define LIBRARY_DGRAPH_MAP_VIEW + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "dgraph.h" +#include "dgraph_halo.h" +#include "arch.h" +#include "dmapping.h" +#include "kdgraph.h" +#include "library_dmapping.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the mapping routines. */ +/* */ +/************************************/ + +/*+ This routine writes distributed mapping +*** statistics to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphMapView ( +SCOTCH_Dgraph * const libgrafptr, +const SCOTCH_Dmapping * const libmappptr, +FILE * const stream) +{ + Dgraph * restrict grafptr; + const LibDmapping * restrict mappptr; + ArchDom domnfrst; /* Largest domain in architecture */ + unsigned int * restrict nmskloctab; /* Local neighbor bitfield */ + unsigned int * restrict nmskglbtab; /* Local neighbor bitfield */ + int nmskidxnbr; /* Size of bitfield; int since sent by MPI */ + Gnum * restrict tgloloctab; /* Local array of terminal domain loads */ + Gnum * restrict tgloglbtab; /* Global array of terminal domain loads */ + Gnum * restrict termgsttax; /* Terminal domain ghost mapping array */ + Anum tgtnbr; /* Number of processors in target topology */ + Anum tgtnum; + Anum mapnbr; /* Number of processors effectively used */ + double mapavg; /* Average mapping weight */ + Gnum mapmin; + Gnum mapmax; + Gnum mapsum; /* (Partial) sum of vertex loads */ + double mapdlt; + double mapmmy; /* Maximum / average ratio */ + Anum ngbsum; + Anum ngbmin; + Anum ngbmax; + Gnum vertlocnum; + Gnum veloval; + Gnum edloval; + Gnum commlocdist[256 + 3]; /* Array of local load distribution */ + Gnum commglbdist[256 + 3]; + Gnum commlocload; /* Total local edge load (edge sum) */ + Gnum commlocdilat; /* Total edge dilation */ + Gnum commlocexpan; /* Total edge expansion */ + Anum distmax; + Anum distval; + int cheklocval; + int chekglbval; + DgraphHaloRequest requdat; + + grafptr = (Dgraph *) libgrafptr; + mappptr = (LibDmapping *) libmappptr; + + if ((grafptr->vertglbnbr == 0) || /* Return if nothing to do */ + (grafptr->edgeglbnbr == 0)) + return (0); + + archDomFrst (&mappptr->m.archdat, &domnfrst); /* Get architecture domain */ + tgtnbr = archDomSize (&mappptr->m.archdat, &domnfrst); /* Get architecture size */ + + if (archVar (&mappptr->m.archdat)) { + errorPrint ("SCOTCH_dgraphMapView: not implemented"); + return (1); + } + + if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("SCOTCH_dgraphMapView: cannot compute ghost edge array"); + return (1); + } + + nmskidxnbr = (tgtnbr + 1 + ((sizeof (int) << 3) - 1)) / (sizeof (int) << 3); /* Size of neighbor subdomain bitfield; TRICK: "+1" to have a "-1" cell for unmapped vertices */ + + cheklocval = 0; + if (memAllocGroup ((void **) (void *) + &nmskloctab, (size_t) (nmskidxnbr * sizeof (unsigned int)), + &nmskglbtab, (size_t) (nmskidxnbr * sizeof (unsigned int)), + &tgloloctab, (size_t) ((tgtnbr + 1) * sizeof (Gnum)), /* TRICK: "+1" to have a "-1" cell for unmapped vertices */ + &tgloglbtab, (size_t) (tgtnbr * sizeof (Gnum)), + &termgsttax, (size_t) (grafptr->vertgstnbr * sizeof (Gnum)), NULL) == NULL) { + cheklocval = 1; + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphMapView: communication error (1)"); + return (1); + } + if (chekglbval != 0) { + if (nmskloctab != NULL) + memFree (nmskloctab); + errorPrint ("SCOTCH_dgraphMapView: out of memory"); + return (1); + } + + if (dmapTerm (&mappptr->m, grafptr, termgsttax) != 0) { + errorPrint ("SCOTCH_dgraphMapView: cannot build local terminal array"); + memFree (nmskloctab); + return (1); + } + dgraphHaloAsync (grafptr, termgsttax, GNUM_MPI, &requdat); + termgsttax -= grafptr->baseval; + + memSet (tgloloctab, 0, (tgtnbr + 1) * sizeof (Gnum)); + tgloloctab ++; /* TRICK: trim array for "-1" cell */ + + veloval = 1; + for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { +#ifdef SCOTCH_DEBUG_DMAP2 + if ((termgsttax[vertlocnum] < -1) || (termgsttax[vertlocnum] >= tgtnbr)) { + errorPrint ("SCOTCH_dgraphMapView: invalid local terminal array"); + memFree (nmskloctab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_DMAP2 */ + if (grafptr->veloloctax != NULL) + veloval = grafptr->veloloctax[vertlocnum]; + tgloloctab[termgsttax[vertlocnum]] += veloval; /* One more vertex of given weight assigned to this target */ + } + + if (MPI_Allreduce (tgloloctab, tgloglbtab, tgtnbr, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphMapView: communication error (2)"); + memFree (nmskloctab); /* Free group leader */ + return (1); + } + + mapmin = GNUMMAX; + mapmax = 0; + mapsum = 0; + mapnbr = 0; + for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) { + Gnum tgtsum; + + tgtsum = tgloglbtab[tgtnum]; + if (tgtsum != 0) { + mapnbr ++; + mapsum += tgtsum; + if (tgtsum < mapmin) + mapmin = tgtsum; + if (tgtsum > mapmax) + mapmax = tgtsum; + } + } + mapavg = (mapnbr == 0) ? 0.0L : ((double) mapsum / (double) mapnbr); + + mapdlt = 0.0L; + for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) + mapdlt += fabs ((double) tgloglbtab[tgtnum] - mapavg); + mapdlt = (mapnbr != 0) ? mapdlt / ((double) mapnbr * mapavg) : 0.0L; + mapmmy = (mapnbr != 0) ? (double) mapmax / (double) mapavg : 0.0L; + + if (stream != NULL) { + fprintf (stream, "M\tProcessors " GNUMSTRING "/" GNUMSTRING "(%g)\n", + (Gnum) mapnbr, + (Gnum) tgtnbr, + (double) mapnbr / (double) tgtnbr); + fprintf (stream, "M\tTarget min=" GNUMSTRING "\tmax=" GNUMSTRING "\tavg=%g\tdlt=%g\tmaxavg=%g\n", + (Gnum) mapmin, + (Gnum) mapmax, + mapavg, + mapdlt, + mapmmy); + } + + if (dgraphHaloWait (&requdat) != 0) { /* Wait for ghost terminal data to be exchanged */ + errorPrint ("SCOTCH_dgraphMapView: cannot complete asynchronous halo exchange"); + memFree (nmskloctab); /* Free group leader */ + return (1); + } + + ngbmin = ANUMMAX; + ngbmax = 0; + ngbsum = 0; + for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) { /* For all subdomain indices */ + int nmskidxnum; + Gnum vertlocnum; + Anum ngbnbr; + + if (tgloglbtab[tgtnum] <= 0) /* If empty subdomain, skip it */ + continue; + + memSet (nmskloctab, 0, nmskidxnbr * sizeof (int)); /* Reset neighbor bit mask */ + + for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { /* For all local vertices */ + Gnum termnum; + Gnum edgelocnum; + Gnum edgelocnnd; + + termnum = termgsttax[vertlocnum]; + if (termnum != tgtnum) /* If vertex does not belong to current part or is not mapped, skip it */ + continue; + + for (edgelocnum = grafptr->vertloctax[vertlocnum], edgelocnnd = grafptr->vendloctax[vertlocnum]; + edgelocnum < edgelocnnd; edgelocnum ++) { + Gnum termend; + + termend = termgsttax[grafptr->edgegsttax[edgelocnum]]; + if (termend != tgtnum) { /* If edge is not internal */ + termend ++; /* TRICK: turn unmapped to 0 and so on */ + nmskloctab[termend / (sizeof (int) << 3)] |= 1 << (termend & ((sizeof (int) << 3) - 1)); /* Flag neighbor in bit array */ + } + } + } + nmskloctab[0] &= ~1; /* Do not account for unmapped vertices (terminal domain 0 because of "+1") */ + + if (MPI_Allreduce (nmskloctab, nmskglbtab, nmskidxnbr, MPI_INT, MPI_BOR, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphMapView: communication error (3)"); + memFree (nmskloctab); /* Free group leader */ + return (1); + } + + for (nmskidxnum = 0, ngbnbr = 0; nmskidxnum < nmskidxnbr; nmskidxnum ++) { + unsigned int nmskbitval; + + for (nmskbitval = nmskglbtab[nmskidxnum]; nmskbitval != 0; nmskbitval >>= 1) + ngbnbr += nmskbitval & 1; + } + + ngbsum += ngbnbr; + if (ngbnbr < ngbmin) + ngbmin = ngbnbr; + if (ngbnbr > ngbmax) + ngbmax = ngbnbr; + } + + if (stream != NULL) { + fprintf (stream, "M\tNeighbors min=" GNUMSTRING "\tmax=" GNUMSTRING "\tsum=" GNUMSTRING "\n", + (Gnum) ngbmin, + (Gnum) ngbmax, + (Gnum) ngbsum); + } + + memSet (commlocdist, 0, 256 * sizeof (Gnum)); /* Initialize the data */ + commlocload = + commlocdilat = + commlocexpan = 0; + + edloval = 1; + for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { /* For all local vertices */ + Gnum termlocnum; + ArchDom termdomdat; + Gnum edgelocnum; + Gnum edgelocnnd; + + termlocnum = termgsttax[vertlocnum]; + if (termlocnum == ~0) /* Skip unmapped vertices */ + continue; + + archDomTerm (&mappptr->m.archdat, &termdomdat, termlocnum); + + for (edgelocnum = grafptr->vertloctax[vertlocnum], edgelocnnd = grafptr->vendloctax[vertlocnum]; + edgelocnum < edgelocnnd; edgelocnum ++) { + ArchDom termdomend; + Gnum termgstend; + Anum distval; + + termgstend = termgsttax[grafptr->edgegsttax[edgelocnum]]; + if (termgstend == ~0) /* Skip unmapped end vertices */ + continue; + + distval = 0; + if (grafptr->edloloctax != NULL) /* Get edge weight if any */ + edloval = grafptr->edloloctax[edgelocnum]; + if (termgstend != termlocnum) { /* If not same domain, compute distance */ + archDomTerm (&mappptr->m.archdat, &termdomend, termgstend); + distval = archDomDist (&mappptr->m.archdat, &termdomdat, &termdomend); + } + commlocdist[(distval > 255) ? 255 : distval] += edloval; + commlocload += edloval; + commlocdilat += distval; + commlocexpan += distval * edloval; + } + } + commlocdist[256] = commlocload; + commlocdist[256 + 1] = commlocdilat; + commlocdist[256 + 2] = commlocexpan; + + if (MPI_Allreduce (commlocdist, commglbdist, 256 + 3, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphMapView: communication error (4)"); + memFree (nmskloctab); /* Free group leader */ + return (1); + } + + if (stream != NULL) { + Gnum commglbload; + + commglbload = commglbdist[256]; + fprintf (stream, "M\tCommDilat=%f\t(" GNUMSTRING ")\n", /* Print expansion parameters */ + (double) commglbdist[256 + 1] / grafptr->edgeglbnbr, + (Gnum) (commglbdist[256 + 1] / 2)); + fprintf (stream, "M\tCommExpan=%f\t(" GNUMSTRING ")\n", + ((commglbload == 0) ? (double) 0.0L + : (double) commglbdist[256 + 2] / (double) commglbload), + (Gnum) (commglbdist[256 + 2] / 2)); + fprintf (stream, "M\tCommCutSz=%f\t(" GNUMSTRING ")\n", + ((commglbload == 0) ? (double) 0.0L + : (double) (commglbload - commglbdist[0]) / (double) commglbload), + (Gnum) ((commglbload - commglbdist[0]) / 2)); + fprintf (stream, "M\tCommDelta=%f\n", + (((double) commglbload * (double) commglbdist[256 + 1]) == 0.0L) + ? (double) 0.0L + : ((double) commglbdist[256 + 2] * (double) grafptr->edgeglbnbr) / + ((double) commglbload * (double) commglbdist[256 + 2])); + + for (distmax = 255; distmax != -1; distmax --) /* Find longest distance */ + if (commglbdist[distmax] != 0) + break; + for (distval = 0; distval <= distmax; distval ++) /* Print distance histogram */ + fprintf (stream, "M\tCommLoad[" ANUMSTRING "]=%f\n", + (Anum) distval, + (double) commglbdist[distval] / (double) commglbload); + } + + memFree (nmskloctab); /* Free group leader */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_map_view_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_map_view_f.c new file mode 100644 index 00000000..d8fd6053 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_map_view_f.c @@ -0,0 +1,104 @@ +/* Copyright 2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_map_view_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed mapping handling routines **/ +/** of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 27 jul 2008 **/ +/** to 27 mar 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHMAPVIEW, scotchfdgraphmapview, ( \ +SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dmapping * const mapptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, mapptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if (*fileptr == -1) /* If process does not want to open a stream */ + stream = NULL; + else { + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFDGRAPHMAPVIEW: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFDGRAPHMAPVIEW: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + } + + o = SCOTCH_dgraphMapView (grafptr, mapptr, stream); + + if (stream != NULL) /* If process has an open stream */ + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order.c b/scotch_6.0.3/src/libscotch/library_dgraph_order.c new file mode 100644 index 00000000..74c89b1d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order.c @@ -0,0 +1,322 @@ +/* Copyright 2007-2010,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted graph ordering routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 25 apr 2006 **/ +/** to 11 nov 2008 **/ +/** # Version 5.1 : from : 29 mar 2010 **/ +/** to 14 aug 2010 **/ +/** # Version 6.0 : from : 08 jan 2012 **/ +/** to 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "dgraph.h" +#include "dorder.h" +#include "hdgraph.h" +#include "hdgraph_order_st.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the distributed graph ordering */ +/* routines. */ +/* */ +/************************************/ + +/*+ This routine initializes an API ordering +*** with respect to the given source graph +*** and the locations of output parameters. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderInit ( +const SCOTCH_Dgraph * const grafptr, /*+ Distributed graph to order +*/ +SCOTCH_Dordering * const ordeptr) /*+ Ordering structure to initialize +*/ +{ + Dgraph * srcgrafptr; + Dorder * srcordeptr; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Dordering) < sizeof (Dorder)) { + errorPrint ("SCOTCH_graphDorderInit: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + srcgrafptr = (Dgraph *) grafptr; /* Use structure as source graph */ + srcordeptr = (Dorder *) ordeptr; + return (dorderInit (srcordeptr, srcgrafptr->baseval, srcgrafptr->vertglbnbr, srcgrafptr->proccomm)); +} + +/*+ This routine frees an API ordering. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_dgraphOrderExit ( +const SCOTCH_Dgraph * const grafptr, +SCOTCH_Dordering * const ordeptr) +{ + dorderExit ((Dorder *) ordeptr); +} + +/*+ This routine saves the contents of +*** the given ordering to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderSave ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Dordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (dorderSave ((Dorder *) ordeptr, (Dgraph *) grafptr, stream)); +} + +/*+ This routine computes an ordering +*** of the API ordering structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderCompute ( +SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Dordering * const ordeptr, /*+ Ordering to compute +*/ +SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ +{ + return (SCOTCH_dgraphOrderComputeList (grafptr, ordeptr, 0, NULL, stratptr)); +} + +/*+ This routine computes a partial ordering +*** of the listed vertices of the API ordering +*** structure graph with respect to the given +*** strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderComputeList ( +SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Dordering * const ordeptr, /*+ Ordering to compute +*/ +const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ +const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ +SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ +{ + Dorder * srcordeptr; /* Pointer to ordering */ + DorderCblk * srccblkptr; /* Initial column block */ + Dgraph * restrict srcgrafptr; /* Pointer to scotch graph */ + Hdgraph srcgrafdat; /* Halo source graph structure */ + Gnum srclistnbr; /* Number of items in list */ + Gnum * restrict srclisttab; /* Subgraph vertex list */ + const Strat * ordstratptr; /* Pointer to ordering strategy */ + + srcgrafptr = (Dgraph *) grafptr; + +#ifdef SCOTCH_DEBUG_DGRAPH2 + if (dgraphCheck (srcgrafptr) != 0) { + errorPrint ("SCOTCH_dgraphOrderComputeList: invalid input graph"); + return (1); + } +#endif /* SCOTCH_DEBUG_DGRAPH2 */ + + if (*((Strat **) stratptr) == NULL) /* Set default ordering strategy if necessary */ + SCOTCH_stratDgraphOrderBuild (stratptr, SCOTCH_STRATQUALITY, srcgrafptr->procglbnbr, 0, 0.2); + + ordstratptr = *((Strat **) stratptr); + if (ordstratptr->tabl != &hdgraphorderststratab) { + errorPrint ("SCOTCH_dgraphOrderComputeList: not a distributed ordering strategy"); + return (1); + } + + srcgrafdat.s = *srcgrafptr; /* Copy non-halo graph data */ + srcgrafdat.s.edloloctax = NULL; /* Never mind about edge loads */ + srcgrafdat.s.vlblloctax = NULL; /* Do not propagate vertex labels */ + srcgrafdat.vhallocnbr = 0; /* No halo on graph */ + srcgrafdat.vhndloctax = srcgrafdat.s.vendloctax; + srcgrafdat.ehallocnbr = 0; + srcgrafdat.levlnum = 0; + + srcordeptr = (Dorder *) ordeptr; /* Get ordering */ + + srclistnbr = (Gnum) listnbr; /* Build vertex list */ + srclisttab = (Gnum *) listtab; + + intRandInit (); /* Check that random number generator is initialized */ + +/* TODO: Take list into account */ + dorderFree (srcordeptr); /* Clean all existing ordering data */ + if ((srccblkptr = dorderFrst (srcordeptr)) == NULL) { + errorPrint ("SCOTCH_dgraphOrderComputeList: cannot create root column block"); + return (1); + } + hdgraphOrderSt (&srcgrafdat, srccblkptr, ordstratptr); + dorderDispose (srccblkptr); + + srcgrafptr->flagval |= srcgrafdat.s.flagval & (DGRAPHFREEEDGEGST | DGRAPHHASEDGEGST); + srcgrafptr->edgegsttax = srcgrafdat.s.edgegsttax; /* Get edge ghost array from working graph if it gained one */ + + *srcgrafptr = srcgrafdat.s; /* Get back Dgraph structure, possibly updated (additional ghost data arrays) */ + + return (0); +} + +/*+ This routine parses the given +*** distributed graph ordering strategy. +*** It returns: +*** - 0 : if string successfully scanned. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratDgraphOrder ( +SCOTCH_Strat * const stratptr, +const char * const string) +{ + if (*((Strat **) stratptr) != NULL) + stratExit (*((Strat **) stratptr)); + + if ((*((Strat **) stratptr) = stratInit (&hdgraphorderststratab, string)) == NULL) { + errorPrint ("SCOTCH_stratDgraphOrder: error in ordering strategy"); + return (1); + } + + return (0); +} + +/*+ This routine provides predefined +*** ordering strategies. +*** It returns: +*** - 0 : if string successfully initialized. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratDgraphOrderBuild ( +SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ +const SCOTCH_Num flagval, /*+ Desired characteristics +*/ +const SCOTCH_Num procnbr, /*+ Number of processes for running +*/ +const SCOTCH_Num levlnbr, /*+ Number of nested dissection levels +*/ +const double balrat) /*+ Desired imbalance ratio +*/ +{ + char bufftab[8192]; /* Should be enough */ + char bbaltab[32]; + char levltab[32]; + char verttab[32]; + Gnum vertnbr; + char * tstpptr; + char * tstsptr; + char * oleaptr; + char * osepptr; + + vertnbr = MAX (2000 * procnbr, 10000); + vertnbr = MIN (vertnbr, 1000000); + + sprintf (bbaltab, "%lf", balrat); + sprintf (levltab, GNUMSTRING, levlnbr); + sprintf (verttab, GNUMSTRING, vertnbr); + + strcpy (bufftab, "n{sep=/()?m{vert=,asc=b{width=3,strat=q{strat=f}},low=q{strat=h},seq=q{strat=m{vert=120,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=h{pass=10}f{bal=}}}}};,ole=q{strat=n{sep=/()?m{vert=120,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=h{pass=10}f{bal=}}};,ole=,ose=}},ose=s,osq=n{sep=/()?m{vert=120,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=h{pass=10}f{bal=}}};,ole=,ose=}}"); + + switch (flagval & (SCOTCH_STRATLEVELMIN | SCOTCH_STRATLEVELMAX)) { + case SCOTCH_STRATLEVELMIN : + tstpptr = "0=0"; + tstsptr = "(levl<)|(vert>240)"; + break; + case SCOTCH_STRATLEVELMAX : + tstpptr = "(levl<)"; + tstsptr = "(levl<)&(vert>240)"; + break; + case (SCOTCH_STRATLEVELMIN | SCOTCH_STRATLEVELMAX) : + tstpptr = + tstsptr = "levl<"; + oleaptr = "s"; /* Simple ordering for leaves */ + break; + default : + tstpptr = "0=0"; + tstsptr = "vert>240"; + break; + } + + oleaptr = ((flagval & SCOTCH_STRATLEAFSIMPLE) != 0) + ? "s" + : "f{cmin=15,cmax=100000,frat=0.0}"; + + osepptr = ((flagval & SCOTCH_STRATSEPASIMPLE) != 0) + ? "s" + : "g"; + + stringSubst (bufftab, "", tstpptr); + stringSubst (bufftab, "", tstsptr); + stringSubst (bufftab, "", levltab); + stringSubst (bufftab, "", oleaptr); + stringSubst (bufftab, "", osepptr); + stringSubst (bufftab, "", bbaltab); + stringSubst (bufftab, "", verttab); + + if (SCOTCH_stratDgraphOrder (stratptr, bufftab) != 0) { + errorPrint ("SCOTCH_stratDgraphOrderBuild: error in parallel ordering strategy"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_f.c new file mode 100644 index 00000000..0aa376e2 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_f.c @@ -0,0 +1,208 @@ +/* Copyright 2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed graph ordering routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 feb 2007 **/ +/** to 31 may 2008 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 25 jul 2010 **/ +/** # Version 6.0 : from : 08 jan 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERINIT, scotchfdgraphorderinit, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Dordering * const ordeptr, \ +int * const revaptr), \ +(grafptr, ordeptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphOrderInit (grafptr, ordeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDEREXIT, scotchfdgraphorderexit, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Dordering * const ordeptr), \ +(grafptr, ordeptr)) +{ + SCOTCH_dgraphOrderExit (grafptr, ordeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERSAVE, scotchfdgraphordersave, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dordering * const ordeptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, ordeptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if (*fileptr == -1) /* If process is not the root */ + stream = NULL; + else { /* Open stream for root process */ + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFDGRAPHORDERSAVE: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFDGRAPHORDERSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + } + + o = SCOTCH_dgraphOrderSave (grafptr, ordeptr, stream); + + if (stream != NULL) + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERCOMPUTE, scotchfdgraphordercompute, ( \ +SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Dordering * const ordeptr, \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(grafptr, ordeptr, stratptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphOrderCompute (grafptr, ordeptr, stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERCOMPUTELIST, scotchfdgraphordercomputelist, ( \ +SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Dordering * const ordeptr, \ +const SCOTCH_Num * listptr, \ +const SCOTCH_Num * const listtab, \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(grafptr, ordeptr, listptr, listtab, stratptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphOrderComputeList (grafptr, ordeptr, *listptr, listtab, stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATDGRAPHORDER, scotchfstratdgraphorder, ( \ +SCOTCH_Strat * const stratptr, \ +const char * const string, \ +int * const revaptr, \ +const int strnbr), \ +(stratptr, string, revaptr, strnbr)) +{ + char * restrict strtab; /* Pointer to null-terminated string */ + + if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ + errorPrint ("SCOTCHFSTRATDGRAPHORDER: out of memory (1)"); + *revaptr = 1; + } + memCpy (strtab, string, strnbr); /* Copy string contents */ + strtab[strnbr] = '\0'; /* Terminate string */ + + *revaptr = SCOTCH_stratDgraphOrder (stratptr, strtab); /* Call original routine */ + + memFree (strtab); /* Prevent compiler warnings */ +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATDGRAPHORDERBUILD, scotchfstratdgraphorderbuild, ( \ +SCOTCH_Strat * const stratptr, \ +const SCOTCH_Num * const flagval, \ +const SCOTCH_Num * const procnbr, \ +const SCOTCH_Num * const levlnbr, \ +const double * const balrat, \ +int * const revaptr), \ +(stratptr, flagval, procnbr, levlnbr, balrat, revaptr)) +{ + *revaptr = SCOTCH_stratDgraphOrderBuild (stratptr, *flagval, *procnbr, *levlnbr, *balrat); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_gather.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_gather.c new file mode 100644 index 00000000..2b768934 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_gather.c @@ -0,0 +1,158 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_gather.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted ordering gathering routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 21 jul 2007 **/ +/** to 04 aug 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "order.h" +#include "dorder.h" +#include "library_order.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the distributed ordering */ +/* handling routines. */ +/* */ +/************************************/ + +/*+ This routine initializes an API centralized +*** ordering with respect to the given distributed +*** source graph and the locations of output parameters. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphCorderInit ( +const SCOTCH_Dgraph * const grafptr, /*+ Distributed graph to order +*/ +SCOTCH_Ordering * const cordptr, /*+ Ordering structure to initialize +*/ +SCOTCH_Num * const permtab, /*+ Direct permutation array +*/ +SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ +SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ +SCOTCH_Num * const rangtab, /*+ Column block range array +*/ +SCOTCH_Num * const treetab) /*+ Separator tree array +*/ +{ + Dgraph * srcgrafptr; + LibOrder * libcordptr; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Ordering) < sizeof (LibOrder)) { + errorPrint ("SCOTCH_dgraphCorderInit: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + srcgrafptr = (Dgraph *) grafptr; /* Use structure as distributed source graph */ + libcordptr = (LibOrder *) cordptr; + libcordptr->permtab = ((permtab == NULL) || ((void *) permtab == (void *) grafptr)) ? NULL : (Gnum *) permtab; + libcordptr->peritab = ((peritab == NULL) || ((void *) peritab == (void *) grafptr)) ? NULL : (Gnum *) peritab; + libcordptr->cblkptr = ((cblkptr == NULL) || ((void *) cblkptr == (void *) grafptr)) ? NULL : (Gnum *) cblkptr; + libcordptr->rangtab = ((rangtab == NULL) || ((void *) rangtab == (void *) grafptr)) ? NULL : (Gnum *) rangtab; + libcordptr->treetab = ((treetab == NULL) || ((void *) treetab == (void *) grafptr)) ? NULL : (Gnum *) treetab; + + return (orderInit (&libcordptr->o, srcgrafptr->baseval, srcgrafptr->vertglbnbr, libcordptr->peritab)); +} + +/*+ This routine frees an API centralized ordering. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_dgraphCorderExit ( +const SCOTCH_Dgraph * const grafptr, +SCOTCH_Ordering * const cordptr) +{ + orderExit (&((LibOrder *) cordptr)->o); +} + +/*+ This routine gathers the contents of +*** the given distributed ordering into the +*** given centralized ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderGather ( +const SCOTCH_Dgraph * const grafptr, /*+ Not used +*/ +const SCOTCH_Dordering * const dordptr, /*+ Distributed ordering +*/ +SCOTCH_Ordering * const cordptr) /*+ Centralized ordering +*/ +{ + LibOrder * libcordptr; /* Pointer to ordering */ + + if ((cordptr != NULL) && ((void *) cordptr != (void *) dordptr)) { /* If potential root process */ + libcordptr = (LibOrder *) cordptr; /* Get centralized ordering */ + + if (dorderGather ((Dorder *) dordptr, &libcordptr->o) != 0) + return (1); + + if (libcordptr->permtab != NULL) /* Build direct permutation if wanted */ + orderPeri (libcordptr->o.peritab, libcordptr->o.baseval, libcordptr->o.vnodnbr, libcordptr->permtab, libcordptr->o.baseval); + if (libcordptr->rangtab != NULL) /* Build range array if column block data wanted */ + orderRang (&libcordptr->o, libcordptr->rangtab); + if (libcordptr->treetab != NULL) /* Build separator tree array if wanted */ + orderTree (&libcordptr->o, libcordptr->treetab); + if (libcordptr->cblkptr != NULL) /* Set number of column blocks if wanted */ + *(libcordptr->cblkptr) = libcordptr->o.cblknbr; + + return (0); + } + else + return (dorderGather ((Dorder *) dordptr, NULL)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_gather_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_gather_f.c new file mode 100644 index 00000000..5709ef92 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_gather_f.c @@ -0,0 +1,108 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_gather_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed ordering gathering routines **/ +/** of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 21 jul 2007 **/ +/** to 22 jul 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering routines. */ +/* */ +/**************************************/ + +FORTRAN ( \ +SCOTCHFDGRAPHCORDERINIT, scotchfdgraphcorderinit, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Ordering * const ordeptr, \ +SCOTCH_Num * const permtab, \ +SCOTCH_Num * const peritab, \ +SCOTCH_Num * const cblkptr, \ +SCOTCH_Num * const rangtab, \ +SCOTCH_Num * const treetab, \ +int * const revaptr), \ +(grafptr, ordeptr, permtab, peritab, \ + cblkptr, rangtab, treetab, revaptr)) +{ + *revaptr = SCOTCH_dgraphCorderInit (grafptr, ordeptr, permtab, peritab, cblkptr, rangtab, treetab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHCORDEREXIT, scotchfdgraphcorderexit, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Ordering * const ordeptr), \ +(grafptr, ordeptr)) +{ + SCOTCH_dgraphCorderExit (grafptr, ordeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERGATHER, scotchfdgraphordergather, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dordering * const dordptr, \ +SCOTCH_Ordering * const cordptr, \ +int * const revaptr), \ +(grafptr, dordptr, cordptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphOrderGather (grafptr, dordptr, cordptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_io.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_io.c new file mode 100644 index 00000000..d45ea242 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_io.c @@ -0,0 +1,101 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_io.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted ordering I/O routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 26 jul 2007 **/ +/** to 18 oct 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dorder.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the distributed ordering */ +/* handling routines. */ +/* */ +/************************************/ + +/*+ This routine saves to the given stream +*** the mapping data associated with the +*** given distributed ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderSaveMap ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Dordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (dorderSaveMap ((Dorder *) ordeptr, (Dgraph *) grafptr, stream)); +} + +/*+ This routine saves to the given stream +*** the separator tree data associated with +*** the given distributed ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderSaveTree ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Dordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (dorderSaveTree ((Dorder *) ordeptr, (Dgraph *) grafptr, stream)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_io_block.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_io_block.c new file mode 100644 index 00000000..904f4008 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_io_block.c @@ -0,0 +1,85 @@ +/* Copyright 2007,2008,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_io_block.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted ordering distributed tree **/ +/** building routine of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 28 may 2008 **/ +/** to 28 may 2008 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dorder.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the distributed ordering */ +/* handling routines. */ +/* */ +/************************************/ + +/*+ This routine saves the contents of +*** the given ordering to the given stream +*** on the form of a block ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderSaveBlock ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Dordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (dorderSaveBlock ((Dorder *) ordeptr, (Dgraph *) grafptr, stream)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_io_block_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_io_block_f.c new file mode 100644 index 00000000..774003ac --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_io_block_f.c @@ -0,0 +1,102 @@ +/* Copyright 2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_io_block_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed graph ordering routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 28 may 2008 **/ +/** to 28 may 2008 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering routines. */ +/* */ +/**************************************/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERSAVEBLOCK, scotchfdgraphordersaveblock, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dordering * const ordeptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, ordeptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if (*fileptr == -1) /* If process is not the root */ + stream = NULL; + else { /* Open stream for root process */ + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFDGRAPHORDERSAVEBLOCK: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFDGRAPHORDERSAVEBLOCK: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + } + + o = SCOTCH_dgraphOrderSaveBlock (grafptr, ordeptr, stream); + + if (stream != NULL) + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_io_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_io_f.c new file mode 100644 index 00000000..3dc0f3f3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_io_f.c @@ -0,0 +1,90 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_io_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed ordering I/O routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 26 jul 2007 **/ +/** to 18 oct 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering routines. */ +/* */ +/**************************************/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERSAVEMAP, scotchfdgraphordersavemap, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dordering * const ordeptr, \ +FILE * const stream, \ +int * const revaptr), \ +(grafptr, ordeptr, stream, revaptr)) +{ + *revaptr = SCOTCH_dgraphOrderSaveMap (grafptr, ordeptr, stream); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERSAVETREE, scotchfdgraphordersavetree, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dordering * const ordeptr, \ +FILE * const stream, \ +int * const revaptr), \ +(grafptr, ordeptr, stream, revaptr)) +{ + *revaptr = SCOTCH_dgraphOrderSaveTree (grafptr, ordeptr, stream); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_perm.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_perm.c new file mode 100644 index 00000000..f4ca5a95 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_perm.c @@ -0,0 +1,84 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_perm.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted ordering permutation building **/ +/** routine of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 18 oct 2007 **/ +/** to 18 oct 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dorder.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the distributed ordering */ +/* handling routines. */ +/* */ +/************************************/ + +/*+ This routine fills the given distributed +*** permutation array with the permutation +*** stored in the given distributed ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderPerm ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Dordering * const ordeptr, /*+ Computed ordering +*/ +SCOTCH_Num * const permloctab) /*+ Direct permutation +*/ +{ + return (dorderPerm ((Dorder *) ordeptr, (Dgraph *) grafptr, permloctab)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_perm_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_perm_f.c new file mode 100644 index 00000000..91c5ba50 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_perm_f.c @@ -0,0 +1,76 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_perm_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed ordering permutation **/ +/** building routine of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 18 oct 2007 **/ +/** to 18 oct 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering routines. */ +/* */ +/**************************************/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERPERM, scotchfdgraphorderperm, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dordering * const ordeptr, \ +SCOTCH_Num * const permloctab, \ +int * const revaptr), \ +(grafptr, ordeptr, permloctab, revaptr)) +{ + *revaptr = SCOTCH_dgraphOrderPerm (grafptr, ordeptr, permloctab); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_tree_dist.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_tree_dist.c new file mode 100644 index 00000000..20183f83 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_tree_dist.c @@ -0,0 +1,102 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_tree_dist.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted ordering distributed tree **/ +/** building routine of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 30 nov 2007 **/ +/** to 30 nov 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "dorder.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the distributed ordering */ +/* handling routines. */ +/* */ +/************************************/ + +/*+ This routine returns the number of +*** distributed column blocks contained +*** in the given distributed ordering. +*** It returns: +*** - >=0 : on success. +*** - <0 : on error. ++*/ + +SCOTCH_Num +SCOTCH_dgraphOrderCblkDist ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Dordering * const ordeptr) /*+ Computed ordering +*/ +{ + return (dorderCblkDist ((Dorder *) ordeptr)); +} + +/*+ This routine fills the given distributed +*** permutation array with the permutation +*** stored in the given distributed ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphOrderTreeDist ( +const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Dordering * const ordeptr, /*+ Computed ordering +*/ +SCOTCH_Num * const treeglbtab, /*+ Father array +*/ +SCOTCH_Num * const sizeglbtab) /*+ Size array +*/ +{ + return (dorderTreeDist ((Dorder *) ordeptr, (Dgraph *) grafptr, treeglbtab, sizeglbtab)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_order_tree_dist_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_order_tree_dist_f.c new file mode 100644 index 00000000..6a270be0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_order_tree_dist_f.c @@ -0,0 +1,91 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_order_tree_dist_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** distributed ordering distributed tree **/ +/** building routine of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 30 nov 2007 **/ +/** to 30 nov 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering routines. */ +/* */ +/**************************************/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERCBLKDIST, scotchfdgraphordercblkdist, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dordering * const ordeptr, \ +SCOTCH_Num * const cblkglbptr), +(grafptr, ordeptr, cblkglbptr)) +{ + *cblkglbptr = SCOTCH_dgraphOrderCblkDist (grafptr, ordeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHORDERTREEDIST, scotchfdgraphordertreedist, ( \ +const SCOTCH_Dgraph * const grafptr, \ +const SCOTCH_Dordering * const ordeptr, \ +SCOTCH_Num * const treeglbtab, \ +SCOTCH_Num * const sizeglbtab, \ +int * const revaptr), \ +(grafptr, ordeptr, treeglbtab, sizeglbtab, revaptr)) +{ + *revaptr = SCOTCH_dgraphOrderTreeDist (grafptr, ordeptr, treeglbtab, sizeglbtab); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_redist.c b/scotch_6.0.3/src/libscotch/library_dgraph_redist.c new file mode 100644 index 00000000..5ab53cc6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_redist.c @@ -0,0 +1,101 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_redist.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the graph redistribution **/ +/** routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 28 mar 2012 **/ +/** to : 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" +#include "dgraph_redist.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/*+ This routine computes a distributed graph +*** that matches the provided partition. +*** It returns: +*** - 0 : if redistributed graph created. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphRedist ( +SCOTCH_Dgraph * const orggrafptr, +const SCOTCH_Num * const partloctab, /* Array of part numbers for each local vertex */ +const SCOTCH_Num * const permgsttab, /* Redistribution permutation array */ +const SCOTCH_Num vertlocdlt, /* Extra size of local vertex array */ +const SCOTCH_Num edgelocdlt, /* Extra size of local edge array */ +SCOTCH_Dgraph * const redgrafptr) +{ + SCOTCH_Num baseval; +#ifdef SCOTCH_DEBUG_LIBRARY1 + int o; + + MPI_Comm_compare (((Dgraph * restrict const) orggrafptr)->proccomm, + ((Dgraph * restrict const) redgrafptr)->proccomm, &o); + if ((o != MPI_IDENT) && (o != MPI_CONGRUENT)) { + errorPrint ("SCOTCH_dgraphRedist: communicators are not congruent"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + baseval = ((Dgraph *) orggrafptr)->baseval; + + return (dgraphRedist ((Dgraph *) orggrafptr, + ((partloctab != NULL) && (partloctab != (SCOTCH_Num *) orggrafptr)) ? (const Gnum * restrict const) (partloctab - baseval) : NULL, + ((permgsttab != NULL) && (permgsttab != (SCOTCH_Num *) orggrafptr)) ? (const Gnum * restrict const) (permgsttab - baseval) : NULL, + (vertlocdlt < 0) ? 0 : vertlocdlt, (edgelocdlt < 0) ? 0 : edgelocdlt, (Dgraph *) redgrafptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_redist_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_redist_f.c new file mode 100644 index 00000000..5b13f87f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_redist_f.c @@ -0,0 +1,80 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_redist_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 28 mar 2012 **/ +/** to : 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/********************************************/ +/* */ +/* These routines are the Fortran API for */ +/* the distributed graph handling routines. */ +/* */ +/********************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHREDIST, scotchfdgraphredist, ( \ +SCOTCH_Dgraph * const srcgrafptr, \ +const SCOTCH_Num * const partloctab, \ +const SCOTCH_Num * const permgsttab, \ +const SCOTCH_Num * const vertlocdlt, \ +const SCOTCH_Num * const edgelocdlt, \ +SCOTCH_Dgraph * const dstgrafptr, \ +int * const revaptr), \ +(srcgrafptr, partloctab, permgsttab, vertlocdlt, edgelocdlt, dstgrafptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphRedist (srcgrafptr, partloctab, permgsttab, *vertlocdlt, *edgelocdlt, dstgrafptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_scatter.c b/scotch_6.0.3/src/libscotch/library_dgraph_scatter.c new file mode 100644 index 00000000..20c6134a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_scatter.c @@ -0,0 +1,85 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_scatter.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the distri- **/ +/** buted source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 28 apr 2006 **/ +/** to 12 jul 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "dgraph.h" +#include "ptscotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/*+ This routine scatters the data of a +*** centralized graph on a distributed graph. +*** It returns: +*** - 0 : if the scattering succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_dgraphScatter ( +SCOTCH_Dgraph * const dgrfptr, +const SCOTCH_Graph * const cgrfptr) +{ + const Graph * srccgrfptr; + + srccgrfptr = (((void *) cgrfptr) == ((void *) dgrfptr)) ? NULL : (const Graph *) cgrfptr; /* Consider same pointers as flag for non-root process */ + + return (dgraphScatter ((Dgraph *) dgrfptr, srccgrfptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_scatter_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_scatter_f.c new file mode 100644 index 00000000..cc8911cf --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_scatter_f.c @@ -0,0 +1,79 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_scatter_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 feb 2007 **/ +/** to 12 jul 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph handling */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHSCATTER, scotchfdgraphscatter, ( \ +SCOTCH_Dgraph * const dgrfptr, \ +SCOTCH_Graph * const cgrfptr, \ +int * const revaptr), \ +(dgrfptr, cgrfptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphScatter (dgrfptr, cgrfptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_stat.c b/scotch_6.0.3/src/libscotch/library_dgraph_stat.c new file mode 100644 index 00000000..450c33fd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_stat.c @@ -0,0 +1,324 @@ +/* Copyright 2007,2008,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_stat.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the source **/ +/** graph handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 23 jun 2007 **/ +/** to 03 apr 2008 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "library_dgraph_stat.h" +#include "ptscotch.h" + +/* +** The static variables. +*/ + +static int dgraphstatblentab[2] = { 7, 3 }; +static MPI_Datatype dgraphstattypetab[2] = { GNUM_MPI, MPI_DOUBLE }; + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/* This routine is the reduction-loc operator which +** returns in inout[2] the rank of the process which +** holds the best partition. +** It returns: +** - void : in all cases. +*/ + +static +void +dgraphStatReduceAll ( +const DgraphStatData * const in, /* First operand */ +DgraphStatData * const inout, /* Second and output operand */ +const int * const len, /* Number of instances; should be 1, not used */ +const MPI_Datatype * const typedat) /* MPI datatype; not used */ +{ + if (inout->velomin > in->velomin) + inout->velomin = in->velomin; + if (inout->velomax < in->velomax) + inout->velomax = in->velomax; + if (inout->degrmin > in->degrmin) + inout->degrmin = in->degrmin; + if (inout->degrmax < in->degrmax) + inout->degrmax = in->degrmax; + if (inout->edlomin > in->edlomin) + inout->edlomin = in->edlomin; + if (inout->edlomax < in->edlomax) + inout->edlomax = in->edlomax; + inout->edlosum += in->edlosum; + inout->velodlt += in->velodlt; + inout->degrdlt += in->degrdlt; + inout->edlodlt += in->edlodlt; +} + +/*+ This routine computes statistics +*** on the given distributed graph. +*** It returns: +*** - VOID : in all cases. ++*/ + +int +SCOTCH_dgraphStat ( +const SCOTCH_Dgraph * const grafptr, +SCOTCH_Num * const velominptr, +SCOTCH_Num * const velomaxptr, +SCOTCH_Num * const velosumptr, +double * veloavgptr, +double * velodltptr, +SCOTCH_Num * const degrminptr, +SCOTCH_Num * const degrmaxptr, +double * degravgptr, +double * degrdltptr, +SCOTCH_Num * const edlominptr, +SCOTCH_Num * const edlomaxptr, +SCOTCH_Num * const edlosumptr, +double * edloavgptr, +double * edlodltptr) +{ + const Dgraph * srcgrafptr; + DgraphStatData srcgstadat; + DgraphStatData srclstadat; + MPI_Datatype srctypedat; + MPI_Aint srcdisptab[2]; + MPI_Op srcoperdat; + Gnum vertlocnum; + double veloglbavg; + double velolocdlt; + Gnum degrlocmin; + Gnum degrlocmax; + double degrglbavg; + double degrlocdlt; + Gnum edloglbsum; + double edloglbavg; + double edlolocdlt; + int o; + + srcgrafptr = (Dgraph *) grafptr; + + velolocdlt = 0.0L; + if (srcgrafptr->vertglbnbr > 0) { + if (srcgrafptr->veloloctax != NULL) { /* If graph has vertex loads */ + const Gnum * restrict veloloctax; + Gnum velolocmin; + Gnum velolocmax; + + veloloctax = srcgrafptr->veloloctax; + velolocmin = GNUMMAX; + velolocmax = 0; + veloglbavg = (double) srcgrafptr->veloglbsum / (double) srcgrafptr->vertglbnbr; + + for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) { + Gnum velolocval; + + velolocval = veloloctax[vertlocnum]; + if (velolocval < velolocmin) + velolocmin = velolocval; + if (velolocval > velolocmax) + velolocmax = velolocval; + velolocdlt += fabs ((double) velolocval - veloglbavg); + } + + srclstadat.velomin = velolocmin; + srclstadat.velomax = velolocmax; + } + else { + srclstadat.velomin = + srclstadat.velomax = 1; + veloglbavg = 1.0L; + } + } + else { + srclstadat.velomin = + srclstadat.velomax = 0; + veloglbavg = 0.0L; + } + srclstadat.velodlt = velolocdlt; + + degrlocmax = 0; + degrlocdlt = 0.0L; + if (srcgrafptr->vertglbnbr > 0) { + degrlocmin = GNUMMAX; + degrglbavg = (double) srcgrafptr->edgeglbnbr / (double) srcgrafptr->vertglbnbr; + for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) { + Gnum degrlocval; + + degrlocval = srcgrafptr->vendloctax[vertlocnum] - srcgrafptr->vertloctax[vertlocnum]; /* Get vertex degree */ + if (degrlocval < degrlocmin) + degrlocmin = degrlocval; + if (degrlocval > degrlocmax) + degrlocmax = degrlocval; + degrlocdlt += fabs ((double) degrlocval - degrglbavg); + } + } + else { + degrlocmin = 0; + degrglbavg = 0.0L; + } + srclstadat.degrmin = degrlocmin; + srclstadat.degrmax = degrlocmax; + srclstadat.degrdlt = degrlocdlt; + + edlolocdlt = 0.0L; + if (srcgrafptr->edgeglbnbr > 0) { + if (srcgrafptr->edloloctax != NULL) { /* If graph has edge loads */ + Gnum edlolocmin; + Gnum edlolocmax; + Gnum edlolocsum; + + edlolocmin = GNUMMAX; + edlolocmax = 0; + edlolocsum = 0; + + for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + + for (edgelocnum = srcgrafptr->vertloctax[vertlocnum]; + edgelocnum < srcgrafptr->vendloctax[vertlocnum]; edgelocnum ++) { + Gnum edlolocval; + + edlolocval = srcgrafptr->edloloctax[edgelocnum]; + edlolocsum += edlolocval; + if (edlolocval < edlolocmin) /* Account for edge load */ + edlolocmin = edlolocval; + if (edlolocval > edlolocmax) + edlolocmax = edlolocval; + } + } + + if (MPI_Allreduce (&edlolocsum, &edloglbsum, 1, GNUM_MPI, MPI_SUM, srcgrafptr->proccomm) != MPI_SUCCESS) { + errorPrint ("SCOTCH_dgraphStat: communication error (1)"); + return (1); + } + edloglbavg = (double) edloglbsum / (double) (2 * srcgrafptr->edgeglbnbr); + + for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) { + Gnum edgelocnum; + + for (edgelocnum = srcgrafptr->vertloctax[vertlocnum]; + edgelocnum < srcgrafptr->vendloctax[vertlocnum]; edgelocnum ++) + edlolocdlt += fabs ((double) srcgrafptr->edloloctax[edgelocnum] - edloglbavg); + } + } + else { + srclstadat.edlomin = + srclstadat.edlomax = 1; + edloglbsum = srcgrafptr->edgeglbnbr / 2; + edloglbavg = 1.0L; + } + } + else { + srclstadat.edlomin = + srclstadat.edlomax = 0; + edloglbsum = 0; + edloglbavg = 0.0L; + } + srclstadat.edlodlt = edlolocdlt; + + MPI_Address (&srclstadat.velomin, &srcdisptab[0]); + MPI_Address (&srclstadat.velodlt, &srcdisptab[1]); + srcdisptab[1] -= srcdisptab[0]; + srcdisptab[0] -= srcdisptab[0]; + + o = 1; /* Assume something will go wrong */ + if ((MPI_Type_struct (2, dgraphstatblentab, srcdisptab, dgraphstattypetab, &srctypedat) == MPI_SUCCESS) && + (MPI_Type_commit (&srctypedat) == MPI_SUCCESS)) { + if (MPI_Op_create ((MPI_User_function *) dgraphStatReduceAll, 0, &srcoperdat) == MPI_SUCCESS) { + if (MPI_Allreduce (&srclstadat, &srcgstadat, 1, srctypedat, srcoperdat, srcgrafptr->proccomm) == MPI_SUCCESS) + o = 0; + + MPI_Op_free (&srcoperdat); + } + MPI_Type_free (&srctypedat); + } + if (o != 0) { + errorPrint ("SCOTCH_dgraphStat: communication error (2)"); + return (1); + } + + if (velominptr != NULL) + *velominptr = (SCOTCH_Num) srcgstadat.velomin; + if (velomaxptr != NULL) + *velomaxptr = (SCOTCH_Num) srcgstadat.velomax; + if (velosumptr != NULL) + *velosumptr = (SCOTCH_Num) srcgrafptr->veloglbsum; + if (veloavgptr != NULL) + *veloavgptr = (double) veloglbavg; + if (velodltptr != NULL) + *velodltptr = srcgstadat.velodlt / (double) srcgrafptr->vertglbnbr; + + if (degrminptr != NULL) + *degrminptr = (SCOTCH_Num) srcgstadat.degrmin; + if (degrmaxptr != NULL) + *degrmaxptr = (SCOTCH_Num) srcgstadat.degrmax; + if (degravgptr != NULL) + *degravgptr = (double) degrglbavg; + if (degrdltptr != NULL) + *degrdltptr = srcgstadat.degrdlt / (double) srcgrafptr->vertglbnbr; + + if (edlominptr != NULL) + *edlominptr = (SCOTCH_Num) srcgstadat.edlomin; + if (edlomaxptr != NULL) + *edlomaxptr = (SCOTCH_Num) srcgstadat.edlomax; + if (edlosumptr != NULL) + *edlosumptr = (SCOTCH_Num) edloglbsum; + if (edloavgptr != NULL) + *edloavgptr = (double) edloglbavg; + if (edlodltptr != NULL) + *edlodltptr = srcgstadat.edlodlt / (double) srcgrafptr->edgeglbnbr; + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_stat.h b/scotch_6.0.3/src/libscotch/library_dgraph_stat.h new file mode 100644 index 00000000..9a9cec46 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_stat.h @@ -0,0 +1,64 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/**********************************************************/ +/* */ +/* NAME : library_dgraph_stat.h */ +/* */ +/* AUTHOR : Francois PELLEGRINI */ +/* */ +/* FUNCTION : These lines are the data declarations */ +/* for the distributed source graph */ +/* analyzing routine. */ +/* */ +/* # Version 5.0 : from : 23 jun 2007 */ +/* to 23 jun 2007 */ +/* */ +/**********************************************************/ + +/* +** The type and structure definitions. +*/ + +/* Communication structure for distributed graph statistics. */ + +typedef struct DgraphStatData_ { + Gnum velomin; + Gnum velomax; + Gnum degrmin; + Gnum degrmax; + Gnum edlomin; + Gnum edlomax; + Gnum edlosum; + double velodlt; + double degrdlt; + double edlodlt; +} DgraphStatData; diff --git a/scotch_6.0.3/src/libscotch/library_dgraph_stat_f.c b/scotch_6.0.3/src/libscotch/library_dgraph_stat_f.c new file mode 100644 index 00000000..7d65cb10 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dgraph_stat_f.c @@ -0,0 +1,98 @@ +/* Copyright 2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dgraph_stat_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the distributed source graph analyzing **/ +/** routine of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 24 jun 2007 **/ +/** to 24 jun 2007 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFDGRAPHSTAT, scotchfdgraphstat, ( \ +const SCOTCH_Dgraph * const grafptr, \ +SCOTCH_Num * const velominptr, \ +SCOTCH_Num * const velomaxptr, \ +SCOTCH_Num * const velosumptr, \ +double * veloavgptr, \ +double * velodltptr, \ +SCOTCH_Num * const degrminptr, \ +SCOTCH_Num * const degrmaxptr, \ +double * degravgptr, \ +double * degrdltptr, \ +SCOTCH_Num * const edlominptr, \ +SCOTCH_Num * const edlomaxptr, \ +SCOTCH_Num * const edlosumptr, \ +double * edloavgptr, \ +double * edlodltptr, \ +int * const revaptr), \ +(grafptr, velominptr, velomaxptr, velosumptr, \ + veloavgptr, velodltptr, degrminptr, \ + degrmaxptr, degravgptr, degrdltptr, \ + edlominptr, edlomaxptr, edlosumptr, \ + edloavgptr, edlodltptr, revaptr)) +{ + *revaptr = SCOTCH_dgraphStat (grafptr, + velominptr, velomaxptr, velosumptr, veloavgptr, velodltptr, + degrminptr, degrmaxptr, degravgptr, degrdltptr, + edlominptr, edlomaxptr, edlosumptr, edloavgptr, edlodltptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_dmapping.c b/scotch_6.0.3/src/libscotch/library_dmapping.c new file mode 100644 index 00000000..8fec505f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dmapping.c @@ -0,0 +1,78 @@ +/* Copyright 2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dmapping.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains miscellaneous **/ +/** routines for handling distributed **/ +/** graph mappings. **/ +/** **/ +/** DATES : # Version 5.1 : from : 17 nov 2010 **/ +/** to 17 nov 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/****************************************/ +/* */ +/* These routines are the C API for */ +/* mapping structure handling routines. */ +/* */ +/****************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** graph mapping structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Dmapping * +SCOTCH_dmapAlloc () +{ + return ((SCOTCH_Dmapping *) memAlloc (sizeof (SCOTCH_Dmapping))); +} diff --git a/scotch_6.0.3/src/libscotch/library_dmapping.h b/scotch_6.0.3/src/libscotch/library_dmapping.h new file mode 100644 index 00000000..623819d8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dmapping.h @@ -0,0 +1,56 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dmapping.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the library ordering **/ +/** structure. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 jun 2008 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Distributed mapping. +*/ + +typedef struct LibDmapping_ { + Dmapping m; /*+ Distributed mapping data +*/ + Gnum * termloctab; /*+ Local mapping array +*/ +} LibDmapping; diff --git a/scotch_6.0.3/src/libscotch/library_dorder.c b/scotch_6.0.3/src/libscotch/library_dorder.c new file mode 100644 index 00000000..0b6fef95 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_dorder.c @@ -0,0 +1,78 @@ +/* Copyright 2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_dorder.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains miscellaneous **/ +/** routines for handling distributed **/ +/** graph orderings. **/ +/** **/ +/** DATES : # Version 5.1 : from : 17 nov 2010 **/ +/** to 17 nov 2010 **/ +/** # Version 6.0 : from : 29 nov 2012 **/ +/** to 29 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" + +/*****************************************/ +/* */ +/* These routines are the C API for */ +/* ordering structure handling routines. */ +/* */ +/*****************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** distributed ordering structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Dordering * +SCOTCH_dorderAlloc () +{ + return ((SCOTCH_Dordering *) memAlloc (sizeof (SCOTCH_Dordering))); +} diff --git a/scotch_6.0.3/src/libscotch/library_errcom.c b/scotch_6.0.3/src/libscotch/library_errcom.c new file mode 100644 index 00000000..99731db2 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_errcom.c @@ -0,0 +1,121 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_errcom.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module redirects the errors **/ +/** generated by the routines of the **/ +/** libSCOTCH library to the standard **/ +/** error processing routines. **/ +/** **/ +/** DATES : # Version 3.3 : from : 06 oct 1998 **/ +/** to 13 oct 1998 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to 01 nov 2001 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY_ERRCOM +#ifndef SCOTCH_COMMON_EXTERNAL +#define SCOTCH_COMMON_EXTERNAL /* Do not redefine errorPrint */ +#endif /* SCOTCH_COMMON_EXTERNAL */ + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/********************************/ +/* */ +/* The error handling routines. */ +/* */ +/********************************/ + +/* This routine prints an error message with +** a variable number of arguments, as printf () +** does, and exits. +** It returns: +** - EXIT : in all cases. +*/ + +void +SCOTCH_errorPrint ( +const char * const errstr, /*+ printf-like variable argument list */ +...) +{ + va_list errlist; /* Argument list of the call */ + char errbuf[1024]; /* Error buffer */ + + va_start (errlist, errstr); /* Open variable-argument list */ +#if ((defined X_ARCHi586_pc_linux2) || (defined X_ARCHi686_pc_linux2)) + vsnprintf (errbuf, 1023, errstr, errlist); /* Write result to buffer */ +#else + vsprintf (errbuf, errstr, errlist); /* Write result to buffer */ +#endif /* X_ARCHi586_pc_linux2 */ + va_end (errlist); /* Close variable-argument list */ + errbuf[1023] = '\0'; /* Set end of string */ + errorPrint (errbuf); /* Print arguments */ + + exit (1); +} + +/* This routine prints a warning message with +** a variable number of arguments, as printf () +** does. +** It returns: +** - VOID : in all cases. +*/ + +void +SCOTCH_errorPrintW ( +const char * const errstr, /*+ printf-like variable argument list */ +...) +{ + va_list errlist; /* Argument list of the call */ + char errbuf[1024]; /* Error buffer */ + + va_start (errlist, errstr); /* Open variable-argument list */ +#if ((defined X_ARCHi586_pc_linux2) || (defined X_ARCHi686_pc_linux2)) + vsnprintf (errbuf, 1023, errstr, errlist); /* Write result to buffer */ +#else + vsprintf (errbuf, errstr, errlist); /* Write result to buffer */ +#endif /* X_ARCHi586_pc_linux2 */ + va_end (errlist); /* Close variable-argument list */ + errbuf[1023] = '\0'; /* Set end of string */ + errorPrintW (errbuf); /* Print arguments */ +} diff --git a/scotch_6.0.3/src/libscotch/library_error.c b/scotch_6.0.3/src/libscotch/library_error.c new file mode 100644 index 00000000..16930e7a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_error.c @@ -0,0 +1,172 @@ +/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_error.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module provides error handling **/ +/** routines to process errors generated by **/ +/** the routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.3 : from : 02 oct 1998 **/ +/** to 02 oct 1998 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to 01 nov 2001 **/ +/** # Version 5.0 : from : 06 mar 2008 **/ +/** to 24 may 2008 **/ +/** # Version 5.1 : from : 27 sep 2008 **/ +/** to 17 jul 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY_ERROR + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/********************************/ +/* */ +/* The error handling routines. */ +/* */ +/********************************/ + +static char _SCOTCHerrorProgName[32] = ""; + +/* This routine sets the program name for +** error reporting. +** It returns: +** - VOID : in all cases. +*/ + +void +SCOTCH_errorProg ( +const char * const progstr) /*+ Program name +*/ +{ + int charnbr; + const char * nsrcptr; + char * ndstptr; + + nsrcptr = progstr; + ndstptr = _SCOTCHerrorProgName; + charnbr = strlen (progstr); + if (charnbr > 31) { + _SCOTCHerrorProgName[0] = + _SCOTCHerrorProgName[1] = + _SCOTCHerrorProgName[2] = '.'; + ndstptr += 3; + nsrcptr += charnbr - 28; + charnbr = 28; + } + strncpy (ndstptr, nsrcptr, charnbr); + _SCOTCHerrorProgName[31] = '\0'; +} + +/* This routine prints an error message with +** a variable number of arguments, as printf () +** does, and exits. +** It returns: +** - void : in all cases. +*/ + +void +SCOTCH_errorPrint ( +const char * const errstr, /*+ printf-like variable argument list */ +...) +{ + va_list errlist; /* The argument list of the call */ +#ifdef SCOTCH_PTSCOTCH + int proclocnum; +#endif /* SCOTCH_PTSCOTCH */ + + fprintf (stderr, "%s", _SCOTCHerrorProgName); +#ifdef SCOTCH_PTSCOTCH + if ((MPI_Initialized (&proclocnum) == MPI_SUCCESS) && + (proclocnum != 0) && + (MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum) == MPI_SUCCESS)) + fprintf (stderr, "(%d): ", proclocnum); + else + fprintf (stderr, ": "); +#else /* SCOTCH_PTSCOTCH */ + if (_SCOTCHerrorProgName[0] != '\0') + fprintf (stderr, ": "); +#endif /* SCOTCH_PTSCOTCH */ + fprintf (stderr, "ERROR: "); + va_start (errlist, errstr); + vfprintf (stderr, errstr, errlist); /* Print arguments */ + va_end (errlist); + fprintf (stderr, "\n"); + fflush (stderr); /* In case it has been set to buffered mode */ +} + +/* This routine prints a warning message with +** a variable number of arguments, as printf () +** does. +** It returns: +** - VOID : in all cases. +*/ + +void +SCOTCH_errorPrintW ( +const char * const errstr, /*+ printf-like variable argument list */ +...) +{ + va_list errlist; /* The argument list of the call */ +#ifdef SCOTCH_PTSCOTCH + int proclocnum; +#endif /* SCOTCH_PTSCOTCH */ + + fprintf (stderr, "%s", _SCOTCHerrorProgName); +#ifdef SCOTCH_PTSCOTCH + if ((MPI_Initialized (&proclocnum) == MPI_SUCCESS) && + (proclocnum != 0) && + (MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum) == MPI_SUCCESS)) + fprintf (stderr, "(%d): ", proclocnum); + else + fprintf (stderr, ": "); +#else /* SCOTCH_PTSCOTCH */ + if (_SCOTCHerrorProgName[0] != '\0') + fprintf (stderr, ": "); +#endif /* SCOTCH_PTSCOTCH */ + fprintf (stderr, "WARNING: "); + va_start (errlist, errstr); + vfprintf (stderr, errstr, errlist); /* Print arguments */ + va_end (errlist); + fprintf (stderr, "\n"); + fflush (stderr); /* In case it has been set to buffered mode */ +} diff --git a/scotch_6.0.3/src/libscotch/library_error_exit.c b/scotch_6.0.3/src/libscotch/library_error_exit.c new file mode 100644 index 00000000..245af98c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_error_exit.c @@ -0,0 +1,178 @@ +/* Copyright 2004,2007-2009,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_error_exit.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module provides error handling **/ +/** routines to process errors generated by **/ +/** the routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.3 : from : 02 oct 1998 **/ +/** to 02 oct 1998 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to 01 nov 2001 **/ +/** # Version 5.0 : from : 06 mar 2008 **/ +/** to 24 may 2008 **/ +/** # Version 5.1 : from : 27 sep 2008 **/ +/** to 17 jul 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY_ERROR + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/********************************/ +/* */ +/* The error handling routines. */ +/* */ +/********************************/ + +static char _SCOTCHerrorProgName[32] = ""; + +/* This routine sets the program name for +** error reporting. +** It returns: +** - VOID : in all cases. +*/ + +void +SCOTCH_errorProg ( +const char * const progstr) /*+ Program name +*/ +{ + int charnbr; + const char * nsrcptr; + char * ndstptr; + + nsrcptr = progstr; + ndstptr = _SCOTCHerrorProgName; + charnbr = strlen (progstr); + if (charnbr > 31) { + _SCOTCHerrorProgName[0] = + _SCOTCHerrorProgName[1] = + _SCOTCHerrorProgName[2] = '.'; + ndstptr += 3; + nsrcptr += charnbr - 28; + charnbr = 28; + } + strncpy (ndstptr, nsrcptr, charnbr); + _SCOTCHerrorProgName[31] = '\0'; +} + +/* This routine prints an error message with +** a variable number of arguments, as printf () +** does, and exits. +** It returns: +** - EXIT : in all cases. +*/ + +void +SCOTCH_errorPrint ( +const char * const errstr, /*+ printf-like variable argument list */ +...) +{ + va_list errlist; /* The argument list of the call */ +#ifdef SCOTCH_PTSCOTCH + int proclocnum; +#endif /* SCOTCH_PTSCOTCH */ + + fprintf (stderr, "%s", _SCOTCHerrorProgName); +#ifdef SCOTCH_PTSCOTCH + if ((MPI_Initialized (&proclocnum) == MPI_SUCCESS) && + (proclocnum != 0) && + (MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum) == MPI_SUCCESS)) + fprintf (stderr, "(%d): ", proclocnum); + else + fprintf (stderr, ": "); +#else /* SCOTCH_PTSCOTCH */ + if (_SCOTCHerrorProgName[0] != '\0') + fprintf (stderr, ": "); +#endif /* SCOTCH_PTSCOTCH */ + fprintf (stderr, "ERROR: "); + va_start (errlist, errstr); + vfprintf (stderr, errstr, errlist); /* Print arguments */ + va_end (errlist); + fprintf (stderr, "\n"); + fflush (stderr); /* In case it has been set to buffered mode */ + +#ifdef SCOTCH_ERROR_SLEEP + sleep (SCOTCH_ERROR_SLEEP); /* Wait for messages to be propagated */ +#endif /* SCOTCH_ERROR_SLEEP */ + + exit (1); +} + +/* This routine prints a warning message with +** a variable number of arguments, as printf () +** does. +** It returns: +** - VOID : in all cases. +*/ + +void +SCOTCH_errorPrintW ( +const char * const errstr, /*+ printf-like variable argument list */ +...) +{ + va_list errlist; /* The argument list of the call */ +#ifdef SCOTCH_PTSCOTCH + int proclocnum; +#endif /* SCOTCH_PTSCOTCH */ + + fprintf (stderr, "%s", _SCOTCHerrorProgName); +#ifdef SCOTCH_PTSCOTCH + if ((MPI_Initialized (&proclocnum) == MPI_SUCCESS) && + (proclocnum != 0) && + (MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum) == MPI_SUCCESS)) + fprintf (stderr, "(%d): ", proclocnum); + else + fprintf (stderr, ": "); +#else /* SCOTCH_PTSCOTCH */ + if (_SCOTCHerrorProgName[0] != '\0') + fprintf (stderr, ": "); +#endif /* SCOTCH_PTSCOTCH */ + fprintf (stderr, "WARNING: "); + va_start (errlist, errstr); + vfprintf (stderr, errstr, errlist); /* Print arguments */ + va_end (errlist); + fprintf (stderr, "\n"); + fflush (stderr); /* In case it has been set to buffered mode */ +} diff --git a/scotch_6.0.3/src/libscotch/library_f.h b/scotch_6.0.3/src/libscotch/library_f.h new file mode 100644 index 00000000..fd5fcb4e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_f.h @@ -0,0 +1,116 @@ +!* Copyright 2004,2007,2009,2010,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +!* +!* This file is part of the Scotch software package for static mapping, +!* graph partitioning and sparse matrix ordering. +!* +!* This software is governed by the CeCILL-C license under French law +!* and abiding by the rules of distribution of free software. You can +!* use, modify and/or redistribute the software under the terms of the +!* CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +!* URL: "http://www.cecill.info". +!* +!* As a counterpart to the access to the source code and rights to copy, +!* modify and redistribute granted by the license, users are provided +!* only with a limited warranty and the software's author, the holder of +!* the economic rights, and the successive licensors have only limited +!* liability. +!* +!* In this respect, the user's attention is drawn to the risks associated +!* with loading, using, modifying and/or developing or reproducing the +!* software by the user in light of its specific status of free software, +!* that may mean that it is complicated to manipulate, and that also +!* therefore means that it is reserved for developers and experienced +!* professionals having in-depth computer knowledge. Users are therefore +!* encouraged to load and test the software's suitability as regards +!* their requirements in conditions enabling the security of their +!* systems and/or data to be ensured and, more generally, to use and +!* operate it in the same conditions as regards security. +!* +!* The fact that you are presently reading this means that you have had +!* knowledge of the CeCILL-C license and that you accept its terms. +!* +!*********************************************************** +!* ** +!* NAME : library_f.h ** +!* ** +!* AUTHOR : Francois PELLEGRINI ** +!* ** +!* FUNCTION : FORTRAN declaration file for the ** +!* LibScotch static mapping and sparse ** +!* matrix block ordering sequential ** +!* library. ** +!* ** +!* DATES : # Version 3.4 : from : 04 feb 2000 ** +!* to 22 oct 2001 ** +!* # Version 4.0 : from : 16 jan 2004 ** +!* to 16 jan 2004 ** +!* # Version 5.0 : from : 26 apr 2006 ** +!* to 26 apr 2006 ** +!* # Version 5.1 : from : 26 mar 2009 ** +!* to 12 feb 2011 ** +!* # Version 6.0 : from : 22 oct 2011 ** +!* to 28 sep 2014 ** +!* ** +!*********************************************************** + +!* Flag definitions for the coarsening +!* routines. + + INTEGER SCOTCH_COARSENNONE + INTEGER SCOTCH_COARSENFOLD + INTEGER SCOTCH_COARSENFOLDDUP + INTEGER SCOTCH_COARSENNOMERGE + PARAMETER (SCOTCH_COARSENNONE = 0) + PARAMETER (SCOTCH_COARSENFOLD = 4096) + PARAMETER (SCOTCH_COARSENFOLDDUP = 12288) + PARAMETER (SCOTCH_COARSENNOMERGE = 16384) + +!* Flag definitions for the strategy +!* string selection routines. + + INTEGER SCOTCH_STRATDEFAULT + INTEGER SCOTCH_STRATQUALITY + INTEGER SCOTCH_STRATSPEED + INTEGER SCOTCH_STRATBALANCE + INTEGER SCOTCH_STRATSAFETY + INTEGER SCOTCH_STRATSCALABILITY + INTEGER SCOTCH_STRATRECURSIVE + INTEGER SCOTCH_STRATREMAP + INTEGER SCOTCH_STRATLEVELMAX + INTEGER SCOTCH_STRATLEVELMIN + INTEGER SCOTCH_STRATLEAFSIMPLE + INTEGER SCOTCH_STRATSEPASIMPLE + PARAMETER (SCOTCH_STRATDEFAULT = 0) + PARAMETER (SCOTCH_STRATQUALITY = 1) + PARAMETER (SCOTCH_STRATSPEED = 2) + PARAMETER (SCOTCH_STRATBALANCE = 4) + PARAMETER (SCOTCH_STRATSAFETY = 8) + PARAMETER (SCOTCH_STRATSCALABILITY = 16) + PARAMETER (SCOTCH_STRATRECURSIVE = 256) + PARAMETER (SCOTCH_STRATREMAP = 512) + PARAMETER (SCOTCH_STRATLEVELMAX = 4096) + PARAMETER (SCOTCH_STRATLEVELMIN = 8192) + PARAMETER (SCOTCH_STRATLEAFSIMPLE = 16384) + PARAMETER (SCOTCH_STRATSEPASIMPLE = 32768) + +!* Size definitions for the SCOTCH opaque +!* structures. These structures must be +!* allocated as arrays of DOUBLEPRECISION +!* values for proper padding. The dummy +!* sizes are computed at compile-time by +!* program "dummysizes". + + INTEGER SCOTCH_ARCHDIM + INTEGER SCOTCH_GEOMDIM + INTEGER SCOTCH_GRAPHDIM + INTEGER SCOTCH_MAPDIM + INTEGER SCOTCH_MESHDIM + INTEGER SCOTCH_ORDERDIM + INTEGER SCOTCH_STRATDIM + PARAMETER (SCOTCH_ARCHDIM = DUMMYSIZEARCH) + PARAMETER (SCOTCH_GEOMDIM = DUMMYSIZEGEOM) + PARAMETER (SCOTCH_GRAPHDIM = DUMMYSIZEGRAPH) + PARAMETER (SCOTCH_MAPDIM = DUMMYSIZEMAP) + PARAMETER (SCOTCH_MESHDIM = DUMMYSIZEMESH) + PARAMETER (SCOTCH_ORDERDIM = DUMMYSIZEORDER) + PARAMETER (SCOTCH_STRATDIM = DUMMYSIZESTRAT) diff --git a/scotch_6.0.3/src/libscotch/library_geom.c b/scotch_6.0.3/src/libscotch/library_geom.c new file mode 100644 index 00000000..b71bc87e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_geom.c @@ -0,0 +1,143 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_geom.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the geom **/ +/** graph handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.4 : from : 10 oct 1999 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 19 jan 2004 **/ +/** # Version 5.1 : from : 17 nov 2010 **/ +/** to 17 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "scotch.h" + +/****************************************/ +/* */ +/* These routines are the C API for the */ +/* graph geometry handling routines. */ +/* */ +/****************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** geometry structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Geom * +SCOTCH_geomAlloc () +{ + return ((SCOTCH_Geom *) memAlloc (sizeof (SCOTCH_Geom))); +} + +/*+ This routine initializes the opaque +*** geom structure used to handle graph +*** geometry in the Scotch library. +*** It returns: +*** - 0 : if the initialization succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_geomInit ( +SCOTCH_Geom * const geomptr) +{ + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_geomInit: internal error (1)"); + return (1); + } + if (sizeof (SCOTCH_Geom) < sizeof (Geom)) { + errorPrint ("SCOTCH_geomInit: internal error (2)"); + return (1); + } + + return (geomInit ((Geom *) geomptr)); +} + +/*+ This routine frees the contents of the +*** given opaque geometry structure. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_geomExit ( +SCOTCH_Geom * const geomptr) +{ + geomExit ((Geom *) geomptr); +} + +/*+ This routine accesses all of the geometry data. +*** NULL pointers on input indicate unwanted +*** data. NULL pointers on output indicate +*** unexisting arrays. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_geomData ( +const SCOTCH_Geom * const geomptr, /* Geometry structure to read */ +SCOTCH_Num * const dimnptr, /* Number of dimensions */ +double ** const geomtab) /* Geometry array [vertnbr] */ +{ + const Geom * srcgeomptr; /* Pointer to source geometry structure */ + + srcgeomptr = (const Geom *) geomptr; + + if (dimnptr != NULL) + *dimnptr = srcgeomptr->dimnnbr; + if (geomtab != NULL) + *geomtab = (double *) srcgeomptr->geomtab; +} diff --git a/scotch_6.0.3/src/libscotch/library_geom_f.c b/scotch_6.0.3/src/libscotch/library_geom_f.c new file mode 100644 index 00000000..c61249ad --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_geom_f.c @@ -0,0 +1,107 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_geom_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the graph geometry handling routines **/ +/** of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 15 jun 2005 **/ +/** to 22 dec 2005 **/ +/** # Version 5.1 : from : 15 apr 2010 **/ +/** to 15 apr 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/******************************************/ +/* */ +/* These routines are the Fortran API for */ +/* the graph geometry handling routines. */ +/* */ +/******************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGEOMINIT, scotchfgeominit, ( \ +SCOTCH_Geom * const geomptr, \ +int * const revaptr), \ +(geomptr, revaptr)) +{ + *revaptr = SCOTCH_geomInit (geomptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGEOMEXIT, scotchfgeomexit, ( \ +SCOTCH_Geom * const geomptr), \ +(geomptr)) +{ + SCOTCH_geomExit (geomptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGEOMDATA, scotchfgeomdata, ( \ +const SCOTCH_Geom * const geomptr, \ +const double * const indxptr, \ +SCOTCH_Num * const dimnptr, \ +SCOTCH_Idx * const geomidx), \ +(geomptr, indxptr, dimnptr, geomidx)) +{ + double * geomtab; + + SCOTCH_geomData (geomptr, dimnptr, &geomtab); + *geomidx = (geomtab - indxptr) + 1; /* Add 1 since Fortran indices start at 1 */ +} diff --git a/scotch_6.0.3/src/libscotch/library_graph.c b/scotch_6.0.3/src/libscotch/library_graph.c new file mode 100644 index 00000000..6d6c5fa5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph.c @@ -0,0 +1,518 @@ +/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the source **/ +/** graph handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 18 aug 1998 **/ +/** to 18 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 09 dec 2005 **/ +/** # Version 5.0 : from : 10 sep 2006 **/ +/** to 03 apr 2008 **/ +/** # Version 5.1 : from : 17 nov 2010 **/ +/** to 17 nov 2010 **/ +/** # Version 6.0 : from : 04 dec 2012 **/ +/** to 04 dec 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "graph_io.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** centralized graph structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Graph * +SCOTCH_graphAlloc () +{ + return ((SCOTCH_Graph *) memAlloc (sizeof (SCOTCH_Graph))); +} + +/*+ This routine initializes the opaque +*** graph structure used to handle graphs +*** in the Scotch library. +*** It returns: +*** - 0 : if the initialization succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphInit ( +SCOTCH_Graph * const grafptr) +{ + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_graphInit: internal error (1)"); + return (1); + } + if (sizeof (SCOTCH_Graph) < sizeof (Graph)) { + errorPrint ("SCOTCH_graphInit: internal error (2)"); + return (1); + } + + return (graphInit ((Graph *) grafptr)); +} + +/*+ This routine frees the contents of the +*** given opaque graph structure. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_graphExit ( +SCOTCH_Graph * const grafptr) +{ + graphExit ((Graph *) grafptr); +} + +/*+ This routine frees the contents of the +*** given opaque graph structure. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_graphFree ( +SCOTCH_Graph * const grafptr) +{ + graphFree ((Graph *) grafptr); +} + +/*+ This routine loads the given opaque graph +*** structure with the data of the given stream. +*** The base value allows the user to set the +*** graph base to 0 or 1, or to the base value +*** of the stream if the base value is equal +*** to -1. On input, vertex loads are discarded if +*** flagval is 1, edge loads are discarded if flagval +*** is 2, and both if flagval is set to 3. +*** It returns: +*** - 0 : if the loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphLoad ( +SCOTCH_Graph * const grafptr, +FILE * const stream, +const SCOTCH_Num baseval, +const SCOTCH_Num flagval) +{ + GraphFlag srcgrafflag; /* Graph flags */ + + if ((baseval < -1) || (baseval > 1)) { + errorPrint ("SCOTCH_graphLoad: invalid base parameter"); + return (1); + } + if ((flagval < 0) || (flagval > 3)) { + errorPrint ("SCOTCH_graphLoad: invalid flag parameter"); + return (1); + } + + srcgrafflag = (((flagval & 1) != 0) ? GRAPHIONOLOADVERT : 0) + + (((flagval & 2) != 0) ? GRAPHIONOLOADEDGE : 0); + + return (graphLoad ((Graph * const) grafptr, stream, (Gnum) baseval, srcgrafflag)); +} + +/*+ This routine saves the contents of the given +*** opaque graph structure to the given stream. +*** It returns: +*** - 0 : if the saving succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphSave ( +const SCOTCH_Graph * const grafptr, +FILE * const stream) +{ + return (graphSave ((const Graph * const) grafptr, stream)); +} + +/*+ This routine fills the contents of the given +*** opaque graph structure with the data provided +*** by the user. The base value allows the user to +*** set the graph base to 0 or 1. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphBuild ( +SCOTCH_Graph * const grafptr, /* Graph structure to fill */ +const SCOTCH_Num baseval, /* Base value */ +const SCOTCH_Num vertnbr, /* Number of vertices */ +const SCOTCH_Num * const verttab, /* Vertex array [vertnbr or vertnbr+1] */ +const SCOTCH_Num * const vendtab, /* Vertex end array [vertnbr] */ +const SCOTCH_Num * const velotab, /* Vertex load array */ +const SCOTCH_Num * const vlbltab, /* Vertex label array */ +const SCOTCH_Num edgenbr, /* Number of edges (arcs) */ +const SCOTCH_Num * const edgetab, /* Edge array [edgenbr] */ +const SCOTCH_Num * const edlotab) /* Edge load array */ +{ + Graph * srcgrafptr; /* Pointer to source graph structure */ + Gnum vertnum; /* Current vertex number */ + Gnum degrmax; /* Maximum degree */ + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Graph) < sizeof (Graph)) { + errorPrint ("SCOTCH_graphBuild: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + if ((baseval < 0) || (baseval > 1)) { + errorPrint ("SCOTCH_graphBuild: invalid base parameter"); + return (1); + } + + srcgrafptr = (Graph *) grafptr; /* Use structure as source graph */ + srcgrafptr->flagval = GRAPHNONE; + srcgrafptr->baseval = baseval; + srcgrafptr->vertnbr = vertnbr; + srcgrafptr->vertnnd = vertnbr + baseval; + srcgrafptr->verttax = (Gnum *) verttab - baseval; + srcgrafptr->vendtax = ((vendtab == NULL) || (vendtab == verttab)) ? srcgrafptr->verttax + 1 : (Gnum *) vendtab - baseval; + srcgrafptr->velotax = ((velotab == NULL) || (velotab == verttab)) ? NULL : (Gnum *) velotab - baseval; + srcgrafptr->vnumtax = NULL; + srcgrafptr->vlbltax = ((vlbltab == NULL) || (vlbltab == verttab)) ? NULL : (Gnum *) vlbltab - baseval; + srcgrafptr->edgenbr = edgenbr; + srcgrafptr->edgetax = (Gnum *) edgetab - baseval; + srcgrafptr->edlotax = ((edlotab == NULL) || (edlotab == edgetab)) ? NULL : (Gnum *) edlotab - baseval; + + if (srcgrafptr->velotax == NULL) /* Compute vertex load sum */ + srcgrafptr->velosum = vertnbr; + else { + Gnum velosum; /* Sum of vertex loads */ + + for (vertnum = srcgrafptr->baseval, velosum = 0; vertnum < srcgrafptr->vertnnd; vertnum ++) + velosum += srcgrafptr->velotax[vertnum]; + srcgrafptr->velosum = velosum; + } + + if (srcgrafptr->edlotax == NULL) { /* If no edge loads */ + srcgrafptr->edlosum = srcgrafptr->edgenbr; /* Edge load sum is known */ + + for (vertnum = srcgrafptr->baseval, degrmax = 0; /* Compute maximum degree only */ + vertnum < srcgrafptr->vertnnd; vertnum ++) { + Gnum degrval; /* Degree of current vertex */ + + degrval = srcgrafptr->vendtax[vertnum] - srcgrafptr->verttax[vertnum]; + if (degrval > degrmax) + degrmax = degrval; + } + } + else { /* Graph has edge loads, compute edge load sum */ + Gnum edlosum; + + for (vertnum = srcgrafptr->baseval, edlosum = degrmax = 0; + vertnum < srcgrafptr->vertnnd; vertnum ++) { + Gnum edgenum; + Gnum degrval; /* Degree of current vertex */ + + degrval = srcgrafptr->vendtax[vertnum] - srcgrafptr->verttax[vertnum]; + if (degrval > degrmax) + degrmax = degrval; + for (edgenum = srcgrafptr->verttax[vertnum]; edgenum < srcgrafptr->vendtax[vertnum]; edgenum ++) + edlosum += srcgrafptr->edlotax[edgenum]; + } + srcgrafptr->edlosum = edlosum; + } + srcgrafptr->degrmax = degrmax; + + return (0); +} + +/*+ This routine accesses graph size data. +*** NULL pointers on input indicate unwanted +*** data. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_graphSize ( +const SCOTCH_Graph * const grafptr, +SCOTCH_Num * const vertnbr, +SCOTCH_Num * const edgenbr) +{ + const Graph * srcgrafptr; + + srcgrafptr = (Graph *) grafptr; + + if (vertnbr != NULL) + *vertnbr = (SCOTCH_Num) (srcgrafptr->vertnbr); + if (edgenbr != NULL) + *edgenbr = (SCOTCH_Num) srcgrafptr->edgenbr; +} + +/*+ This routine accesses all of the graph data. +*** NULL pointers on input indicate unwanted +*** data. NULL pointers on output indicate +*** unexisting arrays. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_graphData ( +const SCOTCH_Graph * const grafptr, /* Graph structure to read */ +SCOTCH_Num * const baseptr, /* Base value */ +SCOTCH_Num * const vertptr, /* Number of vertices */ +SCOTCH_Num ** const verttab, /* Vertex array [vertnbr+1] */ +SCOTCH_Num ** const vendtab, /* Vertex array [vertnbr] */ +SCOTCH_Num ** const velotab, /* Vertex load array */ +SCOTCH_Num ** const vlbltab, /* Vertex label array */ +SCOTCH_Num * const edgeptr, /* Number of edges (arcs) */ +SCOTCH_Num ** const edgetab, /* Edge array [edgenbr] */ +SCOTCH_Num ** const edlotab) /* Edge load array */ +{ + const Graph * srcgrafptr; /* Pointer to source graph structure */ + + srcgrafptr = (const Graph *) grafptr; + + if (baseptr != NULL) + *baseptr = srcgrafptr->baseval; + if (vertptr != NULL) + *vertptr = srcgrafptr->vertnbr; + if (verttab != NULL) + *verttab = srcgrafptr->verttax + srcgrafptr->baseval; + if (vendtab != NULL) + *vendtab = srcgrafptr->vendtax + srcgrafptr->baseval; + if (velotab != NULL) + *velotab = (srcgrafptr->velotax != NULL) ? srcgrafptr->velotax + srcgrafptr->baseval : NULL; + if (vlbltab != NULL) + *vlbltab = (srcgrafptr->vlbltax != NULL) ? srcgrafptr->vlbltax + srcgrafptr->baseval : NULL; + if (edgeptr != NULL) + *edgeptr = srcgrafptr->edgenbr; + if (edgetab != NULL) + *edgetab = srcgrafptr->edgetax + srcgrafptr->baseval; + if (edlotab != NULL) + *edlotab = (srcgrafptr->edlotax != NULL) ? srcgrafptr->edlotax + srcgrafptr->baseval : NULL; +} + +/*+ This routine computes statistics +*** on the given graph. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_graphStat ( +const SCOTCH_Graph * const grafptr, +SCOTCH_Num * const velominptr, +SCOTCH_Num * const velomaxptr, +SCOTCH_Num * const velosumptr, +double * veloavgptr, +double * velodltptr, +SCOTCH_Num * const degrminptr, +SCOTCH_Num * const degrmaxptr, +double * degravgptr, +double * degrdltptr, +SCOTCH_Num * const edlominptr, +SCOTCH_Num * const edlomaxptr, +SCOTCH_Num * const edlosumptr, +double * edloavgptr, +double * edlodltptr) +{ + const Graph * srcgrafptr; + Gnum vertnum; + Gnum vertnbr; + Gnum velomin; + Gnum velomax; + double veloavg; + double velodlt; + Gnum degrval; + Gnum degrmin; + Gnum degrmax; + double degravg; + double degrdlt; + Gnum edgenum; + Gnum edlomin; + Gnum edlomax; + Gnum edlosum; + double edloavg; + double edlodlt; + + srcgrafptr = (Graph *) grafptr; + + vertnbr = srcgrafptr->vertnnd - srcgrafptr->baseval; + + velodlt = 0.0L; + if (vertnbr > 0) { + if (srcgrafptr->velotax != NULL) { /* If graph has vertex loads */ + velomin = GNUMMAX; + velomax = 0; + veloavg = (double) srcgrafptr->velosum / (double) vertnbr; + + for (vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { + if (srcgrafptr->velotax[vertnum] < velomin) /* Account for vertex loads */ + velomin = srcgrafptr->velotax[vertnum]; + if (srcgrafptr->velotax[vertnum] > velomax) + velomax = srcgrafptr->velotax[vertnum]; + velodlt += fabs ((double) srcgrafptr->velotax[vertnum] - veloavg); + } + velodlt /= (double) vertnbr; + } + else { + velomin = + velomax = 1; + veloavg = 1.0L; + } + } + else { + velomin = + velomax = 0; + veloavg = 0.0L; + } + + if (velominptr != NULL) + *velominptr = (SCOTCH_Num) velomin; + if (velomaxptr != NULL) + *velomaxptr = (SCOTCH_Num) velomax; + if (velosumptr != NULL) + *velosumptr = (SCOTCH_Num) srcgrafptr->velosum; + if (veloavgptr != NULL) + *veloavgptr = (double) veloavg; + if (velodltptr != NULL) + *velodltptr = (double) velodlt; + + degrmax = 0; + degrdlt = 0.0L; + if (vertnbr > 0) { + degrmin = GNUMMAX; + degravg = (double) srcgrafptr->edgenbr / (double) vertnbr; + for (vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { + degrval = srcgrafptr->vendtax[vertnum] - srcgrafptr->verttax[vertnum]; /* Get vertex degree */ + if (degrval < degrmin) + degrmin = degrval; + if (degrval > degrmax) + degrmax = degrval; + degrdlt += fabs ((double) degrval - degravg); + } + degrdlt /= (double) vertnbr; + } + else { + degrmin = 0; + degravg = 0.0L; + } + + if (degrminptr != NULL) + *degrminptr = (SCOTCH_Num) degrmin; + if (degrmaxptr != NULL) + *degrmaxptr = (SCOTCH_Num) degrmax; + if (degravgptr != NULL) + *degravgptr = (double) degravg; + if (degrdltptr != NULL) + *degrdltptr = (double) degrdlt; + + edlodlt = 0.0L; + if (srcgrafptr->edgenbr > 0) { + if (srcgrafptr->edlotax != NULL) { /* If graph has edge loads */ + edlomin = GNUMMAX; + edlomax = 0; + edlosum = 0; + + for (vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { + for (edgenum = srcgrafptr->verttax[vertnum]; edgenum < srcgrafptr->vendtax[vertnum]; edgenum ++) { /* For all edges */ + if (srcgrafptr->edlotax[edgenum] < edlomin) /* Account for edge load */ + edlomin = srcgrafptr->edlotax[edgenum]; + if (srcgrafptr->edlotax[edgenum] > edlomax) + edlomax = srcgrafptr->edlotax[edgenum]; + edlosum += srcgrafptr->edlotax[edgenum]; + } + } + edloavg = (double) edlosum / + (double) (2 * srcgrafptr->edgenbr); + + for (vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { + for (edgenum = srcgrafptr->verttax[vertnum]; edgenum < srcgrafptr->vendtax[vertnum]; edgenum ++) /* For all edges */ + edlodlt += fabs ((double) srcgrafptr->edlotax[edgenum] - edloavg); + } + edlodlt /= (double) srcgrafptr->edgenbr; + } + else { + edlomin = + edlomax = 1; + edlosum = srcgrafptr->edgenbr / 2; + edloavg = 1.0L; + } + } + else { + edlomin = + edlomax = 0; + edlosum = 0; + edloavg = 0.0L; + } + + if (edlominptr != NULL) + *edlominptr = (SCOTCH_Num) edlomin; + if (edlomaxptr != NULL) + *edlomaxptr = (SCOTCH_Num) edlomax; + if (edlosumptr != NULL) + *edlosumptr = (SCOTCH_Num) edlosum; + if (edloavgptr != NULL) + *edloavgptr = (double) edloavg; + if (edlodltptr != NULL) + *edlodltptr = (double) edlodlt; +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_base.c b/scotch_6.0.3/src/libscotch/library_graph_base.c new file mode 100644 index 00000000..ef803377 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_base.c @@ -0,0 +1,78 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_base.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the source **/ +/** graph handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 22 apr 2004 **/ +/** to 22 apr 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/* This routine sets the base of the given +** graph to the given base value, and returns +** the old base value. +** It returns: +** - old base value : in all cases. +*/ + +SCOTCH_Num +SCOTCH_graphBase ( +SCOTCH_Graph * const grafptr, +const SCOTCH_Num baseval) +{ + return ((SCOTCH_Num) graphBase ((Graph * const) grafptr, (Gnum) baseval)); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_base_f.c b/scotch_6.0.3/src/libscotch/library_graph_base_f.c new file mode 100644 index 00000000..23aaf755 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_base_f.c @@ -0,0 +1,76 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_base_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 22 apr 2004 **/ +/** to 23 apr 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHBASE, scotchfgraphbase, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const basenew, \ +SCOTCH_Num * const baseold), \ +(grafptr, basenew, baseold)) +{ + *baseold = SCOTCH_graphBase (grafptr, *basenew); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_check.c b/scotch_6.0.3/src/libscotch/library_graph_check.c new file mode 100644 index 00000000..49a5a87c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_check.c @@ -0,0 +1,81 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the source **/ +/** graph handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 18 aug 1998 **/ +/** to 18 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 22 apr 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph handling routines. */ +/* */ +/************************************/ + +/*+ This routine checks the consistency +*** of the given graph. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphCheck ( +const SCOTCH_Graph * const grafptr) +{ + return (graphCheck ((const Graph * const) grafptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_check_f.c b/scotch_6.0.3/src/libscotch/library_graph_check_f.c new file mode 100644 index 00000000..91f73dbc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_check_f.c @@ -0,0 +1,77 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_check_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.4 : from : 02 dec 1999 **/ +/** to 15 nov 2001 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 22 apr 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHCHECK, scotchfgraphcheck, ( \ +const SCOTCH_Graph * const grafptr, \ +int * const revaptr), \ +(grafptr, revaptr)) +{ + *revaptr = SCOTCH_graphCheck (grafptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_coarsen.c b/scotch_6.0.3/src/libscotch/library_graph_coarsen.c new file mode 100644 index 00000000..bb032f0f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_coarsen.c @@ -0,0 +1,108 @@ +/* Copyright 2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_coarsen.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the graph **/ +/** coarsening routine of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 07 aug 2011 **/ +/** to 07 aug 2011 **/ +/** # Version 6.0 : from : 06 sep 2011 **/ +/** to 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "graph.h" +#include "graph_coarsen.h" +#include "scotch.h" + +/*********************************/ +/* */ +/* This routine is the C API for */ +/* the graph coarsening routine. */ +/* */ +/*********************************/ + +/*+ This routine creates a coarse graph from the +*** given fine graph, unless the coarse graph is +*** smaller than some threshold size or the +*** coarsening ratio is above some other threshold. +*** If the coarse graph is created, a coarse-to-fine +*** vertex array is created, that contains a pair of +*** fine indices for each coarse index. The contents +*** of the Scotch internal array are copied to the +*** array provided by the user. +*** It returns: +*** - 0 : if the graph has been coarsened. +*** - 1 : if the graph could not be coarsened. +*** - 2 : on error. ++*/ + +int +SCOTCH_graphCoarsen ( +const SCOTCH_Graph * restrict const finegrafptr, /* Fine graph structure to fill */ +SCOTCH_Graph * restrict const coargrafptr, /* Coarse graph */ +SCOTCH_Num * restrict const coarmulttab, /* Pointer to multinode array */ +const SCOTCH_Num coarnbr, /* Minimum number of coarse vertices */ +const double coarval) /* Maximum contraction ratio */ +{ + GraphCoarsenMulti * restrict coarmultptr; + int o; + + intRandInit (); /* Check that random number generator is initialized */ + + o = graphCoarsen ((const Graph * restrict const) finegrafptr, (Graph * restrict const) coargrafptr, + &coarmultptr, coarnbr, coarval, NULL, NULL, 0, NULL); + + if (o == 0) { /* If coarsening succeeded */ + SCOTCH_Num coarvertnbr; + + SCOTCH_graphSize (coargrafptr, &coarvertnbr, NULL); /* Get number of coarse vertices */ + memCpy (coarmulttab, coarmultptr, coarvertnbr * 2 * sizeof (Gnum)); + } + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_coarsen_f.c b/scotch_6.0.3/src/libscotch/library_graph_coarsen_f.c new file mode 100644 index 00000000..22d58b8e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_coarsen_f.c @@ -0,0 +1,79 @@ +/* Copyright 2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_coarsen_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph coarsening routine of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 07 aug 2011 **/ +/** to 07 aug 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the coarsening routine. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHCOARSEN, scotchfgraphcoarsen, ( \ +SCOTCH_Graph * const finegrafptr, \ +SCOTCH_Graph * const coargrafptr, \ +SCOTCH_Num * const coarmulttab, \ +SCOTCH_Num * const coarnbrptr, \ +double * const coarratptr, \ +int * const revaptr), \ +(finegrafptr, coargrafptr, coarmulttab, coarnbrptr, coarratptr, revaptr)) +{ + *revaptr = SCOTCH_graphCoarsen (finegrafptr, coargrafptr, coarmulttab, *coarnbrptr, *coarratptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_color.c b/scotch_6.0.3/src/libscotch/library_graph_color.c new file mode 100644 index 00000000..df2b97f9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_color.c @@ -0,0 +1,157 @@ +/* Copyright 2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_color.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the graph **/ +/** coloring routine of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 02 jan 2012 **/ +/** to 19 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "arch.h" +#include "graph.h" +#include "graph_coarsen.h" +#include "scotch.h" + +/*********************************/ +/* */ +/* This routine is the C API for */ +/* the graph coloring routine. */ +/* */ +/*********************************/ + +/*+ This routine creates a color array for the +*** given graph. +*** It returns: +*** - 0 : if the graph has been coarsened. +*** - 1 : if the graph could not be coarsened. +*** - 2 : on error. ++*/ + +int +SCOTCH_graphColor ( +const SCOTCH_Graph * restrict const grafptr, /* Graph to color */ +SCOTCH_Num * restrict const colotab, /* Pointer to color array */ +SCOTCH_Num * restrict const coloptr, /* Pointer to number of colors */ +const SCOTCH_Num flagval) /* Flag value (not used) */ +{ + Gnum baseval; + Gnum vertnum; + Gnum vertnbr; + Gnum vertnnd; + Gnum queunnd; + Gnum * restrict queutax; + Gnum * restrict randtax; + Gnum colonum; + Gnum * restrict colotax; + + const Gnum * restrict const verttax = ((Graph *) grafptr)->verttax; + const Gnum * restrict const vendtax = ((Graph *) grafptr)->vendtax; + const Gnum * restrict const edgetax = ((Graph *) grafptr)->edgetax; + + baseval = ((Graph *) grafptr)->baseval; + vertnbr = ((Graph *) grafptr)->vertnbr; + vertnnd = vertnbr + baseval; + + memSet (colotab, ~0, vertnbr * sizeof (Gnum)); + colotax = ((Gnum *) colotab) - baseval; + + if (memAllocGroup ((void **) (void *) + &queutax, (size_t) (vertnbr * sizeof (Gnum)), + &randtax, (size_t) (vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("SCOTCH_graphColor: out of memory"); + return (1); + } + queutax -= baseval; + randtax -= baseval; + + intRandInit (); /* Check that random number generator is initialized */ + + for (vertnum = baseval; vertnum < vertnnd; vertnum ++) + randtax[vertnum] = intRandVal (32768); + + queunnd = vertnnd; + for (colonum = 0; queunnd > baseval; colonum ++) { /* Color numbers are not based */ + Gnum queuold; + Gnum queunew; + + for (queunew = queuold = baseval; queuold < queunnd; queuold ++) { + Gnum vertnum; + Gnum edgenum; + Gnum edgennd; + Gnum randval; + + vertnum = (queunnd == vertnnd) ? queuold : queutax[queuold]; + randval = randtax[vertnum]; + for (edgenum = verttax[vertnum], edgennd = vendtax[vertnum]; edgenum < edgennd; edgenum ++) { + Gnum vertend; + Gnum randend; + + vertend = edgetax[edgenum]; + + if (colotax[vertend] >= 0) + continue; + + randend = randtax[vertend]; + if ((randend > randval) || + ((randend == randval) && (vertend > vertnum))) /* Tie breaking when same random value */ + break; + } + if (edgenum >= edgennd) + colotax[vertnum] = colonum; + else + queutax[queunew ++] = vertnum; + } + queunnd = queunew; + } + + *coloptr = colonum; /* Set number of colors found */ + + memFree (queutax + baseval); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_color_f.c b/scotch_6.0.3/src/libscotch/library_graph_color_f.c new file mode 100644 index 00000000..5f9b9f37 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_color_f.c @@ -0,0 +1,78 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_coarsen_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph coloring routine of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 02 jan 2012 **/ +/** to 02 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the coloring routine. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHCOLOR, scotchfgraphcolor, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Num * const colotab, \ +SCOTCH_Num * const coloptr, \ +const SCOTCH_Num * const flagptr, \ +int * const revaptr), \ +(grafptr, colotab, coloptr, flagptr, revaptr)) +{ + *revaptr = SCOTCH_graphColor (grafptr, colotab, coloptr, *flagptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_f.c b/scotch_6.0.3/src/libscotch/library_graph_f.c new file mode 100644 index 00000000..76d49cab --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_f.c @@ -0,0 +1,291 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the source graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.4 : from : 02 dec 1999 **/ +/** to 15 nov 2001 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 17 mar 2005 **/ +/** # Version 5.0 : from : 11 jul 2007 **/ +/** to 11 jul 2007 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 15 apr 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHINIT, scotchfgraphinit, ( \ +SCOTCH_Graph * const grafptr, \ +int * const revaptr), \ +(grafptr, revaptr)) +{ + *revaptr = SCOTCH_graphInit (grafptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHEXIT, scotchfgraphexit, ( \ +SCOTCH_Graph * const grafptr), \ +(grafptr)) +{ + SCOTCH_graphExit (grafptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHFREE, scotchfgraphfree, ( \ +SCOTCH_Graph * const grafptr), \ +(grafptr)) +{ + SCOTCH_graphFree (grafptr); +} + +/* When an input stream is built from the given +** file handle, it is set as unbuffered, so as to +** allow for multiple stream reads from the same +** file handle. If it were buffered, too many +** input characters would be read on the first +** block read. +*/ + +FORTRAN ( \ +SCOTCHFGRAPHLOAD, scotchfgraphload, ( \ +SCOTCH_Graph * const grafptr, \ +int * const fileptr, \ +const SCOTCH_Num * const baseptr, \ +const SCOTCH_Num * const flagptr, \ +int * const revaptr), \ +(grafptr, fileptr, baseptr, flagptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHLOAD: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHLOAD: cannot open input stream"); + close (filenum); + *revaptr = 1; + return; + } + setbuf (stream, NULL); /* Do not buffer on input */ + + o = SCOTCH_graphLoad (grafptr, stream, *baseptr, *flagptr); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHSAVE, scotchfgraphsave, ( \ +const SCOTCH_Graph * const grafptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphSave (grafptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHBUILD, scotchfgraphbuild, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const baseptr, \ +const SCOTCH_Num * const vertptr, \ +const SCOTCH_Num * const verttab, \ +const SCOTCH_Num * const vendtab, \ +const SCOTCH_Num * const velotab, \ +const SCOTCH_Num * const vlbltab, \ +const SCOTCH_Num * const edgeptr, \ +const SCOTCH_Num * const edgetab, \ +const SCOTCH_Num * const edlotab, \ +int * const revaptr), \ +(grafptr, baseptr, vertptr, verttab, vendtab, \ + velotab, vlbltab, edgeptr, edgetab, edlotab, \ + revaptr)) +{ + *revaptr = SCOTCH_graphBuild (grafptr, *baseptr, *vertptr, verttab, vendtab, + velotab, vlbltab, *edgeptr, edgetab, edlotab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHSIZE, scotchfgraphsize, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Num * const vertptr, \ +SCOTCH_Num * const edgeptr), \ +(grafptr, vertptr, edgeptr)) +{ + SCOTCH_graphSize (grafptr, vertptr, edgeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHDATA, scotchfgraphdata, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const indxptr, \ +SCOTCH_Num * const baseptr, \ +SCOTCH_Num * const vertptr, \ +SCOTCH_Idx * const vertidx, \ +SCOTCH_Idx * const vendidx, \ +SCOTCH_Idx * const veloidx, \ +SCOTCH_Idx * const vlblidx, \ +SCOTCH_Num * const edgeptr, \ +SCOTCH_Idx * const edgeidx, \ +SCOTCH_Idx * const edloidx), \ +(grafptr, indxptr, baseptr, \ + vertptr, vertidx, vendidx, veloidx, vlblidx, \ + edgeptr, edgeidx, edloidx)) +{ + SCOTCH_Num * verttab; /* Pointer to graph arrays */ + SCOTCH_Num * vendtab; + SCOTCH_Num * velotab; + SCOTCH_Num * vlbltab; + SCOTCH_Num * edgetab; + SCOTCH_Num * edlotab; + + SCOTCH_graphData (grafptr, baseptr, vertptr, &verttab, &vendtab, &velotab, &vlbltab, + edgeptr, &edgetab, &edlotab); + *vertidx = (verttab - indxptr) + 1; /* Add 1 since Fortran indices start at 1 */ + *vendidx = (vendtab - indxptr) + 1; + *veloidx = (velotab != NULL) ? (velotab - indxptr) + 1 : *vertidx; + *vlblidx = (vlbltab != NULL) ? (vlbltab - indxptr) + 1 : *vertidx; + *edgeidx = (edgetab - indxptr) + 1; + *edloidx = (edlotab != NULL) ? (edlotab - indxptr) + 1 : *edgeidx; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHSTAT, scotchfgraphstat, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Num * const velominptr, \ +SCOTCH_Num * const velomaxptr, \ +SCOTCH_Num * const velosumptr, \ +double * veloavgptr, \ +double * velodltptr, \ +SCOTCH_Num * const degrminptr, \ +SCOTCH_Num * const degrmaxptr, \ +double * degravgptr, \ +double * degrdltptr, \ +SCOTCH_Num * const edlominptr, \ +SCOTCH_Num * const edlomaxptr, \ +SCOTCH_Num * const edlosumptr, \ +double * edloavgptr, \ +double * edlodltptr), \ +(grafptr, velominptr, velomaxptr, velosumptr, \ + veloavgptr, velodltptr, degrminptr, \ + degrmaxptr, degravgptr, degrdltptr, \ + edlominptr, edlomaxptr, edlosumptr, \ + edloavgptr, edlodltptr)) +{ + SCOTCH_graphStat (grafptr, + velominptr, velomaxptr, velosumptr, veloavgptr, velodltptr, + degrminptr, degrmaxptr, degravgptr, degrdltptr, + edlominptr, edlomaxptr, edlosumptr, edloavgptr, edlodltptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_io_chac.c b/scotch_6.0.3/src/libscotch/library_graph_io_chac.c new file mode 100644 index 00000000..9396dbdb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_io_chac.c @@ -0,0 +1,102 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_io_chac.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the Chaco **/ +/** geometry and graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 28 nov 2003 **/ +/** to 19 jan 2004 **/ +/** # Version 5.1 : from : 27 apr 2010 **/ +/** to 27 apr 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the C API for */ +/* the Chaco graph and geometry */ +/* handling routines. */ +/* */ +/*************************************/ + +/*+ This routine loads the given opaque geom +*** structure with the data of the given stream. +*** - 0 : if loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphGeomLoadChac ( +SCOTCH_Graph * restrict const grafptr, +SCOTCH_Geom * restrict const geomptr, +FILE * const filegrfptr, +FILE * const filegeoptr, +const char * const dataptr) +{ + return (graphGeomLoadChac ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); +} + +/*+ This routine saves the contents of the given +*** opaque graph structure to the given stream. +*** It returns: +*** - 0 : if the saving succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphGeomSaveChac ( +const SCOTCH_Graph * restrict const grafptr, +const SCOTCH_Geom * restrict const geomptr, +FILE * const filegrfptr, +FILE * const filegeoptr, +const char * const dataptr) +{ + return (graphGeomSaveChac ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_io_chac_f.c b/scotch_6.0.3/src/libscotch/library_graph_io_chac_f.c new file mode 100644 index 00000000..c03a37d5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_io_chac_f.c @@ -0,0 +1,174 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_io_chac_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph i/o routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 23 nov 2005 **/ +/** to 23 nov 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFGRAPHGEOMLOADCHAC, scotchfgraphgeomloadchac, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMLOADCHAC: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMLOADCHAC: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMLOADCHAC: cannot open input stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMLOADCHAC: cannot open input stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphGeomLoadChac (grafptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFGRAPHGEOMSAVECHAC, scotchfgraphgeomsavechac, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMSAVECHAC: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMSAVECHAC: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMSAVECHAC: cannot open output stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMSAVECHAC: cannot open output stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphGeomSaveChac (grafptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_io_habo.c b/scotch_6.0.3/src/libscotch/library_graph_io_habo.c new file mode 100644 index 00000000..1e4057d3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_io_habo.c @@ -0,0 +1,84 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_io_habo.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the Harwell- **/ +/** Boeing geometry and graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 18 nov 2003 **/ +/** to 19 jan 2004 **/ +/** # Version 5.1 : from : 27 apr 2010 **/ +/** to 27 apr 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the C API for */ +/* the Harwell-Boeing geometry */ +/* handling routines. */ +/* */ +/*************************************/ + +/*+ This routine loads the given opaque geom +*** structure with the data of the given stream. +*** - 0 : if loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphGeomLoadHabo ( +SCOTCH_Graph * restrict const grafptr, +SCOTCH_Geom * restrict const geomptr, +FILE * const filegrfptr, +FILE * const filegeoptr, +const char * const dataptr) +{ + return (graphGeomLoadHabo ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_io_habo_f.c b/scotch_6.0.3/src/libscotch/library_graph_io_habo_f.c new file mode 100644 index 00000000..f5935224 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_io_habo_f.c @@ -0,0 +1,119 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_io_habo_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph i/o routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 23 nov 2005 **/ +/** to 23 nov 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFGRAPHGEOMLOADHABO, scotchfgraphgeomloadhabo, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMLOADHABO: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMLOADHABO: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMLOADHABO: cannot open input stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMLOADHABO: cannot open input stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphGeomLoadHabo (grafptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_io_mmkt.c b/scotch_6.0.3/src/libscotch/library_graph_io_mmkt.c new file mode 100644 index 00000000..d07379be --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_io_mmkt.c @@ -0,0 +1,102 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_io_mmkt.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the Matrix **/ +/** Market geometry and graph handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 13 mar 2008 **/ +/** to 13 mar 2008 **/ +/** # Version 5.1 : from : 27 apr 2010 **/ +/** to 27 apr 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the C API for */ +/* the Matrix Market graph and */ +/* geometry handling routines. */ +/* */ +/*************************************/ + +/*+ This routine loads the given opaque geom +*** structure with the data of the given stream. +*** - 0 : if loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphGeomLoadMmkt ( +SCOTCH_Graph * restrict const grafptr, +SCOTCH_Geom * restrict const geomptr, +FILE * const filegrfptr, +FILE * const filegeoptr, +const char * const dataptr) +{ + return (graphGeomLoadMmkt ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); +} + +/*+ This routine saves the contents of the given +*** opaque graph structure to the given stream. +*** It returns: +*** - 0 : if the saving succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphGeomSaveMmkt ( +const SCOTCH_Graph * restrict const grafptr, +const SCOTCH_Geom * restrict const geomptr, +FILE * const filegrfptr, +FILE * const filegeoptr, +const char * const dataptr) +{ + return (graphGeomSaveMmkt ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_io_mmkt_f.c b/scotch_6.0.3/src/libscotch/library_graph_io_mmkt_f.c new file mode 100644 index 00000000..82870c4e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_io_mmkt_f.c @@ -0,0 +1,174 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_io_mmkt_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph i/o routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 5.0 : from : 14 mar 2008 **/ +/** to 14 mar 2008 **/ +/** # Version 5.1 : from : 11 oct 2008 **/ +/** to 27 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFGRAPHGEOMLOADMMKT, scotchfgraphgeomloadmmkt, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMLOADMMKT: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMLOADMMKT: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMLOADMMKT: cannot open input stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMLOADMMKT: cannot open input stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphGeomLoadMmkt (grafptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFGRAPHGEOMSAVEMMKT, scotchfgraphgeomsavemmkt, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMSAVEMMKT: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMSAVEMMKT: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMSAVEMMKT: cannot open output stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMSAVEMMKT: cannot open output stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphGeomSaveMmkt (grafptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_io_scot.c b/scotch_6.0.3/src/libscotch/library_graph_io_scot.c new file mode 100644 index 00000000..55db2fac --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_io_scot.c @@ -0,0 +1,104 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_io_scot.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the Scotch **/ +/** geometry and graph handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.4 : from : 10 oct 1999 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 18 dec 2001 **/ +/** to 19 jan 2004 **/ +/** # Version 5.1 : from : 27 apr 2010 **/ +/** to 27 apr 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the C API for */ +/* the Scotch graph and geometry */ +/* handling routines. */ +/* */ +/*************************************/ + +/*+ This routine loads the given opaque graph +*** structure with the data of the given stream. +*** - 0 : if loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphGeomLoadScot ( +SCOTCH_Graph * restrict const grafptr, +SCOTCH_Geom * restrict const geomptr, +FILE * const filegrfptr, +FILE * const filegeoptr, +const char * const dataptr) +{ + return (graphGeomLoadScot ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); +} + +/*+ This routine saves the contents of the given +*** opaque graph structure to the given stream. +*** It returns: +*** - 0 : if the saving succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphGeomSaveScot ( +const SCOTCH_Graph * restrict const grafptr, +const SCOTCH_Geom * restrict const geomptr, +FILE * const filegrfptr, +FILE * const filegeoptr, +const char * const dataptr) +{ + return (graphGeomSaveScot ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_io_scot_f.c b/scotch_6.0.3/src/libscotch/library_graph_io_scot_f.c new file mode 100644 index 00000000..2b1b4db4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_io_scot_f.c @@ -0,0 +1,174 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_io_scot_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph i/o routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 23 nov 2005 **/ +/** to 23 nov 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFGRAPHGEOMLOADSCOT, scotchfgraphgeomloadscot, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMLOADSCOT: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMLOADSCOT: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMLOADSCOT: cannot open input stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMLOADSCOT: cannot open input stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphGeomLoadScot (grafptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFGRAPHGEOMSAVESCOT, scotchfgraphgeomsavescot, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMSAVESCOT: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHGEOMSAVESCOT: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMSAVESCOT: cannot open output stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHGEOMSAVESCOT: cannot open output stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphGeomSaveScot (grafptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_map.c b/scotch_6.0.3/src/libscotch/library_graph_map.c new file mode 100644 index 00000000..1e2fc84e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_map.c @@ -0,0 +1,748 @@ +/* Copyright 2004,2007-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_map.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module is the API for the mapping **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 aug 1998 **/ +/** to 20 aug 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 30 mar 1999 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 13 jan 2004 **/ +/** to 13 nov 2005 **/ +/** # Version 5.1 : from : 29 oct 2007 **/ +/** to 24 jul 2011 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 11 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "arch_dist.h" +#include "mapping.h" +#include "kgraph.h" +#include "kgraph_map_st.h" +#include "library_mapping.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the mapping routines. */ +/* */ +/************************************/ + +/*+ This routine initializes an API opaque +*** mapping with respect to the given source +*** graph and the locations of output parameters. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMapInit ( +const SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +SCOTCH_Mapping * const mappptr, /*+ Mapping structure to initialize +*/ +const SCOTCH_Arch * const archptr, /*+ Target architecture used to map +*/ +SCOTCH_Num * const parttab) /*+ Mapping array +*/ +{ + LibMapping * restrict lmapptr; + + lmapptr = (LibMapping *) mappptr; + + lmapptr->flagval = LIBMAPPINGNONE; /* No options set */ + lmapptr->grafptr = (Graph *) grafptr; + lmapptr->archptr = (Arch *) archptr; + if (parttab == NULL) { + if ((lmapptr->parttab = (Gnum *) memAlloc (lmapptr->grafptr->vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("SCOTCH_graphMapInit: out of memory"); + return (1); + } + memSet (lmapptr->parttab, 0, lmapptr->grafptr->vertnbr * sizeof (Anum)); /* All vertices mapped to first domain */ + lmapptr->flagval |= LIBMAPPINGFREEPART; /* The user did not provided the partition array, so we will free it */ + } + else + lmapptr->parttab = (Gnum *) parttab; + + return (0); +} + +/*+ This routine frees an API mapping. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_graphMapExit ( +const SCOTCH_Graph * const grafptr, +SCOTCH_Mapping * const mappptr) +{ + LibMapping * restrict lmapptr; + + lmapptr = (LibMapping *) mappptr; + + if (((lmapptr->flagval & LIBMAPPINGFREEPART) != 0) && /* If parttab must be freed */ + (lmapptr->parttab != NULL)) /* And if exists */ + memFree (lmapptr->parttab); /* Free it */ + + memSet (lmapptr, 0, sizeof (LibMapping)); +} + +/*+ This routine computes a mapping or a +*** remapping, with or without fixed +*** vertices, of the API mapping +*** structures given in input, with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +static +int +graphMapCompute2 ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Mapping * const mappptr, /*+ Mapping to compute +*/ +SCOTCH_Mapping * const mapoptr, /*+ Old mapping +*/ +const double emraval, /*+ Edge migration ratio +*/ +const SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +const Gnum vfixnbr, /*+ Number of fixed vertices in part array +*/ +SCOTCH_Strat * const straptr) /*+ Mapping strategy +*/ +{ + Kgraph mapgrafdat; /* Effective mapping graph */ + const Strat * mapstraptr; /* Pointer to mapping strategy */ + LibMapping * restrict lmapptr; + Anum * pfixtax; + Gnum baseval; + Anum * parttax; /* Partition array */ + Anum * parotax; /* Old partition array */ + Gnum crloval; /* Coefficient load for regular edges */ + Gnum cmloval; /* Coefficient load for migration edges */ + const Gnum * vmlotax; /* Vertex migration cost array */ + Gnum vertnum; + Gnum vertnnd; + Gnum vertnbr; + int o; + + lmapptr = (LibMapping *) mappptr; +#ifdef SCOTCH_DEBUG_LIBRARY1 + if ((Graph *) grafptr != lmapptr->grafptr) { + errorPrint ("graphMapCompute2: output mapping does not correspond to input graph"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ +#ifdef SCOTCH_DEBUG_LIBRARY2 + if (graphCheck ((Graph *) grafptr) != 0) { /* Vertex loads can be 0 if we have fixed vertices */ + errorPrint ("graphMapCompute2: invalid input graph"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY2 */ + + if (*((Strat **) straptr) == NULL) { /* Set default mapping strategy if necessary */ + ArchDom domnorg; + + archDomFrst (lmapptr->archptr, &domnorg); + SCOTCH_stratGraphMapBuild (straptr, SCOTCH_STRATDEFAULT, archDomSize (lmapptr->archptr, &domnorg), 0.01); + } + + mapstraptr = *((Strat **) straptr); +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (mapstraptr->tabl != &kgraphmapststratab) { + errorPrint ("graphMapCompute2: not a graph mapping strategy"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + baseval = lmapptr->grafptr->baseval; + vertnbr = lmapptr->grafptr->vertnbr; + + if (vfixnbr != 0) { /* We have fixed vertices */ +#ifdef SCOTCH_DEBUG_LIBRARY1 + ArchDom domndat; + Gnum vertnum; + + if (lmapptr->parttab == NULL) { /* We must have fixed vertex information */ + errorPrint ("graphMapCompute2: missing output mapping part array"); + return (1); + } + for (vertnum = 0; vertnum < vertnbr; vertnum ++) { + if ((lmapptr->parttab[vertnum] >= 0) && + (archDomTerm (lmapptr->archptr, &domndat, lmapptr->parttab[vertnum]) != 0)) { + errorPrint ("graphMapCompute2: invalid fixed partition"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + pfixtax = lmapptr->parttab - baseval; + } + else + pfixtax = NULL; + + if (mapoptr != NULL) { /* We are doing a repartitioning */ + const LibMapping * restrict lmaoptr; + Gnum numeval; + Gnum denoval; +#ifdef SCOTCH_DEBUG_LIBRARY1 + ArchDom domndat; + Gnum vertnum; +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + lmaoptr = (LibMapping *) mapoptr; +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (lmapptr->grafptr != lmaoptr->grafptr) { + errorPrint ("graphMapCompute2: output and old mappings must correspond to same graph"); + return (1); + } + if (lmapptr->archptr != lmaoptr->archptr) { + errorPrint ("graphMapCompute2: output and old mappings must correspond to same architecture"); + return (1); + } + for (vertnum = 0; vertnum < vertnbr; vertnum ++) { + if ((lmaoptr->parttab[vertnum] >= 0) && + (archDomTerm (lmapptr->archptr, &domndat, lmaoptr->parttab[vertnum]) != 0)) { + errorPrint ("graphMapCompute2: invalid old partition"); + return (1); + } + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + parotax = lmaoptr->parttab - baseval; + vmlotax = (vmlotab != NULL) ? vmlotab - baseval : NULL; + numeval = (INT) ((emraval * 100.0) + 0.5); + denoval = intGcd (numeval, 100); + cmloval = numeval / denoval; + crloval = 100 / denoval; + } + else { + parotax = NULL; + vmlotax = NULL; + cmloval = + crloval = 1; + } + + intRandInit (); /* Check that random number generator is initialized */ + + if (kgraphInit (&mapgrafdat, (Graph *) grafptr, lmapptr->archptr, NULL, vfixnbr, pfixtax, parotax, crloval, cmloval, vmlotax) != 0) + return (1); + + o = 0; + if (mapgrafdat.vfixnbr < mapgrafdat.s.vertnbr) { /* Perform mapping if not all fixed vertices */ + o = kgraphMapSt (&mapgrafdat, mapstraptr); + mapTerm (&mapgrafdat.m, lmapptr->parttab - baseval); /* Propagate mapping result to part array */ + } + + kgraphExit (&mapgrafdat); + + return (o); +} + +/*+ This routine computes a mapping +*** of the API mapping structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMapCompute ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Mapping * const mappptr, /*+ Mapping to compute +*/ +SCOTCH_Strat * const straptr) /*+ Mapping strategy +*/ +{ + return (graphMapCompute2 (grafptr, mappptr, NULL, 1, NULL, 0, straptr)); +} + +/*+ This routine computes a mapping +*** with fixed vertices of the API +*** mapping structure with respect +*** to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMapFixedCompute ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Mapping * const mappptr, /*+ Mapping to compute +*/ +SCOTCH_Strat * const straptr) /*+ Mapping strategy +*/ +{ + return (SCOTCH_graphRemapFixedCompute (grafptr, mappptr, NULL, 1, NULL, straptr)); +} + +/*+ This routine computes a remapping +*** of the API mapping structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphRemapCompute ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Mapping * const mappptr, /*+ Mapping to compute +*/ +SCOTCH_Mapping * const mapoptr, /*+ Old mapping +*/ +const double emraval, /*+ Edge migration ratio +*/ +const SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +SCOTCH_Strat * const straptr) /*+ Mapping strategy +*/ +{ + return (graphMapCompute2 (grafptr, mappptr, mapoptr, emraval, vmlotab, 0, straptr)); +} + +/*+ This routine computes a remapping +*** with fixed vertices of the API +*** mapping structure with respect +*** to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphRemapFixedCompute ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Mapping * const mappptr, /*+ Mapping to compute +*/ +SCOTCH_Mapping * const mapoptr, /*+ Old mapping +*/ +const double emraval, /*+ Edge migration ratio +*/ +const SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +SCOTCH_Strat * const straptr) /*+ Mapping strategy +*/ +{ + Gnum vfixnbr; + Gnum vertnbr; + Gnum vertnum; + + const Anum * restrict const pfixtab = ((LibMapping *) mappptr)->parttab; + + for (vertnum = 0, vertnbr = ((Graph *) grafptr)->vertnbr, vfixnbr = 0; /* Compute number of fixed vertices */ + vertnum < vertnbr; vertnum ++) { + if (pfixtab[vertnum] != ~0) + vfixnbr ++; + } + + return (graphMapCompute2 (grafptr, mappptr, mapoptr, emraval, vmlotab, vfixnbr, straptr)); +} + +/*+ This routine computes a mapping of the +*** given graph structure onto the given +*** target architecture with respect to the +*** given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMap ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Arch * const archptr, /*+ Target architecture +*/ +SCOTCH_Strat * const straptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + SCOTCH_Mapping mappdat; + int o; + + SCOTCH_graphMapInit (grafptr, &mappdat, archptr, parttab); + o = SCOTCH_graphMapCompute (grafptr, &mappdat, straptr); + SCOTCH_graphMapExit (grafptr, &mappdat); + + return (o); +} + +/*+ This routine computes a mapping of the +*** given graph structure onto the given +*** target architecture with respect to the +*** given strategy and the fixed vertices in +*** maptab. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMapFixed ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Arch * const archptr, /*+ Target architecture +*/ +SCOTCH_Strat * const straptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + SCOTCH_Mapping mappdat; + int o; + + SCOTCH_graphMapInit (grafptr, &mappdat, archptr, parttab); + o = SCOTCH_graphMapFixedCompute (grafptr, &mappdat, straptr); + SCOTCH_graphMapExit (grafptr, &mappdat); + + return (o); +} + +/*+ This routine computes a remapping of the +*** given graph structure onto the given +*** target architecture with respect to the +*** given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphRemap ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Arch * const archptr, /*+ Target architecture +*/ +SCOTCH_Num * const parotab, /*+ Old partition array +*/ +const double emraval, /*+ Edge migration ratio +*/ +const SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +SCOTCH_Strat * const straptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + SCOTCH_Mapping mappdat; + SCOTCH_Mapping mapodat; + int o; + + SCOTCH_graphMapInit (grafptr, &mappdat, archptr, parttab); + SCOTCH_graphMapInit (grafptr, &mapodat, archptr, parotab); + o = SCOTCH_graphRemapCompute (grafptr, &mappdat, &mapodat, emraval, vmlotab, straptr); + SCOTCH_graphMapExit (grafptr, &mapodat); + SCOTCH_graphMapExit (grafptr, &mappdat); + + return (o); +} + +/*+ This routine computes a remapping of the +*** given graph structure onto the given +*** target architecture with respect to the +*** given strategy and the fixed vertices in +*** maptab. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphRemapFixed ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Arch * const archptr, /*+ Target architecture +*/ +SCOTCH_Num * const parotab, /*+ Old partition array +*/ +const double emraval, /*+ Edge migration ratio +*/ +const SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +SCOTCH_Strat * const straptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + SCOTCH_Mapping mappdat; + SCOTCH_Mapping mapodat; + int o; + + SCOTCH_graphMapInit (grafptr, &mappdat, archptr, parttab); + SCOTCH_graphMapInit (grafptr, &mapodat, archptr, parotab); + o = SCOTCH_graphRemapFixedCompute (grafptr, &mappdat, &mapodat, emraval, vmlotab, straptr); + SCOTCH_graphMapExit (grafptr, &mapodat); + SCOTCH_graphMapExit (grafptr, &mappdat); + + return (o); +} + +/*+ This routine computes a partition of +*** the given graph structure with respect +*** to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphPart ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Num partnbr, /*+ Number of parts +*/ +SCOTCH_Strat * const straptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + SCOTCH_Arch archdat; + int o; + + SCOTCH_archInit (&archdat); + SCOTCH_archCmplt (&archdat, partnbr); + o = SCOTCH_graphMap (grafptr, &archdat, straptr, parttab); + SCOTCH_archExit (&archdat); + + return (o); +} + +/*+ This routine computes a partition of +*** the given graph structure with respect +*** to the given strategy and the fixed +*** vertices in maptab. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphPartFixed ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Num partnbr, /*+ Number of parts +*/ +SCOTCH_Strat * const straptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + SCOTCH_Arch archdat; + int o; + + SCOTCH_archInit (&archdat); + SCOTCH_archCmplt (&archdat, partnbr); + o = SCOTCH_graphMapFixed (grafptr, &archdat, straptr, parttab); + SCOTCH_archExit (&archdat); + + return (o); +} + +/*+ This routine computes a repartitionning +*** of the given graph structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphRepart ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Num partnbr, /*+ Number of parts +*/ +SCOTCH_Num * const parotab, /*+ Old partition array +*/ +const double emraval, /*+ Edge migration ratio +*/ +const SCOTCH_Num * const vmlotab, /*+ Vertex migration cost array +*/ +SCOTCH_Strat * const straptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + SCOTCH_Arch archdat; + int o; + + SCOTCH_archInit (&archdat); + SCOTCH_archCmplt (&archdat, partnbr); + o = SCOTCH_graphRemap (grafptr, &archdat, parotab, emraval, vmlotab, straptr, parttab); + SCOTCH_archExit (&archdat); + + return (o); +} + +/*+ This routine computes a repartitionning +*** of the given graph structure with +*** respect to the given strategy and the +*** fixed vertices in maptab. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphRepartFixed ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Num partnbr, /*+ Number of parts +*/ +SCOTCH_Num * const parotab, /*+ Old partition array +*/ +const double emraval, /*+ Edge migration ratio +*/ +const SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +SCOTCH_Strat * const straptr, /*+ Mapping strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + SCOTCH_Arch archdat; + int o; + + SCOTCH_archInit (&archdat); + SCOTCH_archCmplt (&archdat, partnbr); + o = SCOTCH_graphRemapFixed (grafptr, &archdat, parotab, emraval, vmlotab, straptr, parttab); + SCOTCH_archExit (&archdat); + + return (o); +} + +/*+ This routine parses the given +*** mapping strategy. +*** It returns: +*** - 0 : if string successfully scanned. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratGraphMap ( +SCOTCH_Strat * const straptr, +const char * const string) +{ + if (*((Strat **) straptr) != NULL) + stratExit (*((Strat **) straptr)); + + if ((*((Strat **) straptr) = stratInit (&kgraphmapststratab, string)) == NULL) { + errorPrint ("SCOTCH_stratGraphMap: error in mapping strategy"); + return (1); + } + + return (0); +} + +/*+ This routine provides predefined +*** mapping strategies. +*** It returns: +*** - 0 : if string successfully initialized. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratGraphMapBuild ( +SCOTCH_Strat * const straptr, /*+ Strategy to create +*/ +const SCOTCH_Num flagval, /*+ Desired characteristics +*/ +const SCOTCH_Num partnbr, /*+ Number of expected parts/size +*/ +const double kbalval) /*+ Desired imbalance ratio +*/ +{ + char bufftab[8192]; /* Should be enough */ + char bbaltab[64]; + char kbaltab[64]; + char kmovtab[64]; + char mvrttab[64]; + Gunum parttmp; /* "Unsigned" so that ">>" will always insert "0"s */ + const char * difkptr; + const char * difsptr; + const char * exasptr; + const char * exaxptr; + + sprintf (bbaltab, "%lf", kbalval); + sprintf (kbaltab, "%lf", kbalval); + sprintf (kmovtab, GNUMSTRING, ((flagval & SCOTCH_STRATQUALITY) != 0) ? 200 : 80); + sprintf (mvrttab, GNUMSTRING, MAX ((20 * partnbr), 10000)); + + strcpy (bufftab, ((flagval & SCOTCH_STRATRECURSIVE) != 0) + ? "" /* Use only the recursive bipartitioning framework */ + : "m{vert=,low=,asc=b{bnd=f{bal=,move=},org=f{bal=,move=}}}"); + stringSubst (bufftab, "", "r{job=t,map=t,poli=S,bal=,sep=}"); + stringSubst (bufftab, "", ((flagval & SCOTCH_STRATQUALITY) != 0) ? "||" : "|"); + stringSubst (bufftab, "", "m{vert=120,low=h{pass=10}f{bal=,move=120},asc=b{bnd=f{bal=,move=120},org=f{bal=,move=120}}}"); + + if ((flagval & SCOTCH_STRATSAFETY) != 0) + difsptr = ""; + else + difsptr = "d{pass=40}"; + difkptr = "d{pass=40}"; + + if ((flagval & SCOTCH_STRATBALANCE) != 0) { + exasptr = "f{bal=}"; + exaxptr = "x{bal=}f{bal=,move=}"; + } + else { + exasptr = ""; + exaxptr = ""; + } + + stringSubst (bufftab, "", mvrttab); + stringSubst (bufftab, "", exaxptr); + stringSubst (bufftab, "", exasptr); + stringSubst (bufftab, "", difsptr); + stringSubst (bufftab, "", difkptr); + stringSubst (bufftab, "", kmovtab); + stringSubst (bufftab, "", kbaltab); + stringSubst (bufftab, "", bbaltab); + + if (SCOTCH_stratGraphMap (straptr, bufftab) != 0) { + errorPrint ("SCOTCH_stratGraphMapBuild: error in sequential mapping strategy"); + return (1); + } + + return (0); +} + +/*+ This routine provides predefined +*** clustering strategies. +*** It returns: +*** - 0 : if string successfully initialized. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratGraphClusterBuild ( +SCOTCH_Strat * const straptr, /*+ Strategy to create +*/ +const SCOTCH_Num flagval, /*+ Desired characteristics +*/ +const SCOTCH_Num pwgtval, /*+ Threshold part weight +*/ +const double densval, /*+ Threshold density value +*/ +const double bbalval) /*+ Maximum imbalance ratio +*/ +{ + char bufftab[8192]; /* Should be enough */ + char bbaltab[32]; + char pwgttab[32]; + char denstab[32]; + char * difsptr; + char * exasptr; + + sprintf (bbaltab, "%lf", bbalval); + sprintf (denstab, "%lf", densval); + sprintf (pwgttab, GNUMSTRING, pwgtval); + + strcpy (bufftab, "r{job=u,map=t,poli=L,sep=/((load>)&!(edge>vert**(vert-1)))?(m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}});}"); + stringSubst (bufftab, "", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" + : "m{vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}}|"); + + if ((flagval & SCOTCH_STRATBALANCE) != 0) + exasptr = "f{bal=0}"; + else + exasptr = ""; + + if ((flagval & SCOTCH_STRATSAFETY) != 0) + difsptr = ""; + else + difsptr = "(d{pass=40}|)"; + + stringSubst (bufftab, "", exasptr); + stringSubst (bufftab, "", difsptr); + stringSubst (bufftab, "", bbaltab); + stringSubst (bufftab, "", denstab); + stringSubst (bufftab, "", pwgttab); + + if (SCOTCH_stratGraphMap (straptr, bufftab) != 0) { + errorPrint ("SCOTCH_stratGraphClusterBuild: error in sequential mapping strategy"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_map_f.c b/scotch_6.0.3/src/libscotch/library_graph_map_f.c new file mode 100644 index 00000000..124c4b33 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_map_f.c @@ -0,0 +1,363 @@ +/* Copyright 2004,2007,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_map_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** mapping routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 3.4 : from : 02 dec 1999 **/ +/** to 15 nov 2001 **/ +/** # Version 4.0 : from : 12 jan 2004 **/ +/** to 12 dec 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 31 aug 2011 **/ +/** # Version 6.0 : from : 17 apr 2011 **/ +/** to 23 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* +** +*/ +/* TODO update fortran interface... */ +FORTRAN ( \ +SCOTCHFGRAPHMAPINIT, scotchfgraphmapinit, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Mapping * const mappptr, \ +const SCOTCH_Arch * const archptr, \ +SCOTCH_Num * const mapptab, \ +int * const revaptr), \ +(grafptr, mappptr, archptr, mapptab, revaptr)) +{ + *revaptr = SCOTCH_graphMapInit (grafptr, mappptr, archptr, mapptab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHMAPEXIT, scotchfgraphmapexit, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Mapping * const mappptr), \ +(grafptr, mappptr)) +{ + SCOTCH_graphMapExit (grafptr, mappptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHMAPCOMPUTE, scotchfgraphmapcompute, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Mapping * const mappptr, \ +SCOTCH_Strat * const straptr, \ +int * const revaptr), \ +(grafptr, mappptr, straptr, revaptr)) +{ + *revaptr = SCOTCH_graphMapCompute (grafptr, mappptr, straptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHMAPFIXEDCOMPUTE, scotchfgraphmapfixedcompute, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Mapping * const mappptr, \ +SCOTCH_Strat * const straptr, \ +int * const revaptr), \ +(grafptr, mappptr, straptr, revaptr)) +{ + *revaptr = SCOTCH_graphMapFixedCompute (grafptr, mappptr, straptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHREMAPCOMPUTE, scotchfgraphremapcompute, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Mapping * const mappptr, \ +SCOTCH_Mapping * const mapoptr, \ +const double * const emraptr, \ +const SCOTCH_Num * const vmlotab, \ +SCOTCH_Strat * const straptr, \ +int * const revaptr), \ +(grafptr, mappptr, mapoptr, emraptr, vmlotab, straptr, revaptr)) +{ + *revaptr = SCOTCH_graphRemapCompute (grafptr, mappptr, mapoptr, *emraptr, vmlotab, straptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHREMAPFIXEDCOMPUTE, scotchfgraphremapfixedcompute, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Mapping * const mappptr, \ +SCOTCH_Mapping * const mapoptr, \ +const double * const emraptr, \ +const SCOTCH_Num * const vmlotab, \ +SCOTCH_Strat * const straptr, \ +int * const revaptr), \ +(grafptr, mappptr, mapoptr, emraptr, vmlotab, straptr, revaptr)) +{ + *revaptr = SCOTCH_graphRemapFixedCompute (grafptr, mappptr, mapoptr, *emraptr, vmlotab, straptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHMAP, scotchfgraphmap, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Arch * const archptr, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const parttab, \ +int * const revaptr), \ +(grafptr, archptr, straptr, parttab, revaptr)) +{ + *revaptr = SCOTCH_graphMap (grafptr, archptr, straptr, parttab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHMAPFIXED, scotchfgraphmapfixed, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Arch * const archptr, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const parttab, \ +int * const revaptr), \ +(grafptr, archptr, straptr, parttab, revaptr)) +{ + *revaptr = SCOTCH_graphMapFixed (grafptr, archptr, straptr, parttab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHREMAP, scotchfgraphremap, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Arch * const archptr, \ +SCOTCH_Num * const parotab, \ +const double * const emraptr, \ +const SCOTCH_Num * const vmlotab, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const parttab, \ +int * const revaptr), \ +(grafptr, archptr, parotab, emraptr, vmlotab, straptr, parttab, revaptr)) +{ + *revaptr = SCOTCH_graphRemap (grafptr, archptr, parotab, *emraptr, vmlotab, straptr, parttab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHREMAPFIXED, scotchfgraphremapfixed, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Arch * const archptr, \ +SCOTCH_Num * const parotab, \ +const double * const emraptr, \ +const SCOTCH_Num * const vmlotab, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const parttab, \ +int * const revaptr), \ +(grafptr, archptr, parotab, emraptr, vmlotab, straptr, parttab, revaptr)) +{ + *revaptr = SCOTCH_graphRemapFixed (grafptr, archptr, parotab, *emraptr, vmlotab, straptr, parttab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHPART, scotchfgraphpart, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const partptr, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const mapptab, \ +int * const revaptr), \ +(grafptr, partptr, straptr, mapptab, revaptr)) +{ + *revaptr = SCOTCH_graphPart (grafptr, *partptr, straptr, mapptab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHPARTFIXED, scotchfgraphpartfixed, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const partptr, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const mapptab, \ +int * const revaptr), \ +(grafptr, partptr, straptr, mapptab, revaptr)) +{ + *revaptr = SCOTCH_graphPartFixed (grafptr, *partptr, straptr, mapptab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHREPART, scotchfgraphrepart, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const partptr, \ +SCOTCH_Num * const parotab, \ +const double * const emraptr, \ +const SCOTCH_Num * const vmlotab, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const mapptab, \ +int * const revaptr), \ +(grafptr, partptr, parotab, emraptr, vmlotab, straptr, mapptab, revaptr)) +{ + *revaptr = SCOTCH_graphRepart (grafptr, *partptr, parotab, *emraptr, vmlotab, straptr, mapptab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHREPARTFIXED, scotchfgraphrepartfixed, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const partptr, \ +SCOTCH_Num * const parotab, \ +const double * const emraptr, \ +const SCOTCH_Num * const vmlotab, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const mapptab, \ +int * const revaptr), \ +(grafptr, partptr, parotab, emraptr, vmlotab, straptr, mapptab, revaptr)) +{ + *revaptr = SCOTCH_graphRepartFixed (grafptr, *partptr, parotab, *emraptr, vmlotab, straptr, mapptab); +} + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFSTRATGRAPHMAP, scotchfstratgraphmap, ( \ +SCOTCH_Strat * const stratptr, \ +const char * const string, \ +int * const revaptr, \ +const int strnbr), \ +(stratptr, string, revaptr, strnbr)) +{ + char * restrict strtab; /* Pointer to null-terminated string */ + + if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ + errorPrint ("SCOTCHFSTRATGRAPHMAP: out of memory (1)"); + *revaptr = 1; + } + memCpy (strtab, string, strnbr); /* Copy string contents */ + strtab[strnbr] = '\0'; /* Terminate string */ + + *revaptr = SCOTCH_stratGraphMap (stratptr, strtab); /* Call original routine */ + + memFree (strtab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATGRAPHMAPBUILD, scotchfstratgraphmapbuild, ( \ +SCOTCH_Strat * const stratptr, \ +const SCOTCH_Num * const flagval, \ +const SCOTCH_Num * const partnbr, \ +const double * const kbalptr, \ +int * const revaptr), \ +(stratptr, flagval, partnbr, kbalptr, revaptr)) +{ + *revaptr = SCOTCH_stratGraphMapBuild (stratptr, *flagval, *partnbr, *kbalptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATGRAPHCLUSTERBUILD, scotchfstratgraphclusterbuild, ( \ +SCOTCH_Strat * const stratptr, \ +const SCOTCH_Num * const flagval, \ +const SCOTCH_Num * const pwgtval, \ +const double * const densval, \ +const double * const bbalptr, \ +int * const revaptr), \ +(stratptr, flagval, pwgtval, densval, bbalptr, revaptr)) +{ + *revaptr = SCOTCH_stratGraphClusterBuild (stratptr, *flagval, *pwgtval, *densval, *bbalptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_map_io.c b/scotch_6.0.3/src/libscotch/library_graph_map_io.c new file mode 100644 index 00000000..817cc199 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_map_io.c @@ -0,0 +1,257 @@ +/* Copyright 2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_map_io.c **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the API mappings **/ +/** of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 16 apr 2011 **/ +/** to 23 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "library_mapping.h" +#include "library_graph_map_io.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the C API for */ +/* the API mapping handling */ +/* routines. */ +/* */ +/*************************************/ + +/*+ This routine loads the contents of the +*** given mapping array from the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphTabLoad ( +const SCOTCH_Graph * const actgrafptr, /*+ Graph to map +*/ +SCOTCH_Num * const parttab, /*+ Array to load +*/ +FILE * const stream) /*+ Input stream +*/ +{ + VertSort * vertsorttab; /* Pointer to graph sorting array */ + int vertsortflag; /* Flag set if graph data sorted by label */ + VertSort * mappsorttab; /* Pointer to mapping data sorting array */ + int mappsortflag; /* Flag set if mapping data sorted by label */ + Gnum mappsortval; + Gnum mappfileval; + Gnum mappfilenbr; /* Number of mapping pairs in file */ + Gnum mappfilenum; /* Counter of mapping pairs in file */ + Gnum * mappfiletab; /* Pointer to mapping data read from file */ + Graph * grafptr; + Gnum vertnum; + Gnum i, j; + + grafptr = (Graph *) actgrafptr; + memSet (parttab, ~0, grafptr->vertnbr * sizeof (Anum)); /* Pre-initialize the partition array */ + + if ((fscanf (stream, GNUMSTRING,&mappfileval) != 1) || /* Read number of mapping pairs */ + (mappfileval < 1)) { + errorPrint ("SCOTCH_graphTabLoad: bad input (1)"); + return (1); + } + mappfilenbr = (Gnum) mappfileval; + + if (memAllocGroup ((void **) (void *) /* Allocate temporary data */ + &mappfiletab, (size_t) (mappfilenbr * sizeof (Gnum)), + &mappsorttab, (size_t) (mappfilenbr * sizeof (VertSort)), + &vertsorttab, (size_t) (grafptr->vertnbr * sizeof (VertSort)), NULL) == NULL) { + errorPrint ("SCOTCH_graphTabLoad: out of memory (1)"); + return (1); + } + + mappsortflag = 1; /* Assume mapping data sorted */ + for (mappfilenum = 0; mappfilenum < mappfilenbr; mappfilenum ++) { + if (fscanf (stream, GNUMSTRING GNUMSTRING, + &mappsortval, + &mappfileval) != 2) { + errorPrint ("SCOTCH_graphTabLoad: bad input (2)"); + memFree (mappfiletab); /* Free group leader */ + return (1); + } + mappsorttab[mappfilenum].labl = mappsortval; + mappsorttab[mappfilenum].num = mappfilenum; + mappfiletab[mappfilenum] = mappfileval; + + if ((mappfilenum > 0) && /* Check if mapping data sorted */ + (mappsorttab[mappfilenum].labl < mappsorttab[mappfilenum - 1].labl)) + mappsortflag = 0; /* Mapping data not sorted */ + } + if (mappsortflag != 1) /* If mapping data not sorted */ + intSort2asc1 (mappsorttab, mappfilenbr); /* Sort area by ascending labels */ + for (mappfilenum = 1; mappfilenum < mappfilenbr; mappfilenum ++) { /* Check mapping data integrity */ + if (mappsorttab[mappfilenum].labl == mappsorttab[mappfilenum - 1].labl) { + errorPrint ("SCOTCH_graphTabLoad: duplicate vertex label"); + memFree (mappfiletab); /* Free group leader */ + return (1); + } + } + + if (grafptr->vlbltax != NULL) { /* If graph has vertex labels */ + vertsortflag = 1; /* Assume graph data sorted */ + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { + vertsorttab[vertnum].labl = grafptr->vlbltax[vertnum]; + vertsorttab[vertnum].num = vertnum; + if ((vertnum > 0) && /* Check if graph data sorted */ + (vertsorttab[vertnum].labl < vertsorttab[vertnum - 1].labl)) + vertsortflag = 0; /* Graph data not sorted */ + } + if (vertsortflag != 1) /* If graph data not sorted */ + intSort2asc1 (vertsorttab, grafptr->vertnbr); /* Sort sort area by ascending labels */ + } + else { /* Graph does not have vertex labels */ + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { + vertsorttab[vertnum].labl = vertnum + mappsorttab[0].labl; /* Use first index as base value */ + vertsorttab[vertnum].num = vertnum; + } + } + + for (vertnum = 0, mappfilenum = 0; vertnum < grafptr->vertnbr; vertnum ++) { /* For all vertices in graph */ + while ((mappfilenum < mappfilenbr) && (mappsorttab[mappfilenum].labl < vertsorttab[vertnum].labl)) + mappfilenum ++; /* Search mapping vertex with same label */ + if ((mappfilenum >= mappfilenbr) || (mappsorttab[mappfilenum].labl > vertsorttab[vertnum].labl)) /* If label does not exist */ + continue; /* This vertex has no related mapping data */ + ((Anum *) parttab)[vertsorttab[vertnum].num] = mappfiletab[mappsorttab[mappfilenum ++].num]; + } + + memFree (mappfiletab); /* Free group leader */ + + return (0); +} + +/*+ This routine loads the contents of +*** the given user mapping from the +*** given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMapLoad ( +const SCOTCH_Graph * const actgrafptr, /*+ Graph to map +*/ +const SCOTCH_Mapping * const mappptr, /*+ Mapping to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + Graph * grafptr; + LibMapping * restrict lmapptr; + + grafptr = (Graph *) actgrafptr; + lmapptr = (LibMapping *) mappptr; +#ifdef SCOTCH_DEBUG_GRAPH2 + if (grafptr != lmapptr->grafptr) { + errorPrint ("SCOTCH_graphMapLoad: mapping structure must derive from graph"); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + if (lmapptr->parttab == NULL) { /* Allocate array if necessary */ + if ((lmapptr->parttab = (Gnum *) memAlloc (grafptr->vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("SCOTCH_graphMapLoad: out of memory"); + return (1); + } + lmapptr->flagval |= LIBMAPPINGFREEPART; /* As the array was not allocated by the user, it will be freed */ + } + + return (SCOTCH_graphTabLoad (actgrafptr, (SCOTCH_Num *) lmapptr->parttab, stream)); +} + +/*+ This routine saves the contents of +*** the given user mapping to the given +*** stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMapSave ( +const SCOTCH_Graph * const actgrafptr, /*+ Graph to map +*/ +const SCOTCH_Mapping * const mappptr, /*+ Mapping to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + Graph * grafptr; + LibMapping * restrict lmapptr; + Gnum vertnum; + Gnum baseval; + + grafptr = (Graph *) actgrafptr; + lmapptr = (LibMapping *) mappptr; +#ifdef SCOTCH_DEBUG_GRAPH2 + if (grafptr != lmapptr->grafptr) { + errorPrint ("SCOTCH_graphMapSave: mapping structure must derive from graph"); + return (1); + } +#endif /* SCOTCH_DEBUG_GRAPH2 */ + + const Gnum * restrict vlbltax = grafptr->vlbltax; + const Gnum * restrict parttab = lmapptr->parttab; + + if (fprintf (stream, GNUMSTRING "\n", + (Gnum) grafptr->vertnbr) == EOF) { + errorPrint ("SCOTCH_graphMapSave: bad output (1)"); + return (1); + } + + baseval = grafptr->baseval; + for (vertnum = baseval; vertnum < grafptr->vertnnd; vertnum ++) { + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) ((vlbltax != NULL) ? vlbltax[vertnum] : vertnum), + (Gnum) parttab[vertnum - baseval]) == EOF) { + errorPrint ("SCOTCH_graphMapSave: bad output (2)"); + return (1); + } + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_map_io.h b/scotch_6.0.3/src/libscotch/library_graph_map_io.h new file mode 100644 index 00000000..8bc3e1dd --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_map_io.h @@ -0,0 +1,57 @@ +/* Copyright 2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_map_io.h **/ +/** **/ +/** AUTHOR : Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the declarations for **/ +/** the API mapping handling routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 17 apr 2011 **/ +/** to 17 apr 2011 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ The sort structure, used to sort graph + vertices by label. +*/ + +typedef struct VertSort_ { + Gnum labl; /*+ Vertex label +*/ + Gnum num; /*+ Vertex number +*/ +} VertSort; + diff --git a/scotch_6.0.3/src/libscotch/library_graph_map_io_f.c b/scotch_6.0.3/src/libscotch/library_graph_map_io_f.c new file mode 100644 index 00000000..a2473c47 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_map_io_f.c @@ -0,0 +1,165 @@ +/* Copyright 2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_map_io_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph i/o routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 03 jul 2012 **/ +/** to 23 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +FORTRAN ( \ +SCOTCHFGRAPHTABLOAD, scotchfgraphtabload, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Num * const parttab, \ +const int * const fileptr, \ +int * const revaptr), \ +(grafptr, parttab, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHTABLOAD: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHTABLOAD: cannot open input stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphTabLoad (grafptr, parttab, stream); + + fclose (stream); /* This closes file descriptor too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHMAPLOAD, scotchfgraphmapload, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Mapping * const mappptr, \ +const int * const fileptr, \ +int * const revaptr), \ +(grafptr, mappptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHMAPLOAD: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHMAPLOAD: cannot open input stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphMapLoad (grafptr, mappptr, stream); + + fclose (stream); /* This closes file descriptor too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHMAPSAVE, scotchfgraphmapsave, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Mapping * const mappptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, mappptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHMAPSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHMAPSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphMapSave (grafptr, mappptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_map_view.c b/scotch_6.0.3/src/libscotch/library_graph_map_view.c new file mode 100644 index 00000000..2e5491f0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_map_view.c @@ -0,0 +1,652 @@ +/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_map_view.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module is the API for the mapping **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 aug 1998 **/ +/** to 20 aug 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 30 mar 1999 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 13 jan 2004 **/ +/** to 30 nov 2006 **/ +/** # Version 5.0 : from : 04 feb 2007 **/ +/** to 03 apr 2008 **/ +/** # Version 5.1 : from : 27 jul 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 03 mar 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY +#define LIBRARY_GRAPH_MAP_VIEW + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "kgraph.h" +#include "library_mapping.h" +#include "library_graph_map_view.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the mapping routines. */ +/* */ +/************************************/ + +/*+ This routine writes standard or raw +*** mapping or remapping statistics to +*** the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +static +int +graphMapView2 ( +const SCOTCH_Graph * const libgrafptr, /*+ Ordered graph +*/ +const SCOTCH_Mapping * const libmappptr, /*+ Computed mapping +*/ +const SCOTCH_Mapping * const libmapoptr, /*+ Old mapping (equal to NULL if no repartitioning) +*/ +const double emraval, /*+ Edge migration ratio +*/ +SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +Gnum flagval, /*+ 0 : standard output, !0 : raw output for curves +*/ +FILE * const stream) /*+ Output stream +*/ +{ + const Graph * restrict grafptr; + const Arch * restrict archptr; + LibMapping * restrict lmapptr; + LibMapping * restrict lmaoptr; + Mapping mappdat; + Anum * restrict parttax; /* Part array */ + Anum * restrict parotax; /* Old part array */ + MappingSort * restrict domntab; /* Pointer to domain sort array */ + ArchDom domnfrst; /* Largest domain in architecture */ + ArchDom domnorg; /* Vertex domain */ + ArchDom domnend; /* End domain */ + ArchDom domnold; /* Vertex old domain */ + Anum tgtnbr; /* Number of processors in target topology */ + Anum mapnbr; /* Number of processors effectively used */ + Anum mapnum; + double mapavg; /* Average mapping weight */ + Gnum mapmin; + Gnum mapmax; + Gnum mapsum; /* (Partial) sum of vertex loads */ + double mapdlt; + double mapmmy; /* Maximum / average ratio */ + Anum * restrict nghbtab; /* Table storing neighbors of current subdomain */ + Anum nghbnbr; + Anum nghbmin; + Anum nghbmax; + Anum nghbsum; + Gnum vertnum; + Gnum veloval; + Gnum edloval; + Gnum commdist[256]; /* Array of load distribution */ + Gnum commload; /* Total edge load (edge sum) */ + Gnum commdilat; /* Total edge dilation */ + Gnum commexpan; /* Total edge expansion */ + Anum distmax; + Anum distval; + Gnum diammin; + Gnum diammax; + Gnum diamsum; + Gnum migrnbr; + double migrloadavg; + double migrdistavg; + double migrcostsum; + Gnum * restrict vmlotax; + + const Gnum * restrict const verttax = ((Graph *) libgrafptr)->verttax; + const Gnum * restrict const vendtax = ((Graph *) libgrafptr)->vendtax; + const Gnum * restrict const velotax = ((Graph *) libgrafptr)->velotax; + const Gnum * restrict const edgetax = ((Graph *) libgrafptr)->edgetax; + const Gnum * restrict const edlotax = ((Graph *) libgrafptr)->edlotax; + + if (vmlotab != NULL) + vmlotax = (Gnum *) vmlotab - grafptr->baseval; + else + vmlotax = NULL; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Mapping) < sizeof (LibMapping)) { + errorPrint ("SCOTCH_graphMapView: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + lmapptr = (LibMapping *) libmappptr; + grafptr = lmapptr->grafptr; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if ((Graph *) libgrafptr != grafptr) { + errorPrint ("SCOTCH_graphMapView: the graph given in input must be the same than the one in the mapping"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + if (libmapoptr != NULL) { + lmaoptr = (LibMapping *) libmapoptr; + parotax = lmaoptr->parttab; + } + else { + lmaoptr = NULL; + parotax = NULL; + } + + if ((grafptr->vertnbr == 0) || /* Return if nothing to do */ + (grafptr->edgenbr == 0)) + return (0); + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (lmapptr->parttab == NULL) { + errorPrint ("SCOTCH_graphMapView: the mapping given in input must contain a valid partition array"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + archptr = lmapptr->archptr; + parttax = lmapptr->parttab; + + if (memAllocGroup ((void **) (void *) + &domntab, (size_t) ((grafptr->vertnbr + 1) * sizeof (MappingSort)), + &nghbtab, (size_t) ((grafptr->vertnbr + 2) * sizeof (Anum)), NULL) == NULL) { + errorPrint ("SCOTCH_graphMapView: out of memory"); + return (1); + } + + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { + domntab[vertnum].labl = parttax[vertnum]; + domntab[vertnum].peri = vertnum + grafptr->baseval; /* Build inverse permutation */ + } + parttax -= grafptr->baseval; + domntab[grafptr->vertnbr].labl = ARCHDOMNOTTERM; /* TRICK: avoid testing (i+1) */ + domntab[grafptr->vertnbr].peri = ~0; /* Prevent Valgrind from yelling */ + + intSort2asc2 (domntab, grafptr->vertnbr); /* Sort domain label array by increasing target labels */ + + archDomFrst (archptr, &domnfrst); /* Get architecture domain */ + tgtnbr = archDomSize (archptr, &domnfrst); /* Get architecture size */ + + mapsum = 0; + mapnbr = 0; + veloval = 1; /* Assume unweighted vertices */ + for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { + parttax[domntab[vertnum].peri] = mapnbr; /* Build map of partition parts starting from 0 */ + if (domntab[vertnum].labl != domntab[vertnum + 1].labl) /* TRICK: if new (or end) domain label */ + mapnbr ++; + if (velotax != NULL) + veloval = velotax[domntab[vertnum].peri]; + mapsum += veloval; + } + mapavg = (mapnbr == 0) ? 0.0L : (double) mapsum / (double) mapnbr; + + mapsum = 0; + mapmin = GNUMMAX; + mapmax = 0; + mapdlt = 0.0L; + for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { + if (velotax != NULL) + veloval = velotax[domntab[vertnum].peri]; + mapsum += veloval; + + if (domntab[vertnum].labl != domntab[vertnum + 1].labl) { /* TRICK: if new (or end) domain label */ + if (mapsum < mapmin) + mapmin = mapsum; + if (mapsum > mapmax) + mapmax = mapsum; + mapdlt += fabs ((double) mapsum - mapavg); + mapsum = 0; /* Reset domain load sum */ + } + } + mapdlt = (mapnbr != 0) ? mapdlt / ((double) mapnbr * mapavg) : 0.0L; + mapmmy = (mapnbr != 0) ? (double) mapmax / (double) mapavg : 0.0L; + + if (mapnbr > tgtnbr) { /* If more subdomains than architecture size */ +#ifdef SCOTCH_DEBUG_MAP2 + if (! archVar (archptr)) { /* If not a variable-sized architecture */ + errorPrint ("SCOTCH_graphMapView: invalid mapping"); + memFree (domntab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_MAP2 */ + tgtnbr = mapnbr; /* Assume it is a variable-sized architecture */ + } + + if (flagval == 0) { + fprintf (stream, "M\tProcessors " GNUMSTRING "/" GNUMSTRING " (%g)\n", + (Gnum) mapnbr, + (Gnum) tgtnbr, + (double) mapnbr / (double) tgtnbr); + fprintf (stream, "M\tTarget min=" GNUMSTRING "\tmax=" GNUMSTRING "\tavg=%g\tdlt=%g\tmaxavg=%g\n", + (Gnum) mapmin, + (Gnum) mapmax, + mapavg, + mapdlt, + mapmmy); + } + + nghbnbr = 0; + nghbmin = ANUMMAX; + nghbmax = 0; + nghbsum = 0; + nghbnbr = 0; + nghbtab[0] = -2; + for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { + Gnum edgenum; + Gnum edgennd; + Anum partnum; + + partnum = parttax[domntab[vertnum].peri]; + for (edgenum = verttax[domntab[vertnum].peri], + edgennd = vendtax[domntab[vertnum].peri]; + edgenum < edgennd; edgenum ++) { + Anum partend; + + partend = parttax[edgetax[edgenum]]; + if ((partend != partnum) && /* If edge is not internal */ + (partend != nghbtab[nghbnbr])) { /* And neighbor is not sole neighbor or has not just been found */ + Anum partmin; + Anum partmax; + + partmin = 0; + partmax = nghbnbr; + while ((partmax - partmin) > 1) { + Anum partmed; + + partmed = (partmax + partmin) >> 1; + if (nghbtab[partmed] > partend) + partmax = partmed; + else + partmin = partmed; + } + if (nghbtab[partmin] == partend) /* If neighboring part found, skip to next neighbor */ + continue; + +#ifdef SCOTCH_DEBUG_MAP2 + if (nghbnbr >= (grafptr->vertnbr + 1)) { + errorPrint ("SCOTCH_graphMapView: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_MAP2 */ + + nghbnbr ++; + for (partmax = nghbnbr; partmax > (partmin + 1); partmax --) + nghbtab[partmax] = nghbtab[partmax - 1]; + nghbtab[partmin + 1] = partend; /* Add new neighbor part in the right place */ + } + } + if (domntab[vertnum].labl != domntab[vertnum + 1].labl) { /* TRICK: if new (or end) domain label */ + if (nghbnbr < nghbmin) + nghbmin = nghbnbr; + if (nghbnbr > nghbmax) + nghbmax = nghbnbr; + nghbsum += nghbnbr; + + nghbnbr = 0; + } + } + + if (flagval == 0) { + fprintf (stream, "M\tNeighbors min=" GNUMSTRING "\tmax=" GNUMSTRING "\tsum=" GNUMSTRING "\n", + (Gnum) nghbmin, + (Gnum) nghbmax, + (Gnum) nghbsum); + } + + memSet (commdist, 0, 256 * sizeof (Gnum)); /* Initialize the data */ + commload = + commdilat = + commexpan = 0; + + edloval = 1; + for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { + Gnum edgenum; + + if (parttax[vertnum] == ~0) /* Skip unmapped vertices */ + continue; + for (edgenum = verttax[vertnum]; + edgenum < vendtax[vertnum]; edgenum ++) { + if (parttax[edgetax[edgenum]] == ~0) + continue; + archDomTerm (archptr, &domnorg, parttax[vertnum]); /* Get terminal domains */ + archDomTerm (archptr, &domnend, parttax[edgetax[edgenum]]); + distval = archDomDist (archptr, &domnorg, &domnend); + if (edlotax != NULL) /* Get edge weight if any */ + edloval = edlotax[edgenum]; + commdist[(distval > 255) ? 255 : distval] += edloval; + commload += edloval; + commdilat += distval; + commexpan += distval * edloval; + } + } + + if (lmaoptr != NULL) { + migrnbr = 0; + migrdistavg = 0; + migrloadavg = 0; + migrcostsum = 0; + + for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { + if ((parttax[vertnum] == -1) || (parotax[vertnum] == -1)) + continue; + if (parotax[vertnum] != parttax[vertnum]) { + migrnbr ++; + archDomTerm (archptr, &domnorg, parotax[vertnum]); /* Get terminal domains */ + archDomTerm (archptr, &domnold, parotax[vertnum]); + migrdistavg += archDomDist (archptr, &domnorg, &domnold); + migrloadavg += (grafptr->velotax == NULL) ? 1 : grafptr->velotax[vertnum]; + migrcostsum += emraval * ((vmlotax != NULL) ? vmlotax[vertnum] : 1); + } + } + if (migrnbr > 0) { + migrdistavg /= migrnbr; + migrloadavg /= migrnbr; + } + } + + if (flagval == 0) { + fprintf (stream, "M\tCommDilat=%f\t(" GNUMSTRING ")\n", /* Print expansion parameters */ + (double) commdilat / grafptr->edgenbr, + (Gnum) (commdilat / 2)); + fprintf (stream, "M\tCommExpan=%f\t(" GNUMSTRING ")\n", + ((commload == 0) ? (double) 0.0L + : (double) commexpan / (double) commload), + (Gnum) (commexpan / 2)); + fprintf (stream, "M\tCommCutSz=%f\t(" GNUMSTRING ")\n", + ((commload == 0) ? (double) 0.0L + : (double) (commload - commdist[0]) / (double) commload), + (Gnum) ((commload - commdist[0]) / 2)); + fprintf (stream, "M\tCommDelta=%f\n", + (((double) commload * (double) commdilat) == 0.0L) + ? (double) 0.0L + : ((double) commexpan * (double) grafptr->edgenbr) / + ((double) commload * (double) commdilat)); + } + + for (distmax = 255; distmax != -1; distmax --) /* Find longest distance */ + if (commdist[distmax] != 0) + break; + if (flagval == 0) { + for (distval = 0; distval <= distmax; distval ++) /* Print distance histogram */ + fprintf (stream, "M\tCommLoad[" ANUMSTRING "]=%f\n", + (Anum) distval, (double) commdist[distval] / (double) commload); + } + + diammin = GNUMMAX; + diammax = 0; + diamsum = 0; + for (mapnum = 0; mapnum < mapnbr; mapnum ++) { + Gnum diamval; + + diamval = graphMapView3 (grafptr, parttax, mapnum); + diamsum += diamval; + if (diamval < diammin) + diammin = diamval; + if (diamval > diammax) + diammax = diamval; + } + if (flagval == 0) { + fprintf (stream, "M\tPartDiam\tmin=" GNUMSTRING "\tmax=" GNUMSTRING "\tavg=%lf\n", + (Gnum) diammin, + (Gnum) diammax, + (double) diamsum / (double) mapnbr); + } + + if ((flagval == 0) && (lmaoptr != NULL)) { + fprintf (stream, "M\tMigrNbr=" GNUMSTRING "(%lf %%)\n", + migrnbr, (((double) migrnbr) / ((double) grafptr->vertnbr))*100); + fprintf (stream, "M\tAvgMigrDist=%lf\n", + (double) migrdistavg); + fprintf (stream, "M\tAvgMigrLoad=%lf\n", + (double) migrloadavg); + fprintf (stream, "M\tMigrCost=%lf\n", + (double) migrcostsum); + } + + if (flagval != 0) { /* If raw output */ + fprintf (stream, "" GNUMSTRING "\t" GNUMSTRING "\t" GNUMSTRING "\t" GNUMSTRING "\t%g\t%g\t%g\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf", /* Print standard data */ + (Gnum) mapnbr, + (Gnum) tgtnbr, + (Gnum) mapmin, + (Gnum) mapmax, + mapavg, + mapdlt, + mapmmy, + (double) commload, + (double) commexpan, + (double) commdilat / grafptr->edgenbr, + ((commload == 0) ? (double) 0.0L + : (double) commexpan / (double) commload), + ((commload == 0) ? (double) 0.0L + : (double) (commload - commdist[0]) / (double) commload), + (((double) commload * (double) commdilat) == 0.0L) + ? (double) 0.0L + : ((double) commexpan * (double) grafptr->edgenbr) / + ((double) commload * (double) commdilat)); + if (lmaoptr != NULL) /* If we are doing repartitioning */ + fprintf (stream, "\t%lf\t%lf\t%lf\t%lf\t%lf", /* Print repartitioning data */ + (double) emraval, + (double) migrnbr / (double) grafptr->vertnbr, + (double) migrdistavg, + (double) migrloadavg, + (double) migrcostsum); + fprintf (stream, "\n"); + } + + memFree (domntab); /* Free group leader */ + + return (0); +} + +/*+ This routine writes mapping statistics +*** to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMapView ( +const SCOTCH_Graph * const libgrafptr, /*+ Ordered graph +*/ +const SCOTCH_Mapping * const libmappptr, /*+ Computed mapping +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (graphMapView2 (libgrafptr, libmappptr, NULL, 0, NULL, 0, stream)); +} + +/*+ This routine writes remapping statistics +*** to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphRemapView ( +const SCOTCH_Graph * const libgrafptr, /*+ Ordered graph +*/ +const SCOTCH_Mapping * const libmappptr, /*+ Computed mapping +*/ +const SCOTCH_Mapping * const libmapoptr, /*+ Old mapping (equal to NULL if no repartitioning) +*/ +const double emraval, /*+ Edge migration ratio +*/ +SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (graphMapView2 (libgrafptr, libmappptr, libmapoptr, emraval, vmlotab, 0, stream)); +} + +/*+ This routine writes raw mapping statistics +*** to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphMapViewRaw ( +const SCOTCH_Graph * const libgrafptr, /*+ Ordered graph +*/ +const SCOTCH_Mapping * const libmappptr, /*+ Computed mapping +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (graphMapView2 (libgrafptr, libmappptr, NULL, 0, NULL, 1, stream)); +} + +/*+ This routine writes raw remapping statistics +*** to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphRemapViewRaw ( +const SCOTCH_Graph * const libgrafptr, /*+ Ordered graph +*/ +const SCOTCH_Mapping * const libmappptr, /*+ Computed mapping +*/ +const SCOTCH_Mapping * const libmapoptr, /*+ Old mapping (equal to NULL if no repartitioning) +*/ +const double emraval, /*+ Edge migration ratio +*/ +SCOTCH_Num * vmlotab, /*+ Vertex migration cost array +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (graphMapView2 (libgrafptr, libmappptr, libmapoptr, emraval, vmlotab, 1, stream)); +} + +/*+ This routine computes the pseudo-diameter of +*** the given part. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +static +Gnum +graphMapView3 ( +const Graph * const grafptr, /*+ Graph +*/ +const Anum * const parttax, /*+ Part array +*/ +const Anum partval) /*+ Part value +*/ +{ + GraphMapViewQueue queudat; /* Neighbor queue */ + GraphMapViewVertex * restrict vexxtax; /* Based access to vexxtab */ + Gnum rootnum; /* Number of current root vertex */ + Gnum vertdist; /* Vertex distance */ + int diamflag; /* Flag set if diameter changed */ + Gnum diambase; /* Base distance for connected components */ + Gnum diamdist; /* Current diameter distance */ + Gnum diamnum; /* Vertex which achieves diameter */ + Gnum passnum; /* Pass number */ + const Gnum * restrict verttax; /* Based access to vertex array */ + const Gnum * restrict vendtax; /* Based access to vertex end array */ + const Gnum * restrict edgetax; + + if (memAllocGroup ((void **) (void *) + &queudat.qtab, (size_t) (grafptr->vertnbr * sizeof (Gnum)), + &vexxtax, (size_t) (grafptr->vertnbr * sizeof (GraphMapViewVertex)), NULL) == NULL) { + errorPrint ("graphMapView3: out of memory"); + return (-1); + } + + memSet (vexxtax, 0, grafptr->vertnbr * sizeof (GraphMapViewVertex)); /* Initialize pass numbers */ + edgetax = grafptr->edgetax; + verttax = grafptr->verttax; + vendtax = grafptr->vendtax; + vexxtax -= grafptr->baseval; + + diamnum = 0; /* Start distances from zero */ + diamdist = 0; + for (passnum = 1, rootnum = grafptr->baseval; ; passnum ++) { /* For all connected components */ + while ((rootnum < grafptr->vertnbr) && + ((vexxtax[rootnum].passnum != 0) || /* Find first unallocated vertex */ + (parttax[rootnum] != partval))) + rootnum ++; + if (rootnum >= grafptr->vertnbr) /* Exit if all of graph processed */ + break; + + diambase = ++ diamdist; /* Start from previous distance */ + diamnum = rootnum; /* Start from found root */ + + for (diamflag = 1; diamflag -- != 0; passnum ++) { /* Loop if modifications */ + graphMapViewQueueFlush (&queudat); /* Flush vertex queue */ + graphMapViewQueuePut (&queudat, diamnum); /* Start from diameter vertex */ + vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ + vexxtax[diamnum].vertdist = diambase; /* It is at base distance */ + + do { /* Loop on vertices in queue */ + Gnum vertnum; + Gnum edgenum; + + vertnum = graphMapViewQueueGet (&queudat); /* Get vertex from queue */ + vertdist = vexxtax[vertnum].vertdist; /* Get vertex distance */ + + if ((vertdist > diamdist) || /* If vertex increases diameter */ + ((vertdist == diamdist) && /* Or is at diameter distance */ + ((vendtax[vertnum] - verttax[vertnum]) < /* With smaller degree */ + (vendtax[diamnum] - verttax[diamnum])))) { + diamnum = vertnum; /* Set it as new diameter vertex */ + diamdist = vertdist; + diamflag = 1; + } + + vertdist ++; /* Set neighbor distance */ + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = edgetax[edgenum]; + if ((vexxtax[vertend].passnum < passnum) && /* If vertex not queued yet */ + (parttax[vertend] == partval)) { /* And of proper part */ + graphMapViewQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ + vexxtax[vertend].passnum = passnum; + vexxtax[vertend].vertdist = vertdist; + } + } + } while (! graphMapViewQueueEmpty (&queudat)); /* As long as queue is not empty */ + } + } + + memFree (queudat.qtab); /* Free group leader */ + + return (diamdist); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_map_view.h b/scotch_6.0.3/src/libscotch/library_graph_map_view.h new file mode 100644 index 00000000..ec09e5fb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_map_view.h @@ -0,0 +1,86 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_map_view.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the declarations for **/ +/** the mapping viewing routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 04 feb 2007 **/ +/** to 04 feb 2007 **/ +/** **/ +/************************************************************/ + +#define LIBRARY_GRAPH_MAP_VIEW_H + +/* +** The type definitions. +*/ + +/*+ Complementary vertex structure. +*/ + +typedef struct GraphMapViewVertex_ { + Gnum passnum; /*+ Number of pass when vertex selected +*/ + Gnum vertdist; /*+ Current distance from diameter vertex +*/ +} GraphMapViewVertex; + +/*+ Neighbor queue. +*/ + +typedef struct GraphMapViewQueue_ { + Gnum * head; /*+ Head of distance queue +*/ + Gnum * tail; /*+ Tail of distance queue +*/ + Gnum * qtab; /*+ Array of queue elements +*/ +} GraphMapViewQueue; + +/* +** The function prototypes. +*/ + +#ifndef LIBRARY_GRAPH_MAP_VIEW +#define static +#endif + +static Gnum graphMapView3 (const Graph * const, const Anum * const, const Anum); + +#undef static + +/* +** The macro definitions. +*/ + +#define graphMapViewQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) +#define graphMapViewQueueEmpty(queue) ((queue)->head <= (queue)->tail) +#define graphMapViewQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) +#define graphMapViewQueueGet(queue) (* ((queue)->tail ++)) diff --git a/scotch_6.0.3/src/libscotch/library_graph_map_view_f.c b/scotch_6.0.3/src/libscotch/library_graph_map_view_f.c new file mode 100644 index 00000000..e8abdeac --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_map_view_f.c @@ -0,0 +1,100 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_map_view_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** mapping routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 21 nov 2005 **/ +/** to 21 nov 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHMAPVIEW, scotchfgraphmapview, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Mapping * const mapptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, mapptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHMAPVIEW: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHMAPVIEW: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphMapView (grafptr, mapptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_order.c b/scotch_6.0.3/src/libscotch/library_graph_order.c new file mode 100644 index 00000000..5d19c6f3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_order.c @@ -0,0 +1,552 @@ +/* Copyright 2004,2007,2008,2010,2012-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_order.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the graph **/ +/** ordering routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 aug 1998 **/ +/** to 22 aug 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 27 mar 1999 **/ +/** # Version 4.0 : from : 29 jan 2002 **/ +/** to 08 sep 2006 **/ +/** # Version 5.0 : from : 19 dec 2006 **/ +/** to 04 aug 2007 **/ +/** # Version 5.1 : from : 30 oct 2007 **/ +/** to 14 aug 2010 **/ +/** # Version 6.0 : from : 08 jan 2012 **/ +/** to 29 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "order.h" +#include "hgraph.h" +#include "hgraph_order_st.h" +#include "library_order.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the graph ordering routines. */ +/* */ +/************************************/ + +/*+ This routine initializes an API ordering +*** with respect to the given source graph +*** and the locations of output parameters. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderInit ( +const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Ordering * const ordeptr, /*+ Ordering structure to initialize +*/ +SCOTCH_Num * const permtab, /*+ Direct permutation array +*/ +SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ +SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ +SCOTCH_Num * const rangtab, /*+ Column block range array +*/ +SCOTCH_Num * const treetab) /*+ Separator tree array +*/ +{ + const Graph * srcgrafptr; + LibOrder * libordeptr; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Ordering) < sizeof (LibOrder)) { + errorPrint ("SCOTCH_graphOrderInit: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + srcgrafptr = (Graph *) grafptr; /* Use structure as source graph */ + libordeptr = (LibOrder *) ordeptr; + libordeptr->permtab = ((permtab == NULL) || ((void *) permtab == (void *) grafptr)) ? NULL : (Gnum *) permtab; + libordeptr->peritab = ((peritab == NULL) || ((void *) peritab == (void *) grafptr)) ? NULL : (Gnum *) peritab; + libordeptr->cblkptr = ((cblkptr == NULL) || ((void *) cblkptr == (void *) grafptr)) ? NULL : (Gnum *) cblkptr; + libordeptr->rangtab = ((rangtab == NULL) || ((void *) rangtab == (void *) grafptr)) ? NULL : (Gnum *) rangtab; + libordeptr->treetab = ((treetab == NULL) || ((void *) treetab == (void *) grafptr)) ? NULL : (Gnum *) treetab; + + return (orderInit (&libordeptr->o, srcgrafptr->baseval, srcgrafptr->vertnbr, libordeptr->peritab)); +} + +/*+ This routine frees an API ordering. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_graphOrderExit ( +const SCOTCH_Graph * const grafptr, +SCOTCH_Ordering * const ordeptr) +{ + orderExit (&((LibOrder *) ordeptr)->o); +} + +/*+ This routine loads the contents of +*** the given ordering from the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderLoad ( +const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Ordering * restrict const ordeptr, /*+ Ordering to load +*/ +FILE * restrict const stream) /*+ Output stream +*/ +{ + const Graph * srcgrafptr; + LibOrder * libordeptr; + + srcgrafptr = (Graph *) grafptr; + libordeptr = (LibOrder *) ordeptr; + + if (orderLoad (&libordeptr->o, srcgrafptr->vlbltax, stream) != 0) + return (1); + + if (libordeptr->permtab != NULL) /* Build inverse permutation if wanted */ + orderPeri (libordeptr->o.peritab, srcgrafptr->baseval, libordeptr->o.vnodnbr, libordeptr->permtab, srcgrafptr->baseval); + + return (0); +} + +/*+ This routine saves the contents of +*** the given ordering to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderSave ( +const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (orderSave (&((LibOrder *) ordeptr)->o, ((Graph *) grafptr)->vlbltax + ((Graph *) grafptr)->baseval, stream)); +} + +/*+ This routine saves to the given stream +*** the mapping data associated with the +*** given ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderSaveMap ( +const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (orderSaveMap (&((LibOrder *) ordeptr)->o, ((Graph *) grafptr)->vlbltax + ((Graph *) grafptr)->baseval, stream)); +} + +/*+ This routine saves to the given stream +*** the separator tree data associated with +*** the given ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderSaveTree ( +const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (orderSaveTree (&((LibOrder *) ordeptr)->o, ((Graph *) grafptr)->vlbltax + ((Graph *) grafptr)->baseval, stream)); +} + +/*+ This routine computes an ordering +*** of the API ordering structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderCompute ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Ordering * const ordeptr, /*+ Ordering to compute +*/ +SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ +{ + return (SCOTCH_graphOrderComputeList (grafptr, ordeptr, ((Graph *) grafptr)->vertnbr, NULL, stratptr)); +} + +/*+ This routine computes a partial ordering +*** of the listed vertices of the API ordering +*** structure graph with respect to the given +*** strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderComputeList ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Ordering * const ordeptr, /*+ Ordering to compute +*/ +const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ +const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ +SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ +{ + const Graph * restrict srcgrafptr; + LibOrder * libordeptr; /* Pointer to ordering */ + Hgraph halgrafdat; /* Halo source graph structure */ + Hgraph halgraftmp; /* Halo source graph structure */ + Hgraph * halgrafptr; /* Pointer to halo graph structure */ + const Strat * ordstratptr; /* Pointer to ordering strategy */ + OrderCblk * cblkptr; + + srcgrafptr = (Graph *) grafptr; + libordeptr = (LibOrder *) ordeptr; /* Get ordering */ + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if ((listnbr < 0) || (listnbr > srcgrafptr->vertnbr)) { + errorPrint ("SCOTCH_graphOrderComputeList: invalid parameters (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ +#ifdef SCOTCH_DEBUG_LIBRARY2 + if (graphCheck (srcgrafptr) != 0) { + errorPrint ("SCOTCH_graphOrderComputeList: invalid input graph"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY2 */ + + if (listnbr == 0) { /* If empty list, return identity peremutation */ + Gnum * restrict peritab; + Gnum vertnum; + + peritab = libordeptr->o.peritab; + for (vertnum = 0; vertnum < srcgrafptr->vertnbr; vertnum ++) + peritab[vertnum] = vertnum + srcgrafptr->baseval; + return (0); + } + + if (*((Strat **) stratptr) == NULL) /* Set default ordering strategy if necessary */ + SCOTCH_stratGraphOrderBuild (stratptr, SCOTCH_STRATQUALITY, 0, 0.2); + + ordstratptr = *((Strat **) stratptr); + if (ordstratptr->tabl != &hgraphorderststratab) { + errorPrint ("SCOTCH_graphOrderComputeList: not an ordering strategy"); + return (1); + } + + memCpy (&halgrafdat.s, grafptr, sizeof (Graph)); /* Copy non-halo graph data */ + halgrafdat.s.flagval &= ~GRAPHFREETABS; /* Do not allow to free arrays */ + halgrafdat.s.edlotax = NULL; /* Don't mind about edge loads */ + halgrafdat.vnohnbr = halgrafdat.s.vertnbr; /* All vertices are non-halo */ + halgrafdat.vnohnnd = halgrafdat.s.vertnnd; /* No halo present */ + halgrafdat.vnhdtax = halgrafdat.s.vendtax; /* End of non-halo vertices */ + halgrafdat.vnlosum = halgrafdat.s.velosum; /* Sum of node vertex weights */ + halgrafdat.enohnbr = halgrafdat.s.edgenbr; /* No halo present */ + halgrafdat.enohsum = halgrafdat.s.edlosum; + halgrafdat.levlnum = 0; /* No nested dissection yet */ + + if (listnbr == srcgrafptr->vertnbr) { /* If work on full graph */ + halgrafptr = &halgrafdat; + cblkptr = &libordeptr->o.cblktre; + } + else { + VertList listdat; + Gnum * restrict peritax; + Gnum listnum; + Gnum vertnum; + Gnum halonum; + + if ((cblkptr = (OrderCblk *) memAlloc (2 * sizeof (OrderCblk))) == NULL) { + errorPrint ("SCOTCH_graphOrderComputeList: out of memory"); + return (1); + } + libordeptr->o.treenbr = 3; + libordeptr->o.cblknbr = 2; + libordeptr->o.cblktre.typeval = ORDERCBLKNEDI; /* Node becomes a (fake) nested dissection node */ + libordeptr->o.cblktre.vnodnbr = srcgrafptr->vertnbr; + libordeptr->o.cblktre.cblknbr = 2; + libordeptr->o.cblktre.cblktab = cblkptr; + + cblkptr[0].typeval = ORDERCBLKOTHR; /* Build column blocks */ + cblkptr[0].vnodnbr = listnbr; + cblkptr[0].cblknbr = 0; + cblkptr[0].cblktab = NULL; + cblkptr[1].typeval = ORDERCBLKOTHR; + cblkptr[1].vnodnbr = srcgrafptr->vertnbr - listnbr; + cblkptr[1].cblknbr = 0; + cblkptr[1].cblktab = NULL; + + memSet (libordeptr->o.peritab, 0, srcgrafptr->vertnbr * sizeof (Gnum)); /* Fill inverse permutation with dummy values */ + for (listnum = 0, peritax = libordeptr->o.peritab - srcgrafptr->baseval; + listnum < listnbr; listnum ++) { +#ifdef SCOTCH_DEBUG_LIBRARY2 + if ((listtab[listnum] < srcgrafptr->baseval) || + (listtab[listnum] >= srcgrafptr->vertnnd)) { + errorPrint ("SCOTCH_graphOrderComputeList: invalid parameters (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY2 */ + peritax[listtab[listnum]] = ~0; /* TRICK: use peritab as flag array to mark used vertices */ + } + for (vertnum = halonum = srcgrafptr->vertnnd - 1; vertnum >= srcgrafptr->baseval; vertnum --) { + if (peritax[vertnum] == 0) + peritax[halonum --] = vertnum; + } +#ifdef SCOTCH_DEBUG_LIBRARY2 + if (halonum != (listnbr + srcgrafptr->baseval - 1)) { + errorPrint ("SCOTCH_graphOrderComputeList: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY2 */ + + listdat.vnumnbr = listnbr; + listdat.vnumtab = (Gnum * const) listtab; + if (hgraphInduceList (&halgrafdat, &listdat, srcgrafptr->vertnbr - listnbr, &halgraftmp) != 0) { + errorPrint ("SCOTCH_graphOrderComputeList: cannot create induced subgraph"); + return (1); + } + halgrafptr = &halgraftmp; + } + + intRandInit (); /* Check that random number generator is initialized */ + + hgraphOrderSt (halgrafptr, &libordeptr->o, 0, cblkptr, ordstratptr); + + if (halgrafptr != &halgrafdat) /* If induced subgraph created */ + hgraphExit (halgrafptr); /* Free it */ + +#ifdef SCOTCH_DEBUG_LIBRARY2 + if (orderCheck (&libordeptr->o) != 0) + return (1); +#endif /* SCOTCH_DEBUG_LIBRARY2 */ + + if (libordeptr->permtab != NULL) /* Build direct permutation if wanted */ + orderPeri (libordeptr->o.peritab, srcgrafptr->baseval, libordeptr->o.vnodnbr, libordeptr->permtab, srcgrafptr->baseval); + if (libordeptr->rangtab != NULL) /* Build range array if column block data wanted */ + orderRang (&libordeptr->o, libordeptr->rangtab); + if (libordeptr->treetab != NULL) /* Build separator tree array if wanted */ + orderTree (&libordeptr->o, libordeptr->treetab); + if (libordeptr->cblkptr != NULL) /* Set number of column blocks if wanted */ + *(libordeptr->cblkptr) = libordeptr->o.cblknbr; + + return (0); +} + +/*+ This routine computes an ordering +*** of the API ordering structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrder ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +SCOTCH_Strat * const stratptr, /*+ Ordering strategy +*/ +SCOTCH_Num * const permtab, /*+ Ordering permutation +*/ +SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ +SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ +SCOTCH_Num * const rangtab, /*+ Column block range array +*/ +SCOTCH_Num * const treetab) /*+ Separator tree array +*/ +{ + SCOTCH_Ordering ordedat; + int o; + + if (SCOTCH_graphOrderInit (grafptr, &ordedat, permtab, peritab, cblkptr, rangtab, treetab) != 0) + return (1); + + o = SCOTCH_graphOrderCompute (grafptr, &ordedat, stratptr); + SCOTCH_graphOrderExit (grafptr, &ordedat); + + return (o); +} + +/*+ This routine computes an ordering +*** of the subgraph of the API ordering +*** structure graph induced by the given +*** vertex list, with respect to the given +*** strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderList ( +SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ +const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ +const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ +SCOTCH_Strat * const stratptr, /*+ Ordering strategy +*/ +SCOTCH_Num * const permtab, /*+ Ordering permutation +*/ +SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ +SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ +SCOTCH_Num * const rangtab, /*+ Column block range array +*/ +SCOTCH_Num * const treetab) /*+ Column block range array +*/ +{ + SCOTCH_Ordering ordedat; + int o; + + SCOTCH_graphOrderInit (grafptr, &ordedat, permtab, peritab, cblkptr, rangtab, treetab); + o = SCOTCH_graphOrderComputeList (grafptr, &ordedat, listnbr, listtab, stratptr); + SCOTCH_graphOrderExit (grafptr, &ordedat); + + return (o); +} + +/*+ This routine checks the consistency +*** of the given graph ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphOrderCheck ( +const SCOTCH_Graph * const grafptr, +const SCOTCH_Ordering * const ordeptr) /*+ Ordering to check +*/ +{ + return (orderCheck (&((LibOrder *) ordeptr)->o)); +} + +/*+ This routine parses the given +*** graph ordering strategy. +*** It returns: +*** - 0 : if string successfully scanned. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratGraphOrder ( +SCOTCH_Strat * const stratptr, +const char * const string) +{ + if (*((Strat **) stratptr) != NULL) + stratExit (*((Strat **) stratptr)); + + if ((*((Strat **) stratptr) = stratInit (&hgraphorderststratab, string)) == NULL) { + errorPrint ("SCOTCH_stratGraphOrder: error in ordering strategy"); + return (1); + } + + return (0); +} + +/*+ This routine provides predefined +*** ordering strategies. +*** It returns: +*** - 0 : if string successfully initialized. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratGraphOrderBuild ( +SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ +const SCOTCH_Num flagval, /*+ Desired characteristics +*/ +const SCOTCH_Num levlnbr, /*+ Number of nested dissection levels +*/ +const double balrat) /*+ Desired imbalance ratio +*/ +{ + char bufftab[8192]; /* Should be enough */ + char levltab[32]; + char bbaltab[32]; + char * sepaptr; + char * tstsptr; + char * oleaptr; + char * osepptr; + + sprintf (bbaltab, "%lf", balrat); + sprintf (levltab, GNUMSTRING, levlnbr); + + strcpy (bufftab, "c{rat=0.7,cpr=n{sep=/()?m{rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}};,ole=,ose=},unc=n{sep=/()?m{rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}};,ole=,ose=}}"); + + switch (flagval & (SCOTCH_STRATLEVELMIN | SCOTCH_STRATLEVELMAX)) { + case SCOTCH_STRATLEVELMIN : + tstsptr = "(levl<)|(vert>240)"; + break; + case SCOTCH_STRATLEVELMAX : + tstsptr = "(levl<)&(vert>240)"; + break; + case (SCOTCH_STRATLEVELMIN | SCOTCH_STRATLEVELMAX) : + tstsptr = "levl<"; + break; + default : + tstsptr = "vert>240"; + break; + } + + sepaptr = ((flagval & SCOTCH_STRATSPEED) != 0) + ? "" + : "|m{rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}}"; + + oleaptr = ((flagval & SCOTCH_STRATLEAFSIMPLE) != 0) + ? "s" + : "f{cmin=15,cmax=100000,frat=0.0}"; + + osepptr = ((flagval & SCOTCH_STRATSEPASIMPLE) != 0) + ? "s" + : "g"; + + stringSubst (bufftab, "", sepaptr); + stringSubst (bufftab, "", tstsptr); + stringSubst (bufftab, "", levltab); + stringSubst (bufftab, "", oleaptr); + stringSubst (bufftab, "", osepptr); + stringSubst (bufftab, "", bbaltab); + + if (SCOTCH_stratGraphOrder (stratptr, bufftab) != 0) { + errorPrint ("SCOTCH_stratGraphOrderBuild: error in sequential ordering strategy"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_order_f.c b/scotch_6.0.3/src/libscotch/library_graph_order_f.c new file mode 100644 index 00000000..b21efbee --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_order_f.c @@ -0,0 +1,341 @@ +/* Copyright 2004,2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_order_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph ordering routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.4 : from : 02 feb 2000 **/ +/** to 15 nov 2001 **/ +/** # Version 4.0 : from : 02 feb 2002 **/ +/** to 13 dec 2005 **/ +/** # Version 5.0 : from : 04 aug 2007 **/ +/** to 31 may 2008 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 25 jul 2010 **/ +/** # Version 6.0 : from : 08 jan 2012 **/ +/** to 08 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDERINIT, scotchfgraphorderinit, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Ordering * const ordeptr, \ +SCOTCH_Num * const permtab, \ +SCOTCH_Num * const peritab, \ +SCOTCH_Num * const cblkptr, \ +SCOTCH_Num * const rangtab, \ +SCOTCH_Num * const treetab, \ +int * const revaptr), \ +(grafptr, ordeptr, permtab, peritab, \ + cblkptr, rangtab, treetab, revaptr)) +{ + *revaptr = SCOTCH_graphOrderInit (grafptr, ordeptr, permtab, peritab, cblkptr, rangtab, treetab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDEREXIT, scotchfgraphorderexit, ( \ +const SCOTCH_Graph * const grafptr, \ +SCOTCH_Ordering * const ordeptr), \ +(grafptr, ordeptr)) +{ + SCOTCH_graphOrderExit (grafptr, ordeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDERSAVE, scotchfgraphordersave, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Ordering * const ordeptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, ordeptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHORDERSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHORDERSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphOrderSave (grafptr, ordeptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDERSAVEMAP, scotchfgraphordersavemap, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Ordering * const ordeptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, ordeptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHORDERSAVEMAP: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHORDERSAVEMAP: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphOrderSaveMap (grafptr, ordeptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDERSAVETREE, scotchfgraphordersavetree, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Ordering * const ordeptr, \ +int * const fileptr, \ +int * const revaptr), \ +(grafptr, ordeptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFGRAPHORDERSAVETREE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFGRAPHORDERSAVETREE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_graphOrderSaveTree (grafptr, ordeptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDERCOMPUTE, scotchfgraphordercompute, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Ordering * const ordeptr, \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(grafptr, ordeptr, stratptr, revaptr)) +{ + *revaptr = SCOTCH_graphOrderCompute (grafptr, ordeptr, stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDERCOMPUTELIST, scotchfgraphordercomputelist, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Ordering * const ordeptr, \ +const SCOTCH_Num * listptr, \ +const SCOTCH_Num * const listtab, \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(grafptr, ordeptr, listptr, listtab, stratptr, revaptr)) +{ + *revaptr = SCOTCH_graphOrderComputeList (grafptr, ordeptr, *listptr, listtab, stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDER, scotchfgraphorder, ( \ +SCOTCH_Graph * const grafptr, \ +SCOTCH_Strat * const stratptr, \ +SCOTCH_Num * const permtab, \ +SCOTCH_Num * const peritab, \ +SCOTCH_Num * const cblkptr, \ +SCOTCH_Num * const rangtab, \ +SCOTCH_Num * const treetab, \ +int * const revaptr), \ +(grafptr, stratptr, permtab, peritab, \ + cblkptr, rangtab, treetab, revaptr)) +{ + *revaptr = SCOTCH_graphOrder (grafptr, stratptr, permtab, peritab, cblkptr, rangtab, treetab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDERLIST, scotchfgraphorderlist, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const listptr, \ +const SCOTCH_Num * const listtab, \ +SCOTCH_Strat * const stratptr, \ +SCOTCH_Num * const permtab, \ +SCOTCH_Num * const peritab, \ +SCOTCH_Num * const cblkptr, \ +SCOTCH_Num * const rangtab, \ +SCOTCH_Num * const treetab, \ +int * const revaptr), \ +(grafptr, listptr, listtab, stratptr, \ + permtab, peritab, cblkptr, rangtab, treetab, revaptr)) +{ + *revaptr = SCOTCH_graphOrderList (grafptr, *listptr, listtab, stratptr, permtab, peritab, cblkptr, rangtab, treetab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHORDERCHECK, scotchfgraphordercheck, ( \ +const SCOTCH_Graph * const grafptr, \ +const SCOTCH_Ordering * const ordeptr, \ +int * const revaptr), \ +(grafptr, ordeptr, revaptr)) +{ + *revaptr = SCOTCH_graphOrderCheck (grafptr, ordeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATGRAPHORDER, scotchfstratgraphorder, ( \ +SCOTCH_Strat * const stratptr, \ +const char * const string, \ +int * const revaptr, \ +const int strnbr), \ +(stratptr, string, revaptr, strnbr)) +{ + char * restrict strtab; /* Pointer to null-terminated string */ + + if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ + errorPrint ("SCOTCHFSTRATGRAPHORDER: out of memory (1)"); + *revaptr = 1; + } + memCpy (strtab, string, strnbr); /* Copy string contents */ + strtab[strnbr] = '\0'; /* Terminate string */ + + *revaptr = SCOTCH_stratGraphOrder (stratptr, strtab); /* Call original routine */ + + memFree (strtab); /* Prevent compiler warnings */ +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATGRAPHORDERBUILD, scotchfstratgraphorderbuild, ( \ +SCOTCH_Strat * const stratptr, \ +const SCOTCH_Num * const flagval, \ +const SCOTCH_Num * const levlnbr, \ +const double * const balrat, \ +int * const revaptr), \ +(stratptr, flagval, levlnbr, balrat, revaptr)) +{ + *revaptr = SCOTCH_stratGraphOrderBuild (stratptr, *levlnbr, *flagval, *balrat); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_part_ovl.c b/scotch_6.0.3/src/libscotch/library_graph_part_ovl.c new file mode 100644 index 00000000..b7a3ea90 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_part_ovl.c @@ -0,0 +1,165 @@ +/* Copyright 2010,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_part_ovl.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the graph **/ +/** partitioning routines with overlap of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 28 may 2010 **/ +/** to 20 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "wgraph.h" +#include "wgraph_part_st.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* graph partitioning with overlap. */ +/* */ +/************************************/ + +/*+ This routine computes a partition with +*** overlap of the given graph structure +*** with respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_graphPartOvl ( +SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ +const SCOTCH_Num partnbr, /*+ Number of parts +*/ +SCOTCH_Strat * const straptr, /*+ Partitioning strategy +*/ +SCOTCH_Num * const parttab) /*+ Partition array +*/ +{ + Wgraph grafdat; + const Strat * partstraptr; + int o; + + if (*((Strat **) straptr) == NULL) /* Set default partitioning strategy if necessary */ + SCOTCH_stratGraphPartOvlBuild (straptr, SCOTCH_STRATQUALITY, (Gnum) partnbr, (double) 0.05); + + partstraptr = *((Strat **) straptr); + if (partstraptr->tabl != &wgraphpartststratab) { + errorPrint ("SCOTCH_graphPartOvl: not a graph partitioning with overlap strategy"); + return (1); + } + + intRandInit (); /* Check that random number generator is initialized */ + + wgraphInit (&grafdat, (Graph *) grafptr, partnbr); /* Initialize graph from given graph */ + grafdat.parttax = ((Gnum *) parttab) - grafdat.s.baseval; /* Directly use given part array */ + grafdat.levlnum = 0; + if (wgraphAlloc (&grafdat) != 0) { /* Always allocate graph data when calling */ + errorPrint ("SCOTCH_graphPartOvl: out of memory"); + return (1); + } + + o = wgraphPartSt (&grafdat, partstraptr); + + wgraphExit (&grafdat); + + return (o); +} + +/*+ This routine parses the given +*** partitioning strategy. +*** It returns: +*** - 0 : if string successfully scanned. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratGraphPartOvl ( +SCOTCH_Strat * const straptr, +const char * const string) +{ + if (*((Strat **) straptr) != NULL) + stratExit (*((Strat **) straptr)); + + if ((*((Strat **) straptr) = stratInit (&wgraphpartststratab, string)) == NULL) { + errorPrint ("SCOTCH_stratGraphPartOvl: error in sequential overlap partitioning strategy"); + return (1); + } + + return (0); +} + +/*+ This routine provides predefined +*** overlap partitioning strategies. +*** It returns: +*** - 0 : if string successfully initialized. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratGraphPartOvlBuild ( +SCOTCH_Strat * const straptr, /*+ Strategy to create +*/ +const SCOTCH_Num flagval, /*+ Desired characteristics +*/ +const SCOTCH_Num partnbr, /*+ Number of expected parts/size +*/ +const double balrat) /*+ Desired imbalance ratio +*/ +{ + char bufftab[8192]; /* Should be enough */ + char kbaltab[64]; + + sprintf (bufftab, "m{vert=%ld,low=r{sep=m{rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}}|m{rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}}},asc=f{bal=}}", + (long) (20 * partnbr)); + + sprintf (kbaltab, "%lf", balrat); + stringSubst (bufftab, "", kbaltab); + + if (SCOTCH_stratGraphPartOvl (straptr, bufftab) != 0) { + errorPrint ("SCOTCH_stratGraphPartOvlBuild: error in sequential overlap partitioning strategy"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_graph_part_ovl_f.c b/scotch_6.0.3/src/libscotch/library_graph_part_ovl_f.c new file mode 100644 index 00000000..449c0663 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_graph_part_ovl_f.c @@ -0,0 +1,120 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_graph_part_ovl_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** graph partitioning routines with **/ +/** overlap of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 29 may 2010 **/ +/** to 17 oct 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the partitioning routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFGRAPHPARTOVL, scotchfgraphpartovl, ( \ +SCOTCH_Graph * const grafptr, \ +const SCOTCH_Num * const partptr, \ +SCOTCH_Strat * const straptr, \ +SCOTCH_Num * const parttab, \ +int * const revaptr), \ +(grafptr, partptr, straptr, parttab, revaptr)) +{ + *revaptr = SCOTCH_graphPartOvl (grafptr, *partptr, straptr, parttab); +} + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFSTRATGRAPHPARTOVL, scotchfstratgraphpartovl, ( \ +SCOTCH_Strat * const straptr, \ +const char * const string, \ +int * const revaptr, \ +const int strnbr), \ +(straptr, string, revaptr, strnbr)) +{ + char * restrict strtab; /* Pointer to null-terminated string */ + + if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ + errorPrint ("SCOTCHFSTRATGRAPHPARTOVL: out of memory (1)"); + *revaptr = 1; + } + memCpy (strtab, string, strnbr); /* Copy string contents */ + strtab[strnbr] = '\0'; /* Terminate string */ + + *revaptr = SCOTCH_stratGraphPartOvl (straptr, strtab); /* Call original routine */ + + memFree (strtab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATGRAPHPARTOVLBUILD, scotchfstratgraphpartovlbuild, ( \ +SCOTCH_Strat * const straptr, \ +const SCOTCH_Num * const flagptr, \ +const SCOTCH_Num * const partptr, \ +const double * const balrptr, \ +int * const revaptr), \ +(straptr, flagptr, partptr, balrptr, revaptr)) +{ + *revaptr = SCOTCH_stratGraphPartOvlBuild (straptr, *flagptr, *partptr, *balrptr); /* Call original routine */ +} diff --git a/scotch_6.0.3/src/libscotch/library_mapping.c b/scotch_6.0.3/src/libscotch/library_mapping.c new file mode 100644 index 00000000..a464566a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mapping.c @@ -0,0 +1,76 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mapping.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains miscellaneous **/ +/** routines for handling centralized **/ +/** graph mappings. **/ +/** **/ +/** DATES : # Version 5.1 : from : 17 nov 2010 **/ +/** to 17 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/****************************************/ +/* */ +/* These routines are the C API for */ +/* mapping structure handling routines. */ +/* */ +/****************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** graph mapping structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Mapping * +SCOTCH_mapAlloc () +{ + return ((SCOTCH_Mapping *) memAlloc (sizeof (SCOTCH_Mapping))); +} diff --git a/scotch_6.0.3/src/libscotch/library_mapping.h b/scotch_6.0.3/src/libscotch/library_mapping.h new file mode 100644 index 00000000..085b705a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mapping.h @@ -0,0 +1,73 @@ +/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mapping.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the library ordering **/ +/** structure. **/ +/** **/ +/** DATES : # Version 4.0 : from : 28 jun 2004 **/ +/** to 28 jun 2004 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 17 nov 2010 **/ +/** # Version 6.0 : from : 15 apr 2011 **/ +/** to 23 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ User mapping option flags. +*/ + +#define LIBMAPPINGNONE 0x0000 /* No options set */ + +#define LIBMAPPINGFREEPART 0x0001 /* Free parttab array */ + +/* +** The type and structure definitions. +*/ + +/*+ User mapping. +*/ + +typedef struct LibMapping_ { + Gnum flagval; + Graph * grafptr; /*+ Graph data +*/ + Arch * archptr; /*+ Architecture data +*/ + Gnum * parttab; /*+ Mapping array +*/ +} LibMapping; diff --git a/scotch_6.0.3/src/libscotch/library_memory.c b/scotch_6.0.3/src/libscotch/library_memory.c new file mode 100644 index 00000000..360aaa03 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_memory.c @@ -0,0 +1,86 @@ +/* Copyright 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_memory.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the memory **/ +/** handling routines. **/ +/** **/ +/** DATES : # Version 6.0 : from : 21 sep 2014 **/ +/** to 23 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the memory management routines. */ +/* */ +/************************************/ + +/*+ This routine frees a structure allocated +*** by a SCOTCH_*Alloc () routine. +*** It returns: +*** - void : in all cases. ++*/ + +void +SCOTCH_memFree ( +void * const dataptr) +{ + memFree (dataptr); +} + +/*+ This routine returns the size, in bytes, +*** of a SCOTCH_Num. +*** It returns: +*** - void : in all cases. ++*/ + +int +SCOTCH_numSizeof () +{ + return (sizeof (SCOTCH_Num)); +} diff --git a/scotch_6.0.3/src/libscotch/library_memory_f.c b/scotch_6.0.3/src/libscotch/library_memory_f.c new file mode 100644 index 00000000..597e1dad --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_memory_f.c @@ -0,0 +1,75 @@ +/* Copyright 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_memory_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the some miscellaneous routines **/ +/** provided by the common files of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 6.0 : from : 23 sep 2014 **/ +/** to 23 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for some miscellaneous routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFNUMSIZEOF, scotchfnumsizeof, ( \ +int * const sizeptr), \ +(sizeptr)) +{ + *sizeptr = SCOTCH_numSizeof (); +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh.c b/scotch_6.0.3/src/libscotch/library_mesh.c new file mode 100644 index 00000000..8df3c56d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh.c @@ -0,0 +1,515 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the source **/ +/** mesh handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 23 sep 2002 **/ +/** to 11 may 2004 **/ +/** # Version 5.1 : from : 17 nov 2010 **/ +/** to 17 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the mesh handling routines. */ +/* */ +/************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** centralized mesh structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Mesh * +SCOTCH_meshAlloc () +{ + return ((SCOTCH_Mesh *) memAlloc (sizeof (SCOTCH_Mesh))); +} + +/*+ This routine initializes the opaque +*** mesh structure used to handle meshes +*** in the Scotch library. +*** It returns: +*** - 0 : if the initialization succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshInit ( +SCOTCH_Mesh * const meshptr) +{ + if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { + errorPrint ("SCOTCH_meshInit: internal error (1)"); + return (1); + } + if (sizeof (SCOTCH_Mesh) < sizeof (Mesh)) { + errorPrint ("SCOTCH_meshInit: internal error (2)"); + return (1); + } + + return (meshInit ((Mesh *) meshptr)); +} + +/*+ This routine frees the contents of the +*** given opaque mesh structure. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_meshExit ( +SCOTCH_Mesh * const meshptr) +{ + meshExit ((Mesh *) meshptr); +} + +/*+ This routine loads the given opaque mesh +*** structure with the data of the given stream. +*** The base value allows the user to set the +*** mesh base to 0 or 1, or to the base value +*** of the stream if the base value is equal +*** to -1. +*** It returns: +*** - 0 : if the loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshLoad ( +SCOTCH_Mesh * const meshptr, +FILE * const stream, +const SCOTCH_Num baseval) +{ + if ((baseval < -1) || (baseval > 1)) { + errorPrint ("SCOTCH_meshLoad: invalid base parameter"); + return (1); + } + + return (meshLoad ((Mesh * const) meshptr, stream, (Gnum) baseval)); +} + +/*+ This routine saves the contents of the given +*** opaque mesh structure to the given stream. +*** It returns: +*** - 0 : if the saving succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshSave ( +const SCOTCH_Mesh * const meshptr, +FILE * const stream) +{ + return (meshSave ((const Mesh * const) meshptr, stream)); +} + +/*+ This routine fills the contents of the given +*** opaque mesh structure with the data provided +*** by the user. The base value allows the user to +*** set the mesh base to 0 or 1. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshBuild ( +SCOTCH_Mesh * const meshptr, /* Mesh structure to fill */ +const SCOTCH_Num velmbas, /* Base index for element vertices */ +const SCOTCH_Num vnodbas, /* Base index for node vertices */ +const SCOTCH_Num velmnbr, /* Number of elements in mesh graph */ +const SCOTCH_Num vnodnbr, /* Number of vertices in mesh graph */ +const SCOTCH_Num * const verttab, /* Vertex array [vertnbr or vertnbr+1] */ +const SCOTCH_Num * const vendtab, /* Vertex end array [vertnbr] */ +const SCOTCH_Num * const velotab, /* Element vertex load array */ +const SCOTCH_Num * const vnlotab, /* Node vertex load array */ +const SCOTCH_Num * const vlbltab, /* Vertex label array */ +const SCOTCH_Num edgenbr, /* Number of edges (arcs) */ +const SCOTCH_Num * const edgetab) /* Edge array [edgenbr] */ +{ + Mesh * srcmeshptr; /* Pointer to source mesh structure */ + Gnum degrmax; /* Maximum degree */ + Gnum veisnbr; /* Number of isolated element vertices */ + Gnum vertnum; /* Current vertex number */ + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Mesh) < sizeof (Mesh)) { + errorPrint ("SCOTCH_meshBuild: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + if ((velmbas < 0) || + (vnodbas < 0) || + ((velmbas > 1) && (vnodbas > 1))) { + errorPrint ("SCOTCH_meshBuild: invalid base parameters"); + return (1); + } + if (((velmbas + velmnbr) != vnodbas) && + ((vnodbas + vnodnbr) != velmbas)) { + errorPrint ("SCOTCH_meshBuild: invalid element or node range"); + return (1); + } + + srcmeshptr = (Mesh *) meshptr; /* Use structure as source mesh */ + + srcmeshptr->flagval = MESHNONE; + srcmeshptr->baseval = MIN (velmbas, vnodbas); + srcmeshptr->velmnbr = velmnbr; + srcmeshptr->velmbas = velmbas; + srcmeshptr->velmnnd = velmbas + velmnbr; + srcmeshptr->vnodnbr = vnodnbr; + srcmeshptr->vnodbas = vnodbas; + srcmeshptr->vnodnnd = vnodbas + vnodnbr; + srcmeshptr->verttax = (Gnum *) verttab - srcmeshptr->baseval; + srcmeshptr->vendtax = ((vendtab == NULL) || (vendtab == verttab) || (vendtab == verttab + 1)) + ? srcmeshptr->verttax + 1 : (Gnum *) vendtab - srcmeshptr->baseval; + srcmeshptr->velotax = ((velotab == NULL) || (velotab == verttab)) ? NULL : (Gnum *) velotab - srcmeshptr->velmbas; + srcmeshptr->vnlotax = ((vnlotab == NULL) || (vnlotab == verttab)) ? NULL : (Gnum *) vnlotab - srcmeshptr->vnodbas; + srcmeshptr->vlbltax = ((vlbltab == NULL) || (vlbltab == verttab)) ? NULL : (Gnum *) vlbltab - srcmeshptr->baseval; + srcmeshptr->edgenbr = edgenbr; + srcmeshptr->edgetax = (Gnum *) edgetab - srcmeshptr->baseval; + + if (srcmeshptr->velotax == NULL) /* Compute element vertex load sum */ + srcmeshptr->velosum = srcmeshptr->velmnbr; + else { + Gnum velosum; /* Sum of element vertex loads */ + + for (vertnum = srcmeshptr->velmbas, velosum = 0; + vertnum < srcmeshptr->velmnnd; vertnum ++) + velosum += srcmeshptr->velotax[vertnum]; + + srcmeshptr->velosum = velosum; + } + if (srcmeshptr->vnlotax == NULL) /* Compute node vertex load sum */ + srcmeshptr->vnlosum = srcmeshptr->vnodnbr; + else { + Gnum vnlosum; /* Sum of node vertex loads */ + + for (vertnum = srcmeshptr->vnodbas, vnlosum = 0; + vertnum < srcmeshptr->vnodnnd; vertnum ++) + vnlosum += srcmeshptr->vnlotax[vertnum]; + + srcmeshptr->vnlosum = vnlosum; + } + + for (vertnum = srcmeshptr->velmbas, veisnbr = degrmax = 0; /* Compute maximum degree */ + vertnum < srcmeshptr->velmnnd; vertnum ++) { + Gnum degrval; /* Degree of current vertex */ + + degrval = srcmeshptr->vendtax[vertnum] - srcmeshptr->verttax[vertnum]; + if (degrval > degrmax) + degrmax = degrval; + else if (degrval == 0) /* Count number of isolated element vertices */ + veisnbr ++; + } + srcmeshptr->veisnbr = veisnbr; + + for (vertnum = srcmeshptr->vnodbas; /* Compute maximum degree */ + vertnum < srcmeshptr->vnodnnd; vertnum ++) { + Gnum degrval; /* Degree of current vertex */ + + degrval = srcmeshptr->vendtax[vertnum] - srcmeshptr->verttax[vertnum]; + if (degrval > degrmax) + degrmax = degrval; + } + srcmeshptr->degrmax = degrmax; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (meshCheck (srcmeshptr) != 0) { + errorPrint ("SCOTCH_meshBuild: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + return (0); +} + +/*+ This routine checks the consistency +*** of the given mesh. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshCheck ( +const SCOTCH_Mesh * const meshptr) +{ + return (meshCheck ((const Mesh * const) meshptr)); +} + +/*+ This routine accesses mesh size data. +*** NULL pointers on input indicate unwanted +*** data. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_meshSize ( +const SCOTCH_Mesh * const meshptr, +SCOTCH_Num * const velmnbr, +SCOTCH_Num * const vnodnbr, +SCOTCH_Num * const edgenbr) +{ + const Mesh * srcmeshptr; + + srcmeshptr = (Mesh *) meshptr; + + if (velmnbr != NULL) + *velmnbr = (SCOTCH_Num) srcmeshptr->velmnbr; + if (vnodnbr != NULL) + *vnodnbr = (SCOTCH_Num) srcmeshptr->vnodnbr; + if (edgenbr != NULL) + *edgenbr = (SCOTCH_Num) srcmeshptr->edgenbr; +} + +/*+ This routine accesses all of the mesh data. +*** NULL pointers on input indicate unwanted +*** data. NULL pointers on output indicate +*** unexisting arrays. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_meshData ( +const SCOTCH_Mesh * const meshptr, /* Mesh structure to read */ +SCOTCH_Num * const velmbas, /* Base index for elements */ +SCOTCH_Num * const vnodbas, /* Base index for nodes */ +SCOTCH_Num * const velmnbr, /* Number of elements */ +SCOTCH_Num * const vnodnbr, /* Number of nodes */ +SCOTCH_Num ** const verttab, /* Vertex array [vertnbr+1] */ +SCOTCH_Num ** const vendtab, /* Vertex array [vertnbr] */ +SCOTCH_Num ** const velotab, /* Element vertex load array */ +SCOTCH_Num ** const vnlotab, /* Vertex load array */ +SCOTCH_Num ** const vlbltab, /* Vertex label array */ +SCOTCH_Num * const edgenbr, /* Number of edges (arcs) */ +SCOTCH_Num ** const edgetab, /* Edge array [edgenbr] */ +SCOTCH_Num * const degrnbr) /* Maximum degree */ +{ + const Mesh * srcmeshptr; /* Pointer to source mesh structure */ + + srcmeshptr = (const Mesh *) meshptr; + + if (velmnbr != NULL) + *velmnbr = srcmeshptr->velmnbr; + if (vnodnbr != NULL) + *vnodnbr = srcmeshptr->vnodnbr; + if (velmbas != NULL) + *velmbas = srcmeshptr->velmbas; + if (vnodbas != NULL) + *vnodbas = srcmeshptr->vnodbas; + if (verttab != NULL) + *verttab = srcmeshptr->verttax + srcmeshptr->baseval; + if (vendtab != NULL) + *vendtab = srcmeshptr->vendtax + srcmeshptr->baseval; + if (velotab != NULL) + *velotab = (srcmeshptr->velotax != NULL) ? (srcmeshptr->velotax + srcmeshptr->velmbas) : NULL; + if (vnlotab != NULL) + *vnlotab = (srcmeshptr->vnlotax != NULL) ? (srcmeshptr->vnlotax + srcmeshptr->vnodbas) : NULL; + if (vlbltab != NULL) + *vlbltab = (srcmeshptr->vlbltax != NULL) ? (srcmeshptr->vlbltax + srcmeshptr->baseval) : NULL; + if (edgenbr != NULL) + *edgenbr = srcmeshptr->edgenbr; + if (edgetab != NULL) + *edgetab = srcmeshptr->edgetax + srcmeshptr->baseval; + if (degrnbr != NULL) + *degrnbr = srcmeshptr->degrmax; +} + +/*+ This routine computes statistics +*** on the given graph. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_meshStat ( +const SCOTCH_Mesh * const meshptr, +SCOTCH_Num * const vnlominptr, /* Vertex loads only for nodes */ +SCOTCH_Num * const vnlomaxptr, +SCOTCH_Num * const vnlosumptr, +double * const vnloavgptr, +double * const vnlodltptr, +SCOTCH_Num * const edegminptr, /* Element degree data */ +SCOTCH_Num * const edegmaxptr, +double * const edegavgptr, +double * const edegdltptr, +SCOTCH_Num * const ndegminptr, /* Node degree data */ +SCOTCH_Num * const ndegmaxptr, +double * const ndegavgptr, +double * const ndegdltptr) +{ + const Mesh * restrict srcmeshptr; + Gnum vnlomin; + Gnum vnlomax; + double vnloavg; + double vnlodlt; + Gnum degrmin; + Gnum degrmax; + double degravg; + double degrdlt; + + srcmeshptr = (Mesh *) meshptr; + + vnlodlt = 0.0L; + if (srcmeshptr->vnodnbr > 0) { + if (srcmeshptr->vnlotax != NULL) { /* If mesh has node vertex loads */ + Gnum vnodnum; + + vnlomin = GNUMMAX; + vnlomax = 0; + vnloavg = (double) srcmeshptr->vnlosum / (double) srcmeshptr->vnodnbr; + + for (vnodnum = srcmeshptr->vnodbas; vnodnum < srcmeshptr->vnodnnd; vnodnum ++) { + if (srcmeshptr->vnlotax[vnodnum] < vnlomin) /* Account for vertex loads */ + vnlomin = srcmeshptr->vnlotax[vnodnum]; + if (srcmeshptr->vnlotax[vnodnum] > vnlomax) + vnlomax = srcmeshptr->vnlotax[vnodnum]; + vnlodlt += fabs ((double) srcmeshptr->vnlotax[vnodnum] - vnloavg); + } + vnlodlt /= (double) srcmeshptr->vnodnbr; + } + else { + vnlomin = + vnlomax = 1; + vnloavg = 1.0L; + } + } + else { + vnlomin = + vnlomax = 0; + vnloavg = 0.0L; + } + + if (vnlominptr != NULL) + *vnlominptr = (SCOTCH_Num) vnlomin; + if (vnlomaxptr != NULL) + *vnlomaxptr = (SCOTCH_Num) vnlomax; + if (vnlosumptr != NULL) + *vnlosumptr = (SCOTCH_Num) srcmeshptr->vnlosum; + if (vnloavgptr != NULL) + *vnloavgptr = (double) vnloavg; + if (vnlodltptr != NULL) + *vnlodltptr = (double) vnlodlt; + + degrmax = 0; + degrdlt = 0.0L; + if (srcmeshptr->velmnbr > 0) { + Gnum velmnum; + + degrmin = GNUMMAX; + degravg = (double) srcmeshptr->edgenbr / (double) (2 * srcmeshptr->velmnbr); + for (velmnum = srcmeshptr->velmbas; velmnum < srcmeshptr->velmnnd; velmnum ++) { + Gnum degrval; + + degrval = srcmeshptr->vendtax[velmnum] - srcmeshptr->verttax[velmnum]; /* Get element degree */ + if (degrval < degrmin) + degrmin = degrval; + if (degrval > degrmax) + degrmax = degrval; + degrdlt += fabs ((double) degrval - degravg); + } + degrdlt /= (double) srcmeshptr->velmnbr; + } + else { + degrmin = 0; + degravg = 0.0L; + } + + if (edegminptr != NULL) + *edegminptr = (SCOTCH_Num) degrmin; + if (edegmaxptr != NULL) + *edegmaxptr = (SCOTCH_Num) degrmax; + if (edegavgptr != NULL) + *edegavgptr = (double) degravg; + if (edegdltptr != NULL) + *edegdltptr = (double) degrdlt; + + degrmax = 0; + degrdlt = 0.0L; + if (srcmeshptr->vnodnbr > 0) { + Gnum vnodnum; + + degrmin = GNUMMAX; + degravg = (double) srcmeshptr->edgenbr / (double) (2 * srcmeshptr->vnodnbr); + for (vnodnum = srcmeshptr->vnodbas; vnodnum < srcmeshptr->vnodnnd; vnodnum ++) { + Gnum degrval; + + degrval = srcmeshptr->vendtax[vnodnum] - srcmeshptr->verttax[vnodnum]; /* Get element degree */ + if (degrval < degrmin) + degrmin = degrval; + if (degrval > degrmax) + degrmax = degrval; + degrdlt += fabs ((double) degrval - degravg); + } + degrdlt /= (double) srcmeshptr->vnodnbr; + } + else { + degrmin = 0; + degravg = 0.0L; + } + + if (ndegminptr != NULL) + *ndegminptr = (SCOTCH_Num) degrmin; + if (ndegmaxptr != NULL) + *ndegmaxptr = (SCOTCH_Num) degrmax; + if (ndegavgptr != NULL) + *ndegavgptr = (double) degravg; + if (ndegdltptr != NULL) + *ndegdltptr = (double) degrdlt; +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_f.c b/scotch_6.0.3/src/libscotch/library_mesh_f.c new file mode 100644 index 00000000..036e8bb0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_f.c @@ -0,0 +1,262 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the source mesh handling routines of **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 23 sep 2002 **/ +/** to 13 dec 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 15 apr 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mesh handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHINIT, scotchfmeshinit, ( \ +SCOTCH_Mesh * const meshptr, \ +int * const revaptr), \ +(meshptr, revaptr)) +{ + *revaptr = SCOTCH_meshInit (meshptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHEXIT, scotchfmeshexit, ( \ +SCOTCH_Mesh * const meshptr), \ +(meshptr)) +{ + SCOTCH_meshExit (meshptr); +} + +/* When an input stream is built from the given +** file handle, it is set as unbuffered, so as to +** allow for multiple stream reads from the same +** file handle. If it were buffered, too many +** input characters would be read on the first +** block read. +*/ + +FORTRAN ( \ +SCOTCHFMESHLOAD, scotchfmeshload, ( \ +SCOTCH_Mesh * const meshptr, \ +int * const fileptr, \ +const SCOTCH_Num * const baseptr, \ +int * const revaptr), \ +(meshptr, fileptr, baseptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHLOAD: cannot duplicate handle"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHLOAD: cannot open input stream"); + close (filenum); + *revaptr = 1; + return; + } + setbuf (stream, NULL); /* Do not buffer on input */ + + o = SCOTCH_meshLoad (meshptr, stream, *baseptr); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHSAVE, scotchfmeshsave, ( \ +const SCOTCH_Mesh * const meshptr, \ +int * const fileptr, \ +int * const revaptr), \ +(meshptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_meshSave (meshptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHBUILD, scotchfmeshbuild, ( \ +SCOTCH_Mesh * const meshptr, \ +const SCOTCH_Num * const velmbas, \ +const SCOTCH_Num * const vnodbas, \ +const SCOTCH_Num * const velmnbr, \ +const SCOTCH_Num * const vnodnbr, \ +const SCOTCH_Num * const verttab, \ +const SCOTCH_Num * const vendtab, \ +const SCOTCH_Num * const velotab, \ +const SCOTCH_Num * const vnlotab, \ +const SCOTCH_Num * const vlbltab, \ +const SCOTCH_Num * const edgenbr, \ +const SCOTCH_Num * const edgetab, \ +int * const revaptr), \ +(meshptr, velmbas, vnodbas, velmnbr, vnodnbr, \ + verttab, vendtab, velotab, vnlotab, vlbltab, \ + edgenbr, edgetab, revaptr)) +{ + *revaptr = SCOTCH_meshBuild (meshptr, *velmnbr, *vnodnbr, *velmbas, *vnodbas, + verttab, vendtab, velotab, vnlotab, vlbltab, + *edgenbr, edgetab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHCHECK, scotchfmeshcheck, ( \ +const SCOTCH_Mesh * const meshptr, \ +int * const revaptr), \ +(meshptr, revaptr)) +{ + *revaptr = SCOTCH_meshCheck (meshptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHSIZE, scotchfmeshsize, ( \ +const SCOTCH_Mesh * const meshptr, \ +SCOTCH_Num * const velmnbr, \ +SCOTCH_Num * const vnodnbr, \ +SCOTCH_Num * const edgenbr), \ +(meshptr, velmnbr, vnodnbr, edgenbr)) +{ + SCOTCH_meshSize (meshptr, velmnbr, vnodnbr, edgenbr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHDATA, scotchfmeshdata, ( \ +const SCOTCH_Mesh * const meshptr, \ +const SCOTCH_Num * const indxptr, \ +SCOTCH_Num * const velmbas, \ +SCOTCH_Num * const vnodbas, \ +SCOTCH_Num * const velmnbr, \ +SCOTCH_Num * const vnodnbr, \ +SCOTCH_Idx * const vertidx, \ +SCOTCH_Idx * const vendidx, \ +SCOTCH_Idx * const veloidx, \ +SCOTCH_Idx * const vnloidx, \ +SCOTCH_Idx * const vlblidx, \ +SCOTCH_Num * const edgenbr, \ +SCOTCH_Idx * const edgeidx, \ +SCOTCH_Num * const degrnbr), \ +(meshptr, indxptr, velmbas, vnodbas, velmnbr, vnodnbr, \ + vertidx, vendidx, veloidx, vnloidx, vlblidx, \ + edgenbr, edgeidx, degrnbr)) +{ + SCOTCH_Num * verttab; /* Pointer to mesh arrays */ + SCOTCH_Num * vendtab; + SCOTCH_Num * velotab; + SCOTCH_Num * vnlotab; + SCOTCH_Num * vlbltab; + SCOTCH_Num * edgetab; + + SCOTCH_meshData (meshptr, velmbas, vnodbas, velmnbr, vnodnbr, + &verttab, &vendtab, &velotab, &vnlotab, &vlbltab, + edgenbr, &edgetab, degrnbr); + *vertidx = (verttab - indxptr) + 1; /* Add 1 since Fortran indices start at 1 */ + *vendidx = (vendtab - indxptr) + 1; + *veloidx = (velotab != NULL) ? (velotab - indxptr) + 1 : *vertidx; + *vnloidx = (vnlotab != NULL) ? (vnlotab - indxptr) + 1 : *vertidx; + *vlblidx = (vlbltab != NULL) ? (vlbltab - indxptr) + 1 : *vertidx; + *edgeidx = (edgetab - indxptr) + 1; +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_graph.c b/scotch_6.0.3/src/libscotch/library_mesh_graph.c new file mode 100644 index 00000000..b06dc8e2 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_graph.c @@ -0,0 +1,78 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_graph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the Scotch **/ +/** mesh-to-graph converter. **/ +/** **/ +/** DATES : # Version 4.0 : from : 21 jan 2004 **/ +/** to 21 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the C API for */ +/* the Scotch graph and geometry */ +/* handling routines. */ +/* */ +/*************************************/ + +/*+ This routine loads the given opaque graph +*** structure with the data of the given stream. +*** - 0 : if loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshGraph ( +const SCOTCH_Mesh * restrict const meshptr, +SCOTCH_Graph * restrict const grafptr) +{ + return (meshGraph ((Mesh *) meshptr, (Graph *) grafptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_graph_f.c b/scotch_6.0.3/src/libscotch/library_mesh_graph_f.c new file mode 100644 index 00000000..c32f6167 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_graph_f.c @@ -0,0 +1,76 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_graph_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the mesh-to-graph converter of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 21 jan 2004 **/ +/** to 21 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mesh handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHGRAPH, scotchfmeshgraph, ( \ +const SCOTCH_Mesh * const meshptr, \ +SCOTCH_Graph * const grafptr, \ +int * const revaptr), \ +(meshptr, grafptr, revaptr)) +{ + *revaptr = SCOTCH_meshGraph (meshptr, grafptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_io_habo.c b/scotch_6.0.3/src/libscotch/library_mesh_io_habo.c new file mode 100644 index 00000000..6fddc6e3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_io_habo.c @@ -0,0 +1,83 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_io_habo.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the Harwell- **/ +/** Boeing geometry and mesh handling **/ +/** routines of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 jan 2004 **/ +/** to 19 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "mesh.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the C API for */ +/* the Harwell-Boeing mesh and */ +/* geometry handling routines. */ +/* */ +/*************************************/ + +/*+ This routine loads the given opaque geom +*** structure with the data of the given stream. +*** - 0 : if loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshGeomLoadHabo ( +SCOTCH_Mesh * restrict const meshptr, +SCOTCH_Geom * restrict const geomptr, +FILE * const filesrcptr, +FILE * const filegeoptr, +const char * const dataptr) /* No use */ +{ + return (meshGeomLoadHabo ((Mesh *) meshptr, (Geom *) geomptr, filesrcptr, filegeoptr, dataptr)); +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_io_habo_f.c b/scotch_6.0.3/src/libscotch/library_mesh_io_habo_f.c new file mode 100644 index 00000000..22903c4c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_io_habo_f.c @@ -0,0 +1,119 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_io_habo_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** mesh i/o routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 24 nov 2005 **/ +/** to 24 nov 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFMESHGEOMLOADHABO, scotchfmeshgeomloadhabo, ( \ +SCOTCH_Mesh * const meshptr, \ +SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(meshptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHGEOMLOADHABO: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHGEOMLOADHABO: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHGEOMLOADHABO: cannot open input stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHGEOMLOADHABO: cannot open input stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_meshGeomLoadHabo (meshptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_io_scot.c b/scotch_6.0.3/src/libscotch/library_mesh_io_scot.c new file mode 100644 index 00000000..22ca601d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_io_scot.c @@ -0,0 +1,101 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_io_scot.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the Scotch **/ +/** geometry and mesh handling routines o f **/ +/** the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 jan 2004 **/ +/** to 19 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "mesh.h" +#include "scotch.h" + +/*************************************/ +/* */ +/* These routines are the C API for */ +/* the Scotch mesh and geometry */ +/* handling routines. */ +/* */ +/*************************************/ + +/*+ This routine loads the given opaque mesh +*** structure with the data of the given stream. +*** - 0 : if loading succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshGeomLoadScot ( +SCOTCH_Mesh * restrict const meshptr, +SCOTCH_Geom * restrict const geomptr, +FILE * const filesrcptr, +FILE * const filegeoptr, +const char * const dataptr) /* No use */ +{ + return (meshGeomLoadScot ((Mesh *) meshptr, (Geom *) geomptr, filesrcptr, filegeoptr, NULL)); +} + +/*+ This routine saves the contents of the given +*** opaque mesh structure to the given stream. +*** It returns: +*** - 0 : if the saving succeeded. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshGeomSaveScot ( +const SCOTCH_Mesh * restrict const meshptr, +const SCOTCH_Geom * restrict const geomptr, +FILE * const filesrcptr, +FILE * const filegeoptr, +const char * const dataptr) /* No use */ +{ + return (meshGeomSaveScot ((Mesh *) meshptr, (Geom *) geomptr, filesrcptr, filegeoptr, NULL)); +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_io_scot_f.c b/scotch_6.0.3/src/libscotch/library_mesh_io_scot_f.c new file mode 100644 index 00000000..bd87a8e9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_io_scot_f.c @@ -0,0 +1,174 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_io_scot_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** mesh i/o routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 24 nov 2005 **/ +/** to 24 nov 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the mapping routines. */ +/* */ +/**************************************/ + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFMESHGEOMLOADSCOT, scotchfmeshgeomloadscot, ( \ +SCOTCH_Mesh * const meshptr, \ +SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(meshptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHGEOMLOADSCOT: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHGEOMLOADSCOT: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHGEOMLOADSCOT: cannot open input stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHGEOMLOADSCOT: cannot open input stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_meshGeomLoadScot (meshptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} + +/* String lengths are passed at the very +** end of the argument list. +*/ + +FORTRAN ( \ +SCOTCHFMESHGEOMSAVESCOT, scotchfmeshgeomsavescot, ( \ +const SCOTCH_Mesh * const meshptr, \ +const SCOTCH_Geom * const geomptr, \ +const int * const filegrfptr, \ +const int * const filegeoptr, \ +const char * const dataptr, /* No use */ \ +int * const revaptr, \ +const int datanbr), \ +(meshptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) +{ + FILE * filegrfstream; /* Streams to build from handles */ + FILE * filegeostream; + int filegrfnum; /* Duplicated handle */ + int filegeonum; + int o; + + if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHGEOMSAVESCOT: cannot duplicate handle (1)"); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHGEOMSAVESCOT: cannot duplicate handle (2)"); + close (filegrfnum); + *revaptr = 1; /* Indicate error */ + return; + } + if ((filegrfstream = fdopen (filegrfnum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHGEOMSAVESCOT: cannot open output stream (1)"); + close (filegrfnum); + close (filegeonum); + *revaptr = 1; + return; + } + if ((filegeostream = fdopen (filegeonum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHGEOMSAVESCOT: cannot open output stream (2)"); + fclose (filegrfstream); + close (filegeonum); + *revaptr = 1; + return; + } + + o = SCOTCH_meshGeomSaveScot (meshptr, geomptr, filegrfstream, filegeostream, NULL); + + fclose (filegrfstream); /* This closes file descriptors too */ + fclose (filegeostream); + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_order.c b/scotch_6.0.3/src/libscotch/library_mesh_order.c new file mode 100644 index 00000000..f4a9700e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_order.c @@ -0,0 +1,410 @@ +/* Copyright 2004,2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_order.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the mesh **/ +/** ordering routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 aug 1998 **/ +/** to 22 aug 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 27 mar 1999 **/ +/** # Version 4.0 : from : 29 jan 2002 **/ +/** to 20 dec 2005 **/ +/** # Version 5.0 : from : 04 aug 2007 **/ +/** to 31 may 2008 **/ +/** # Version 5.1 : from : 29 mar 2010 **/ +/** to 14 aug 2010 **/ +/** # Version 6.0 : from : 14 nov 2012 **/ +/** to 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "mesh.h" +#include "order.h" +#include "hmesh.h" +#include "hmesh_order_st.h" +#include "library_order.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the mesh ordering routines. */ +/* */ +/************************************/ + +/*+ This routine initializes an API ordering +*** with respect to the given source graph +*** and the locations of output parameters. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrderInit ( +const SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ +SCOTCH_Ordering * const ordeptr, /*+ Ordering structure to initialize +*/ +SCOTCH_Num * const permtab, /*+ Direct permutation array +*/ +SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ +SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ +SCOTCH_Num * const rangtab, /*+ Column block range array +*/ +SCOTCH_Num * const treetab) /*+ Separator tree array +*/ +{ + Mesh * srcmeshptr; + LibOrder * libordeptr; + +#ifdef SCOTCH_DEBUG_LIBRARY1 + if (sizeof (SCOTCH_Ordering) < sizeof (LibOrder)) { + errorPrint ("SCOTCH_meshOrderInit: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_LIBRARY1 */ + + srcmeshptr = (Mesh *) meshptr; /* Use structure as source mesh */ + libordeptr = (LibOrder *) ordeptr; + libordeptr->permtab = ((permtab == NULL) || ((void *) permtab == (void *) meshptr)) ? NULL : (Gnum *) permtab; + libordeptr->peritab = ((peritab == NULL) || ((void *) peritab == (void *) meshptr)) ? NULL : (Gnum *) peritab; + libordeptr->cblkptr = ((cblkptr == NULL) || ((void *) cblkptr == (void *) meshptr)) ? NULL : (Gnum *) cblkptr; + libordeptr->rangtab = ((rangtab == NULL) || ((void *) rangtab == (void *) meshptr)) ? NULL : (Gnum *) rangtab; + libordeptr->treetab = ((treetab == NULL) || ((void *) treetab == (void *) meshptr)) ? NULL : (Gnum *) treetab; + + return (orderInit (&libordeptr->o, srcmeshptr->baseval, srcmeshptr->vnodnbr, libordeptr->peritab)); +} + +/*+ This routine frees an API ordering. +*** It returns: +*** - VOID : in all cases. ++*/ + +void +SCOTCH_meshOrderExit ( +const SCOTCH_Mesh * const meshptr, +SCOTCH_Ordering * const ordeptr) +{ + orderExit (&((LibOrder *) ordeptr)->o); +} + +/*+ This routine saves the contents of +*** the given ordering to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrderSave ( +const SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ +const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (orderSave (&((LibOrder *) ordeptr)->o, ((Mesh *) meshptr)->vlbltax, stream)); +} + +/*+ This routine saves the mapping data +*** associated with the given ordering +*** to the given stream. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrderSaveMap ( +const SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ +const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (orderSaveMap (&((LibOrder *) ordeptr)->o, ((Mesh *) meshptr)->vlbltax, stream)); +} + +/*+ This routine saves to the given stream +*** the separator tree data associated with +*** the given ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrderSaveTree ( +const SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ +const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ +FILE * const stream) /*+ Output stream +*/ +{ + return (orderSaveTree (&((LibOrder *) ordeptr)->o, ((Mesh *) meshptr)->vlbltax, stream)); +} + +/*+ This routine computes an ordering +*** of the API ordering structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrderCompute ( +SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ +SCOTCH_Ordering * const ordeptr, /*+ Ordering to compute +*/ +SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ +{ + return (SCOTCH_meshOrderComputeList (meshptr, ordeptr, 0, NULL, stratptr)); +} + +/*+ This routine computes a partial ordering +*** of the listed nodes of the API ordering +*** structure mesh with respect to the given +*** strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrderComputeList ( +SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ +SCOTCH_Ordering * const ordeptr, /*+ Ordering to compute +*/ +const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ +const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ +SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ +{ + LibOrder * libordeptr; /* Pointer to ordering */ + Mesh * srcmeshptr; /* Pointer to source mesh */ + Hmesh srcmeshdat; /* Halo source mesh structure */ + VertList srclistdat; /* Subgraph vertex list */ + VertList * srclistptr; /* Pointer to subgraph vertex list */ + const Strat * ordstratptr; /* Pointer to ordering strategy */ + + srcmeshptr = (Mesh *) meshptr; + +#ifdef SCOTCH_DEBUG_MESH2 + if (meshCheck (srcmeshptr) != 0) { + errorPrint ("SCOTCH_meshOrderComputeList: invalid input mesh"); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + if (*((Strat **) stratptr) == NULL) /* Set default ordering strategy if necessary */ + SCOTCH_stratMeshOrderBuild (stratptr, SCOTCH_STRATQUALITY, 0.1); + + ordstratptr = *((Strat **) stratptr); + if (ordstratptr->tabl != &hmeshorderststratab) { + errorPrint ("SCOTCH_meshOrderComputeList: not a mesh ordering strategy"); + return (1); + } + + memCpy (&srcmeshdat.m, srcmeshptr, sizeof (Mesh)); /* Copy non-halo mesh data */ + srcmeshdat.m.flagval &= ~MESHFREETABS; /* Do not allow to free arrays */ + srcmeshdat.vehdtax = srcmeshdat.m.vendtax; /* End of non-halo vertices */ + srcmeshdat.veihnbr = 0; /* No halo isolated elements */ + srcmeshdat.vnohnbr = srcmeshdat.m.vnodnbr; /* All nodes are non-halo */ + srcmeshdat.vnohnnd = srcmeshdat.m.vnodnnd; /* No halo present */ + srcmeshdat.vnhlsum = srcmeshdat.m.vnlosum; /* Sum of node vertex weights */ + srcmeshdat.enohnbr = srcmeshdat.m.edgenbr; /* All edges are non-halo */ + srcmeshdat.levlnum = 0; /* Start from level zero */ + + libordeptr = (LibOrder *) ordeptr; /* Get ordering */ + srclistdat.vnumnbr = (Gnum) listnbr; /* Build vertex list */ + srclistdat.vnumtab = (Gnum *) listtab; + srclistptr = ((srclistdat.vnumnbr == 0) || + (srclistdat.vnumnbr == srcmeshdat.m.vnodnbr)) + ? NULL : &srclistdat; /* Is the list really necessary */ + if (srclistptr != NULL) { + errorPrint ("SCOTCH_meshOrderComputeList: node lists not yet implemented"); + return (1); + } + + intRandInit (); /* Check that random number generator is initialized */ + + hmeshOrderSt (&srcmeshdat, &libordeptr->o, 0, &libordeptr->o.cblktre, ordstratptr); + +#ifdef SCOTCH_DEBUG_LIBRARY2 + orderCheck (&libordeptr->o); +#endif /* SCOTCH_DEBUG_LIBRARY2 */ + + if (libordeptr->permtab != NULL) /* Build direct permutation if wanted */ + orderPeri (libordeptr->o.peritab, libordeptr->o.baseval, libordeptr->o.vnodnbr, libordeptr->permtab, libordeptr->o.baseval); + if (libordeptr->rangtab != NULL) /* Build range array if column block data wanted */ + orderRang (&libordeptr->o, libordeptr->rangtab); + if (libordeptr->treetab != NULL) /* Build separator tree array if wanted */ + orderTree (&libordeptr->o, libordeptr->treetab); + if (libordeptr->cblkptr != NULL) /* Set number of column blocks if wanted */ + *(libordeptr->cblkptr) = libordeptr->o.cblknbr; + + meshExit (&srcmeshdat.m); /* Free in case mesh had been reordered */ + + return (0); +} + +/*+ This routine computes an ordering +*** of the API ordering structure with +*** respect to the given strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrder ( +SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ +SCOTCH_Strat * const stratptr, /*+ Ordering strategy +*/ +SCOTCH_Num * const permtab, /*+ Ordering permutation +*/ +SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ +SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ +SCOTCH_Num * const rangtab, /*+ Column block range array +*/ +SCOTCH_Num * const treetab) /*+ Separator tree array +*/ +{ + SCOTCH_Ordering ordedat; + int o; + + SCOTCH_meshOrderInit (meshptr, &ordedat, permtab, peritab, cblkptr, rangtab, treetab); + o = SCOTCH_meshOrderCompute (meshptr, &ordedat, stratptr); + SCOTCH_meshOrderExit (meshptr, &ordedat); + + return (o); +} + +/*+ This routine computes an ordering +*** of the submesh of the API ordering +*** structure mesh induced by the given +*** vertex list, with respect to the given +*** strategy. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrderList ( +SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ +const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ +const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ +SCOTCH_Strat * const stratptr, /*+ Ordering strategy +*/ +SCOTCH_Num * const permtab, /*+ Ordering permutation +*/ +SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ +SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ +SCOTCH_Num * const rangtab, /*+ Column block range array +*/ +SCOTCH_Num * const treetab) /*+ Column block range array +*/ +{ + SCOTCH_Ordering ordedat; + int o; + + SCOTCH_meshOrderInit (meshptr, &ordedat, permtab, peritab, cblkptr, rangtab, treetab); + o = SCOTCH_meshOrderComputeList (meshptr, &ordedat, listnbr, listtab, stratptr); + SCOTCH_meshOrderExit (meshptr, &ordedat); + + return (o); +} + +/*+ This routine checks the consistency +*** of the given mesh ordering. +*** It returns: +*** - 0 : on success. +*** - !0 : on error. ++*/ + +int +SCOTCH_meshOrderCheck ( +const SCOTCH_Mesh * const meshptr, +const SCOTCH_Ordering * const ordeptr) /*+ Ordering to check +*/ +{ + return (orderCheck (&((LibOrder *) ordeptr)->o)); +} + +/*+ This routine parses the given +*** mesh ordering strategy. +*** It returns: +*** - 0 : if string successfully scanned. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratMeshOrder ( +SCOTCH_Strat * const stratptr, +const char * const string) +{ + if (*((Strat **) stratptr) != NULL) + stratExit (*((Strat **) stratptr)); + + if ((*((Strat **) stratptr) = stratInit (&hmeshorderststratab, string)) == NULL) { + errorPrint ("SCOTCH_stratMeshOrder: error in ordering strategy"); + return (1); + } + + return (0); +} + +/*+ This routine provides predefined +*** ordering strategies. +*** It returns: +*** - 0 : if string successfully initialized. +*** - !0 : on error. ++*/ + +int +SCOTCH_stratMeshOrderBuild ( +SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ +const SCOTCH_Num flagval, /*+ Desired characteristics +*/ +const double balrat) /*+ Desired imbalance ratio +*/ +{ + char bufftab[8192]; /* Should be enough */ + char bbaltab[32]; + + strcpy (bufftab, "c{rat=0.7,cpr=n{sep=/(vnod>120)?m{vnod=100,low=h{pass=10},asc=f{bal=}}:;,ole=v{strat=d{cmin=0,cmax=10000000,frat=0}},ose=g},unc=n{sep=/(vnod>120)?m{vnod=100,low=h{pass=10},asc=f{bal=}}:;,ole=v{strat=d{cmin=0,cmax=10000000,frat=0}},ose=g}}"); + + sprintf (bbaltab, "%lf", balrat); + stringSubst (bufftab, "", bbaltab); + + if (SCOTCH_stratMeshOrder (stratptr, bufftab) != 0) { + errorPrint ("SCOTCH_stratMeshOrderBuild: error in sequential ordering strategy"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/library_mesh_order_f.c b/scotch_6.0.3/src/libscotch/library_mesh_order_f.c new file mode 100644 index 00000000..b6139133 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_mesh_order_f.c @@ -0,0 +1,336 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_mesh_order_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** mesh ordering routines of the libSCOTCH **/ +/** library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 14 jan 2004 **/ +/** to 20 dec 2005 **/ +/** # Version 5.0 : from : 04 aug 2007 **/ +/** to 04 aug 2007 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 25 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDERINIT, scotchfmeshorderinit, ( \ +const SCOTCH_Mesh * const meshptr, \ +SCOTCH_Ordering * const ordeptr, \ +SCOTCH_Num * const permtab, \ +SCOTCH_Num * const peritab, \ +SCOTCH_Num * const cblkptr, \ +SCOTCH_Num * const rangtab, \ +SCOTCH_Num * const treetab, \ +int * const revaptr), \ +(meshptr, ordeptr, permtab, peritab, \ + cblkptr, rangtab, treetab, revaptr)) +{ + *revaptr = SCOTCH_meshOrderInit (meshptr, ordeptr, permtab, peritab, cblkptr, rangtab, treetab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDEREXIT, scotchfmeshorderexit, ( \ +const SCOTCH_Mesh * const meshptr, \ +SCOTCH_Ordering * const ordeptr), \ +(meshptr, ordeptr)) +{ + SCOTCH_meshOrderExit (meshptr, ordeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDERSAVE, scotchfmeshordersave, ( \ +const SCOTCH_Mesh * const meshptr, \ +const SCOTCH_Ordering * const ordeptr, \ +int * const fileptr, \ +int * const revaptr), \ +(meshptr, ordeptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHORDERSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHORDERSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_meshOrderSave (meshptr, ordeptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDERSAVEMAP, scotchfmeshordersavemap, ( \ +const SCOTCH_Mesh * const meshptr, \ +const SCOTCH_Ordering * const ordeptr, \ +int * const fileptr, \ +int * const revaptr), \ +(meshptr, ordeptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHORDERSAVEMAP: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHORDERSAVEMAP: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_meshOrderSaveMap (meshptr, ordeptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDERSAVETREE, scotchfmeshordersavetree, ( \ +const SCOTCH_Mesh * const meshptr, \ +const SCOTCH_Ordering * const ordeptr, \ +int * const fileptr, \ +int * const revaptr), \ +(meshptr, ordeptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFMESHORDERSAVETREE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFMESHORDERSAVETREE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_meshOrderSaveTree (meshptr, ordeptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDERCOMPUTE, scotchfmeshordercompute, ( \ +SCOTCH_Mesh * const meshptr, \ +SCOTCH_Ordering * const ordeptr, \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(meshptr, ordeptr, stratptr, revaptr)) +{ + *revaptr = SCOTCH_meshOrderCompute (meshptr, ordeptr, stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDERCOMPUTELIST, scotchfmeshordercomputelist, ( \ +SCOTCH_Mesh * const meshptr, \ +SCOTCH_Ordering * const ordeptr, \ +const SCOTCH_Num * listptr, \ +const SCOTCH_Num * const listtab, \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(meshptr, ordeptr, listptr, listtab, stratptr, revaptr)) +{ + *revaptr = SCOTCH_meshOrderComputeList (meshptr, ordeptr, *listptr, listtab, stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDER, scotchfmeshorder, ( \ +SCOTCH_Mesh * const meshptr, \ +SCOTCH_Strat * const stratptr, \ +SCOTCH_Num * const permtab, \ +SCOTCH_Num * const peritab, \ +SCOTCH_Num * const cblkptr, \ +SCOTCH_Num * const rangtab, \ +SCOTCH_Num * const treetab, \ +int * const revaptr), \ +(meshptr, stratptr, permtab, peritab, \ + cblkptr, rangtab, treetab, revaptr)) +{ + *revaptr = SCOTCH_meshOrder (meshptr, stratptr, permtab, peritab, cblkptr, rangtab, treetab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDERLIST, scotchfmeshorderlist, ( \ +SCOTCH_Mesh * const meshptr, \ +const SCOTCH_Num * const listptr, \ +const SCOTCH_Num * const listtab, \ +SCOTCH_Strat * const stratptr, \ +SCOTCH_Num * const permtab, \ +SCOTCH_Num * const peritab, \ +SCOTCH_Num * const cblkptr, \ +SCOTCH_Num * const rangtab, \ +SCOTCH_Num * const treetab, \ +int * const revaptr), \ +(meshptr, listptr, listtab, stratptr, \ + permtab, peritab, cblkptr, rangtab, treetab, revaptr)) +{ + *revaptr = SCOTCH_meshOrderList (meshptr, *listptr, listtab, stratptr, permtab, peritab, cblkptr, rangtab, treetab); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFMESHORDERCHECK, scotchfmeshordercheck, ( \ +const SCOTCH_Mesh * const meshptr, \ +SCOTCH_Ordering * const ordeptr, \ +int * const revaptr), \ +(meshptr, ordeptr, revaptr)) +{ + *revaptr = SCOTCH_meshOrderCheck (meshptr, ordeptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATMESHORDER, scotchfstratmeshorder, ( \ +SCOTCH_Strat * const stratptr, \ +const char * const string, \ +int * const revaptr, \ +const int strnbr), \ +(stratptr, string, revaptr, strnbr)) +{ + char * restrict strtab; /* Pointer to null-terminated string */ + + if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ + errorPrint ("SCOTCHFSTRATMESHORDER: out of memory (1)"); + *revaptr = 1; + } + memCpy (strtab, string, strnbr); /* Copy string contents */ + strtab[strnbr] = '\0'; /* Terminate string */ + + *revaptr = SCOTCH_stratMeshOrder (stratptr, strtab); /* Call original routine */ + + memFree (strtab); /* Prevent compiler warnings */ +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATMESHORDERBUILD, scotchfstratmeshorderbuild, ( \ +SCOTCH_Strat * const stratptr, \ +const SCOTCH_Num * const flagval, \ +const double * const balrat, \ +int * const revaptr), \ +(stratptr, flagval, balrat, revaptr)) +{ + *revaptr = SCOTCH_stratMeshOrderBuild (stratptr, *flagval, *balrat); +} diff --git a/scotch_6.0.3/src/libscotch/library_order.c b/scotch_6.0.3/src/libscotch/library_order.c new file mode 100644 index 00000000..bcb94baa --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_order.c @@ -0,0 +1,76 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_order.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains miscellaneous **/ +/** routines for handling centralized **/ +/** graph orderings. **/ +/** **/ +/** DATES : # Version 5.1 : from : 17 nov 2010 **/ +/** to 17 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/*****************************************/ +/* */ +/* These routines are the C API for */ +/* ordering structure handling routines. */ +/* */ +/*****************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** graph ordering structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Ordering * +SCOTCH_orderAlloc () +{ + return ((SCOTCH_Ordering *) memAlloc (sizeof (SCOTCH_Ordering))); +} diff --git a/scotch_6.0.3/src/libscotch/library_order.h b/scotch_6.0.3/src/libscotch/library_order.h new file mode 100644 index 00000000..3e2a813a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_order.h @@ -0,0 +1,64 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_order.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the library ordering **/ +/** structure. **/ +/** **/ +/** DATES : # Version 3.3 : from : 08 oct 1998 **/ +/** to : 08 oct 1998 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 25 dec 2004 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Ordering. +*/ + +typedef struct LibOrder_ { + Order o; /*+ Ordering data +*/ + Gnum * permtab; /*+ Direct permutation array +*/ + Gnum * peritab; /*+ Inverse permutation array +*/ + Gnum * cblkptr; /*+ Pointer to number of column blocks +*/ + Gnum * rangtab; /*+ Column block range array +*/ + Gnum * treetab; /*+ Separator tree array +*/ +} LibOrder; diff --git a/scotch_6.0.3/src/libscotch/library_parser.c b/scotch_6.0.3/src/libscotch/library_parser.c new file mode 100644 index 00000000..6474a14a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_parser.c @@ -0,0 +1,136 @@ +/* Copyright 2004,2007,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_parser.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the generic **/ +/** strategy handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 aug 1998 **/ +/** to 19 aug 1998 **/ +/** DATES : # Version 3.3 : from : 01 oct 1998 **/ +/** to 31 may 1999 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 23 dec 2001 **/ +/** to : 23 dec 2001 **/ +/** # Version 6.0 : from : 07 jan 2014 **/ +/** to 07 jan 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the strategy handling routines. */ +/* */ +/************************************/ + +/* This routine initializes a strategy +** structure. +** It returns: +** - 0 : in all cases. +*/ + +int +SCOTCH_stratInit ( +SCOTCH_Strat * const stratptr) +{ + if (sizeof (SCOTCH_Strat) < sizeof (Strat *)) { + errorPrint ("SCOTCH_stratInit: internal error (1)"); + return (1); + } + + *((Strat **) stratptr) = NULL; /* Initialize pointer to strategy */ + + return (0); +} + +/* This routine frees a strategy structure. +** It returns: +** - VOID : in all cases. +*/ + +void +SCOTCH_stratExit ( +SCOTCH_Strat * const stratptr) +{ + if (*((Strat **) stratptr) != NULL) /* If strategy is not null */ + stratExit (*((Strat **) stratptr)); /* Free strategy structure */ +} + +/* This routine frees the contents of a +** strategy structure and cleans it for +** future use. +** It returns: +** - VOID : in all cases. +*/ + +void +SCOTCH_stratFree ( +SCOTCH_Strat * const stratptr) +{ + if (*((Strat **) stratptr) != NULL) { /* If strategy is not null */ + stratExit (*((Strat **) stratptr)); /* Free strategy structure */ + *((Strat **) stratptr) = NULL; /* Initialize pointer to strategy */ + } +} + +/* This routine outputs the contents of the +** given strategy to the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +SCOTCH_stratSave ( +const SCOTCH_Strat * const stratptr, +FILE * const stream) +{ + return (stratSave (*((Strat **) stratptr), stream)); +} diff --git a/scotch_6.0.3/src/libscotch/library_parser_f.c b/scotch_6.0.3/src/libscotch/library_parser_f.c new file mode 100644 index 00000000..8d2efbc4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_parser_f.c @@ -0,0 +1,135 @@ +/* Copyright 2004,2007,2010,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_parser_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the Fortran API for the **/ +/** strategy handling routines of the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 17 jan 2004 **/ +/** to 17 mar 2005 **/ +/** # Version 5.1 : from : 27 mar 2010 **/ +/** to 27 mar 2010 **/ +/** # Version 6.0 : from : 07 jan 2014 **/ +/** to 07 jan 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "scotch.h" + +/***************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the ordering handling routines. */ +/* */ +/***************************************/ + +FORTRAN ( \ +SCOTCHFSTRATINIT, scotchfstratinit, ( \ +SCOTCH_Strat * const stratptr, \ +int * const revaptr), \ +(stratptr, revaptr)) +{ + *revaptr = SCOTCH_stratInit (stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATEXIT, scotchfstratexit, ( \ +SCOTCH_Strat * const stratptr), \ +(stratptr)) +{ + SCOTCH_stratExit (stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATFREE, scotchfstratfree, ( \ +SCOTCH_Strat * const stratptr), \ +(stratptr)) +{ + SCOTCH_stratFree (stratptr); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFSTRATSAVE, scotchfstratsave, ( \ +const SCOTCH_Strat * const stratptr, \ +int * const fileptr, \ +int * const revaptr), \ +(stratptr, fileptr, revaptr)) +{ + FILE * stream; /* Stream to build from handle */ + int filenum; /* Duplicated handle */ + int o; + + if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ + errorPrint ("SCOTCHFSTRATSAVE: cannot duplicate handle"); + + *revaptr = 1; /* Indicate error */ + return; + } + if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ + errorPrint ("SCOTCHFSTRATSAVE: cannot open output stream"); + close (filenum); + *revaptr = 1; + return; + } + + o = SCOTCH_stratSave (stratptr, stream); + + fclose (stream); /* This closes filenum too */ + + *revaptr = o; +} diff --git a/scotch_6.0.3/src/libscotch/library_pt.h b/scotch_6.0.3/src/libscotch/library_pt.h new file mode 100644 index 00000000..135c935b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_pt.h @@ -0,0 +1,172 @@ +/* Copyright 2004,2007-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_pt.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Jun-Ho HER (v6.0) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : Declaration file for the LibPtscotch **/ +/** parallel static mapping and sparse **/ +/** matrix block ordering library. **/ +/** **/ +/** DATES : # Version 3.2 : from : 07 sep 1996 **/ +/** to 22 aug 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to 31 may 1999 **/ +/** # Version 3.4 : from : 10 oct 1999 **/ +/** to 15 nov 2001 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 20 dec 2005 **/ +/** # Version 5.0 : from : 26 apr 2006 **/ +/** to : 20 feb 2008 **/ +/** # Version 5.1 : from : 30 nov 2007 **/ +/** to : 07 aug 2011 **/ +/** # Version 6.0 : from : 12 sep 2008 **/ +/** to 01 dec 2012 **/ +/** **/ +/************************************************************/ + +#ifndef PTSCOTCH_H +#define PTSCOTCH_H + +/* +** The defines and includes. +*/ + +#ifndef SCOTCH_H +#include "scotch.h" +#endif /* SCOTCH_H */ + +/* +** The type and structure definitions. +*/ + +/*+ Parallel processing flag. +*/ + +#ifndef SCOTCH_PTSCOTCH +#define SCOTCH_DUMMYPTFLAG +#endif /* SCOTCH_PTSCOTCH */ + +/*+ Opaque objects. The dummy sizes of these +objects, computed at compile-time by program +"dummysizes", are given as double values for +proper padding +*/ + +typedef struct { + double dummy[DUMMYSIZEDGRAPH]; +} SCOTCH_Dgraph; + +typedef struct { + double dummy[DUMMYSIZEDGRAPHHALOREQ]; +} SCOTCH_DgraphHaloReq; + +typedef struct { + double dummy[DUMMYSIZEDMAP]; +} SCOTCH_Dmapping; + +typedef struct { + double dummy[DUMMYSIZEDORDER]; +} SCOTCH_Dordering; + +/* +** The function prototypes. +*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +SCOTCH_Dgraph * SCOTCH_dgraphAlloc (void); +int SCOTCH_dgraphInit (SCOTCH_Dgraph * const, MPI_Comm); +void SCOTCH_dgraphExit (SCOTCH_Dgraph * const); +void SCOTCH_dgraphFree (SCOTCH_Dgraph * const); +int SCOTCH_dgraphLoad (SCOTCH_Dgraph * const, FILE * const, const SCOTCH_Num, const SCOTCH_Num); +int SCOTCH_dgraphSave (SCOTCH_Dgraph * const, FILE * const); +int SCOTCH_dgraphCheck (const SCOTCH_Dgraph * const); +int SCOTCH_dgraphBand (SCOTCH_Dgraph * const, const SCOTCH_Num, SCOTCH_Num * const, const SCOTCH_Num, SCOTCH_Dgraph * const); +int SCOTCH_dgraphBuild (SCOTCH_Dgraph * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +int SCOTCH_dgraphBuildGrid3D (SCOTCH_Dgraph * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const int); +int SCOTCH_dgraphCoarsen (SCOTCH_Dgraph * const, const SCOTCH_Num, const double, const SCOTCH_Num, SCOTCH_Dgraph * const, SCOTCH_Num * const); +int SCOTCH_dgraphGather (const SCOTCH_Dgraph * const, SCOTCH_Graph * const); +int SCOTCH_dgraphGrow (SCOTCH_Dgraph * const, const SCOTCH_Num, SCOTCH_Num * const, const SCOTCH_Num, SCOTCH_Num * const); +int SCOTCH_dgraphInducePart (SCOTCH_Dgraph * const, const SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num, SCOTCH_Dgraph * const); +int SCOTCH_dgraphScatter (SCOTCH_Dgraph * const, const SCOTCH_Graph * const); +int SCOTCH_dgraphRedist (SCOTCH_Dgraph * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num, SCOTCH_Dgraph * const); +void SCOTCH_dgraphSize (const SCOTCH_Dgraph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void SCOTCH_dgraphData (const SCOTCH_Dgraph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, MPI_Comm * const); +int SCOTCH_dgraphStat (const SCOTCH_Dgraph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const); +int SCOTCH_dgraphGhst (SCOTCH_Dgraph * const); +int SCOTCH_dgraphHalo (SCOTCH_Dgraph * const, void * const, const MPI_Datatype); +int SCOTCH_dgraphHaloAsync (SCOTCH_Dgraph * const, void * const, const MPI_Datatype, SCOTCH_DgraphHaloReq * const); +SCOTCH_DgraphHaloReq * SCOTCH_dgraphHaloReqAlloc (void); +int SCOTCH_dgraphHaloWait (SCOTCH_DgraphHaloReq * const); +int SCOTCH_dgraphMapInit (const SCOTCH_Dgraph * const, SCOTCH_Dmapping * const, const SCOTCH_Arch * const, SCOTCH_Num * const); +void SCOTCH_dgraphMapExit (const SCOTCH_Dgraph * const, SCOTCH_Dmapping * const); +int SCOTCH_dgraphMapSave (const SCOTCH_Dgraph * const, const SCOTCH_Dmapping * const, FILE * const); +int SCOTCH_dgraphMapView (SCOTCH_Dgraph * const, const SCOTCH_Dmapping * const, FILE * const); +int SCOTCH_dgraphMapCompute (SCOTCH_Dgraph * const, SCOTCH_Dmapping * const, SCOTCH_Strat * const); +int SCOTCH_dgraphMap (SCOTCH_Dgraph * const, const SCOTCH_Arch * const, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_dgraphPart (SCOTCH_Dgraph * const, const SCOTCH_Num, SCOTCH_Strat * const, SCOTCH_Num * const); +int SCOTCH_dgraphCorderInit (const SCOTCH_Dgraph * const, SCOTCH_Ordering * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void SCOTCH_dgraphCorderExit (const SCOTCH_Dgraph * const, SCOTCH_Ordering * const); + +int SCOTCH_dgraphOrderInit (const SCOTCH_Dgraph * const, SCOTCH_Dordering * const); +void SCOTCH_dgraphOrderExit (const SCOTCH_Dgraph * const, SCOTCH_Dordering * const); +int SCOTCH_dgraphOrderSave (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, FILE * const); +int SCOTCH_dgraphOrderSaveBlock (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, FILE * const); +int SCOTCH_dgraphOrderSaveMap (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, FILE * const); +int SCOTCH_dgraphOrderSaveTree (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, FILE * const); +int SCOTCH_dgraphOrderPerm (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, SCOTCH_Num * const); +SCOTCH_Num SCOTCH_dgraphOrderCblkDist (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const); +int SCOTCH_dgraphOrderTreeDist (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, SCOTCH_Num * const, SCOTCH_Num * const); +int SCOTCH_dgraphOrderCompute (SCOTCH_Dgraph * const, SCOTCH_Dordering * const, SCOTCH_Strat * const); +int SCOTCH_dgraphOrderComputeList (SCOTCH_Dgraph * const, SCOTCH_Dordering * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const); +int SCOTCH_dgraphOrderGather (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, SCOTCH_Ordering * const); + +SCOTCH_Dmapping * SCOTCH_dmapAlloc (void); + +SCOTCH_Dordering * SCOTCH_dorderAlloc (void); + +int SCOTCH_stratDgraphMap (SCOTCH_Strat * const, const char * const); +int SCOTCH_stratDgraphMapBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const double); +int SCOTCH_stratDgraphClusterBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const double, const double); +int SCOTCH_stratDgraphOrder (SCOTCH_Strat * const, const char * const); +int SCOTCH_stratDgraphOrderBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const double); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* PTSCOTCH_H */ diff --git a/scotch_6.0.3/src/libscotch/library_pt_f.h b/scotch_6.0.3/src/libscotch/library_pt_f.h new file mode 100644 index 00000000..e693f193 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_pt_f.h @@ -0,0 +1,116 @@ +!* Copyright 2004,2007,2009,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +!* +!* This file is part of the Scotch software package for static mapping, +!* graph partitioning and sparse matrix ordering. +!* +!* This software is governed by the CeCILL-C license under French law +!* and abiding by the rules of distribution of free software. You can +!* use, modify and/or redistribute the software under the terms of the +!* CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +!* URL: "http://www.cecill.info". +!* +!* As a counterpart to the access to the source code and rights to copy, +!* modify and redistribute granted by the license, users are provided +!* only with a limited warranty and the software's author, the holder of +!* the economic rights, and the successive licensors have only limited +!* liability. +!* +!* In this respect, the user's attention is drawn to the risks associated +!* with loading, using, modifying and/or developing or reproducing the +!* software by the user in light of its specific status of free software, +!* that may mean that it is complicated to manipulate, and that also +!* therefore means that it is reserved for developers and experienced +!* professionals having in-depth computer knowledge. Users are therefore +!* encouraged to load and test the software's suitability as regards +!* their requirements in conditions enabling the security of their +!* systems and/or data to be ensured and, more generally, to use and +!* operate it in the same conditions as regards security. +!* +!* The fact that you are presently reading this means that you have had +!* knowledge of the CeCILL-C license and that you accept its terms. +!* +!*********************************************************** +!* ** +!* NAME : library_pt_f.h ** +!* ** +!* AUTHOR : Francois PELLEGRINI ** +!* ** +!* FUNCTION : FORTRAN declaration file for the ** +!* LibPtscotch parallel static mapping and ** +!* sparse matrix block ordering sequential ** +!* library. ** +!* ** +!* DATES : # Version 3.4 : from : 04 feb 2000 ** +!* to 22 oct 2001 ** +!* # Version 4.0 : from : 16 jan 2004 ** +!* to 16 jan 2004 ** +!* # Version 5.0 : from : 26 apr 2006 ** +!* to 26 apr 2006 ** +!* # Version 5.1 : from : 26 mar 2009 ** +!* to 12 feb 2011 ** +!* # Version 6.0 : from : 22 oct 2011 ** +!* to 27 nov 2012 ** +!* ** +!*********************************************************** + +!* Flag definitions for the coarsening +!* routines. + + INTEGER SCOTCH_COARSENNOMERGE + PARAMETER (SCOTCH_COARSENNOMERGE = 16384) + +!* Flag definitions for the strategy +!* string selection routines. + + INTEGER SCOTCH_STRATDEFAULT + INTEGER SCOTCH_STRATQUALITY + INTEGER SCOTCH_STRATSPEED + INTEGER SCOTCH_STRATBALANCE + INTEGER SCOTCH_STRATSAFETY + INTEGER SCOTCH_STRATSCALABILITY + INTEGER SCOTCH_STRATRECURSIVE + INTEGER SCOTCH_STRATREMAP + INTEGER SCOTCH_STRATLEVELMAX + INTEGER SCOTCH_STRATLEVELMIN + INTEGER SCOTCH_STRATLEAFSIMPLE + INTEGER SCOTCH_STRATSEPASIMPLE + PARAMETER (SCOTCH_STRATDEFAULT = 0) + PARAMETER (SCOTCH_STRATQUALITY = 1) + PARAMETER (SCOTCH_STRATSPEED = 2) + PARAMETER (SCOTCH_STRATBALANCE = 4) + PARAMETER (SCOTCH_STRATSAFETY = 8) + PARAMETER (SCOTCH_STRATSCALABILITY = 16) + PARAMETER (SCOTCH_STRATRECURSIVE = 256) + PARAMETER (SCOTCH_STRATREMAP = 512) + PARAMETER (SCOTCH_STRATLEVELMAX = 4096) + PARAMETER (SCOTCH_STRATLEVELMIN = 8192) + PARAMETER (SCOTCH_STRATLEAFSIMPLE = 16384) + PARAMETER (SCOTCH_STRATSEPASIMPLE = 32768) + +!* Size definitions for the SCOTCH opaque +!* structures. These structures must be +!* allocated as arrays of DOUBLEPRECISION +!* values for proper padding. The dummy +!* sizes are computed at compile-time by +!* program "dummysizes". + + INTEGER SCOTCH_ARCHDIM + INTEGER SCOTCH_DGRAPHDIM + INTEGER SCOTCH_DGRAPHHALOREQDIM + INTEGER SCOTCH_DORDERDIM + INTEGER SCOTCH_GEOMDIM + INTEGER SCOTCH_GRAPHDIM + INTEGER SCOTCH_MAPDIM + INTEGER SCOTCH_MESHDIM + INTEGER SCOTCH_ORDERDIM + INTEGER SCOTCH_STRATDIM + PARAMETER (SCOTCH_ARCHDIM = DUMMYSIZEARCH) + PARAMETER (SCOTCH_DGRAPHDIM = DUMMYSIZEDGRAPH) + PARAMETER (SCOTCH_DGRAPHHALOREQDIM = DUMMYSIZEDGRAPHHALOREQ) + PARAMETER (SCOTCH_DORDERDIM = DUMMYSIZEDORDER) + PARAMETER (SCOTCH_GEOMDIM = DUMMYSIZEGEOM) + PARAMETER (SCOTCH_GRAPHDIM = DUMMYSIZEGRAPH) + PARAMETER (SCOTCH_MAPDIM = DUMMYSIZEMAP) + PARAMETER (SCOTCH_MESHDIM = DUMMYSIZEMESH) + PARAMETER (SCOTCH_ORDERDIM = DUMMYSIZEORDER) + PARAMETER (SCOTCH_STRATDIM = DUMMYSIZESTRAT) diff --git a/scotch_6.0.3/src/libscotch/library_random.c b/scotch_6.0.3/src/libscotch/library_random.c new file mode 100644 index 00000000..a97681e1 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_random.c @@ -0,0 +1,88 @@ +/* Copyright 2004,2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_random.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the API for the random **/ +/** generator control routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 15 jan 2005 **/ +/** to 15 jun 2005 **/ +/** # Version 6.0 : from : 08 oct 2012 **/ +/** to 08 oct 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the random handling routines. */ +/* */ +/************************************/ + +/*+ This routine resets the random generator +*** to simulate a start from scratch. +*** It returns: +*** - void : in all cases. ++*/ + +void +SCOTCH_randomReset () +{ + intRandReset (); +} + +/*+ This routine resets the random generator +*** to simulate a start from scratch. +*** It returns: +*** - void : in all cases. ++*/ + +void +SCOTCH_randomSeed ( +INT seedval) +{ + intRandSeed (seedval); +} diff --git a/scotch_6.0.3/src/libscotch/library_random_f.c b/scotch_6.0.3/src/libscotch/library_random_f.c new file mode 100644 index 00000000..1a7f6a6c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_random_f.c @@ -0,0 +1,87 @@ +/* Copyright 2004,2007,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_random_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** the random generator handling routines **/ +/** of the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 4.0 : from : 21 nov 2005 **/ +/** to 23 nov 2005 **/ +/** # Version 6.0 : from : 08 oct 2012 **/ +/** to 08 oct 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the random handling routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFRANDOMRESET, scotchfrandomreset, (), \ +()) +{ + SCOTCH_randomReset (); +} + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFRANDOMSEED, scotchfrandomseed, ( \ +const SCOTCH_Num * const seedptr), \ +(seedptr)) +{ + SCOTCH_randomSeed (*seedptr); +} diff --git a/scotch_6.0.3/src/libscotch/library_strat.c b/scotch_6.0.3/src/libscotch/library_strat.c new file mode 100644 index 00000000..a470adbf --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_strat.c @@ -0,0 +1,76 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_strat.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains miscellaneous **/ +/** routines for handling strategy **/ +/** strings. **/ +/** **/ +/** DATES : # Version 5.1 : from : 17 nov 2010 **/ +/** to 17 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/*****************************************/ +/* */ +/* These routines are the C API for */ +/* ordering structure handling routines. */ +/* */ +/*****************************************/ + +/*+ This routine reserves a memory area +*** of a size sufficient to store a +*** distributed ordering structure. +*** It returns: +*** - !NULL : if the initialization succeeded. +*** - NULL : on error. ++*/ + +SCOTCH_Strat * +SCOTCH_stratAlloc () +{ + return ((SCOTCH_Strat *) memAlloc (sizeof (SCOTCH_Strat))); +} diff --git a/scotch_6.0.3/src/libscotch/library_version.c b/scotch_6.0.3/src/libscotch/library_version.c new file mode 100644 index 00000000..9147f9a7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_version.c @@ -0,0 +1,82 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_version.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains miscellaneous **/ +/** routines for handling API- and **/ +/** version-related routines in the **/ +/** libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 nov 2010 **/ +/** to 16 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/************************************/ +/* */ +/* These routines are the C API for */ +/* miscellaneous routines. */ +/* */ +/************************************/ + +/*+ This routine returns the version, +*** release and patchlevel numbers of +*** the library being used (useful for +*** dynamic libraries). +*** It returns: +*** - void : in all cases. ++*/ + +void +SCOTCH_version ( +int * const versptr, +int * const relaptr, +int * const patcptr) +{ + *versptr = SCOTCH_VERSION; + *relaptr = SCOTCH_RELEASE; + *patcptr = SCOTCH_PATCHLEVEL; +} diff --git a/scotch_6.0.3/src/libscotch/library_version_f.c b/scotch_6.0.3/src/libscotch/library_version_f.c new file mode 100644 index 00000000..a16d0d7e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/library_version_f.c @@ -0,0 +1,76 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : library_version_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API for **/ +/** handling API- and version-related **/ +/** routines in the libSCOTCH library. **/ +/** **/ +/** DATES : # Version 5.1 : from : 16 nov 2010 **/ +/** to 16 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the version-related routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +SCOTCHFVERSION, scotchfversion, ( \ +int * const versptr, \ +int * const relaptr, \ +int * const patcptr), \ +(versptr, relaptr, patcptr)) +{ + SCOTCH_version (versptr, relaptr, patcptr); +} diff --git a/scotch_6.0.3/src/libscotch/mapping.c b/scotch_6.0.3/src/libscotch/mapping.c new file mode 100644 index 00000000..65da249f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mapping.c @@ -0,0 +1,516 @@ +/* Copyright 2004,2007-2009,2011,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mapping.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles (partial) mappings. **/ +/** **/ +/** DATES : # Version 0.0 : from : 31 mar 1993 **/ +/** to 31 mar 1993 **/ +/** # Version 1.0 : from : 04 oct 1993 **/ +/** to 06 oct 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.3 : from : 09 apr 1994 **/ +/** to 11 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 17 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 18 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 19 oct 1995 **/ +/** # Version 3.1 : from : 30 oct 1995 **/ +/** to 14 jun 1996 **/ +/** # Version 3.2 : from : 23 aug 1996 **/ +/** to 07 sep 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 30 mar 1999 **/ +/** # Version 3.4 : from : 11 sep 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 16 jan 2004 **/ +/** to 05 jan 2005 **/ +/** # Version 5.1 : from : 25 jun 2008 **/ +/** to 28 apr 2009 **/ +/** # Version 6.0 : from : 04 mar 2011 **/ +/** to 16 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MAPPING + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" + +/***********************************/ +/* */ +/* These routines handle mappings. */ +/* */ +/***********************************/ + +/* This routine builds a mapping. +** It returns: +** - 0 : if mapping successfully initialized. +** - !0 : on error. +*/ + +void +mapInit ( +Mapping * restrict const mappptr, /*+ Mapping structure +*/ +const Graph * restrict const grafptr, /*+ Graph data +*/ +const Arch * restrict const archptr, /*+ Architecture data +*/ +const ArchDom * restrict const domnptr) /*+ Target architecture initial domain +*/ +{ + Anum domnmax; /* Maximum number of domains */ + + domnmax = (archVar (archptr) != 0) /* If target architecture is variable-sized */ + ? MIN (1023, grafptr->vertnbr) /* Pre-set number of domains */ + : archDomSize (archptr, domnptr); /* Else get architecture size */ + domnmax ++; /* +1 for empty domain in mapBuild()/mapLoad() */ + + mapInit2 (mappptr, grafptr, archptr, domnptr, domnmax, 0); +} + +void +mapInit2 ( +Mapping * restrict const mappptr, /*+ Mapping structure +*/ +const Graph * restrict const grafptr, /*+ Graph data +*/ +const Arch * restrict const archptr, /*+ Architecture data +*/ +const ArchDom * restrict const domnptr, /*+ Target architecture initial domain +*/ +const Anum domnmax, +const Anum domnnbr) +{ + mappptr->flagval = MAPPINGNONE; + mappptr->grafptr = grafptr; + mappptr->archptr = archptr; + mappptr->parttax = NULL; + mappptr->domntab = NULL; + mappptr->domnnbr = domnnbr; + mappptr->domnmax = domnmax; + mappptr->domnorg = *domnptr; /* Use provided domain as original domain (e.g. when running a piece of parallel partitioning) */ +} + +/* This routine allocates the contents of a mapping. +** It returns: +** - 0 : if mapping successfully allocated. +** - !0 : on error. +*/ + +int +mapAlloc ( +Mapping * restrict const mappptr) /*+ Mapping structure to fill +*/ +{ + if ((mappptr->flagval & MAPPINGFREEPART) == 0) { /* If no private partition array yet */ + Anum * restrict parttab; + + if ((parttab = (Anum *) memAlloc (mappptr->grafptr->vertnbr * sizeof (Anum))) == NULL) { + errorPrint ("mapAlloc: out of memory (1)"); + return (1); + } + mappptr->flagval |= MAPPINGFREEPART; + mappptr->parttax = parttab - mappptr->grafptr->baseval; + } + + if ((mappptr->flagval & MAPPINGFREEDOMN) == 0) { /* If no private domain array yet */ + if ((mappptr->domntab = (ArchDom *) memAlloc (mappptr->domnmax * sizeof (ArchDom))) == NULL) { + errorPrint ("mapAlloc: out of memory (2)"); + return (1); + } + mappptr->flagval |= MAPPINGFREEDOMN; + } + + return (0); +} + +/* This routine resizes the domain array of a +** mapping and preserves its existing contents. +** It returns: +** - 0 : if mapping successfully allocated. +** - !0 : on error. +*/ + +int +mapResize ( +Mapping * restrict const mappptr, /*+ Mapping structure to fill +*/ +const Anum domnmax) +{ + int flagval; + const ArchDom * restrict domntab; + + flagval = mappptr->flagval; /* Save old flag value */ + domntab = mappptr->domntab; /* Save pointer to old domain array */ + + if (mapResize2 (mappptr, domnmax) != 0) /* Resize array */ + return (1); + + if (flagval != mappptr->flagval) /* If a new private array has been created */ + memCpy (mappptr->domntab, domntab, mappptr->domnnbr * sizeof (ArchDom)); + + return (0); +} + +/* This routine resizes the domain array of a +** mapping without preserving its existing contents. +** It returns: +** - 0 : if mapping successfully allocated. +** - !0 : on error. +*/ + +int +mapResize2 ( +Mapping * restrict const mappptr, /*+ Mapping structure to fill +*/ +const Anum domnmax) +{ + ArchDom * domntab; + + domntab = ((mappptr->flagval & MAPPINGFREEDOMN) != 0) /* If it was a privately owned array */ + ? memRealloc (mappptr->domntab, domnmax * sizeof (ArchDom)) /* Reallocate it */ + : memAlloc (domnmax * sizeof (ArchDom)); /* Else allocate it privately */ + if (domntab == NULL) { + errorPrint ("mapResize2: out of memory"); + return (1); + } + + mappptr->domntab = domntab; + mappptr->domnmax = domnmax; + mappptr->flagval |= MAPPINGFREEDOMN; /* Array is now private anyway */ + + return (0); +} + +/* This routine builds an initial mapping. +** It returns: +** - void : in all cases. +*/ + +void +mapFrst ( +Mapping * restrict const mappptr) /*+ Mapping structure to fill +*/ +{ + mappptr->domnnbr = 1; /* One domain in mapping to date */ + mappptr->domntab[0] = mappptr->domnorg; /* Set first domain */ + memSet (mappptr->parttax + mappptr->grafptr->baseval, 0, mappptr->grafptr->vertnbr * sizeof (Anum)); /* Set parttax to first domain */ +} + +/* This routine frees the contents +** of the given mapping. +** It returns: +** - void : in all cases. +*/ + +void +mapFree ( +Mapping * const mappptr) +{ + if (((mappptr->flagval & MAPPINGFREEDOMN) != 0) && /* If domntab must be freed */ + (mappptr->domntab != NULL)) /* And if exists */ + memFree (mappptr->domntab); /* Free it */ + if (((mappptr->flagval & MAPPINGFREEPART) != 0) && /* If parttax must be freed */ + (mappptr->parttax != NULL)) /* And if exists */ + memFree (mappptr->parttax + mappptr->grafptr->baseval); /* Free it */ + + mappptr->parttax = NULL; + mappptr->domntab = NULL; +} + +/* This routine frees the contents +** of the given mapping. +** It returns: +** - void : in all cases. +*/ + +void +mapExit ( +Mapping * const mappptr) +{ + mapFree (mappptr); + +#ifdef SCOTCH_DEBUG_MAP2 + memSet (mappptr, ~0, sizeof (Mapping)); +#endif /* SCOTCH_DEBUG_MAP2 */ +} + +/* This routine copies a mapping onto another. +** It returns: +** - 0 : if mapping successfully copied. +** - !0 : on error. +*/ + +int +mapCopy ( +Mapping * restrict const mappptr, /*+ Mapping to set +*/ +const Mapping * restrict const mapoptr) /*+ Old mapping +*/ +{ + ArchDom * domntab; + Anum domnnbr; + Gnum baseval; + +#ifdef SCOTCH_DEBUG_MAP2 + if (mappptr->grafptr->vertnbr != mapoptr->grafptr->vertnbr) { + errorPrint ("mapCopy: mappings do not match"); + return (1); + } +#endif /* SCOTCH_DEBUG_MAP2 */ + + baseval = mapoptr->grafptr->baseval; + domnnbr = mapoptr->domnnbr; + if (domnnbr > mappptr->domnmax) { /* If we have to resize domain array */ + if (mapResize2 (mappptr, domnnbr) != 0) /* Resize it */ + return (1); + } + + mappptr->domnnbr = domnnbr; + memCpy (mappptr->domntab, mapoptr->domntab, domnnbr * sizeof (ArchDom)); + memCpy (mappptr->parttax + baseval, mapoptr->parttax + baseval, mapoptr->grafptr->vertnbr * sizeof (Anum)); + + return (0); +} + +/* This routine builds a mapping from a +** terminal domain partition array. +** It returns: +** - 0 : if mapping successfully filled. +** - !0 : on error. +*/ + +static +int +mapBuild2 ( +Mapping * restrict const mappptr, /*+ Mapping to set +*/ +MappingHash * restrict * const hashtabptr, /*+ Pointer to hash table to set up +*/ +Gnum * const hashsizptr) /*+ Size of hash table +*/ +{ + ArchDom domndat; + MappingHash * hashtab; + Gnum hashnbr; /* Prospective number of cells in table */ + Gnum hashsiz; /* Size of hash table */ + + const Arch * restrict const archptr = mappptr->archptr; + +#ifdef SCOTCH_DEBUG_MAP2 + if (mappptr->domnmax < 1) { + errorPrint ("mapBuild2: domain array is too small"); + return (1); + } +#endif /* SCOTCH_DEBUG_MAP2 */ + + archDomFrst (archptr, &domndat); + hashnbr = (archVar (archptr) == 0) /* If fixed size architecture */ + ? archDomSize (archptr, &domndat) /* Get maximum size of distinct terminal domains */ + : mappptr->grafptr->vertnbr; /* Else take upper bound as number of vertices */ + hashnbr ++; /* Add one extra slot for unknown terminal domain */ + + for (hashsiz = 32; hashsiz < hashnbr; hashsiz <<= 1) ; /* Get upper power of two */ + hashsiz <<= 2; /* Fill hash table at 25% maximum */ + + if ((hashtab = (MappingHash *) memAlloc (hashsiz * sizeof (MappingHash))) == NULL) { + errorPrint ("mapBuild2: out of memory"); + return (1); + } + memSet (hashtab, ~0, hashsiz * sizeof (MappingHash)); /* Set all vertex numbers to ~0 */ + + *hashtabptr = hashtab; + *hashsizptr = hashsiz; + + return (0); +} + +static +int +mapBuild3 ( +Mapping * restrict const mappptr, /*+ Mapping to fill +*/ +MappingHash * restrict const hashtab, /*+ Hash table +*/ +const Gnum hashsiz, /*+ Hash table size +*/ +const Anum * restrict const termtax) /*+ Terminal array to load +*/ +{ + ArchDom * restrict domntab; + Anum domnnbr; + Anum domnmax; + Gnum hashmsk; + Gnum vertnnd; + Gnum vertnum; + int o; + + const Arch * restrict const archptr = mappptr->archptr; + Anum * restrict const parttax = mappptr->parttax; + + o = 1; /* Assume loop will fail */ + hashmsk = hashsiz - 1; + domntab = mappptr->domntab; + domnnbr = mappptr->domnnbr; + domnmax = mappptr->domnmax; + for (vertnum = mappptr->grafptr->baseval, vertnnd = mappptr->grafptr->vertnnd; + vertnum < vertnnd; vertnum ++) { + Gnum hashnum; + Anum termnum; + Anum domnnum; + + termnum = termtax[vertnum]; + if (termnum == ~0) /* If unknown part, skip it */ + continue; + + for (hashnum = (termnum * MAPPINGHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + if (hashtab[hashnum].termnum == termnum) { /* If hash slot found */ + domnnum = hashtab[hashnum].domnnum; /* Domain number found */ + break; + } + if (hashtab[hashnum].termnum == ~0) { /* If hash slot empty */ + hashtab[hashnum].termnum = termnum; /* Create slot */ + hashtab[hashnum].domnnum = domnnbr; + + if (domnnbr == domnmax) { + domnmax += (domnmax >> 2) + 8; /* Increase size by 25% */ + if (mapResize (mappptr, domnmax) != 0) + goto fail; + domntab = mappptr->domntab; /* Re-read pointer in case it changed */ + } + archDomTerm (archptr, &domntab[domnnbr], termnum); /* Create slot with terminal number domain */ + domnnum = domnnbr ++; /* Get position of new slot; one more slot created */ + break; + } + } + parttax[vertnum] = domnnum; /* Refer to the proper domain */ + } + o = 0; /* Success */ + +fail: + mappptr->domnnbr = domnnbr; /* Set updated number of domains */ + + memFree (hashtab); /* Free hash table */ + + return (o); +} + +int +mapBuild ( +Mapping * restrict const mappptr, /*+ Mapping to set +*/ +const Anum * restrict const termtax) /*+ Terminal array to load +*/ +{ + MappingHash * restrict hashtab; + Gnum hashsiz; /* Size of hash table */ + + if (mapBuild2 (mappptr, &hashtab, &hashsiz) != 0) + return (1); + return (mapBuild3 (mappptr, hashtab, hashsiz, termtax)); +} + +/* This routine updates a mapping with a +** terminal domain partition array. +** It returns: +** - 0 : if mapping successfully updated. +** - !0 : on error. +*/ + +int +mapMerge ( +Mapping * restrict const mappptr, /*+ Mapping to set +*/ +const Anum * restrict const termtab) /*+ Terminal array to load +*/ +{ + MappingHash * restrict hashtab; + Gnum hashsiz; /* Size of hash table */ + Gnum hashmsk; + Anum domnnbr; + Anum domnnum; + + const Arch * restrict const archptr = mappptr->archptr; + const ArchDom * restrict const domntab = mappptr->domntab; + + if (mapBuild2 (mappptr, &hashtab, &hashsiz) != 0) + return (1); + + hashmsk = hashsiz - 1; + for (domnnum = 0, domnnbr = mappptr->domnnbr; domnnum < domnnbr; domnnum ++) { + const ArchDom * domnptr; + Gnum hashnum; + Anum termnum; + + domnptr = &domntab[domnnum]; + if (archDomSize (archptr, domnptr) != 1) /* If domain is not terminal, skip it */ + continue; + + termnum = archDomNum (archptr, domnptr); + + for (hashnum = (termnum * MAPPINGHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { /* Fill hash table with existing domains */ +#ifdef SCOTCH_DEBUG_MAP2 + if (hashtab[hashnum].termnum == termnum) { /* If hash slot found */ + errorPrint ("mapMerge: internal error"); /* Multiple domains with same terminal number */ + return (1); + } +#endif /* SCOTCH_DEBUG_MAP2 */ + if (hashtab[hashnum].termnum == ~0) { /* If hash slot empty */ + hashtab[hashnum].termnum = termnum; /* Create slot */ + hashtab[hashnum].domnnum = domnnum; + break; + } + } + } + + return (mapBuild3 (mappptr, hashtab, hashsiz, termtab)); /* Add new domains to existing domain array */ +} + +/* This routine propagates back mapping +** information to a terminal part array. +** It returns: +** - void : in all cases. +*/ + +void +mapTerm ( +const Mapping * restrict const mappptr, +Anum * restrict const termtax) +{ + Gnum vertnnd; + Gnum vertnum; + + const Arch * restrict const archptr = mappptr->archptr; + const ArchDom * restrict const domntab = mappptr->domntab; + const Anum * restrict const parttax = mappptr->parttax; + + vertnum = mappptr->grafptr->baseval; + if (domntab != NULL) { + for (vertnnd = mappptr->grafptr->vertnnd; + vertnum < vertnnd; vertnum ++) + termtax[vertnum] = archDomNum (archptr, &domntab[parttax[vertnum]]); + } + else + memSet (termtax + vertnum, ~0, mappptr->grafptr->vertnbr * sizeof (Anum)); +} diff --git a/scotch_6.0.3/src/libscotch/mapping.h b/scotch_6.0.3/src/libscotch/mapping.h new file mode 100644 index 00000000..047fadef --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mapping.h @@ -0,0 +1,164 @@ +/* Copyright 2004,2007,2008,2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mapping.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the declarations for **/ +/** the mapping handling routines. **/ +/** **/ +/** DATES : # Version 0.0 : from : 15 dec 1992 **/ +/** to 01 apr 1993 **/ +/** # Version 1.0 : from : 04 oct 1993 **/ +/** to 06 oct 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.3 : from : 09 apr 1994 **/ +/** to 11 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 02 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 18 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 04 jul 1995 **/ +/** # Version 3.1 : from : 30 oct 1995 **/ +/** to 06 jun 1996 **/ +/** # Version 3.2 : from : 23 aug 1996 **/ +/** to 26 may 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 30 mar 1999 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 13 nov 2005 **/ +/** # Version 5.1 : from : 25 jun 2008 **/ +/** to 04 nov 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 14 sep 2014 **/ +/** **/ +/** NOTES : # While Anum and Gnum are different **/ +/** types, because architectures are **/ +/** most often much smaller than **/ +/** than graphs and require smaller **/ +/** integer ranges, for interface **/ +/** consistency reasons as well as for **/ +/** variable-sized architecture handling, **/ +/** they will always amount to the same **/ +/** type. **/ +/** **/ +/************************************************************/ + +#define MAPPING_H + +/* +** The defines. +*/ + +/*+ Prime number for hashing terminal domain numbers. +*/ + +#define MAPPINGHASHPRIME 17 /*+ Prime number for hashing +*/ + +/*+ Graph option flags. +*/ + +#define MAPPINGNONE 0x0000 /* No options set */ + +#define MAPPINGFREEPART 0x0001 /* Free partition array */ +#define MAPPINGFREEDOMN 0x0002 /* Free domain array */ + +/* +** The type definitions. +*/ + +/*+ This structure defines an (eventually + partial) mapping of a source graph to + a target architecture. +*/ + +typedef struct Mapping_ { + int flagval; /*+ Mapping properties +*/ + const Graph * grafptr; /*+ Graph data +*/ + const Arch * archptr; /*+ Architecture data +*/ + Anum * parttax; /*+ Mapping array [vertnbr] +*/ + ArchDom * domntab; /*+ Array of domains [domnmax] +*/ + Anum domnnbr; /*+ Current number of domains +*/ + Anum domnmax; /*+ Maximum number of domains +*/ + ArchDom domnorg; /*+ Initial (sub)domain +*/ +} Mapping; + +/*+ The target architecture sort structure, used + to sort vertices by increasing label value. +*/ + +typedef struct MappingHash_ { + Anum termnum; /*+ Terminal vertex number +*/ + Anum domnnum; /*+ Domain number +*/ +} MappingHash; + +/*+ The target architecture sort structure, used + to sort vertices by increasing label value. +*/ + +typedef struct MappingSort_ { + Anum labl; /*+ Target architecture vertex label +*/ + Anum peri; /*+ Inverse permutation +*/ +} MappingSort; + +/* +** The function prototypes. +*/ +void mapExit (Mapping * const); + +#ifndef MAPPING +#define static +#endif + +void mapInit (Mapping * restrict const, const Graph * restrict const, const Arch * restrict const, const ArchDom * restrict const); +void mapInit2 (Mapping * restrict const, const Graph * restrict const, const Arch * restrict const, const ArchDom * restrict const, const Anum, const Anum); +void mapExit (Mapping * const); +int mapAlloc (Mapping * const); +void mapFree (Mapping * const); +int mapResize (Mapping * restrict const, const Anum); +int mapResize2 (Mapping * restrict const, const Anum); +int mapCopy (Mapping * const, const Mapping * const); +void mapFrst (Mapping * const); +int mapBuild (Mapping * restrict const, const Anum * restrict const); +int mapMerge (Mapping * restrict const, const Anum * restrict const); +void mapTerm (const Mapping * restrict const, Anum * restrict const); +int mapLoad (Mapping * restrict const, const Gnum * restrict const, FILE * restrict const); +int mapSave (const Mapping * restrict const, FILE * restrict const); +int mapView (const Mapping * restrict const, const Graph * restrict const, FILE * const); + +#undef static + +/* +** The macro definitions. +*/ + +#define mapDomain(map,idx) (&((map)->domntab[(map)->parttax[(idx)]])) diff --git a/scotch_6.0.3/src/libscotch/mapping_io.c b/scotch_6.0.3/src/libscotch/mapping_io.c new file mode 100644 index 00000000..d7177f96 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mapping_io.c @@ -0,0 +1,239 @@ +/* Copyright 2004,2007,2008,2010,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mapping_io.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module handles (partial) mappings. **/ +/** **/ +/** DATES : # Version 0.0 : from : 31 mar 1993 **/ +/** to 31 mar 1993 **/ +/** # Version 1.0 : from : 04 oct 1993 **/ +/** to 06 oct 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.3 : from : 09 apr 1994 **/ +/** to 11 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 17 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 18 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 19 oct 1995 **/ +/** # Version 3.1 : from : 30 oct 1995 **/ +/** to 14 jun 1996 **/ +/** # Version 3.2 : from : 23 aug 1996 **/ +/** to 07 sep 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 30 mar 1999 **/ +/** # Version 3.4 : from : 11 sep 2001 **/ +/** to 08 nov 2001 **/ +/** # Version 4.0 : from : 16 jan 2004 **/ +/** to 14 nov 2005 **/ +/** # Version 5.0 : from : 13 sep 2006 **/ +/** to 27 feb 2008 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 03 mar 2011 **/ +/** to 22 aug 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MAPPING_IO + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "mapping_io.h" + +/***********************************/ +/* */ +/* These routines handle mappings. */ +/* */ +/***********************************/ + +/* This routine reads the contents of the given mapping +** file to the given mapping, reordering vertices +** according to the given vertex label table if necessary. +** It returns: +** - 0 : if mapping successfully written. +** - 1 : on error. +** - 2 : variable-sized architectures cannot be loaded. +*/ + +/* TODO remove it */ +int /* TODO copy the one from gout? */ +mapLoad ( +Mapping * restrict const mappptr, +const Gnum * restrict const vlbltab, +FILE * restrict const stream) +{ + Gnum vertnum; + Gnum mappnum; + Gnum mappnbr; + MappingLoadMap * mapptab; /* Mapping array */ + MappingLoadPerm * permtab; /* Array of sorted label/index pairs */ + Anum archnbr; /* Size of the target architecture */ + ArchDom fdomdat; /* First domain of architecture */ + + if (strcmp (archName (mappptr->archptr), "term") == 0) /* If target architecture is variable-sized */ + return (2); + + archDomFrst (mappptr->archptr, &fdomdat); /* Get architecture size */ + archnbr = archDomSize (mappptr->archptr, &fdomdat); + if (mappptr->domnmax < (archnbr + 1)) { /* If mapping array too small to store mapping data */ + ArchDom * restrict domntab; + + if ((domntab = (ArchDom *) memRealloc (mappptr->domntab, (archnbr + 1) * sizeof (ArchDom))) == NULL) { /* If cannot resize domain array */ + errorPrint ("mapLoad: out of memory (1)"); + return (1); + } + + mappptr->domnmax = archnbr + 1; /* Point to new array */ + mappptr->domntab = domntab; + } + mappptr->domnnbr = archnbr + 1; /* One more for first domain, for unmapped vertices */ + archDomFrst (mappptr->archptr, &mappptr->domntab[0]); /* Set first domain with root domain data */ + for (mappnum = 0; mappnum < archnbr; mappnum ++) /* For all terminal domain numbers */ + archDomTerm (mappptr->archptr, &mappptr->domntab[mappnum + 1], mappnum); /* Set domain with terminal domain data */ + + if ((intLoad (stream, &mappnbr) != 1) || /* Read number of mapping entries */ + (mappnbr < 1)) { + errorPrint ("mapLoad: bad input (1)"); + return (1); + } + + if (memAllocGroup ((void **) (void *) + &mapptab, (size_t) (mappnbr * sizeof (MappingLoadMap)), + &permtab, (size_t) (mappptr->grafptr->vertnbr * sizeof (MappingLoadPerm)), NULL) == NULL) { + errorPrint ("mapLoad: out of memory (2)"); + return (1); + } + + for (mappnum = 0; mappnum < mappnbr; mappnum ++) { /* Load mapping array */ + if ((intLoad (stream, &mapptab[mappnum].slblnum) != 1) || + (intLoad (stream, &mapptab[mappnum].tlblnum) != 1)) { + errorPrint ("mapLoad: bad input (2)"); + return (1); + } + } + intSort2asc1 (mapptab, mappnbr); /* Sort mapping array by increasing source labels */ + + if (vlbltab != NULL) { /* If graph has vertex labels */ + Gnum vertnum; + + for (vertnum = 0; vertnum < mappptr->grafptr->vertnbr; vertnum ++) { /* Build inverse permutation */ + permtab[vertnum].vertnum = vertnum + mappptr->grafptr->baseval; + permtab[vertnum].vlblnum = vlbltab[vertnum]; + } + intSort2asc1 (permtab, mappptr->grafptr->vertnbr); /* Sort vertex array by increasing labels */ + } + else { + Gnum vertnum; + + for (vertnum = 0; vertnum < mappptr->grafptr->vertnbr; vertnum ++) { /* Build identity permutation */ + permtab[vertnum].vertnum = vertnum + mappptr->grafptr->baseval; + permtab[vertnum].vlblnum = vertnum + mappptr->grafptr->baseval; + } + } + + for (vertnum = 0, mappnum = 0; /* For all graph vertices */ + vertnum < mappptr->grafptr->vertnbr; vertnum ++) { + while ((mappnum < mappnbr) && /* Skip useless mapping data (if graph is subgraph of originally mapped graph) */ + (permtab[vertnum].vlblnum > mapptab[mappnum].slblnum)) + mappnum ++; + if (mappnum >= mappnbr) /* If all mapping data exhausted */ + break; /* Exit the matching loop */ + + if (permtab[vertnum].vlblnum == mapptab[mappnum].slblnum) { /* If matching mapping data found */ + if ((mapptab[mappnum].tlblnum >= 0) && /* If mapping valid */ + (mapptab[mappnum].tlblnum < archnbr)) + mappptr->parttax[permtab[vertnum].vertnum] = mapptab[mappnum].tlblnum + 1; /* Set mapping to terminal domain */ + mappnum ++; /* Mapping pair has been used */ + } + } + + memFree (mapptab); /* Free group leader */ + + return (0); +} + +/* This routine writes the contents of the +** given mapping to the given string. +** It returns: +** - 0 : if mapping successfully written. +** - !0 : on error. +*/ + +int +mapSave ( +const Mapping * restrict const mappptr, +FILE * restrict const stream) +{ + + Gnum vertnnd; + Gnum vertnum; + + const Arch * restrict const archptr = mappptr->archptr; + const ArchDom * restrict const domntab = mappptr->domntab; + const Anum * restrict const parttax = mappptr->parttax; + const Gnum * restrict const vlbltax = mappptr->grafptr->vlbltax; + + vertnum = mappptr->grafptr->baseval; + vertnnd = mappptr->grafptr->vertnbr; /* Un-based number at first */ + + if (fprintf (stream, GNUMSTRING "\n", + (Gnum) vertnnd) == EOF) { + errorPrint ("mapSave: bad output (1)"); + return (1); + } + + for (vertnnd += vertnum; vertnum < vertnnd; vertnum ++) { + if (fprintf (stream, GNUMSTRING "\t" ANUMSTRING "\n", + (Gnum) ((vlbltax != NULL) ? vlbltax[vertnum] : vertnum), + (Anum) (parttax != NULL) ? archDomNum (archptr, &domntab[parttax[vertnum]]) : -1) == EOF) { + errorPrint ("mapSave: bad output (2)"); + return (1); + } + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/mapping_io.h b/scotch_6.0.3/src/libscotch/mapping_io.h new file mode 100644 index 00000000..e5412a72 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mapping_io.h @@ -0,0 +1,97 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mapping_io.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the declarations for **/ +/** the mapping handling routines. **/ +/** **/ +/** DATES : # Version 0.0 : from : 15 dec 1992 **/ +/** to 01 apr 1993 **/ +/** # Version 1.0 : from : 04 oct 1993 **/ +/** to 06 oct 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.3 : from : 09 apr 1994 **/ +/** to 11 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 02 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 18 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 04 jul 1995 **/ +/** # Version 3.1 : from : 30 oct 1995 **/ +/** to 06 jun 1996 **/ +/** # Version 3.2 : from : 23 aug 1996 **/ +/** to 26 may 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to 30 mar 1999 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 13 nov 2005 **/ +/** # Version 5.0 : from : 13 sep 2006 **/ +/** to 13 sep 2006 **/ +/** **/ +/************************************************************/ + +#define MAPPING_H + +/* +** The defines. +*/ + +/*+ Ordering option flags. +*/ + +#define MAPNONE 0x0000 /* No options set */ +#define MAPFREEPART 0x0001 /* Free partition array */ + +/* +** The type definitions. +*/ + +/*+ This structure defines a source label + to target label mapping element. +*/ + +typedef struct MappingLoadMap_ { + Gnum slblnum; /*+ Source graph vertex label: FIRST +*/ + Gnum tlblnum; /*+ Target architecture vertex label +*/ +} MappingLoadMap; + +/*+ The source graph sort structure, used to + sort vertices by increasing label value. +*/ + +typedef struct MappingLoadPerm { + Gnum vlblnum; /*+ Vertex label: FIRST +*/ + Gnum vertnum; /*+ Vertex number +*/ +} MappingLoadPerm; diff --git a/scotch_6.0.3/src/libscotch/mesh.c b/scotch_6.0.3/src/libscotch/mesh.c new file mode 100644 index 00000000..829ece44 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh.c @@ -0,0 +1,191 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the source mesh **/ +/** functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 29 dec 2001 **/ +/** to 05 may 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MESH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" + +/****************************************/ +/* */ +/* These routines handle source meshes. */ +/* */ +/****************************************/ + +/* This routine initializes a source mesh +** structure. +** It returns: +** - 0 : in all cases. +*/ + +int +meshInit ( +Mesh * const meshptr) +{ + memSet (meshptr, 0, sizeof (Mesh)); /* Initialize mesh fields */ + meshptr->flagval = MESHFREETABS; /* By default, free all arrays */ + + return (0); +} + +/* This routine frees a source mesh structure. +** It returns: +** - VOID : in all cases. +*/ + +void +meshExit ( +Mesh * const meshptr) +{ + meshFree (meshptr); /* Exit mesh data */ + +#ifdef SCOTCH_DEBUG_MESH2 + memSet (meshptr, ~0, sizeof (Mesh)); /* Purge mesh fields */ +#endif /* SCOTCH_DEBUG_MESH2 */ +} + +/* This routine frees the mesh data. Because +** vertex load arrays are either passed by +** the user, or grouped with other arrays, +** they are not considered for explicit +** freeing. This is also much simpler, as +** load arrays can be grouped or not. +** It returns: +** - VOID : in all cases. +*/ + +void +meshFree ( +Mesh * const meshptr) +{ + if (((meshptr->flagval & MESHFREEEDGE) != 0) && /* If edgetab must be freed */ + (meshptr->edgetax != NULL)) /* And if it exists */ + memFree (meshptr->edgetax + meshptr->baseval); /* Free it */ + + if ((meshptr->flagval & MESHFREEVEND) != 0) { /* If vendtab must be freed */ + if ((meshptr->vendtax != NULL) && /* If vendtab is distinct from verttab */ + (meshptr->vendtax != meshptr->verttax + 1) && /* (if vertex arrays grouped, vendtab not distinct anyway) */ + ((meshptr->flagval & MESHVERTGROUP) == 0)) + memFree (meshptr->vendtax + meshptr->baseval); /* Then free vendtab */ + } + if ((meshptr->flagval & MESHFREEVERT) != 0) { /* If verttab must be freed */ + if (meshptr->verttax != NULL) /* Free verttab anyway, as it is the array group leader */ + memFree (meshptr->verttax + meshptr->baseval); + } +#ifdef SCOTCH_DEBUG_MESH2 + if ((meshptr->flagval & MESHFREEVNUM) != 0) { /* If vnumtab must be freed */ + if ((meshptr->vnumtax != NULL) && /* And is not in vertex array group */ + ((meshptr->flagval & MESHVERTGROUP) == 0)) + errorPrint ("meshFree: vnumtab should never be freed as its base may vary according to creation routines"); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + if ((meshptr->flagval & MESHFREEOTHR) != 0) { /* If other arrays must be freed */ + if (meshptr->vlbltax != NULL) + memFree (meshptr->vlbltax + meshptr->baseval); + } + +#ifdef SCOTCH_DEBUG_MESH2 + memSet (meshptr, ~0, sizeof (Mesh)); /* Purge mesh fields */ +#endif /* SCOTCH_DEBUG_MESH2 */ +} + +/* This routine sets the base of the given +** mesh to the given base value, and returns +** the old base value. +** It returns: +** - old base value : in all cases. +*/ + +Gnum +meshBase ( +Mesh * const meshptr, +const Gnum baseval) +{ + Gnum baseold; /* Old base value */ + Gnum baseadj; /* Base adjustment */ + Gnum vertnum; + Gnum edgenum; + + if (meshptr->baseval == baseval) /* If nothing to do */ + return (baseval); + + baseold = meshptr->baseval; /* Record old base value */ + baseadj = baseval - baseold; /* Compute adjustment */ + + for (vertnum = meshptr->baseval; vertnum < (meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval); vertnum ++) { + for (edgenum = meshptr->verttax[vertnum]; edgenum < meshptr->vendtax[vertnum]; edgenum ++) + meshptr->edgetax[edgenum] += baseadj; + meshptr->verttax[vertnum] += baseadj; + } + if (meshptr->vendtax != meshptr->verttax + 1) { /* If distinct vertex end array */ + for (vertnum = meshptr->baseval; vertnum < (meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval); vertnum ++) + meshptr->vendtax[vertnum] += baseadj; + } + else /* If same vertex end array (of size +1) */ + meshptr->verttax[meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval] += baseadj; /* Adjust last entry of verttab */ + + meshptr->verttax -= baseadj; /* Adjust array accesses */ + meshptr->vendtax -= baseadj; + meshptr->edgetax -= baseadj; + + if (meshptr->vnumtax != NULL) + meshptr->vnumtax -= baseadj; + if (meshptr->vlbltax != NULL) + meshptr->vlbltax -= baseadj; + + meshptr->baseval = baseval; /* Set new base value */ + meshptr->velmbas += baseadj; /* Adjust mesh parameter */ + meshptr->velmnnd += baseadj; + meshptr->vnodbas += baseadj; + meshptr->vnodnnd += baseadj; + + return (baseold); /* Return old base value */ +} diff --git a/scotch_6.0.3/src/libscotch/mesh.h b/scotch_6.0.3/src/libscotch/mesh.h new file mode 100644 index 00000000..fceb882c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh.h @@ -0,0 +1,151 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source mesh functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 29 dec 2001 **/ +/** to 11 may 2004 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Mesh option flags. +*/ + +#define MESHNONE 0x0000 /* No options set */ + +#define MESHFREEEDGE 0x0001 /* Free edgetab array */ +#define MESHFREEVERT 0x0002 /* Free verttab array */ +#define MESHFREEVEND 0x0004 /* Free verttab array */ +#define MESHFREEVNUM 0x0008 /* Free vnumtab array */ +#define MESHFREEOTHR 0x0010 /* Free all other arrays */ +#define MESHFREETABS 0x001F /* Free all mesh arrays */ +#define MESHVERTGROUP 0x0010 /* All vertex arrays grouped */ + +/*+ The Mesh flag type. +*/ + +typedef int MeshFlag; /*+ Mesh property flags +*/ + +/*+ Mesh structure. It is basically a graph + structure. It is a bipartite graph in the + sense that node vertices are adjacent + to element vertices only, and that element + vertices are adjacent to node vertices only. + Node vertices can all be put before or after + element vertices, but node and element + vertices cannot be mixed. In most algorithms, + elements are put at the beginning because + critical algorithms, such as the mesh + induction and mesh coarsening routines, + start by scanning element edges, such that + elements can then be built on the fly before + nodes are processed. Furthermore, as halo + meshes comprise halo nodes but not halo + elements, all halo nodes will be put at the + end of the node array, making un-haloing much + easier and inexpensive. + Vertex global indices are also different, + as vnumtab is only valid for (non-halo) + node vertices. The base of the vnumtax array + is thus vnodbas, and not s.baseval . Moreover, + the contents of vnumtab is based with respect + to baseval, and not to vnodbas, so that + building the inverse permutation does not + require to know vnodbas to trim node indices. + When vertex loads are available, node loads + represent the number of degrees of freedom + per node, and element loads should be set as + the sum of the vertex loads of all of their + adjacent nodes (used by routines such as + vmeshSeparateGg). +*/ + +typedef struct Mesh_ { + MeshFlag flagval; /*+ Graph properties +*/ + Gnum baseval; /*+ Base index for edge/vertex arrays +*/ + Gnum velmnbr; /*+ Number of element vertices +*/ + Gnum velmbas; /*+ Based number of first element +*/ + Gnum velmnnd; /*+ Based number of first non-element vertex +*/ + Gnum veisnbr; /*+ Number of isolated element vertices +*/ + Gnum vnodnbr; /*+ Number of node vertices in mesh +*/ + Gnum vnodbas; /*+ Based number of first node +*/ + Gnum vnodnnd; /*+ Based number of first non-node vertex +*/ + Gnum * verttax; /*+ Vertex array [based] +*/ + Gnum * vendtax; /*+ End vertex array [based] +*/ + Gnum * velotax; /*+ Element vertex load array (if present) +*/ + Gnum * vnlotax; /*+ Node vertex load array (if present) +*/ + Gnum velosum; /*+ Sum of element vertex weights +*/ + Gnum vnlosum; /*+ Sum of node vertex weights +*/ + Gnum * vnumtax; /*+ Vertex number in ancestor graph +*/ + Gnum * vlbltax; /*+ Vertex label (from file) +*/ + Gnum edgenbr; /*+ Number of edges (arcs) in graph +*/ + Gnum * edgetax; /*+ Edge array [based] +*/ + Gnum degrmax; /*+ Maximum degree +*/ +} Mesh; + +/* +** The function prototypes. +*/ + +#ifndef MESH +#define static +#endif + +int meshInit (Mesh * const); +void meshExit (Mesh * const); +void meshFree (Mesh * const); +int meshLoad (Mesh * restrict const, FILE * restrict const, const Gnum); +int meshSave (const Mesh * restrict const, FILE * restrict const); +Gnum meshBase (Mesh * const, const Gnum); +int meshGraph (const Mesh * restrict const, Graph * restrict const); +int meshInduceList (const Mesh *, Mesh *, const VertList *); +int meshInducePart (const Mesh *, Mesh *, const Gnum, const GraphPart *, const GraphPart); +int meshInduceSepa (const Mesh * restrict const, const GraphPart * restrict const, const Gnum, const Gnum * restrict const, Mesh * restrict const); +int meshCheck (const Mesh * const); +int meshReorder (const Mesh * restrict const, Mesh * restrict const); + +#ifdef GEOM_H +int meshGeomLoadHabo (Mesh * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); +int meshGeomLoadScot (Mesh * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); +int meshGeomSaveScot (const Mesh * restrict const, const Geom * restrict const, FILE * const, FILE * const, const char * const); +#endif /* GEOM_H */ + +#undef static diff --git a/scotch_6.0.3/src/libscotch/mesh_check.c b/scotch_6.0.3/src/libscotch/mesh_check.c new file mode 100644 index 00000000..95b13e2c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_check.c @@ -0,0 +1,229 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the source mesh **/ +/** functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 29 dec 2001 **/ +/** to 11 may 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MESH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" + +/****************************************/ +/* */ +/* These routines handle source meshes. */ +/* */ +/****************************************/ + +/* This routine checks the consistency +** of the given mesh. +** It returns: +** - 0 : if mesh data are consistent. +** - !0 : on error. +*/ + +int +meshCheck ( +const Mesh * const meshptr) +{ + Gnum vertnnd; /* Maximum vertex index */ + Gnum vertnum; /* Number of current vertex */ + Gnum veisnbr; /* Number of isolated element vertices */ + Gnum velosum; /* Vertex element load sum */ + Gnum vnlosum; /* Vertex node load sum */ + Gnum degrmax; /* Maximum degree */ + + if ((meshptr->velmbas > meshptr->velmnnd) || + (meshptr->vnodbas > meshptr->vnodnnd) || + ((meshptr->velmnnd != meshptr->vnodbas) && + (meshptr->vnodnnd != meshptr->velmbas))) { + errorPrint ("meshCheck: invalid node and element numbers"); + return (1); + } + + vertnnd = meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval; + degrmax = 0; + veisnbr = 0; + for (vertnum = meshptr->velmbas; vertnum < meshptr->velmnnd; vertnum ++) { /* For all element vertices */ + Gnum degrval; + Gnum edgenum; + + if ((meshptr->verttax[vertnum] < meshptr->baseval) || + (meshptr->vendtax[vertnum] < meshptr->verttax[vertnum])) { + errorPrint ("meshCheck: invalid vertex arrays (1)"); + return (1); + } + + degrval = meshptr->vendtax[vertnum] - meshptr->verttax[vertnum]; + if (degrval > degrmax) + degrmax = degrval; + else if (degrval == 0) + veisnbr ++; + + for (edgenum = meshptr->verttax[vertnum]; edgenum < meshptr->vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* Number of end vertex */ + Gnum edgeend; /* Number of end vertex edge */ + + vertend = meshptr->edgetax[edgenum]; + + if ((vertend < meshptr->baseval) || (vertend >= vertnnd)) { /* If invalid edge end */ + errorPrint ("meshCheck: invalid edge array (1)"); + return (1); + } + if ((vertend >= meshptr->velmbas) && + (vertend < meshptr->velmnnd)) { + errorPrint ("meshCheck: element vertices must not be connected together"); + return (1); + } + + for (edgeend = meshptr->verttax[vertend]; /* Search for matching arc */ + (edgeend < meshptr->vendtax[vertend]) && (meshptr->edgetax[edgeend] != vertnum); + edgeend ++) ; + if (edgeend >= meshptr->vendtax[vertend]) { + errorPrint ("meshCheck: arc data do not match (1)"); + return (1); + } + for (edgeend ++; /* Search for duplicate arcs */ + (edgeend < meshptr->vendtax[vertend]) && (meshptr->edgetax[edgeend] != vertnum); + edgeend ++) ; + if (edgeend < meshptr->vendtax[vertend]) { + errorPrint ("meshCheck: duplicate arc (1)"); + return (1); + } + } + } + if (veisnbr != meshptr->veisnbr) { + errorPrint ("meshCheck: invalid number of isolated element vertices (1)"); + return (1); + } + + for (vertnum = meshptr->vnodbas; vertnum < meshptr->vnodnnd; vertnum ++) { /* For all node vertices */ + Gnum edgenum; + + if ((meshptr->verttax[vertnum] < meshptr->baseval) || + (meshptr->vendtax[vertnum] < meshptr->verttax[vertnum])) { + errorPrint ("meshCheck: invalid vertex arrays (2)"); + return (1); + } + if ((meshptr->vendtax[vertnum] - meshptr->verttax[vertnum]) > degrmax) + degrmax = meshptr->vendtax[vertnum] - meshptr->verttax[vertnum]; + + for (edgenum = meshptr->verttax[vertnum]; edgenum < meshptr->vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* Number of end vertex */ + Gnum edgeend; /* Number of end vertex edge */ + + vertend = meshptr->edgetax[edgenum]; + + if ((vertend < meshptr->baseval) || (vertend >= vertnnd)) { /* If invalid edge end */ + errorPrint ("meshCheck: invalid edge array (2)"); + return (1); + } + if ((vertend >= meshptr->vnodbas) && + (vertend < meshptr->vnodnnd)) { + errorPrint ("meshCheck: node vertices must not be connected together"); + return (1); + } + + for (edgeend = meshptr->verttax[vertend]; /* Search for matching arc */ + (edgeend < meshptr->vendtax[vertend]) && (meshptr->edgetax[edgeend] != vertnum); + edgeend ++) ; + if (edgeend >= meshptr->vendtax[vertend]) { + errorPrint ("meshCheck: arc data do not match (2)"); + return (1); + } + for (edgeend ++; /* Search for duplicate arcs */ + (edgeend < meshptr->vendtax[vertend]) && (meshptr->edgetax[edgeend] != vertnum); + edgeend ++) ; + if (edgeend < meshptr->vendtax[vertend]) { + errorPrint ("meshCheck: duplicate arc (2)"); + return (1); + } + } + } + + if (meshptr->velotax == NULL) /* Recompute node vertex load sum */ + velosum = meshptr->velmnnd - meshptr->velmbas; + else { + for (vertnum = meshptr->velmbas, velosum = 0; + vertnum < meshptr->velmnnd; vertnum ++) { + if (meshptr->velotax[vertnum] < 1) { + errorPrint ("meshCheck: invalid element vertex load"); + return (1); + } + velosum += meshptr->velotax[vertnum]; + } + } + if (velosum != meshptr->velosum) { + errorPrint ("meshCheck: invalid element vertex load sum"); + return (1); + } + + if (meshptr->vnlotax == NULL) /* Recompute node vertex load sum */ + vnlosum = meshptr->vnodnnd - meshptr->vnodbas; + else { + for (vertnum = meshptr->vnodbas, vnlosum = 0; + vertnum < meshptr->vnodnnd; vertnum ++) { + if (meshptr->vnlotax[vertnum] < 1) { + errorPrint ("meshCheck: invalid node vertex load"); + return (1); + } + vnlosum += meshptr->vnlotax[vertnum]; + } + } + if (vnlosum != meshptr->vnlosum) { + errorPrint ("meshCheck: invalid node vertex load sum"); + return (1); + } + + if (meshptr->degrmax < degrmax) { + errorPrint ("meshCheck: invalid maximum degree"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/mesh_coarsen.c b/scotch_6.0.3/src/libscotch/mesh_coarsen.c new file mode 100644 index 00000000..1b84eaac --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_coarsen.c @@ -0,0 +1,614 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_coarsen.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the source mesh **/ +/** coarsening functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 30 jan 2004 **/ +/** to 05 may 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to 12 sep 2007 **/ +/** **/ +/** NOTES : # The coarsening process is as follows. **/ +/** First, node collapsing is performed, **/ +/** such that pairs of matching nodes are **/ +/** created, or kept as single nodes. **/ +/** Then, elements are built, and merged **/ +/** whenever possible. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MESH_COARSEN + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "mesh_coarsen.h" + +/* +** The static variables. +*/ + +static void (* meshCoarFuncTab[MESHCOARSENNBR]) () = { /* Tables of matching routines */ + meshCoarsenMatchNg }; + +/***************************/ +/* */ +/* The coarsening routine. */ +/* */ +/***************************/ + +/* This routine coarsens the given "finemesh" into +** "coarmesh", as long as the coarsening ratio remains +** below some threshold value and the coarsened mesh +** is not too small. +** It returns: +** - 0 : if the mesh has been coarsened. +** - 1 : if the mesh could not be coarsened. +** - 2 : on error. +*/ + +int +meshCoarsen ( +const Mesh * restrict const finemeshptr, /*+ Mesh to coarsen +*/ +Mesh * restrict const coarmeshptr, /*+ Coarse mesh to build +*/ +Gnum * restrict * const finecoarptr, /*+ Pointer to multinode data +*/ +const Gnum coarnbr, /*+ Minimum number of coarse nodes +*/ +const double coarrat, /*+ Maximum contraction ratio +*/ +const MeshCoarsenType coartype) /*+ Matching type +*/ +{ + Gnum coarhashsiz; /* Size of the hash table */ + Gnum coarhashmsk; /* Mask for access to hash table */ + MeshCoarsenHngb * restrict coarhngbtab; /* Table of edges to other multinodes */ + MeshCoarsenHbdg * restrict coarhbdgtab; /* Table of bridge nodes to other multinodes */ + Gnum * restrict coarverttax; /* Pointer to coarse vertex array */ + Gnum * restrict coarvelotax; /* Pointer to coarse vertex load array */ + Gnum * restrict coaredgetax; /* Pointer to coarse edge array */ + Gnum coaredgenbr; /* (Upper bound of) number of edges in mesh */ + Gnum coaredgenum; /* Number of current coarse edge */ + Gnum coarvertnbr; /* Number of vertices in coarse mesh */ + Gnum coarvelmnbr; /* Number of coarse element vertices */ + Gnum coarvnodnbr; /* Number of coarse node vertices */ + Gnum finevertnbr; /* Number of vertices in fine graph */ + Gnum * restrict finecoartax; /* Based access to finecoartab */ + Gnum coarvelmnum; /* Number of currently selected coarse element */ + Gnum coareelmnum; + Gnum coarvnodnum; + Gnum coardegrmax; + MeshCoarsenMult * restrict finemulttax; + Gnum coaredgetmp; + size_t coarvelooftval; + size_t coaredgeoftval; + +#ifdef SCOTCH_DEBUG_MESH2 + if (coartype >= MESHCOARSENNBR) { + errorPrint ("meshCoarsen: invalid parameter"); + return (2); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + memSet (coarmeshptr, 0, sizeof (Mesh)); /* Initialize coarse mesh */ + coarmeshptr->flagval = GRAPHFREEVERT; + coarmeshptr->baseval = finemeshptr->baseval; + + finevertnbr = finemeshptr->velmnbr + finemeshptr->vnodnbr; + if ((finecoartax = (Gnum *) memAlloc (finevertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("meshCoarsen: out of memory (1)"); /* Allocate coarse mesh uncoarsening array */ + return (2); + } + memSet (finecoartax, ~0, finevertnbr * sizeof (Gnum)); + finecoartax -= finemeshptr->baseval; /* Set based access to finecoartax */ + + for (coarhashmsk = 31, coarhashsiz = finemeshptr->degrmax * finemeshptr->degrmax - 1; /* Compute size of hash table */ + coarhashmsk < coarhashsiz; coarhashmsk = coarhashmsk * 2 + 1) ; + coarhashsiz = coarhashmsk + 1; + + if (memAllocGroup ((void **) (void *) + &coarverttax, (size_t) ((finevertnbr + 1) * sizeof (Gnum)), /* Upper bound on number of coarse vertices */ + &coarvelotax, (size_t) ( finevertnbr * sizeof (Gnum)), /* Upper bound on number of coarse vertices */ + &coaredgetax, (size_t) ( finemeshptr->edgenbr * sizeof (Gnum)), + &coarhngbtab, (size_t) ( coarhashsiz * sizeof (MeshCoarsenHngb)), + &coarhbdgtab, (size_t) ( coarhashsiz * sizeof (MeshCoarsenHbdg)), + &finemulttax, (size_t) ( finemeshptr->velmnbr * sizeof (MeshCoarsenMult)), NULL) == NULL) { + errorPrint ("meshCoarsen: out of memory (2)"); /* Allocate coarser mesh structure */ + memFree (finecoartax + finemeshptr->baseval); + return (2); + } + memSet (coarhngbtab, ~0, coarhashsiz * sizeof (MeshCoarsenHngb)); + memSet (coarhbdgtab, ~0, coarhashsiz * sizeof (MeshCoarsenHbdg)); + finemulttax -= coarmeshptr->baseval; + +#define SCOTCH_DEBUG_MESH3 +#ifdef SCOTCH_DEBUG_MESH3 +fprintf (stderr, "-------- ENTERING COARSENING ---------\n"); + +fprintf (stderr, "finenodenbr=%ld, fineelemnbr=%ld, fineedgenbr=%ld, finedegrmax=%ld\n", (long) finemeshptr->vnodnbr, (long) finemeshptr->velmnbr, (long) finemeshptr->edgenbr, (long) finemeshptr->degrmax); +#endif /* SCOTCH_DEBUG_MESH3 */ + + meshCoarFuncTab[coartype] (finemeshptr, finemulttax, finecoartax, &coarvelmnbr, &coarvnodnbr, &coaredgenbr); /* Call proper matching function */ + +#ifndef DEAD_CODE + coarvnodnbr = finemeshptr->vnodnbr; /* TODO : coarvnodnbr estimator is wrong : too tight */ + coaredgenbr = finemeshptr->edgenbr; +#endif /* DEAD_CODE */ + coarvertnbr = coarvelmnbr + coarvnodnbr; + + memOffset ((void *) coarverttax, + &coarverttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), + &coarvelotax, (size_t) ( coarvertnbr * sizeof (Gnum)), + &coaredgetax, (size_t) ( coaredgenbr * sizeof (Gnum)), NULL); /* Hast tables and finemulttax stay in place */ + coarverttax -= coarmeshptr->baseval; + coarvelotax -= coarmeshptr->baseval; + coaredgetax -= coarmeshptr->baseval; + + coarmeshptr->velmbas = coarmeshptr->baseval; + coarmeshptr->velmnbr = coarvelmnbr; + coarmeshptr->velmnnd = + coarmeshptr->vnodbas = coarvelmnbr + coarmeshptr->velmbas; + + for (coarvelmnum = coaredgenum = coarmeshptr->baseval, coarvnodnum = coarmeshptr->vnodbas, coardegrmax = 0; /* For all coarse elements */ + coarvelmnum < coarmeshptr->velmnnd; coarvelmnum ++) { + Gnum coarveloval; /* Weight of coarsened element */ + Gnum coarvnisnum; /* Number of coarse isolated node */ + Gnum finevelmnum; /* Number of current element */ + int i; + + coarverttax[coarvelmnum] = coaredgenum; + + coarvnisnum = ~0; /* No isolated node yet for this element pair */ + coarveloval = 0; + i = 0; + do { /* For both elements of element pair (if they are different) */ + Gnum fineeelmnum; + + finevelmnum = finemulttax[coarvelmnum].finevelmnum[i]; /* Get number of current element */ + coarveloval += ((finemeshptr->velotax != NULL) ? finemeshptr->velotax[finevelmnum] : 1); + for (fineeelmnum = finemeshptr->verttax[finevelmnum]; + fineeelmnum < finemeshptr->vendtax[finevelmnum]; fineeelmnum ++) { + Gnum finevnodnum; /* Number of current node neighbor */ + Gnum fineenodnum; + Gnum finevdegval; + Gnum finevnloval; + Gnum finevelmend; + Gnum coarvnodtmp; + Gnum coarhnodtmp; + + finevnodnum = finemeshptr->edgetax[fineeelmnum]; + fineenodnum = finemeshptr->verttax[finevnodnum]; + finevdegval = finemeshptr->vendtax[finevnodnum] - fineenodnum; + finevnloval = (finemeshptr->vnlotax != NULL) ? finemeshptr->vnlotax[finevnodnum] : 1; + + if ((finevdegval == 2) && /* If node is an external bridge to another coarse element */ + ((finevelmend = (finemeshptr->edgetax[fineenodnum] + finemeshptr->edgetax[fineenodnum + 1] - finevelmnum)) != finemulttax[coarvelmnum].finevelmnum[1 - i])) { + Gnum coarvelmend; + Gnum coarhelmend; + + coarvelmend = finecoartax[finevelmend]; /* Get coarse index of end element */ + coarvnodtmp = finecoartax[finevnodnum]; /* Get coarse number of fine node */ + for (coarhelmend = (coarvelmend * MESHCOARSENHASHPRIME) & coarhashmsk; ; coarhelmend = (coarhelmend + 1) & coarhashmsk) { + if (coarhbdgtab[coarhelmend].coarvelmnum != coarvelmnum) { /* If bridge not yet considered */ + coarhbdgtab[coarhelmend].coarvelmnum = coarvelmnum; /* Add it to element neighbor list */ + coarhbdgtab[coarhelmend].coarvelmend = coarvelmend; + if (coarvnodtmp == -1) { /* If bridge nodes not considered before by other element */ + coarhbdgtab[coarhelmend].coarvnodnum = /* Assign it */ + finecoartax[finevnodnum] = coarvnodtmp = coarvnodnum ++; + coarverttax[coarvnodtmp] = 2; /* Prepare the fact that another element will see the node */ + coarvelotax[coarvnodtmp] = finevnloval; + } + coaredgetax[coaredgenum ++] = coarvnodtmp; /* Directly add coarse node to element neighborhood */ + break; + } + if (coarhbdgtab[coarhelmend].coarvelmend == coarvelmend) { /* If bridge already present */ + if (coarvnodtmp == -1) { /* If we are the first element to see the bridge node */ + finecoartax[finevnodnum] = coarvnodtmp = coarhbdgtab[coarhelmend].coarvnodnum; /* Assign it */ + coarvelotax[coarvnodtmp] += finevnloval; /* Update the weight of the node */ + } /* Else node already processed with full load, so nothing to do */ + break; + } + } + continue; /* Edge has been added or will not be */ + } + else if (finevdegval < 3) { /* Else if node is isolated or is an internal bridge */ + if ((finevdegval == 2) && /* Process bridge edges only once */ + (finevelmnum >= finemulttax[coarvelmnum].finevelmnum[1 - i])) + continue; + + if (coarvnisnum == ~0) { /* If no isolated node for this element pair */ + coarvnisnum = coarvnodnum ++; /* Create isolated node */ + coarverttax[coarvnisnum] = 1; + coarvelotax[coarvnisnum] = finevnloval; + coaredgetax[coaredgenum ++] = coarvnisnum; + } + else /* If isolated node already exists */ + coarvelotax[coarvnisnum] += finevnloval; /* Add node contribution to it */ + finecoartax[finevnodnum] = coarvnisnum; /* Map fine node to isolated node */ + continue; + } + else { + coarvnodtmp = finecoartax[finevnodnum]; /* Get coarse number of fine node */ + if (coarvnodtmp == ~0) { /* If coarse number not yet assigned */ + finecoartax[finevnodnum] = coarvnodtmp = coarvnodnum ++; /* Assign it */ + coarverttax[coarvnodtmp] = 0; /* No connections to the node yet */ + coarvelotax[coarvnodtmp] = finevnloval; + } + } + + for (coarhnodtmp = (coarvnodtmp * MESHCOARSENHASHPRIME) & coarhashmsk; ; coarhnodtmp = (coarhnodtmp + 1) & coarhashmsk) { + if (coarhngbtab[coarhnodtmp].coarvelmnum != coarvelmnum) { /* If node neighbor not yet considered */ + coarhngbtab[coarhnodtmp].coarvelmnum = coarvelmnum; /* Add it to element neighbor list */ + coarhngbtab[coarhnodtmp].coarvnodnum = coarvnodtmp; + coaredgetax[coaredgenum ++] = coarvnodtmp; + coarverttax[coarvnodtmp] ++; /* One more edge referencing the node */ + break; + } + if (coarhngbtab[coarhnodtmp].coarvnodnum == coarvnodtmp) /* If node already present, nothing to do */ + break; + } + } + } while (i ++, finevelmnum != finemulttax[coarvelmnum].finevelmnum[1]); + + coarvelotax[coarvelmnum] = coarveloval; /* Lose initial weights of elements, if any, to keep coarsening weights */ + if ((coaredgenum - coarverttax[coarvelmnum]) > coardegrmax) + coardegrmax = (coaredgenum - coarverttax[coarvelmnum]); + } + coarmeshptr->vnodnnd = coarvnodnum; + coarmeshptr->vnodnbr = coarvnodnum - coarmeshptr->vnodbas; + coarmeshptr->velosum = finemeshptr->velosum; + coarmeshptr->vnlosum = finemeshptr->vnlosum; + coarmeshptr->edgenbr = 2 * (coaredgenum - coarmeshptr->baseval); + + for (coarvnodnum = coarmeshptr->vnodbas, coaredgetmp = coaredgenum; /* Build start indices for node edge sub-arrays */ + coarvnodnum < coarmeshptr->vnodnnd; coarvnodnum ++) { + Gnum coardegrval; + + coardegrval = coarverttax[coarvnodnum]; + coarverttax[coarvnodnum] = coaredgetmp; + coaredgetmp += coardegrval; + + if (coardegrval > coardegrmax) + coardegrmax = coardegrval; + } + coarmeshptr->degrmax = coardegrmax; + for (coarvelmnum = coareelmnum = coarmeshptr->baseval; + coarvelmnum < coarmeshptr->velmnnd; coarvelmnum ++) { + Gnum coareelmnnd; + + coareelmnnd = (coarvelmnum < (coarmeshptr->velmnnd - 1)) ? coarverttax[coarvelmnum + 1] : coaredgenum; + while (coareelmnum < coareelmnnd) { + Gnum coarvnodnum; + + coarvnodnum = coaredgetax[coareelmnum ++]; + coaredgetax[coarverttax[coarvnodnum] ++] = coarvelmnum; + } + } + memMov (&coarverttax[coarmeshptr->vnodbas + 1], /* Re-build start indices for node edge sub-arrays */ + &coarverttax[coarmeshptr->vnodbas], + coarmeshptr->vnodnbr * sizeof (Gnum)); + coarverttax[coarmeshptr->vnodbas] = coaredgenum; + + coarvelooftval = coarvelotax - coarverttax; + coaredgeoftval = coaredgetax - coarverttax; + coarverttax = memRealloc (coarverttax + coarmeshptr->baseval, (coaredgeoftval + coarmeshptr->edgenbr) * sizeof (Gnum)); /* Re-allocate array to save space */ + coarmeshptr->verttax = coarverttax - coarmeshptr->baseval; + coarmeshptr->vendtax = coarmeshptr->verttax + 1; + coarmeshptr->velotax = coarmeshptr->verttax + coarvelooftval; + coarmeshptr->vnlotax = coarmeshptr->velotax; /* Same array for both vertex load sub-arrays */ + coarmeshptr->edgetax = coarmeshptr->verttax + coaredgeoftval; + +#ifdef SCOTCH_DEBUG_MESH2 + if (meshCheck (coarmeshptr) != 0) { /* Check mesh consistency */ + errorPrint ("meshCoarsen: internal error (7)"); + return (2); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + *finecoarptr = finecoartax; /* Return multinode array */ + +#ifdef SCOTCH_DEBUG_MESH3 +fprintf (stderr, "coarvnodnbr=%ld\tcoarvelmnbr=%ld\tcoaredgenbr=%ld, coardegrmax=%ld\n", (long) coarmeshptr->vnodnbr, (long) coarmeshptr->velmnbr, (long) coarmeshptr->edgenbr, (long) coarmeshptr->degrmax); +fprintf (stderr, "-------- EXITING COARSENING ---------\n"); /* TODO REMOVE */ +#endif /* SCOTCH_DEBUG_MESH3 */ + + return (0); +} + +/********************************************/ +/* */ +/* The matching subroutines. In fact, these */ +/* are merging routines, which merge */ +/* elements of the fine mesh to form larger */ +/* elements in the coarse mesh. */ +/* New elements are ordered in increasing */ +/* order from baseval, while nodes are */ +/* ordered in decreasing order from -2, as */ +/* -1 is a reserved flag value used */ +/* for labelling non yet considered */ +/* vertices. */ +/* */ +/********************************************/ + + +/* This routine performs elements matching by +** selecting the elements that share most nodes +** with the first element. +*/ + +static +void +meshCoarsenMatchNg ( +const Mesh * restrict const finemeshptr, /* Fine mesh to perform matching on */ +MeshCoarsenMult * restrict const finemulttax, /* Array of fine multielements */ +Gnum * restrict const finecoartax, /* Fine to coarse vertex array */ +Gnum * restrict const coarvelmptr, /* Pointer to number of coarse element vertices */ +Gnum * restrict const coarvnodptr, /* Pointer to (upper bound on) number of coarse node vertices */ +Gnum * restrict const coaredgeptr) /* Pointer to (upper bound on) number of edges */ +{ + Gnum coarvelmnum; /* Number of current coarse element vertex */ + Gnum finepertbas; /* Index of base of perturbation area */ + Gnum finepertnbr; /* Size of perturbation area */ + MeshCoarsenNgHash * restrict finehashtab; /* Hash table of neighbor elements */ + Gnum finehashsiz; + Gnum finehashmsk; + Gnum coarvnodnbr; + Gnum coaredgenbr; + + for (finehashmsk = 31, finehashsiz = finemeshptr->degrmax * finemeshptr->degrmax - 1; /* Compute size of hash table */ + finehashmsk < finehashsiz; finehashmsk = finehashmsk * 2 + 1) ; + finehashsiz = finehashmsk + 1; + if ((finehashtab = (MeshCoarsenNgHash *) memAlloc (finehashsiz * sizeof (MeshCoarsenNgHash))) == NULL) { + *coarvelmptr = finemeshptr->velmnbr; /* Indicate no coarsening occured */ + return; + } + memSet (finehashtab, ~0, finehashsiz * sizeof (MeshCoarsenNgHash)); + finehashmsk = finehashsiz - 1; + + coarvelmnum = finemeshptr->baseval; /* Start numbering elements in ascending order */ + coarvnodnbr = finemeshptr->vnodnbr; + coaredgenbr = finemeshptr->edgenbr; + + if (finemeshptr->velotax != NULL) { /* If fine mesh has element coarsening vertex weights, perform first pass */ + Gnum finevelomin; + Gnum finevelomax; + Gnum finevelmnum; + + finevelomin = (3 * finemeshptr->velosum) / (5 * finemeshptr->velmnbr); + finevelomax = (5 * finemeshptr->velosum) / finemeshptr->velmnbr; + + for (finevelmnum = finemeshptr->velmbas; finevelmnum < finemeshptr->velmnnd; finevelmnum ++) { + Gnum fineeelmnum; + Gnum finehelmnum; + Gnum finevnisnbr; /* Number of isolated node vertices */ + Gnum finehebsnum; /* Hash number of best matching element */ + Gnum finevebsnum; /* Number of best matching element */ + Gnum finevnbsnbr; /* Number of nodes shared with best element */ + + if (finecoartax[finevelmnum] != ~0) /* If element already selected */ + continue; + if (finemeshptr->velotax[finevelmnum] >= finevelomin) { /* If element is large enough, leave it for the second pass */ + if (finemeshptr->velotax[finevelmnum] > finevelomax) { /* Except if it is too large, as then it is not matched */ + finecoartax[finevelmnum] = coarvelmnum; + finemulttax[coarvelmnum].finevelmnum[0] = + finemulttax[coarvelmnum].finevelmnum[1] = finevelmnum; +fprintf (stderr, "++ %ld %ld\n", (long) finevelmnum, (long) finemeshptr->velotax[finevelmnum]); /* TODO REMOVE */ + coarvelmnum ++; /* One more single vertex created */ + } + continue; + } + + finecoartax[finevelmnum] = coarvelmnum; /* Set vertex as used so that it will not be considered as an end vertex */ + + finehelmnum = (finevelmnum * MESHCOARSENHASHPRIME) & finehashmsk; + finehashtab[finehelmnum].velmnum = finevelmnum; /* Put element in hash table so that number of end vertex is right even for uncoarsened elements */ + finehashtab[finehelmnum].velmend = finevelmnum; + finehebsnum = finehelmnum; /* Mate is element itself */ + finevnbsnbr = 0; /* Will never be selected */ + + finevnisnbr = 0; /* No isolated node vertices yet */ + for (fineeelmnum = finemeshptr->verttax[finevelmnum]; /* For all node neighbors of current element */ + fineeelmnum < finemeshptr->vendtax[finevelmnum]; fineeelmnum ++) { + Gnum finevnodnum; + Gnum fineenodnum; + Gnum fineenodnnd; + Gnum finevdegval; + Gnum finevnbgval; + + finevnodnum = finemeshptr->edgetax[fineeelmnum]; + fineenodnum = finemeshptr->verttax[finevnodnum]; + fineenodnnd = finemeshptr->vendtax[finevnodnum]; + finevdegval = fineenodnnd - fineenodnum; + if (finevdegval == 1) { /* If node is isolated */ + finevnisnbr ++; + continue; /* Directly skip to next node */ + } + finevnbgval = (finevdegval == 2) ? 1 : 0; /* If node is a bridge which connects the element to only one other element */ + + for ( ; fineenodnum < fineenodnnd; fineenodnum ++) { /* For all elements which are neighbors of current node */ + Gnum finevelmend; + Gnum finehelmend; + Gnum finevnngnbr; /* Current number of neigoboring nodes that connect the two elements */ + + finevelmend = finemeshptr->edgetax[fineenodnum]; + if (finecoartax[finevelmend] != ~0) /* If end element vertex already matched, do not consider it */ + continue; + + for (finehelmend = (finevelmend * MESHCOARSENHASHPRIME) & finehashmsk; ; finehelmend = (finehelmend + 1) & finehashmsk) { + if (finehashtab[finehelmend].velmnum != finevelmnum) { /* If element neighbor not yet considered */ + finevnngnbr = 1; + finehashtab[finehelmend].velmnum = finevelmnum; + finehashtab[finehelmend].velmend = finevelmend; + finehashtab[finehelmend].vnngnbr = finevnngnbr; + finehashtab[finehelmend].vnbgnbr = finevnbgval; + } + else if (finehashtab[finehelmend].velmend == finevelmend) { /* Else if element found */ + finevnngnbr = ++ finehashtab[finehelmend].vnngnbr; + finehashtab[finehelmend].vnbgnbr += finevnbgval; + } + else /* Else go on searching */ + continue; + + if (finevnngnbr > finevnbsnbr) { + finehebsnum = finehelmend; + finevnbsnbr = finevnngnbr; + } + break; + } + } + } + + finevebsnum = finehashtab[finehebsnum].velmend; + finemulttax[coarvelmnum].finevelmnum[0] = finevelmnum; /* Set matching pair */ + finemulttax[coarvelmnum].finevelmnum[1] = finevebsnum; + if (finevelmnum != finevebsnum) { /* If a matching element has been found */ + finecoartax[finevebsnum] = coarvelmnum; + if (finevnisnbr > 0) + finevnisnbr --; + coarvnodnbr -= finehashtab[finehebsnum].vnbgnbr + finevnisnbr; + coaredgenbr -= 2 * finevnisnbr + 4 * finehashtab[finehebsnum].vnbgnbr; + } + coarvelmnum ++; /* Number nodes in ascending order */ + } + } + + for (finepertbas = finemeshptr->velmbas, /* Run cache-friendly perturbation on elements */ + finepertnbr = 2 + intRandVal (MESHCOARSENPERTPRIME - 2); /* Compute perturbation area size */ + finepertbas < finemeshptr->velmnnd; finepertbas += finepertnbr) { + Gnum finepertval; /* Current index in perturbation area */ + + if (finepertbas + finepertnbr > finemeshptr->velmnnd) + finepertnbr = finemeshptr->velmnnd - finepertbas; + + finepertval = 0; /* Start from first perturbation element vertex */ + do { /* Loop on perturbation element vertices */ + Gnum finevelmnum; /* Number of currently selected fine element vertex */ + Gnum fineeelmnum; + Gnum finehelmnum; + Gnum finevnisnbr; /* Number of isolated node vertices */ + Gnum finehebsnum; /* Hash number of best matching element */ + Gnum finevebsnum; /* Number of best matching element */ + Gnum finevnbsnbr; /* Number of nodes shared with best element */ + + finevelmnum = finepertbas + finepertval; /* Compute corresponding elemennt number */ + if (finecoartax[finevelmnum] != ~0) /* If element already selected */ + continue; + + finecoartax[finevelmnum] = coarvelmnum; /* Set vertex as used so that it will not be considered as an end vertex */ + + finehelmnum = (finevelmnum * MESHCOARSENHASHPRIME) & finehashmsk; + finehashtab[finehelmnum].velmnum = finevelmnum; /* Put element in hash table so that number of end vertex is right even for uncoarsened elements */ + finehashtab[finehelmnum].velmend = finevelmnum; + finehebsnum = finehelmnum; /* Mate is element itself */ + finevnbsnbr = 0; /* Will never be selected */ + + finevnisnbr = 0; /* No isolated node vertices yet */ + for (fineeelmnum = finemeshptr->verttax[finevelmnum]; /* For all node neighbors of current element */ + fineeelmnum < finemeshptr->vendtax[finevelmnum]; fineeelmnum ++) { + Gnum finevnodnum; + Gnum fineenodnum; + Gnum fineenodnnd; + Gnum finevdegval; + Gnum finevnbgval; + + finevnodnum = finemeshptr->edgetax[fineeelmnum]; + fineenodnum = finemeshptr->verttax[finevnodnum]; + fineenodnnd = finemeshptr->vendtax[finevnodnum]; + finevdegval = fineenodnnd - fineenodnum; + if (finevdegval == 1) { /* If node is isolated */ + finevnisnbr ++; + continue; /* Directly skip to next node */ + } + finevnbgval = (finevdegval == 2) ? 1 : 0; /* If node is a bridge which connects the element to only one other element */ + + for ( ; fineenodnum < fineenodnnd; fineenodnum ++) { /* For all elements which are neighbors of current node */ + Gnum finevelmend; + Gnum finehelmend; + Gnum finevnngnbr; /* Current number of neigoboring nodes that connect the two elements */ + + finevelmend = finemeshptr->edgetax[fineenodnum]; + if (finecoartax[finevelmend] != ~0) /* If end element vertex already matched, do not consider it */ + continue; + + for (finehelmend = (finevelmend * MESHCOARSENHASHPRIME) & finehashmsk; ; finehelmend = (finehelmend + 1) & finehashmsk) { + if (finehashtab[finehelmend].velmnum != finevelmnum) { /* If element neighbor not yet considered */ + finevnngnbr = 1; + finehashtab[finehelmend].velmnum = finevelmnum; + finehashtab[finehelmend].velmend = finevelmend; + finehashtab[finehelmend].vnngnbr = finevnngnbr; + finehashtab[finehelmend].vnbgnbr = finevnbgval; + } + else if (finehashtab[finehelmend].velmend == finevelmend) { /* Else if element found */ + finevnngnbr = ++ finehashtab[finehelmend].vnngnbr; + finehashtab[finehelmend].vnbgnbr += finevnbgval; + } + else /* Else go on searching */ + continue; + + if (finevnngnbr > finevnbsnbr) { + finehebsnum = finehelmend; + finevnbsnbr = finevnngnbr; + } + break; + } + } + } + + finevebsnum = finehashtab[finehebsnum].velmend; + finemulttax[coarvelmnum].finevelmnum[0] = finevelmnum; /* Set matching pair */ + finemulttax[coarvelmnum].finevelmnum[1] = finevebsnum; + if (finevelmnum != finevebsnum) { /* If a matching element has been found */ + finecoartax[finevebsnum] = coarvelmnum; + if (finevnisnbr > 0) + finevnisnbr --; + coarvnodnbr -= finehashtab[finehebsnum].vnbgnbr + finevnisnbr; + coaredgenbr -= 2 * finevnisnbr + 4 * finehashtab[finehebsnum].vnbgnbr; + } + coarvelmnum ++; /* Number nodes in ascending order */ + } while ((finepertval = (finepertval + MESHCOARSENPERTPRIME) % finepertnbr) != 0); /* Compute next perturbation index */ + } + + memFree (finehashtab); + + *coarvelmptr = coarvelmnum - finemeshptr->velmbas; + *coarvnodptr = coarvnodnbr; + *coaredgeptr = coaredgenbr; + + return; +} diff --git a/scotch_6.0.3/src/libscotch/mesh_coarsen.h b/scotch_6.0.3/src/libscotch/mesh_coarsen.h new file mode 100644 index 00000000..3226dd44 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_coarsen.h @@ -0,0 +1,121 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_coarsen.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source mesh coarsening **/ +/** functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 oct 2003 **/ +/** to 04 feb 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** Prime number for cache-friendly perturbations. **/ + +#define MESHCOARSENPERTPRIME 31 /* Prime number */ + +/** Prime number for hashing vertex numbers. **/ + +#define MESHCOARSENHASHPRIME 17 /* Prime number */ + +/* +** The type and structure definitions. +*/ + +/*+ Here are the edge matching function types for coarsening. +*/ + +typedef enum MeshCoarsenType_ { + MESHCOARSENNGB, /*+ Most neighbors matching +*/ + MESHCOARSENNBR /*+ Number of matching types +*/ +} MeshCoarsenType; + +/*+ A table made of such elements is used during + coarsening to build the edge array of the new + mesh, after the labeling of the vertices. +*/ + +typedef struct MeshCoarsenMult_ { + Gnum finevelmnum[2]; +} MeshCoarsenMult; + +/*+ A table made of such cells is used during + coarsening to build the edge array of the + elements of the new mesh. +*/ + +typedef struct MeshCoarsenHngb_ { + Gnum coarvelmnum; /*+ Coarse origin element vertex (i.e. pass) number +*/ + Gnum coarvnodnum; /*+ Neighbor fine node vertex number +*/ +} MeshCoarsenHngb; + +/*+ A table made of such cells is used during + coarsening to detect and merge bridge nodes, + that is, nodes that connect only two coarse + nodes together. +*/ + +typedef struct MeshCoarsenHbdg_ { + Gnum coarvelmnum; /*+ Coarse origin element vertex (i.e. pass) number +*/ + Gnum coarvelmend; /*+ Coarse end element vertex number +*/ + Gnum coarvnodnum; /*+ Number of connecting coarse node +*/ +} MeshCoarsenHbdg; + +/*+ A table made of such elements is used during + coarsening to build the edge array of the new + mesh, after the labeling of the vertices. +*/ + +typedef struct MeshCoarsenNgHash_ { + Gnum velmnum; /*+ Origin element vertex (i.e. pass) number +*/ + Gnum velmend; /*+ End element vertex number in fine mesh +*/ + Gnum vnngnbr; /*+ Number of shared neighboring node vertices +*/ + Gnum vnbgnbr; /*+ Number of bridge neighboring node vertices +*/ +} MeshCoarsenNgHash; + +/* +** The function prototypes. +*/ + +#ifndef MESH_COARSEN +#define static +#endif + +int meshCoarsen (const Mesh * restrict const, Mesh * restrict const, Gnum * restrict * const, const Gnum, const double, const MeshCoarsenType); + +static void meshCoarsenMatchNg (const Mesh * restrict const, MeshCoarsenMult * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/mesh_graph.c b/scotch_6.0.3/src/libscotch/mesh_graph.c new file mode 100644 index 00000000..a1be7bf9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_graph.c @@ -0,0 +1,211 @@ +/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_graph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the source mesh **/ +/** to graph conversion function. **/ +/** **/ +/** DATES : # Version 4.0 : from : 11 oct 2003 **/ +/** to 05 may 2004 **/ +/** # Version 5.1 : from : 19 nov 2009 **/ +/** to 19 nov 2009 **/ +/** **/ +/** NOTES : # From a given mesh is created a graph, **/ +/** such that all vertices of the graph **/ +/** represent the nodes of the mesh, and **/ +/** there exists an edge between two **/ +/** vertices if there exists at least one **/ +/** element to which the two associated **/ +/** nodes belong. **/ +/** In order to extract mesh vertex **/ +/** partitions from graph vertex **/ +/** partitions easily, the vertices of **/ +/** the graph are numbered in the same **/ +/** order as the nodes of the mesh. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MESH_GRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "mesh_graph.h" + +/*******************************/ +/* */ +/* The graph building routine. */ +/* */ +/*******************************/ + +/* This routine builds a graph from the +** given mesh. +** It returns: +** - 0 : if the graph has been successfully built. +** - 1 : on error. +*/ + +int +meshGraph ( +const Mesh * restrict const meshptr, /*+ Original mesh +*/ +Graph * restrict const grafptr) /*+ Graph to build +*/ +{ + Gnum hashnbr; /* Number of vertices in hash table */ + Gnum hashsiz; /* Size of hash table */ + Gnum hashmsk; /* Mask for access to hash table */ + MeshGraphHash * restrict hashtab; /* Table of edges to other node vertices */ + Gnum edgemax; /* Upper bound of number of edges in mesh */ + Gnum edgennd; /* Based upper bound on number of edges */ + Gnum edgenum; /* Number of current graph edge */ + Gnum vertnum; /* Number of current graph vertex */ + Gnum degrmax; + + grafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; + grafptr->baseval = meshptr->baseval; + grafptr->vertnbr = meshptr->vnodnbr; + grafptr->vertnnd = meshptr->vnodnbr + meshptr->baseval; + + for (hashsiz = 32, hashnbr = meshptr->degrmax * meshptr->degrmax * 2; /* Compute size of hash table */ + hashsiz < hashnbr; hashsiz <<= 1) ; + hashmsk = hashsiz - 1; + + if (((grafptr->verttax = memAlloc ((meshptr->vnodnbr + 1) * sizeof (Gnum))) == NULL) || + ((hashtab = memAlloc (hashsiz * sizeof (MeshGraphHash))) == NULL)) { + errorPrint ("meshGraph: out of memory (1)"); + if (grafptr->verttax != NULL) + memFree (grafptr->verttax); + return (1); + } + grafptr->verttax -= grafptr->baseval; + grafptr->vendtax = grafptr->verttax + 1; + + if (meshptr->vnlotax != NULL) /* Keep node part of mesh vertex load array as graph vertex load array */ + grafptr->velotax = meshptr->vnlotax + meshptr->vnodbas - grafptr->baseval; /* Since GRAPHVERTGROUP, no problem on graphFree */ + + grafptr->velosum = meshptr->vnlosum; + + edgemax = 2 * meshptr->edgenbr; /* Compute lower bound on number of edges in graph */ +#ifdef SCOTCH_DEBUG_MESH2 + edgemax = meshptr->degrmax + 1; /* Allow testing dynamic reallocation of edge array */ +#endif /* SCOTCH_DEBUG_MESH2 */ + + if ((grafptr->edgetax = memAlloc (edgemax * sizeof (Gnum))) == NULL) { + errorPrint ("meshGraph: out of memory (2)"); + graphFree (grafptr); + return (1); + } + grafptr->edgetax -= grafptr->baseval; + + memSet (hashtab, ~0, hashsiz * sizeof (MeshGraphHash)); /* Initialize hash table */ + + for (vertnum = edgenum = grafptr->baseval, edgennd = edgemax + grafptr->baseval, degrmax = 0; /* Build graph edges */ + vertnum < grafptr->vertnnd; vertnum ++) { + Gnum vnodnum; + Gnum hnodnum; + Gnum enodnum; + + grafptr->verttax[vertnum] = edgenum; + + vnodnum = vertnum + (meshptr->vnodbas - meshptr->baseval); + hnodnum = (vnodnum * MESHGRAPHHASHPRIME) & hashmsk; /* Prevent adding loop edge */ + hashtab[hnodnum].vertnum = vnodnum; + hashtab[hnodnum].vertend = vnodnum; + + for (enodnum = meshptr->verttax[vnodnum]; enodnum < meshptr->vendtax[vnodnum]; enodnum ++) { + Gnum velmnum; + Gnum eelmnum; + + velmnum = meshptr->edgetax[enodnum]; + + for (eelmnum = meshptr->verttax[velmnum]; eelmnum < meshptr->vendtax[velmnum]; eelmnum ++) { + Gnum vnodend; + Gnum hnodend; + + vnodend = meshptr->edgetax[eelmnum]; + + for (hnodend = (vnodend * MESHGRAPHHASHPRIME) & hashmsk; ; hnodend = (hnodend + 1) & hashmsk) { + if (hashtab[hnodend].vertnum != vnodnum) { /* If edge not yet created */ + if (edgenum == edgennd) { /* If edge array already full */ + Gnum edgemax; + Gnum * restrict edgetmp; + + edgemax = edgennd - grafptr->baseval; /* Increase size by 25 % */ + edgemax = edgemax + (edgemax >> 2); + + if ((edgetmp = memRealloc (grafptr->edgetax + grafptr->baseval, edgemax * sizeof (Gnum))) == NULL) { + errorPrint ("meshGraph: out of memory (3)"); + graphFree (grafptr); + memFree (hashtab); + return (1); + } + + grafptr->edgetax = edgetmp - grafptr->baseval; + edgennd = edgemax + grafptr->baseval; + } + + hashtab[hnodend].vertnum = vnodnum; /* Record new edge */ + hashtab[hnodend].vertend = vnodend; + grafptr->edgetax[edgenum ++] = vnodend - (meshptr->vnodbas - grafptr->baseval); /* Build new edge */ + break; + } + if (hashtab[hnodend].vertend == vnodend) /* If edge already exists */ + break; /* Skip to next neighbor */ + } + } + } + + if ((edgenum - grafptr->verttax[vertnum]) > degrmax) /* Compute maximum degree */ + degrmax = (edgenum - grafptr->verttax[vertnum]); + } + grafptr->verttax[vertnum] = edgenum; /* Set end of vertex array */ + + grafptr->edgenbr = edgenum - grafptr->baseval; + grafptr->degrmax = degrmax; + +#ifdef SCOTCH_DEBUG_MESH2 + if (graphCheck (grafptr) != 0) { + errorPrint ("meshGraph: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/mesh_graph.h b/scotch_6.0.3/src/libscotch/mesh_graph.h new file mode 100644 index 00000000..3043c7a4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_graph.h @@ -0,0 +1,66 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_graph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source mesh to source graph **/ +/** building routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 13 oct 2003 **/ +/** to 13 oct 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** Prime number for cache-friendly perturbations. **/ + +#define MESHGRAPHHASHPRIME 37 /* Prime number */ + +/* +** The type and structure definitions. +*/ + +/*+ A table made of such elements is used during + graph building to build the edge array of the + graph from the one of the mesh. +*/ + +typedef struct MeshGraphHash_ { + Gnum vertnum; /*+ Origin vertex (i.e. pass) number in mesh +*/ + Gnum vertend; /*+ End vertex number in mesh +*/ +} MeshGraphHash; diff --git a/scotch_6.0.3/src/libscotch/mesh_induce_sepa.c b/scotch_6.0.3/src/libscotch/mesh_induce_sepa.c new file mode 100644 index 00000000..7d6e7a2f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_induce_sepa.c @@ -0,0 +1,357 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_induce_sepa.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the source **/ +/** mesh separator subgraph-making **/ +/** functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 26 jan 2003 **/ +/** to 11 may 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to 03 apr 2008 **/ +/** **/ +/** NOTES : # This routine differs from the **/ +/** standard mesh induction routine by **/ +/** the fact that neighboring elements do **/ +/** not bear the same part number as the **/ +/** vertices to keep and are found on the **/ +/** fly. **/ +/** **/ +/** # This routine is used in hmeshInduce- **/ +/** Nd to build the induced separator **/ +/** mesh. **/ +/** Since separator vertices are likely **/ +/** to be surrounded by elements that **/ +/** belong to different parts but connect **/ +/** the same vertices in the separator, **/ +/** a simple detection mechanism is used **/ +/** to try to reduce the number of such **/ +/** redundant elements. **/ +/** Also, since this mesh is to be **/ +/** ordered with the highest available **/ +/** numbers, halo is not really needed **/ +/** so this "mesh*" routine is used. If **/ +/** halo was needed, a "hmesh*" routine **/ +/** should be used instead. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MESH +#define MESH_INDUCE_SEPA + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "mesh_induce_sepa.h" + +/***************************************/ +/* */ +/* This routine handles source meshes. */ +/* */ +/***************************************/ + +/* This routine builds the separator mesh +** induced by the original mesh, the list of +** selected separator node vertices, and the +** vertex part array. Elements which are +** adjacent to the selected nodes are themselves +** selected. +** The induced vnumtab array is the baseval-based +** list of remaining node vertices if the original +** mesh does not have a vnumtab, or the proper +** subset of the original vnumtab else. +** This routine builds a mesh with nodes first +** and elements last. If a halo version of this +** algorithm had to be created, it should be +** re-worked such that elements are put first +** and nodes last, to enforce the structure of +** halo meshes. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +meshInduceSepa ( +const Mesh * restrict const orgmeshptr, /* Pointer to original mesh */ +const GraphPart * restrict const orgparttax, /* Array of vertex partition flags */ +const Gnum orgsepanbr, /* Number of node vertices in separator */ +const Gnum * restrict const orgsepatab, /* Array of node indices */ +Mesh * restrict const indmeshptr) /* Pointer to induced submesh */ +{ + Gnum orgvertnbr; /* Number of vertices in original mesh */ + Gnum orgbitssiz; /* Size of int array holding as many bits as element vertices */ + unsigned int * restrict orgbitstab; /* Array of bit flags for mesh elements */ + Gnum indvnumnum; /* Current vertex number index in separator node list */ + Gnum * restrict indvneltax; /* Array of original numbers for induced elements */ + Gnum indvelmnbr; /* (Approximate) number of element vertices in induced mesh */ + Gnum indvertnbr; /* (Approximate) number of vertices in induced mesh */ + Gnum indvnodnum; /* Number of current node vertex in induced mesh */ + Gnum indvnlosum; /* Sum of node vertex load array */ + Gnum indvelmnum; /* Number of current element vertex in induced mesh */ + Gnum * restrict indedgetax; /* Based array to edge array of induced mesh */ + Gnum indedgenum; /* Number of current edge to be created in induced mesh */ + Gnum indedgenbr; /* (Approximate) number of edges in induced mesh graph */ + Gnum * restrict orgindxtax; /* Original to induced vertex number translation */ + MeshInduceSepaHash * restrict hashtab; /* Node hash array */ + Gnum hashmsk; /* Mask for hash array */ + void * restrict p; + + orgbitssiz = (orgmeshptr->velmnbr + (INTSIZEBITS - 1)) / INTSIZEBITS; /* Compute size of element bit array */ + if ((orgbitstab = (unsigned int *) memAlloc (orgbitssiz * sizeof (unsigned int))) == NULL) { + errorPrint ("meshInduceSepa: out of memory (1)"); + return (1); + } + memSet (orgbitstab, ~0, orgbitssiz * sizeof (unsigned int)); + + for (indvnumnum = 0, indvelmnbr = 0, indedgenbr = 0; /* For all separator nodes in list */ + indvnumnum < orgsepanbr; indvnumnum ++) { + Gnum orgvnodnum; /* Number of current node in original mesh */ + Gnum orgenodnum; + + orgvnodnum = orgsepatab[indvnumnum]; /* Get number of separator node */ + + for (orgenodnum = orgmeshptr->verttax[orgvnodnum], indedgenbr += (orgmeshptr->vendtax[orgvnodnum] - orgenodnum); + orgenodnum < orgmeshptr->vendtax[orgvnodnum]; orgenodnum ++) { + Gnum orgvelmidx; /* Index of incident element in bit array */ + Gnum orgvelmbit; /* Bit to update in element bit array */ + + orgvelmidx = orgmeshptr->edgetax[orgenodnum] - orgmeshptr->velmbas; + orgvelmbit = orgvelmidx & (INTSIZEBITS - 1); + orgvelmidx /= INTSIZEBITS; + indvelmnbr += (orgbitstab[orgvelmidx] >> orgvelmbit) & 1; /* Count element vertex if not yet accounted for */ + orgbitstab[orgvelmidx] &= ~(1 << orgvelmbit); + } + } + indedgenbr *= 2; /* Number of arcs is twice number of edges */ + memFree (orgbitstab); + + memSet (indmeshptr, 0, sizeof (Mesh)); /* Initialize mesh fields */ + indmeshptr->baseval = orgmeshptr->baseval; + indmeshptr->flagval = MESHFREETABS | MESHVERTGROUP; + indmeshptr->vnodnbr = orgsepanbr; /* Nodes first */ + indmeshptr->vnodbas = indmeshptr->baseval; + indmeshptr->vnodnnd = + indmeshptr->velmbas = orgsepanbr + indmeshptr->baseval; /* Elements last */ + indmeshptr->veisnbr = 0; /* No isolated elements */ + + for (hashmsk = 15; hashmsk < orgmeshptr->degrmax; hashmsk = hashmsk * 2 + 1) ; + hashmsk = hashmsk * 4 + 3; /* Compute size of node hash table */ + + indvertnbr = indvelmnbr + orgsepanbr; /* Upper bound on number of all vertices */ + if (orgmeshptr->velotax != NULL) { + p = memAllocGroup ((void **) (void *) + &indmeshptr->verttax, (size_t) (indvertnbr * sizeof (Gnum)), /* verttab is not compact */ + &indmeshptr->vendtax, (size_t) (indvertnbr * sizeof (Gnum)), + &indmeshptr->vnumtax, (size_t) (orgsepanbr * sizeof (Gnum)), /* vnumtab is of size indnodenbr */ + &indmeshptr->velotax, (size_t) (orgsepanbr * sizeof (Gnum)), NULL); /* Element vertices assumed not weighted */ + indmeshptr->velotax -= indmeshptr->vnodbas; + } + else + p = memAllocGroup ((void **) (void *) + &indmeshptr->verttax, (size_t) (indvertnbr * sizeof (Gnum)), + &indmeshptr->vendtax, (size_t) (indvertnbr * sizeof (Gnum)), + &indmeshptr->vnumtax, (size_t) (orgsepanbr * sizeof (Gnum)), NULL); /* vnumtab is of size indnodenbr */ + orgvertnbr = orgmeshptr->velmnbr + orgmeshptr->vnodnbr; + if (p != 0) { + indmeshptr->verttax -= indmeshptr->baseval; + indmeshptr->vendtax -= indmeshptr->baseval; + indmeshptr->vnumtax -= indmeshptr->vnodbas; /* vnumtab is of size indmeshptr->vnodnbr */ + + p = memAllocGroup ((void **) (void *) + &indedgetax, (size_t) (indedgenbr * sizeof (Gnum)), + &indvneltax, (size_t) (indvelmnbr * sizeof (Gnum)), + &orgindxtax, (size_t) (orgvertnbr * sizeof (Gnum)), + &hashtab, (size_t) ((hashmsk + 1) * sizeof (MeshInduceSepaHash)), NULL); + } + if (p == 0) { + errorPrint ("meshInduceSepa: out of memory (2)"); /* Allocate induced mesh graph structure */ + return (1); + } + memSet (orgindxtax, ~0, orgvertnbr * sizeof (Gnum)); + memSet (hashtab, ~0, (hashmsk + 1) * sizeof (MeshInduceSepaHash)); + indedgetax -= indmeshptr->baseval; + indvneltax -= indmeshptr->velmbas; + orgindxtax -= orgmeshptr->baseval; + + for (indvnumnum = 0, indvnodnum = indedgenum = indmeshptr->baseval, indvelmnum = orgsepanbr + indvnodnum, indedgenbr = 0, indvnlosum = 0; + indvnumnum < orgsepanbr; indvnumnum ++) { /* For all node vertices in separator */ + Gnum orgvnodnum; /* Number of current node in original mesh */ + Gnum orgenodnum; + Gnum indenodnum; /* Current index in node edge sub-array */ + + orgvnodnum = orgsepatab[indvnumnum]; /* Get number of separator node */ + + if (orgindxtax[orgvnodnum] == ~0) /* If separator node not yet numbered */ + orgindxtax[orgvnodnum] = indvnodnum ++; /* One more node vertex created */ + indmeshptr->verttax[orgindxtax[orgvnodnum]] = indedgenum; /* Set beginning of edge sub-array */ + indmeshptr->vnumtax[orgindxtax[orgvnodnum]] = orgvnodnum - (orgmeshptr->vnodbas - orgmeshptr->baseval); + if (indmeshptr->velotax != NULL) { + Gnum indvnloval; + + indvnloval = orgmeshptr->velotax[orgvnodnum]; + indvnlosum += indvnloval; + indmeshptr->velotax[orgindxtax[orgvnodnum]] = indvnloval; + } + + indenodnum = indedgenum; /* Record position of node edge sub-array */ + indedgenum += orgmeshptr->vendtax[orgvnodnum] - /* Reserve space for node edges */ + orgmeshptr->verttax[orgvnodnum]; + + for (orgenodnum = orgmeshptr->verttax[orgvnodnum]; /* For all element vertices neighboring the separator node */ + orgenodnum < orgmeshptr->vendtax[orgvnodnum]; orgenodnum ++) { + Gnum orgvelmnum; /* Number of element node in original mesh */ + + orgvelmnum = orgmeshptr->edgetax[orgenodnum]; /* Get number of element */ + + if (orgindxtax[orgvelmnum] == -2) /* If discarded element */ + continue; /* Skip to next element */ + if (orgindxtax[orgvelmnum] == ~0) { /* If element not yet created */ + Gnum indedgetmp; /* Save value for edge index */ + Gnum orgeelmnum; + Gnum indenodtmp; + + indmeshptr->verttax[indvelmnum] = indedgenum; /* Set beginning of element edge sub-array */ + indedgetmp = indedgenum; + + for (orgeelmnum = orgmeshptr->verttax[orgvelmnum]; /* For all nodes neighboring the element vertex */ + orgeelmnum < orgmeshptr->vendtax[orgvelmnum]; orgeelmnum ++) { + Gnum orgvnodend; /* Number of current end node vertex in original mesh */ + + orgvnodend = orgmeshptr->edgetax[orgeelmnum]; /* Get number of end node */ + + if (orgparttax[orgvnodend] == 2) { /* If end node is in separator */ + Gnum hashnum; + + if (orgindxtax[orgvnodend] == ~0) /* If end node not yet numbered */ + orgindxtax[orgvnodend] = indvnodnum ++; /* Assign number to end node */ + + indedgetax[indedgenum ++] = orgindxtax[orgvnodend]; /* Add node to element edge sub-array */ + + for (hashnum = (orgindxtax[orgvnodend] * MESHINDUCESEPAHASHPRIME) & hashmsk; + hashtab[hashnum].orgvelmnum == orgvelmnum; hashnum = (hashnum + 1) & hashmsk) ; + hashtab[hashnum].orgvelmnum = orgvelmnum; /* Add vertex to hash table */ + hashtab[hashnum].indvnodnum = orgindxtax[orgvnodend]; + } + } + indmeshptr->vendtax[indvelmnum] = indedgenum; /* Set end of element edge sub-array */ + + for (indenodtmp = indenodnum - 1; indenodtmp >= indmeshptr->verttax[orgindxtax[orgvnodnum]]; indenodtmp --) { + Gnum indvelmtmp; /* Number of current already declared element for current node */ + Gnum indeelmtmp; /* Number of current edge of already declared element for current node */ + Gnum mtchnbr; /* Number of matches between new element and current element */ + + indvelmtmp = indedgetax[indenodtmp]; + + for (indeelmtmp = indmeshptr->verttax[indvelmtmp], mtchnbr = 0; + indeelmtmp < indmeshptr->vendtax[indvelmtmp]; indeelmtmp ++) { + Gnum indvnodend; + Gnum hashnum; + + indvnodend = indedgetax[indeelmtmp]; /* Get number of current end node of already declared element */ + + for (hashnum = (indvnodend * MESHINDUCESEPAHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + if (hashtab[hashnum].orgvelmnum != orgvelmnum) /* If end node not present */ + break; + if (hashtab[hashnum].indvnodnum == indvnodend) { /* If end node found */ + mtchnbr ++; /* One more matching node */ + break; + } + } + } + + if (mtchnbr == (indedgenum - indmeshptr->verttax[indvelmnum])) { /* If we are useless */ + orgindxtax[orgvelmnum] = -2; /* Never consider this element again */ + indedgenum = indedgetmp; /* Recycle edge sub-array of new element */ + break; /* No need to go any further */ + } + if (mtchnbr == (indmeshptr->vendtax[indvelmtmp] - indmeshptr->verttax[indvelmtmp])) { /* If other element is useless */ + indedgenbr -= mtchnbr; /* Remove its edges */ + indmeshptr->verttax[indvelmtmp] = indmeshptr->verttax[indvelmnum]; /* Recycle it into our element */ + indmeshptr->vendtax[indvelmtmp] = indmeshptr->vendtax[indvelmnum]; + orgindxtax[indvneltax[indvelmtmp]] = -2; + indvneltax[indvelmtmp] = orgvelmnum; + } + } + if (indenodtmp < indmeshptr->verttax[orgindxtax[orgvnodnum]]) { /* If new element distinct from all other neighboring elements */ + indedgetax[indenodnum ++] = indvelmnum; /* Record element in edge sub-array of current node */ + indedgenbr += indedgenum - indmeshptr->verttax[indvelmnum]; + indvneltax[indvelmnum] = orgvelmnum; /* Record original number of element in case we have to remove it afterwards */ + orgindxtax[orgvelmnum] = indvelmnum ++; + } + } + else /* Element already exists */ + indedgetax[indenodnum ++] = orgindxtax[orgvelmnum]; /* Record element in edge sub-array of current node */ + } + indmeshptr->vendtax[orgindxtax[orgvnodnum]] = indenodnum; /* Set end of edge sub-array for current node */ + indedgenbr += (indenodnum - indmeshptr->verttax[orgindxtax[orgvnodnum]]); /* Account for thes edges */ + } +#ifdef SCOTCH_DEBUG_MESH2 + if (indvnodnum != (orgsepanbr + indmeshptr->baseval)) { + errorPrint ("meshInduceSepa: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + indmeshptr->velmnbr = indvelmnum - indmeshptr->velmbas; + indmeshptr->velmnnd = indvelmnum; + indmeshptr->edgenbr = indedgenbr; + + if ((indmeshptr->edgetax = (Gnum *) memRealloc (indedgetax + indmeshptr->baseval, (indedgenum - indmeshptr->baseval) * sizeof (Gnum))) == NULL) { + errorPrint ("meshInduceSepa: out of memory (3)"); + memFree (indedgetax + indmeshptr->baseval); /* Free group leader */ + meshFree (indmeshptr); + return (1); + } + indmeshptr->edgetax -= indmeshptr->baseval; + + indmeshptr->velosum = indmeshptr->velmnbr; /* TODO: account for element weights */ + indmeshptr->vnlosum = (indmeshptr->velotax == NULL) ? orgsepanbr : indvnlosum; + indmeshptr->degrmax = orgmeshptr->degrmax; /* Rough estimate */ + + if (orgmeshptr->vnumtax != NULL) { /* If mesh is a submesh */ + for (indvnodnum = indmeshptr->vnodbas; indvnodnum < indmeshptr->vnodnnd; indvnodnum ++) + indmeshptr->vnumtax[indvnodnum] = orgmeshptr->vnumtax[indmeshptr->vnumtax[indvnodnum] + (orgmeshptr->vnodbas - orgmeshptr->baseval)]; + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/mesh_induce_sepa.h b/scotch_6.0.3/src/libscotch/mesh_induce_sepa.h new file mode 100644 index 00000000..f98edaec --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_induce_sepa.h @@ -0,0 +1,64 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_induce_sepa.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the improved Fiduccia-Mattheyses **/ +/** graph separation routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 04 feb 2003 **/ +/** to 09 feb 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Prime number for hashing vertex numbers. +*/ + +#define MESHINDUCESEPAHASHPRIME 17 /*+ Prime number for hashing +*/ + +/* +** The type and structure definitions. +*/ + +/*+ The hash vertex structure. +*/ + +typedef struct MeshInduceSepaHash_ { + Gnum orgvelmnum; /*+ Number of element in original mesh +*/ + Gnum indvnodnum; /*+ Number of neighbor node vertex in induced mesh +*/ +} MeshInduceSepaHash; diff --git a/scotch_6.0.3/src/libscotch/mesh_io.c b/scotch_6.0.3/src/libscotch/mesh_io.c new file mode 100644 index 00000000..132bdb90 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_io.c @@ -0,0 +1,402 @@ +/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_io.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles the source graph **/ +/** input/output functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 05 nov 2002 **/ +/** to 06 may 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to 27 feb 2008 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MESH_IO + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "graph_io.h" +#include "mesh.h" +#include "mesh_io.h" + +/******************************************/ +/* */ +/* These routines handle source mesh I/O. */ +/* */ +/******************************************/ + +/* This routine loads a source mesh from +** the given stream. +** Edge loads, whenever present, are +** always discarded. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +meshLoad ( +Mesh * restrict const meshptr, /* Mesh structure to fill */ +FILE * restrict const stream, /* Stream from which to read graph data */ +const Gnum baseval) /* Base value (-1 means keep file base) */ +{ + Gnum edgenum; /* Number of edges really allocated */ + Gnum edgennd; + Gnum vertnbr; + Gnum velmnbr; /* Number of elements in mesh */ + Gnum velmbas; /* Base index for element vertices */ + Gnum vnodnbr; /* Number of nodes in mesh */ + Gnum vnodbas; /* Base index for node vertices */ + Gnum vlblmax; /* Maximum vertex label number */ + Gnum vlblval; /* Value where to read vertex label */ + Gnum velonbr; /* Size of vertex load array */ + Gnum veloval; /* Value where to read vertex load */ + Gnum vlblnbr; /* Size of vertex label array */ + Gnum edloval; /* Value where to read edge load */ + Gnum edgeval; /* Value where to read edge end */ + Gnum baseadj; + Gnum versval; + Gnum degrmax; + Gnum propval; + char proptab[4]; + Gnum vertbastab[2]; + Gnum vertnndtab[2]; + Gnum edgeadjtab[2]; + int i; + + memSet (meshptr, 0, sizeof (Mesh)); + + if ((intLoad (stream, &versval) != 1) || /* Read version number */ + (versval != 1)) { + errorPrint ("meshLoad: bad input (1)"); + return (1); + } + + if ((intLoad (stream, &velmnbr) != 1) || /* Read rest of header */ + (intLoad (stream, &vnodnbr) != 1) || + (intLoad (stream, &meshptr->edgenbr) != 1) || + (intLoad (stream, &velmbas) != 1) || + (intLoad (stream, &vnodbas) != 1) || + (intLoad (stream, &propval) != 1) || + (velmnbr < 0) || + (vnodnbr < 0) || + (velmbas < 0) || + (vnodbas < 0) || + (propval < 0) || + (propval > 111) || + (((velmbas + velmnbr) != vnodbas) && + ((vnodbas + vnodnbr) != velmbas))) { + errorPrint ("meshLoad: bad input (2)"); + return (1); + } + sprintf (proptab, "%3.3d", (int) propval); /* Compute file properties */ + proptab[0] -= '0'; /* Vertex labels flag */ + proptab[1] -= '0'; /* Edge weights flag */ + proptab[2] -= '0'; /* Vertex loads flag */ + + baseadj = MIN (velmbas, vnodbas); /* Get file graph base value */ + if (baseval == -1) { /* If keep file graph base */ + meshptr->baseval = baseadj; /* Set graph base as file base */ + baseadj = 0; /* No base adjustment needed */ + } + else { /* If set graph base */ + meshptr->baseval = baseval; /* Set wanted graph base */ + baseadj = baseval - baseadj; /* Update base adjust */ + } + meshptr->flagval = MESHFREEVERT | MESHVERTGROUP; /* Edge array grouped with vertex array */ + meshptr->velmnbr = velmnbr; + meshptr->velmbas = velmbas + baseadj; + meshptr->velmnnd = velmnbr + (velmbas + baseadj); + meshptr->vnodnbr = vnodnbr; + meshptr->vnodbas = vnodbas + baseadj; + meshptr->vnodnnd = vnodnbr + (vnodbas + baseadj); + vertnbr = velmnbr + vnodnbr; + + velonbr = (proptab[2] != 0) ? vertnbr : 0; + vlblnbr = (proptab[0] != 0) ? vertnbr : 0; + + if (memAllocGroup ((void **) (void *) + &meshptr->verttax, (size_t) ((vertnbr + 1) * sizeof (Gnum)), + &meshptr->vlbltax, (size_t) ( vlblnbr * sizeof (Gnum)), + &meshptr->velotax, (size_t) ( velonbr * sizeof (Gnum)), /* Allocate single array for both element and node vertices */ + &meshptr->edgetax, (size_t) ( meshptr->edgenbr * sizeof (Gnum)), NULL) == NULL) { /* Edge array grouped with vertex arrays */ + errorPrint ("meshLoad: out of memory (1)"); + meshFree (meshptr); + return (1); + } + meshptr->verttax -= meshptr->baseval; + meshptr->vendtax = meshptr->verttax + 1; /* Use compact vertex array */ + meshptr->velotax = (velonbr != 0) ? (meshptr->velotax - meshptr->baseval) : NULL; /* Store based load array access in velotax */ + meshptr->vnlotax = meshptr->velotax; + meshptr->vlbltax = (vlblnbr != 0) ? (meshptr->vlbltax - meshptr->baseval) : NULL; + meshptr->velosum = meshptr->velmnbr; /* Assume element and node vertices not weighted */ + meshptr->vnlosum = meshptr->vnodnbr; + meshptr->edgetax -= meshptr->baseval; + + degrmax = 0; + edgennd = meshptr->edgenbr + meshptr->baseval; + edgenum = meshptr->baseval; /* No edges allocated yet */ + vlblmax = vertnbr + meshptr->baseval - 1; /* No vertex labels known */ + + if (meshptr->velmbas <= meshptr->vnodbas) { /* If elements first */ + vertbastab[0] = meshptr->velmbas; + vertnndtab[0] = meshptr->velmnnd; + edgeadjtab[0] = meshptr->vnodbas - meshptr->baseval; + vertbastab[1] = meshptr->vnodbas; + vertnndtab[1] = meshptr->vnodnnd; + edgeadjtab[1] = meshptr->velmbas - meshptr->baseval; + } + else { + vertbastab[0] = meshptr->vnodbas; + vertnndtab[0] = meshptr->vnodnnd; + edgeadjtab[0] = meshptr->velmbas - meshptr->baseval; + vertbastab[1] = meshptr->velmbas; + vertnndtab[1] = meshptr->velmnnd; + edgeadjtab[1] = meshptr->vnodbas - meshptr->baseval; + } + for (i = 0; i < 2; i ++) { /* For both kinds of vertices */ + Gnum vertbas; + Gnum vertnnd; + Gnum edgeadj; + Gnum vertnum; + Gnum velosum; + Gnum velomax; + + vertbas = vertbastab[i]; + vertnnd = vertnndtab[i]; + edgeadj = edgeadjtab[i]; + velosum = 0; + velomax = 1; /* Assume vertex loads all equal to 1 */ + + for (vertnum = vertbas; vertnum < vertnnd; vertnum ++) { /* For all vertices of same kind */ + Gnum degrval; + + if (meshptr->vlbltax != NULL) { /* If must read label */ + if (intLoad (stream, &vlblval) != 1) { /* Read label data */ + errorPrint ("meshLoad: bad input (3)"); + meshFree (meshptr); + return (1); + } + meshptr->vlbltax[vertnum] = vlblval + vertbas + baseadj; /* Adjust vertex label */ + if (meshptr->vlbltax[vertnum] > vlblmax) /* Get maximum vertex label */ + vlblmax = meshptr->vlbltax[vertnum]; + } + if (proptab[2] != 0) { /* If must read vertex load */ + if ((intLoad (stream, &veloval) != 1) || /* Read vertex load data */ + (veloval < 1)) { + errorPrint ("meshLoad: bad input (4)"); + meshFree (meshptr); + return (1); + } + if (veloval > velomax) + velomax = veloval; + meshptr->velotax[vertnum] = veloval; + velosum += veloval; + } + if (intLoad (stream, °rval) != 1) { /* Read vertex degree */ + errorPrint ("meshLoad: bad input (5)"); + meshFree (meshptr); + return (1); + } + if (degrmax < degrval) /* Set maximum degree */ + degrmax = degrval; + + meshptr->verttax[vertnum] = edgenum; /* Set index in edge array */ + degrval += edgenum; + if (degrval > edgennd) { /* Check if edge array overflows */ + errorPrint ("meshLoad: invalid arc count (1)"); + meshFree (meshptr); + return (1); + } + + for ( ; edgenum < degrval; edgenum ++) { + if (proptab[1] != 0) { /* If must read edge load */ + if (intLoad (stream, &edloval) != 1) { /* Read edge load data (useless) */ + errorPrint ("meshLoad: bad input (6)"); + meshFree (meshptr); + return (1); + } + } + if (intLoad (stream, &edgeval) != 1) { /* Read edge data */ + errorPrint ("meshLoad: bad input (7)"); + meshFree (meshptr); + return (1); + } + meshptr->edgetax[edgenum] = edgeval + edgeadj; + } + } + + if (vertbastab[i] == meshptr->velmbas) { /* If elements are processed */ + if (velomax == 1) /* If element loads not significant */ + meshptr->velotax = NULL; + else + meshptr->velosum = velosum; + } + else { + if (velomax == 1) /* If node loads not significant */ + meshptr->vnlotax = NULL; + else + meshptr->vnlosum = velosum; + } + } + meshptr->verttax[vertnbr + meshptr->baseval] = meshptr->edgenbr + meshptr->baseval; /* Set end of edge array */ + + if (edgenum != edgennd) { /* Check if number of edges is valid */ + errorPrint ("meshLoad: invalid arc count (2)"); + meshFree (meshptr); + return (1); + } + + meshptr->degrmax = degrmax; + + if (meshptr->vlbltax != NULL) { /* If vertex label renaming necessary */ + if (graphLoad2 (meshptr->baseval, vertnbr + meshptr->baseval, meshptr->verttax, /* Rename edge ends */ + meshptr->vendtax, meshptr->edgetax, vlblmax, meshptr->vlbltax) != 0) { + errorPrint ("meshLoad: cannot relabel vertices"); + meshFree (meshptr); + return (1); + } + } + +#ifdef SCOTCH_DEBUG_MESH2 + if (meshCheck (meshptr) != 0) { /* Check mesh consistency */ + errorPrint ("meshLoad: inconsistent mesh data"); + meshFree (meshptr); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + return (0); +} + +/* This routine saves a source mesh to +** the given stream. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +meshSave ( +const Mesh * restrict const meshptr, +FILE * restrict const stream) +{ + char propstr[4]; /* Property string */ + Gnum vertbastab[2]; + Gnum vertnndtab[2]; + Gnum * velotabtab[2]; + Gnum edgeadjtab[2]; + int i; + int o; + + propstr[0] = (meshptr->vlbltax != NULL) ? '1' : '0'; /* Set property string */ + propstr[1] = '0'; /* No edge loads written */ + propstr[2] = ((meshptr->velotax != NULL) || (meshptr->vnlotax != NULL)) ? '1' : '0'; + propstr[3] = '\0'; + + if (fprintf (stream, "1\n" GNUMSTRING "\t" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t" GNUMSTRING "\t%3s\n", /* Write file header */ + (Gnum) meshptr->velmnbr, + (Gnum) meshptr->vnodnbr, + (Gnum) meshptr->edgenbr, + (Gnum) meshptr->velmbas, + (Gnum) meshptr->vnodbas, + propstr) == EOF) { + errorPrint ("meshSave: bad output (1)"); + return (1); + } + + vertbastab[0] = meshptr->baseval; + vertnndtab[1] = meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval; + if (meshptr->velmbas <= meshptr->vnodbas) { /* If elements first */ + vertnndtab[0] = meshptr->velmnnd; + velotabtab[0] = meshptr->velotax; + edgeadjtab[0] = meshptr->vnodbas - meshptr->baseval; + vertbastab[1] = meshptr->vnodbas; + velotabtab[0] = meshptr->vnlotax; + edgeadjtab[1] = meshptr->velmbas - meshptr->baseval; + } + else { + vertnndtab[0] = meshptr->vnodnnd; + velotabtab[0] = meshptr->vnlotax; + edgeadjtab[0] = meshptr->velmbas - meshptr->baseval; + vertbastab[1] = meshptr->velmbas; + velotabtab[1] = meshptr->velotax; + edgeadjtab[1] = meshptr->vnodbas - meshptr->baseval; + } + for (i = 0; i < 2; i ++) { /* For both kinds of vertices */ + Gnum vertbas; + Gnum vertnnd; + Gnum * restrict velotax; + Gnum edgeadj; + Gnum vertnum; + + vertbas = vertbastab[i]; + vertnnd = vertnndtab[i]; + velotax = velotabtab[i]; + edgeadj = edgeadjtab[i]; + + for (vertnum = vertbas, o = 0; (vertnum < vertnnd) && (o == 0); vertnum ++) { + Gnum edgenum; + + if (meshptr->vlbltax != NULL) /* Write vertex label if necessary */ + o = (fprintf (stream, GNUMSTRING "\t", (Gnum) meshptr->vlbltax[vertnum]) == EOF); + if (propstr[2] != '0') /* Write vertex load if necessary */ + o |= (fprintf (stream, GNUMSTRING "\t", (Gnum) ((velotax != NULL) ? velotax[vertnum] : 1)) == EOF); + o |= (fprintf (stream, GNUMSTRING, (Gnum) (meshptr->vendtax[vertnum] - meshptr->verttax[vertnum])) == EOF); /* Write vertex degree */ + + for (edgenum = meshptr->verttax[vertnum]; + (edgenum < meshptr->vendtax[vertnum]) && (o == 0); edgenum ++) { + o |= (putc ('\t', stream) == EOF); + o |= (intSave (stream, /* Write edge end */ + (meshptr->vlbltax != NULL) ? meshptr->vlbltax[meshptr->edgetax[edgenum]] : meshptr->edgetax[edgenum] - edgeadj) != 1); + } + o |= (putc ('\n', stream) == EOF); + } + } + + if (o != 0) + errorPrint ("meshSave: bad output (2)"); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/mesh_io.h b/scotch_6.0.3/src/libscotch/mesh_io.h new file mode 100644 index 00000000..2475024e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_io.h @@ -0,0 +1,57 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_io.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the source graph input/output **/ +/** functions. **/ +/** **/ +/** DATES : # Version 4.0 : from : 14 nov 2002 **/ +/** to 14 nov 2002 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef MESH_IO +#define static +#endif + +int meshLoad2 (const Gnum, const Gnum, const Gnum * const, const Gnum * const, Gnum * const, const Gnum, const Gnum * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/mesh_io_habo.c b/scotch_6.0.3/src/libscotch/mesh_io_habo.c new file mode 100644 index 00000000..c2455afa --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_io_habo.c @@ -0,0 +1,302 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_io_habo.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the I/O routines **/ +/** for handling the Harwell-Boeing **/ +/** elemental matrix format. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 jan 2004 **/ +/** to 20 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MESH_IO_HABO + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "mesh.h" + +/* This routine loads the geometrical mesh +** in the Harwell-Boeing matrix format, and +** allocates the proper structures. +** - 0 : on success. +** - !0 : on error. +*/ + +int +meshGeomLoadHabo ( +Mesh * restrict const meshptr, /* Mesh to load */ +Geom * restrict const geomptr, /* Geometry to load */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* No use */ +{ + long habmattag; /* Matrix tag number in file */ + long habmatnum; /* Current matrix number */ + char habmatbuf[4][84]; /* Matrix header line buffers */ + char habmattype[4]; /* Matrix type */ + long habcrdnbr; /* Total number of data lines */ + long habrhsnbr; /* Number of right hand side lines */ + int habcolsiz; /* Size of column type */ + int habnzrsiz; /* Size of non-zero type */ + Gnum habevlnbr; /* Number of element matrix values (not uesd) */ + Gnum habvixnbr; /* Number of element matrix variable indices */ + Gnum habeltnbr; /* Number of elements */ + Gnum habvarnbr; /* Number of variables, that is, nodes */ + Gnum velmnum; /* Number of current element vertex */ + Gnum vnodnum; /* Number of current node vertex */ + Gnum edgenum; /* Number of current edge (arc) */ + Gnum edgesum; /* Accumulated number of edges in node part */ + Gnum degrmax; /* Maximum degree */ + int c; + + if (((habmattag = atol (dataptr)) == 0) && /* Get tag value */ + (dataptr[0] != '0') && (dataptr[0] != '\0')) { + errorPrint ("meshGeomLoadHabo: bad input (1)"); + return (1); + } + + for (habmatnum = 0; habmatnum <= habmattag; habmatnum ++) { /* Read headers and skip if necessary */ + memSet (habmatbuf[0], ' ', &habmatbuf[3][83] - &habmatbuf[0][0]); /* Initialize header buffers */ + if ((fgets (habmatbuf[0], 83, filesrcptr) == NULL) || /* Read mesh header */ + (fgets (habmatbuf[1], 83, filesrcptr) == NULL) || + (fgets (habmatbuf[2], 83, filesrcptr) == NULL) || + (fgets (habmatbuf[3], 83, filesrcptr) == NULL)) { + errorPrint ("meshGeomLoadHabo: bad input (2)"); + return (1); + } + habmatbuf[1][70] = '\0'; /* Extract header values */ + habrhsnbr = atol (&habmatbuf[1][56]); + habmatbuf[1][14] = '\0'; + habcrdnbr = atol (&habmatbuf[1][00]); + habmattype[0] = toupper (habmatbuf[2][0]); + habmattype[1] = toupper (habmatbuf[2][1]); + habmattype[2] = toupper (habmatbuf[2][2]); + habmatbuf[2][70] = '\0'; + habevlnbr = (Gnum) atol (&habmatbuf[2][57]); /* NELTVL */ + habmatbuf[2][56] = '\0'; + habvixnbr = (Gnum) atol (&habmatbuf[2][43]); /* VARIX */ + habmatbuf[2][42] = '\0'; + habeltnbr = (Gnum) atol (&habmatbuf[2][29]); /* NELT */ + habmatbuf[2][28] = '\0'; + habvarnbr = (Gnum) atol (&habmatbuf[2][14]); /* NVAR */ + habmatbuf[2][14] = '\0'; + + if ((c = sscanf (habmatbuf[3], "(%*d%*[Ii]%d) (%*d%*[Ii]%d)", + &habcolsiz, &habnzrsiz)) != 2) { + errorPrint ("meshGeomLoadHabo: bad input (3, %d)", c); + return (1); + } + + if (habrhsnbr != 0) { + while ((c = getc (filesrcptr)) != '\n'){ /* Skip RHS format line */ + if (c == EOF) { + errorPrint ("meshGeomLoadHabo: bad input (4)"); + return (1); + } + } + } + + if (habmatnum < habmattag) { /* If we have to skip file */ + while (habcrdnbr -- > 0) { /* Skip all of file lines */ + while ((c = getc (filesrcptr)) != '\n') { /* Skip line */ + if (c == EOF) { + errorPrint ("meshGeomLoadHabo: bad input (5)"); + return (1); + } + } + } + } + } + + if (habmattype[2] != 'E') { + errorPrint ("meshGeomLoadHabo: only elemental matrices supported"); + return (1); + } + if (habmattype[1] == 'R') { + errorPrint ("meshGeomLoadHabo: rectangular matrices not supported"); + return (1); + } + + if (((meshptr->verttax = (Gnum *) memAlloc ((habeltnbr + habvarnbr + 1) * sizeof (Gnum))) == NULL) || + ((meshptr->edgetax = (Gnum *) memAlloc (habvixnbr * 2 * sizeof (Gnum))) == NULL)) { + errorPrint ("meshGeomLoadHabo: out of memory (1)"); + if (meshptr->verttax != NULL) { + memFree (meshptr->verttax); + meshptr->verttax = NULL; + } + return (1); + } + + meshptr->flagval = MESHFREETABS; /* Totally new mesh structure */ + meshptr->baseval = 1; /* Harwell-Boeing meshs have base 1 */ + meshptr->vendtax = meshptr->verttax; + meshptr->verttax --; + meshptr->edgenbr = habvixnbr * 2; + meshptr->edgetax --; + meshptr->velmnbr = habeltnbr; + meshptr->velmbas = habvarnbr + 1; + meshptr->velmnnd = habeltnbr + habvarnbr + 1; + meshptr->vnodnbr = habvarnbr; + meshptr->vnodbas = 1; + meshptr->vnodnnd = meshptr->velmbas; + meshptr->vnlosum = habvarnbr; + + for (velmnum = meshptr->velmbas; velmnum <= meshptr->velmnnd; velmnum ++) { /* Read ELTPTR as second part of vertex array */ + Gnum habcolval; /* Current column value */ + int habcolidx; /* Current index in column value */ + + while (((c = getc (filesrcptr)) == '\n') || (c == '\r')) ; + habcolval = (c == ' ') ? 0 : (c - '0'); + for (habcolidx = 1; habcolidx < habcolsiz; habcolidx ++) { + if ((c = getc (filesrcptr)) != ' ') + habcolval = habcolval * 10 + c - '0'; + } + if (c == EOF) { + errorPrint ("meshGeomLoadHabo: bad input (6)"); + meshFree (meshptr); + return (1); + } +#ifdef SCOTCH_DEBUG_MESH2 + if ((habcolval < 1) || (habcolval > (habvixnbr + 1))) { + errorPrint ("meshGeomLoadHabo: bad input (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + meshptr->verttax[velmnum] = habcolval + habvixnbr; + } + if (meshptr->verttax[velmnum - 1] != (habvixnbr + habvixnbr + 1)) { + errorPrint ("meshGeomLoadHabo: bad input (8)"); + meshFree (meshptr); + return (1); + } + + memSet (meshptr->verttax + 1, 0, habvarnbr * sizeof (Gnum)); /* Pre-set node adjacency array */ + + for (edgenum = habvixnbr + 1; edgenum <= meshptr->edgenbr; edgenum ++) { /* Read VARIND as second part of edge array */ + Gnum habnodval; /* Current non-zero value */ + int habnzridx; /* Current index in non-zero value */ + + while (((c = getc (filesrcptr)) == '\n') || (c == '\r')) ; + habnodval = (c == ' ') ? 0 : (c - '0'); + for (habnzridx = 1; habnzridx < habnzrsiz; habnzridx ++) { + if ((c = getc (filesrcptr)) != ' ') + habnodval = habnodval * 10 + c - '0'; + } + if (c == EOF) { + errorPrint ("meshGeomLoadHabo: bad input (9)"); + meshFree (meshptr); + return (1); + } +#ifdef SCOTCH_DEBUG_MESH2 + if ((habnodval < 1) || (habnodval > habvarnbr)) { + errorPrint ("meshGeomLoadHabo: bad input (10)"); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + meshptr->edgetax[edgenum] = habnodval; + meshptr->verttax[habnodval] ++; + } + + degrmax = 1; + for (vnodnum = edgesum = 1; vnodnum < meshptr->vnodnnd; vnodnum ++) { /* Accumulate start indices for node part of vertex array */ + Gnum degrval; + + degrval = meshptr->verttax[vnodnum]; + if (degrval > degrmax) + degrmax = degrval; + + meshptr->verttax[vnodnum] = edgesum; + edgesum += degrval; + } +#ifdef SCOTCH_DEBUG_MESH2 + if (edgesum != meshptr->verttax[meshptr->velmbas]) { + errorPrint ("meshGeomLoadHabo: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + for (velmnum = meshptr->velmbas, edgenum = habvixnbr + 1; /* Re-scan element part of edge array to build node part of edge array */ + velmnum < meshptr->velmnnd; velmnum ++) { + if ((meshptr->vendtax[velmnum] - edgenum) > degrmax) + degrmax = (meshptr->vendtax[velmnum] - edgenum); + + for ( ; edgenum < meshptr->vendtax[velmnum]; edgenum ++) { + Gnum vnodnum; + + vnodnum = meshptr->edgetax[edgenum]; +#ifdef SCOTCH_DEBUG_MESH2 + if ((vnodnum < 1) || (vnodnum > habvarnbr)) { + errorPrint ("meshGeomLoadHabo: internal error (2)"); + return (1); + } + if (meshptr->verttax[vnodnum] > habvixnbr) { + errorPrint ("meshGeomLoadHabo: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + meshptr->edgetax[meshptr->verttax[vnodnum] ++] = velmnum; + } + } + + meshptr->degrmax = degrmax; + + for (vnodnum = edgesum = 1; vnodnum < meshptr->vnodnnd; vnodnum ++) { /* Restore start indices for node part of vertex array */ + Gnum edgenum; + + edgenum = meshptr->verttax[vnodnum]; + meshptr->verttax[vnodnum] = edgesum; + edgesum = edgenum; + } + + +#ifdef SCOTCH_DEBUG_MESH2 + if (meshCheck (meshptr) != 0) { + errorPrint ("meshGeomLoadHabo: inconsistent mesh data"); + return (1); + } +#endif /* SCOTCH_DEBUG_MESH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/mesh_io_scot.c b/scotch_6.0.3/src/libscotch/mesh_io_scot.c new file mode 100644 index 00000000..8e285288 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/mesh_io_scot.c @@ -0,0 +1,267 @@ +/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mesh_io_scot.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the I/O routines **/ +/** for handling the Scotch mesh format. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 jan 2004 **/ +/** to 19 jan 2004 **/ +/** # Version 5.0 : from : 13 sep 2006 **/ +/** to 27 feb 2008 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MESH_IO_SCOT + +#include "module.h" +#include "common.h" +#include "geom.h" +#include "graph.h" +#include "mesh.h" + +/* This routine loads the geometrical mesh +** in the Scotch graph format, and allocates +** the proper structures. +** - 0 : on success. +** - !0 : on error. +*/ + +int +meshGeomLoadScot ( +Mesh * restrict const meshptr, /* Graph to load */ +Geom * restrict const geomptr, /* Geometry to load */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* No use */ +{ +#ifdef DEAD_CODE /* TODO */ + double * restrict coorfiletab; /* Pointer to geometric data read from file */ + MeshGeomScotSort * restrict coorsorttab; /* Pointer to geometric data sorting array */ + int coorsortflag; /* Flag set if geometric data sorted by label */ + Gnum coornbr; /* Number of geometric coordinates in file */ + Gnum coornum; /* Number of current coordinate */ + MeshGeomScotSort * restrict vertsorttab; /* Pointer to graph sorting array */ + int vertsortflag; /* Flag set if graph data sorted by label */ + Gnum vertnum; /* Current graph vertex */ + Gnum dimnnbr; /* Dimension of geometry file */ + int o; + + if (filesrcptr != NULL) { + if (graphLoad (meshptr, filesrcptr, -1, 0) != 0) + return (1); + } + + if (filegeoptr == NULL) + return (0); + + if ((intLoad (filegeoptr, &dimnnbr) != 1) || /* Read type and number of geometry items */ + (intLoad (filegeoptr, &coornbr) != 1) || + (dimnnbr < 1) || + (dimnnbr > 3) || + (dimnnbr < 1)) { + errorPrint ("meshGeomLoadScot: bad input (1)"); + return (1); + } + if ((filesrcptr != NULL) && (meshptr->vertnbr != coornbr)) { + errorPrint ("meshGeomLoadScot: inconsistent number of vertices"); + return (1); + } + + if (meshptr->vertnbr == 0) + return (0); + + if ((geomptr->geomtab == NULL) && /* Allocate geometry if necessary */ + ((geomptr->geomtab = (double *) memAlloc (meshptr->vertnbr * dimnnbr * sizeof (double))) == NULL)) { + errorPrint ("meshGeomLoadScot: out of memory (1)"); + return (1); + } + + if (memAllocGroup ((void **) + &coorfiletab, (size_t) (coornbr * dimnnbr * sizeof (double)), + &coorsorttab, (size_t) (coornbr * sizeof (MeshGeomScotSort)), + &vertsorttab, (size_t) (meshptr->vertnbr * sizeof (MeshGeomScotSort)), NULL) == NULL) { + errorPrint ("meshGeomLoadScot: out of memory (2)"); + return (1); + } + + o = 0; + coorsortflag = 1; /* Assume geometry data sorted */ + for (coornum = 0; (o == 0) && (coornum < coornbr); coornum ++) { + Gnum vlblnum; + + o = 1 - intLoad (filegeoptr, &vlblnum); + coorsorttab[coornum].labl = vlblnum; + coorsorttab[coornum].num = coornum; + if ((coornum > 0) && /* Check if geometry data sorted */ + (coorsorttab[coornum].labl < coorsorttab[coornum - 1].labl)) + coorsortflag = 0; /* Geometry data not sorted */ + + o |= 1 - fscanf (filegeoptr, "%lf", /* Read X coordinate */ + &coorfiletab[coornum * dimnnbr]); + if (dimnnbr > 1) { + o |= 1 - fscanf (filegeoptr, "%lf", /* Read Y coordinate */ + &coorfiletab[(coornum * dimnnbr) + 1]); + if (dimnnbr > 2) + o |= 1 - fscanf (filegeoptr, "%lf", /* Read Z coordinate */ + &coorfiletab[(coornum * dimnnbr) + 2]); + } + } + if (o != 0) { + errorPrint ("meshGeomLoadScot: bad input (2)"); + memFree (coorfiletab); /* Free group leader */ + return (1); + } + + if (coorsortflag != 1) /* If geometry data not sorted */ + intSort2asc1 (coorsorttab, coornbr); /* Sort sort area by ascending labels */ + for (coornum = 1; coornum < coornbr; coornum ++) { /* Check geometric data integrity */ + if (coorsorttab[coornum].labl == coorsorttab[coornum - 1].labl) { + errorPrint ("meshGeomLoadScot: duplicate vertex label"); + memFree (coorfiletab); /* Free group leader */ + return (1); + } + } + + if (meshptr->vlbltax != NULL) { /* If graph has vertex labels */ + vertsortflag = 1; /* Assume graph data sorted */ + for (vertnum = 0; vertnum < meshptr->vertnbr; vertnum ++) { + vertsorttab[vertnum].labl = meshptr->vlbltax[vertnum + meshptr->baseval]; + vertsorttab[vertnum].num = vertnum; + if ((vertnum > 0) && /* Check if graph data sorted */ + (vertsorttab[vertnum].labl < vertsorttab[vertnum - 1].labl)) + vertsortflag = 0; /* Graph data not sorted */ + } + if (vertsortflag != 1) /* If graph data not sorted */ + intSort2asc1 (vertsorttab, meshptr->vertnbr); /* Sort sort area by ascending labels */ + } + else { /* Graph does not have vertex labels */ + for (vertnum = 0; vertnum < meshptr->vertnbr; vertnum ++) + vertsorttab[vertnum].labl = + vertsorttab[vertnum].num = vertnum; + } + + for (coornum = vertnum = 0; vertnum < meshptr->vertnbr; vertnum ++) { /* For all vertices in graph */ + while ((coornum < coornbr) && (coorsorttab[coornum].labl < vertsorttab[vertnum].labl)) + coornum ++; /* Search geometry vertex with same label */ + if ((coornum >= coornbr) || (coorsorttab[coornum].labl > vertsorttab[vertnum].labl)) { /* If label does not exist */ + errorPrint ("meshGeomLoadScot: vertex geometry data not found (%d)", + vertsorttab[vertnum].labl); + memFree (coorfiletab); /* Free group leader */ + return (1); + } + memCpy (&geomptr->geomtab[vertsorttab[vertnum].num * dimnnbr], &coorfiletab[coorsorttab[coornum ++].num * dimnnbr], dimnnbr * sizeof (double)); + } + + memFree (coorfiletab); /* Free group leader */ +#endif /* DEAD_CODE */ + return (0); +} + +/* This routine saves the source mesh +** in the Scotch mesh and geometry formats. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +meshGeomSaveScot ( +const Mesh * restrict const meshptr, /* Mesh to save */ +const Geom * restrict const geomptr, /* Geometry to save */ +FILE * const filesrcptr, /* Topological data */ +FILE * const filegeoptr, /* No use */ +const char * const dataptr) /* No use */ +{ + Gnum vnodnum; + int dimnnbr; + int o; + + if (filesrcptr != NULL) { + if (meshSave (meshptr, filesrcptr) != 0) /* Save mesh structural data */ + return (1); + } + + dimnnbr = geomptr->dimnnbr; + + o = 0; + if (geomptr->geomtab != NULL) { /* If geometrical data present */ + o = (fprintf (filegeoptr, GNUMSTRING "\n" GNUMSTRING "\n", /* Output file header */ + (Gnum) geomptr->dimnnbr, + (Gnum) meshptr->vnodnbr) == EOF); + + switch (dimnnbr) { /* Output geometry data */ + case 1 : + for (vnodnum = meshptr->vnodbas; (o == 0) && (vnodnum < meshptr->vnodnnd); vnodnum ++) + o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\n", + (Gnum) ((meshptr->vlbltax != NULL) ? meshptr->vlbltax[vnodnum] : vnodnum), + (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr]) == EOF); + break; + case 2 : + for (vnodnum = meshptr->vnodbas; (o == 0) && (vnodnum < meshptr->vnodnnd); vnodnum ++) + o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\n", + (Gnum) ((meshptr->vlbltax != NULL) ? meshptr->vlbltax[vnodnum] : vnodnum), + (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr], + (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr + 1]) == EOF); + break; + case 3 : + for (vnodnum = meshptr->vnodbas; (o == 0) && (vnodnum < meshptr->vnodnnd); vnodnum ++) + o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\t%lf\n", + (Gnum) ((meshptr->vlbltax != NULL) ? meshptr->vlbltax[vnodnum] : vnodnum), + (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr], + (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr + 1], + (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr + 2]) == EOF); + break; +#ifdef SCOTCH_DEBUG_MESH2 + default : + errorPrint ("meshGeomSaveScot: invalid geometry type"); + return (1); +#endif /* SCOTCH_DEBUG_MESH2 */ + } + + if (o != 0) { + errorPrint ("meshGeomSaveScot: bad output"); + } + } + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/module.h b/scotch_6.0.3/src/libscotch/module.h new file mode 100644 index 00000000..11eb602a --- /dev/null +++ b/scotch_6.0.3/src/libscotch/module.h @@ -0,0 +1,834 @@ +/* Copyright 2004,2007-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : module.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This is the global configuration file **/ +/** for the whole libSCOTCH library module. **/ +/** **/ +/** DATES : # Version 3.2 : from : 22 jun 1998 **/ +/** to 13 may 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 03 oct 1998 **/ +/** # Version 3.4 : from : 01 nov 2001 **/ +/** to 01 nov 2001 **/ +/** # Version 4.0 : from : 12 dec 2001 **/ +/** to 24 nov 2005 **/ +/** # Version 5.0 : from : 24 feb 2007 **/ +/** to 24 jul 2007 **/ +/** # Version 5.1 : from : 25 oct 2007 **/ +/** to 20 feb 2011 **/ +/** # Version 6.0 : from : 12 sep 2008 **/ +/** to 01 sep 2014 **/ +/** **/ +/************************************************************/ + +#define MODULE_H + +/* +** Version string. +*/ + +#define SCOTCH_VERSION_STRING SCOTCH_VERSION_STRING2(SCOTCH_VERSION) "." SCOTCH_VERSION_STRING2(SCOTCH_RELEASE) "." SCOTCH_VERSION_STRING2(SCOTCH_PATCHLEVEL) +#define SCOTCH_VERSION_STRING2(x) SCOTCH_VERSION_STRING3(x) +#define SCOTCH_VERSION_STRING3(x) #x + +/* +** Debug values. +*/ + +#ifdef SCOTCH_DEBUG_ALL +#ifndef SCOTCH_DEBUG +#define SCOTCH_DEBUG +#endif /* SCOTCH_DEBUG */ + +#define COMMON_DEBUG +#define SCOTCH_DEBUG_ARCH2 +#define SCOTCH_DEBUG_FIBO2 +#define SCOTCH_DEBUG_GAIN2 +#define SCOTCH_DEBUG_PARSER2 +#define SCOTCH_DEBUG_BDGRAPH2 +#define SCOTCH_DEBUG_BGRAPH2 +#define SCOTCH_DEBUG_DGRAPH2 +#define SCOTCH_DEBUG_DMAP2 +#define SCOTCH_DEBUG_DORDER2 +#define SCOTCH_DEBUG_GEOM2 +#define SCOTCH_DEBUG_GRAPH2 +#define SCOTCH_DEBUG_HDGRAPH2 +#define SCOTCH_DEBUG_HGRAPH2 +#define SCOTCH_DEBUG_HMESH2 +#define SCOTCH_DEBUG_KDGRAPH2 +#define SCOTCH_DEBUG_KDMAP2 +#define SCOTCH_DEBUG_KGRAPH2 +#define SCOTCH_DEBUG_LIBRARY2 +#define SCOTCH_DEBUG_MAP2 +#define SCOTCH_DEBUG_MESH2 +#define SCOTCH_DEBUG_ORDER2 +#define SCOTCH_DEBUG_PARSER2 +#define SCOTCH_DEBUG_VDGRAPH2 +#define SCOTCH_DEBUG_VGRAPH2 +#define SCOTCH_DEBUG_VMESH2 +#define SCOTCH_DEBUG_WGRAPH2 +#endif /* SCOTCH_DEBUG_ALL */ + +#ifdef SCOTCH_DEBUG +#define SCOTCH_DEBUG_ARCH1 +#define SCOTCH_DEBUG_FIBO1 +#define SCOTCH_DEBUG_GAIN1 +#define SCOTCH_DEBUG_PARSER1 +#define SCOTCH_DEBUG_BDGRAPH1 +#define SCOTCH_DEBUG_BGRAPH1 +#define SCOTCH_DEBUG_DGRAPH1 +#define SCOTCH_DEBUG_DMAP1 +#define SCOTCH_DEBUG_DORDER1 +#define SCOTCH_DEBUG_GEOM1 +#define SCOTCH_DEBUG_GRAPH1 +#define SCOTCH_DEBUG_HDGRAPH1 +#define SCOTCH_DEBUG_HGRAPH1 +#define SCOTCH_DEBUG_HMESH1 +#define SCOTCH_DEBUG_KDGRAPH1 +#define SCOTCH_DEBUG_KDMAP1 +#define SCOTCH_DEBUG_KGRAPH1 +#define SCOTCH_DEBUG_LIBRARY1 +#define SCOTCH_DEBUG_MAP1 +#define SCOTCH_DEBUG_MESH1 +#define SCOTCH_DEBUG_ORDER1 +#define SCOTCH_DEBUG_PARSER1 +#define SCOTCH_DEBUG_VDGRAPH1 +#define SCOTCH_DEBUG_VGRAPH1 +#define SCOTCH_DEBUG_VMESH1 +#define SCOTCH_DEBUG_WGRAPH1 +#endif /* SCOTCH_DEBUG */ + +/* +** Function renaming. +*/ + +#if ((! defined SCOTCH_COMMON_EXTERNAL) || (defined SCOTCH_COMMON_RENAME)) +#define memCur SCOTCH_memCur +#define memMax SCOTCH_memMax + +#define clockGet _SCOTCHclockGet + +#define commonStubDummy _SCOTCHcommonStubDummy + +#define errorPrint SCOTCH_errorPrint +#define errorPrintW SCOTCH_errorPrintW +#define errorProg SCOTCH_errorProg + +#define fileBlockClose _SCOTCHfileBlockClose +#define fileBlockOpen _SCOTCHfileBlockOpen +#define fileBlockOpenDist _SCOTCHfileBlockOpenDist +#define fileCompress _SCOTCHfileCompress +#define fileCompressType _SCOTCHfileCompressType +#define fileUncompress _SCOTCHfileUncompress +#define fileUncompressType _SCOTCHfileUncompressType +#define fileNameDistExpand _SCOTCHfileNameDistExpand + +#define intLoad _SCOTCHintLoad +#define intSave _SCOTCHintSave +#define intAscn _SCOTCHintAscn +#define intGcd _SCOTCHintGcd +#define intPerm _SCOTCHintPerm +#define intRandInit _SCOTCHintRandInit +#define intRandReset _SCOTCHintRandReset +#define intRandSeed _SCOTCHintRandSeed +#ifndef COMMON_RANDOM_SYSTEM +#define intRandVal _SCOTCHintRandVal +#endif /* COMMON_RANDOM_SYSTEM */ +#define intSort1asc1 _SCOTCHintSort1asc1 +#define intSort2asc1 _SCOTCHintSort2asc1 +#define intSort2asc2 _SCOTCHintSort2asc2 +#define intSort3asc1 _SCOTCHintSort3asc1 +#define intSort3asc2 _SCOTCHintSort3asc2 + +#define memAllocGroup _SCOTCHmemAllocGroup +#define memAllocRecord _SCOTCHmemAllocRecord +#define memCheck _SCOTCHmemCheck +#define memCheckExists _SCOTCHmemCheckExists +#define memCheckSize _SCOTCHmemCheckSize +#define memCheckToggle _SCOTCHmemCheckToggle +#define memCheckWatch _SCOTCHmemCheckWatch +#define memFreeRecord _SCOTCHmemFreeRecord +#define memReallocGroup _SCOTCHmemReallocGroup +#define memReallocRecord _SCOTCHmemReallocRecord +#define memOffset _SCOTCHmemOffset + +#define stringSubst _SCOTCHstringSubst + +#define usagePrint _SCOTCHusagePrint +#endif /* ((! defined SCOTCH_COMMON_EXTERNAL) || (defined SCOTCH_COMMON_RENAME)) */ + +#ifdef SCOTCH_RENAME +#define archInit _SCOTCHarchInit +#define archExit _SCOTCHarchExit +#define archFree _SCOTCHarchFree +#define archLoad _SCOTCHarchLoad +#define archSave _SCOTCHarchSave +/* #define archName _SCOTCHarchName Already a macro */ +#define archClass _SCOTCHarchClass +#define archClassTab _SCOTCHarchClassTab +#define archDomLoad _SCOTCHarchDomLoad +#define archDomSave _SCOTCHarchDomSave +#ifdef SCOTCH_DEBUG_ARCH2 /* If already redefined */ +#define archDomNum _SCOTCHarchDomNum +#define archDomDist _SCOTCHarchDomDist +#define archDomFrst _SCOTCHarchDomFrst +#define archDomIncl _SCOTCHarchDomIncl +#define archDomSize _SCOTCHarchDomSize +#define archDomTerm _SCOTCHarchDomTerm +#define archDomWght _SCOTCHarchDomWght +#define archDomBipart _SCOTCHarchDomBipart +#endif /* SCOTCH_DEBUG_ARCH2 */ +#define archDomMpiType _SCOTCHarchDomMpiType +#define archBuild _SCOTCHarchBuild +#define archCmpltArchLoad _SCOTCHarchCmpltArchLoad +#define archCmpltArchSave _SCOTCHarchCmpltArchSave +#define archCmpltDomNum _SCOTCHarchCmpltDomNum +#define archCmpltDomTerm _SCOTCHarchCmpltDomTerm +#define archCmpltDomSize _SCOTCHarchCmpltDomSize +/* #define archCmpltDomWght _SCOTCHarchCmpltDomWght Already a macro */ +#define archCmpltDomDist _SCOTCHarchCmpltDomDist +#define archCmpltDomFrst _SCOTCHarchCmpltDomFrst +#define archCmpltDomIncl _SCOTCHarchCmpltDomIncl +#define archCmpltDomLoad _SCOTCHarchCmpltDomLoad +#define archCmpltDomSave _SCOTCHarchCmpltDomSave +#define archCmpltDomBipart _SCOTCHarchCmpltDomBipart +#define archCmpltDomMpiType _SCOTCHarchCmpltDomMpiType +#define archCmpltwArchBuild _SCOTCHarchCmpltwArchBuild +#define archCmpltwArchFree _SCOTCHarchCmpltwArchFree +#define archCmpltwArchLoad _SCOTCHarchCmpltwArchLoad +#define archCmpltwArchSave _SCOTCHarchCmpltwArchSave +#define archCmpltwDomNum _SCOTCHarchCmpltwDomNum +#define archCmpltwDomTerm _SCOTCHarchCmpltwDomTerm +#define archCmpltwDomSize _SCOTCHarchCmpltwDomSize +#define archCmpltwDomWght _SCOTCHarchCmpltwDomWght +#define archCmpltwDomDist _SCOTCHarchCmpltwDomDist +#define archCmpltwDomFrst _SCOTCHarchCmpltwDomFrst +#define archCmpltwDomIncl _SCOTCHarchCmpltwDomIncl +#define archCmpltwDomLoad _SCOTCHarchCmpltwDomLoad +#define archCmpltwDomSave _SCOTCHarchCmpltwDomSave +#define archCmpltwDomBipart _SCOTCHarchCmpltwDomBipart +#define archCmpltwDomMpiType _SCOTCHarchCmpltwDomMpiType +#define archDecoArchBuild _SCOTCHarchDecoArchBuild +#define archDecoArchFree _SCOTCHarchDecoArchFree +#define archDecoArchLoad _SCOTCHarchDecoArchLoad +#define archDecoArchSave _SCOTCHarchDecoArchSave +#define archDecoDomNum _SCOTCHarchDecoDomNum +#define archDecoDomTerm _SCOTCHarchDecoDomTerm +#define archDecoDomSize _SCOTCHarchDecoDomSize +#define archDecoDomWght _SCOTCHarchDecoDomWght +#define archDecoDomDist _SCOTCHarchDecoDomDist +#define archDecoDomFrst _SCOTCHarchDecoDomFrst +#define archDecoDomIncl _SCOTCHarchDecoDomIncl +#define archDecoDomLoad _SCOTCHarchDecoDomLoad +#define archDecoDomSave _SCOTCHarchDecoDomSave +#define archDecoDomBipart _SCOTCHarchDecoDomBipart +#define archDecoDomMpiType _SCOTCHarchDecoDomMpiType +#define archDistArchLoad _SCOTCHarchDistArchLoad +#define archDistArchSave _SCOTCHarchDistArchSave +#define archDistArchBuild _SCOTCHarchDistArchBuild +#define archDistDomNum _SCOTCHarchDistDomNum +#define archDistDomTerm _SCOTCHarchDistDomTerm +#define archDistDomSize _SCOTCHarchDistDomSize +#define archDistDomWght _SCOTCHarchDistDomWght +#define archDistDomDist _SCOTCHarchDistDomDist +#define archDistDomFrst _SCOTCHarchDistDomFrst +#define archDistDomIncl _SCOTCHarchDistDomIncl +#define archDistDomLoad _SCOTCHarchDistDomLoad +#define archDistDomSave _SCOTCHarchDistDomSave +#define archDistDomBipart _SCOTCHarchDistDomBipart +#define archDistDomMpiType _SCOTCHarchDistDomMpiType +#define archHcubArchLoad _SCOTCHarchHcubArchLoad +#define archHcubArchSave _SCOTCHarchHcubArchSave +#define archHcubDomNum _SCOTCHarchHcubDomNum +#define archHcubDomTerm _SCOTCHarchHcubDomTerm +#define archHcubDomSize _SCOTCHarchHcubDomSize +/* #define archHcubDomWght _SCOTCHarchHcubDomWght Already a macro */ +#define archHcubDomDist _SCOTCHarchHcubDomDist +#define archHcubDomFrst _SCOTCHarchHcubDomFrst +#define archHcubDomIncl _SCOTCHarchHcubDomIncl +#define archHcubDomLoad _SCOTCHarchHcubDomLoad +#define archHcubDomSave _SCOTCHarchHcubDomSave +#define archHcubDomBipart _SCOTCHarchHcubDomBipart +#define archHcubDomMpiType _SCOTCHarchHcubDomMpiType +#define archLtleafArchLoad _SCOTCHarchLtleafArchLoad +#define archLtleafArchSave _SCOTCHarchLtleafArchSave +#define archLtleafDomNum _SCOTCHarchLtleafDomNum +#define archLtleafDomTerm _SCOTCHarchLtleafDomTerm +#define archTleafArchLoad _SCOTCHarchTleafArchLoad +#define archTleafArchFree _SCOTCHarchTleafArchFree +#define archTleafArchSave _SCOTCHarchTleafArchSave +#define archTleafDomNum _SCOTCHarchTleafDomNum +#define archTleafDomTerm _SCOTCHarchTleafDomTerm +#define archTleafDomSize _SCOTCHarchTleafDomSize +/* #define archTleafDomWght _SCOTCHarchTleafDomWght Already a macro */ +#define archTleafDomDist _SCOTCHarchTleafDomDist +#define archTleafDomFrst _SCOTCHarchTleafDomFrst +#define archTleafDomIncl _SCOTCHarchTleafDomIncl +#define archTleafDomLoad _SCOTCHarchTleafDomLoad +#define archTleafDomSave _SCOTCHarchTleafDomSave +#define archTleafDomBipart _SCOTCHarchTleafDomBipart +#define archTleafDomMpiType _SCOTCHarchTleafDomMpiType +#define archMesh2ArchLoad _SCOTCHarchMesh2ArchLoad +#define archMesh2ArchSave _SCOTCHarchMesh2ArchSave +#define archMesh2DomNum _SCOTCHarchMesh2DomNum +#define archMesh2DomTerm _SCOTCHarchMesh2DomTerm +#define archMesh2DomSize _SCOTCHarchMesh2DomSize +/* #define archMesh2DomWght _SCOTCHarchMesh2DomWght Already a macro */ +#define archMesh2DomDist _SCOTCHarchMesh2DomDist +#define archMesh2DomFrst _SCOTCHarchMesh2DomFrst +#define archMesh2DomIncl _SCOTCHarchMesh2DomIncl +#define archMesh2DomLoad _SCOTCHarchMesh2DomLoad +#define archMesh2DomSave _SCOTCHarchMesh2DomSave +#define archMesh2DomBipart _SCOTCHarchMesh2DomBipart +#define archMesh2DomBipartO _SCOTCHarchMesh2DomBipartO +#define archMesh2DomBipartU _SCOTCHarchMesh2DomBipartU +#define archMesh2DomMpiType _SCOTCHarchMesh2DomMpiType +#define archMesh3ArchLoad _SCOTCHarchMesh3ArchLoad +#define archMesh3ArchSave _SCOTCHarchMesh3ArchSave +#define archMesh3DomNum _SCOTCHarchMesh3DomNum +#define archMesh3DomTerm _SCOTCHarchMesh3DomTerm +#define archMesh3DomSize _SCOTCHarchMesh3DomSize +/* #define archMesh3DomWght _SCOTCHarchMesh3DomWght Already a macro */ +#define archMesh3DomDist _SCOTCHarchMesh3DomDist +#define archMesh3DomFrst _SCOTCHarchMesh3DomFrst +#define archMesh3DomIncl _SCOTCHarchMesh3DomIncl +#define archMesh3DomLoad _SCOTCHarchMesh3DomLoad +#define archMesh3DomSave _SCOTCHarchMesh3DomSave +#define archMesh3DomBipart _SCOTCHarchMesh3DomBipart +#define archMesh3DomMpiType _SCOTCHarchMesh3DomMpiType +#define archTermArchLoad _SCOTCHarchTermArchLoad +#define archTermArchSave _SCOTCHarchTermArchSave +#define archTermDomNum _SCOTCHarchTermDomNum +#define archTermDomTerm _SCOTCHarchTermDomTerm +#define archTermDomSize _SCOTCHarchTermDomSize +/* #define archTermDomWght _SCOTCHarchTermDomWght Already a macro */ +#define archTermDomDist _SCOTCHarchTermDomDist +#define archTermDomFrst _SCOTCHarchTermDomFrst +#define archTermDomIncl _SCOTCHarchTermDomIncl +#define archTermDomLoad _SCOTCHarchTermDomLoad +#define archTermDomSave _SCOTCHarchTermDomSave +#define archTermDomBipart _SCOTCHarchTermDomBipart +#define archTermDomMpiType _SCOTCHarchTermDomMpiType +#define archTorus2ArchLoad _SCOTCHarchTorus2ArchLoad +#define archTorus2ArchSave _SCOTCHarchTorus2ArchSave +#define archTorus2DomNum _SCOTCHarchTorus2DomNum +#define archTorus2DomTerm _SCOTCHarchTorus2DomTerm +#define archTorus2DomSize _SCOTCHarchTorus2DomSize +/* #define archTorus2DomWght _SCOTCHarchTorus2DomWght Already a macro */ +#define archTorus2DomDist _SCOTCHarchTorus2DomDist +/* #define archTorus2DomFrst _SCOTCHarchTorus2DomFrst Already a macro */ +#define archTorus2DomIncl _SCOTCHarchTorus2DomIncl +#define archTorus2DomBipart _SCOTCHarchTorus2DomBipart +/* #define archTorus2DomLoad _SCOTCHarchTorus2DomLoad Already a macro */ +/* #define archTorus2DomSave _SCOTCHarchTorus2DomSave Already a macro */ +#define archTorus2DomBipart _SCOTCHarchTorus2DomBipart +#define archTorus2DomMpiType _SCOTCHarchTorus2DomMpiType +#define archTorus3ArchLoad _SCOTCHarchTorus3ArchLoad +#define archTorus3ArchSave _SCOTCHarchTorus3ArchSave +#define archTorus3DomNum _SCOTCHarchTorus3DomNum +#define archTorus3DomTerm _SCOTCHarchTorus3DomTerm +#define archTorus3DomSize _SCOTCHarchTorus3DomSize +/* #define archTorus3DomWght _SCOTCHarchTorus3DomWght Already a macro */ +#define archTorus3DomDist _SCOTCHarchTorus3DomDist +/* #define archTorus3DomFrst _SCOTCHarchTorus3DomFrst Already a macro */ +#define archTorus3DomIncl _SCOTCHarchTorus3DomIncl +/* #define archTorus3DomLoad _SCOTCHarchTorus3DomLoad Already a macro */ +/* #define archTorus3DomSave _SCOTCHarchTorus3DomSave Already a macro */ +#define archTorus3DomBipart _SCOTCHarchTorus3DomBipart +#define archTorus3DomMpiType _SCOTCHarchTorus3DomMpiType +#define archTorusXArchLoad _SCOTCHarchTorusXArchLoad +#define archTorusXArchSave _SCOTCHarchTorusXArchSave +#define archTorusXDomNum _SCOTCHarchTorusXDomNum +#define archTorusXDomTerm _SCOTCHarchTorusXDomTerm +#define archTorusXDomSize _SCOTCHarchTorusXDomSize +/* #define archTorusXDomWght _SCOTCHarchTorusXDomWght Already a macro */ +#define archTorusXDomDist _SCOTCHarchTorusXDomDist +#define archTorusXDomFrst _SCOTCHarchTorusXDomFrst +#define archTorusXDomIncl _SCOTCHarchTorusXDomIncl +#define archTorusXDomLoad _SCOTCHarchTorusXDomLoad +#define archTorusXDomSave _SCOTCHarchTorusXDomSave +#define archTorusXDomBipart _SCOTCHarchTorusXDomBipart +#define archTorusXDomMpiType _SCOTCHarchTorusXDomMpiType +/* #define archVcmpltArchLoad _SCOTCHarchVcmpltArchLoad Already a macro */ +/* #define archVcmpltArchSave _SCOTCHarchVcmpltArchSave Already a macro */ +#define archVcmpltDomNum _SCOTCHarchVcmpltDomNum +#define archVcmpltDomTerm _SCOTCHarchVcmpltDomTerm +#define archVcmpltDomSize _SCOTCHarchVcmpltDomSize +/* #define archVcmpltDomWght _SCOTCHarchVcmpltDomWght Already a macro */ +#define archVcmpltDomDist _SCOTCHarchVcmpltDomDist +#define archVcmpltDomFrst _SCOTCHarchVcmpltDomFrst +#define archVcmpltDomIncl _SCOTCHarchVcmpltDomIncl +#define archVcmpltDomBipart _SCOTCHarchVcmpltDomBipart +#define archVcmpltDomLoad _SCOTCHarchVcmpltDomLoad +#define archVcmpltDomSave _SCOTCHarchVcmpltDomSave +#define archVcmpltDomBipart _SCOTCHarchVcmpltDomBipart +#define archVcmpltDomMpiType _SCOTCHarchVcmpltDomMpiType +/* #define archVhcubArchLoad _SCOTCHarchVhcubArchLoad Already a macro */ +/* #define archVhcubArchSave _SCOTCHarchVhcubArchSave Already a macro */ +#define archVhcubDomNum _SCOTCHarchVhcubDomNum +#define archVhcubDomTerm _SCOTCHarchVhcubDomTerm +#define archVhcubDomSize _SCOTCHarchVhcubDomSize +/* #define archVhcubDomWght _SCOTCHarchVhcubDomWght Already a macro */ +#define archVhcubDomDist _SCOTCHarchVhcubDomDist +#define archVhcubDomFrst _SCOTCHarchVhcubDomFrst +#define archVhcubDomIncl _SCOTCHarchVhcubDomIncl +#define archVhcubDomLoad _SCOTCHarchVhcubDomLoad +#define archVhcubDomSave _SCOTCHarchVhcubDomSave +#define archVhcubDomBipart _SCOTCHarchVhcubDomBipart +#define archVhcubDomMpiType _SCOTCHarchVhcubDomMpiType + +#define bdgraphInit _SCOTCHbdgraphInit +#define bdgraphInit2 _SCOTCHbdgraphInit2 +#define bdgraphExit _SCOTCHbdgraphExit +#define bdgraphZero _SCOTCHbdgraphZero +#define bdgraphbipartststratab _SCOTCHbdgraphbipartststratab +#define bdgraphCheck _SCOTCHbdgraphCheck +#define bdgraphGatherAll _SCOTCHbdgraphGatherAll +#define bdgraphBipartBd _SCOTCHbdgraphBipartBd +#define bdgraphBipartDf _SCOTCHbdgraphBipartDf +#define bdgraphBipartEx _SCOTCHbdgraphBipartEx +#define bdgraphBipartMl _SCOTCHbdgraphBipartMl +#define bdgraphBipartSq _SCOTCHbdgraphBipartSq +#define bdgraphBipartSt _SCOTCHbdgraphBipartSt +#define bdgraphBipartZr _SCOTCHbdgraphBipartZr +#define bdgraphStoreInit _SCOTCHbdgraphStoreInit +#define bdgraphStoreExit _SCOTCHbdgraphStoreExit +#define bdgraphStoreSave _SCOTCHbdgraphStoreSave +#define bdgraphStoreUpdt _SCOTCHbdgraphStoreUpdt + +#define bgraphbipartststratab _SCOTCHbgraphbipartststratab +#define bgraphInit _SCOTCHbgraphInit +#define bgraphInit2 _SCOTCHbgraphInit2 +#define bgraphInit3 _SCOTCHbgraphInit3 +#define bgraphInit4 _SCOTCHbgraphInit4 +#define bgraphInit5 _SCOTCHbgraphInit5 +#define bgraphExit _SCOTCHbgraphExit +#define bgraphCheck _SCOTCHbgraphCheck +#define bgraphSwal _SCOTCHbgraphSwal +#define bgraphZero _SCOTCHbgraphZero +#define bgraphBipartBd _SCOTCHbgraphBipartBd +#define bgraphBipartDf _SCOTCHbgraphBipartDf +#define bgraphBipartDf2 _SCOTCHbgraphBipartDf2 +#define bgraphBipartDfJoin _SCOTCHbgraphBipartDfJoin +#define bgraphBipartEx _SCOTCHbgraphBipartEx +#define bgraphBipartFm _SCOTCHbgraphBipartFm +#define bgraphBipartGg _SCOTCHbgraphBipartGg +#define bgraphBipartGp _SCOTCHbgraphBipartGp +#define bgraphBipartMl _SCOTCHbgraphBipartMl +#define bgraphBipartSt _SCOTCHbgraphBipartSt +#define bgraphBipartZr _SCOTCHbgraphBipartZr +#define bgraphStoreInit _SCOTCHbgraphStoreInit +#define bgraphStoreExit _SCOTCHbgraphStoreExit +#define bgraphStoreSave _SCOTCHbgraphStoreSave +#define bgraphStoreUpdt _SCOTCHbgraphStoreUpdt + +#if ((defined INTSIZE64) || (defined COMM)) +#define commAllgatherv _SCOTCHcommAllgatherv +#define commGatherv _SCOTCHcommGatherv +#define commScatterv _SCOTCHcommScatterv +#endif /* ((defined INTSIZE64) || (defined COMM)) */ + +#define dgraphAllreduceMaxSum2 _SCOTCHdgraphAllreduceMaxSum2 +#define dgraphBuild _SCOTCHdgraphBuild +#define dgraphBuild2 _SCOTCHdgraphBuild2 +#define dgraphBuild3 _SCOTCHdgraphBuild3 +#define dgraphBuild4 _SCOTCHdgraphBuild4 +#define dgraphBuildGrid3D _SCOTCHdgraphBuildGrid3D +#define dgraphBuildHcub _SCOTCHdgraphBuildHcub +#define dgraphCheck _SCOTCHdgraphCheck +#define dgraphBand _SCOTCHdgraphBand +#define dgraphBandColl _SCOTCHdgraphBandColl +#define dgraphBandPtop _SCOTCHdgraphBandPtop +#define dgraphCoarsen _SCOTCHdgraphCoarsen +#define dgraphExit _SCOTCHdgraphExit +#define dgraphFold _SCOTCHdgraphFold +#define dgraphFold2 _SCOTCHdgraphFold2 +#define dgraphFoldComm _SCOTCHdgraphFoldComm +#define dgraphFoldDup _SCOTCHdgraphFoldDup +#define dgraphFree _SCOTCHdgraphFree +#define dgraphGather _SCOTCHdgraphGather +#define dgraphGatherAll _SCOTCHdgraphGatherAll +#define dgraphGatherAll2 _SCOTCHdgraphGatherAll2 +/* #define dgraphGhst _SCOTCHdgraphGhst Already a macro */ +/* #define dgraphGhstReplace _SCOTCHdgraphGhstReplace Already a macro */ +#define dgraphGhst2 _SCOTCHdgraphGhst2 +#define dgraphGrow _SCOTCHdgraphGrow /* Used before macro replacement */ +#define dgraphGrowColl _SCOTCHdgraphGrowColl +#define dgraphGrowPtop _SCOTCHdgraphGrowPtop +#define dgraphHaloSync _SCOTCHdgraphHaloSync +#define dgraphHaloAsync _SCOTCHdgraphHaloAsync +#define dgraphHaloWait _SCOTCHdgraphHaloWait +#define dgraphHaloCheck _SCOTCHdgraphHaloCheck +#define dgraphInduceList _SCOTCHdgraphInduceList +#define dgraphInducePart _SCOTCHdgraphInducePart +#define dgraphInduce2 _SCOTCHdgraphInduce2 +#define dgraphInit _SCOTCHdgraphInit +#define dgraphLoad _SCOTCHdgraphLoad +#define dgraphMatchInit _SCOTCHdgraphMatchInit +#define dgraphMatchExit _SCOTCHdgraphMatchExit +#define dgraphMatchSync _SCOTCHdgraphMatchSync +#define dgraphMatchSyncColl _SCOTCHdgraphMatchSyncColl +#define dgraphMatchSyncPtop _SCOTCHdgraphMatchSyncPtop +#define dgraphMatchCheck _SCOTCHdgraphMatchCheck +#define dgraphMatchHl _SCOTCHdgraphMatchHl +#define dgraphMatchHy _SCOTCHdgraphMatchHy +#define dgraphMatchLc _SCOTCHdgraphMatchLc +#define dgraphMatchLy _SCOTCHdgraphMatchLy +#define dgraphMatchSc _SCOTCHdgraphMatchSc +#define dgraphRedist _SCOTCHdgraphRedist +#define dgraphSave _SCOTCHdgraphSave +#define dgraphScatter _SCOTCHdgraphScatter +#define dgraphView _SCOTCHdgraphView + +#define dmapInit _SCOTCHdmapInit +#define dmapExit _SCOTCHdmapExit +#define dmapAdd _SCOTCHdmapAdd +#define dmapTerm _SCOTCHdmapTerm +#define dmapSave _SCOTCHdmapSave + +#define dorderDispose _SCOTCHdorderDispose +#define dorderExit _SCOTCHdorderExit +#define dorderFree _SCOTCHdorderFree +#define dorderFrst _SCOTCHdorderFrst +#define dorderGather _SCOTCHdorderGather +#define dorderGatherTree _SCOTCHdorderGatherTree +#define dorderInit _SCOTCHdorderInit +#define dorderNew _SCOTCHdorderNew +#define dorderNewSequ _SCOTCHdorderNewSequ +#define dorderNewSequIndex _SCOTCHdorderNewSequIndex +#define dorderPerm _SCOTCHdorderPerm +#define dorderSave _SCOTCHdorderSave +#define dorderSaveBlock _SCOTCHdorderSaveBlock +#define dorderSaveMap _SCOTCHdorderSaveMap +#define dorderSaveTree _SCOTCHdorderSaveTree +#define dorderSaveTree2 _SCOTCHdorderSaveTree2 +#define dorderCblkDist _SCOTCHdorderCblkDist +#define dorderTreeDist _SCOTCHdorderTreeDist + +#define fiboTreeCheck _SCOTCHfiboTreeCheck +#define fiboTreeConsolidate _SCOTCHfiboTreeConsolidate +/* #define fiboTreeAdd _SCOTCHfiboTreeAdd Already a macro */ +#define fiboTreeDel _SCOTCHfiboTreeDel +#define fiboTreeExit _SCOTCHfiboTreeExit +#define fiboTreeFree _SCOTCHfiboTreeFree +#define fiboTreeInit _SCOTCHfiboTreeInit +#define fiboTreeMin _SCOTCHfiboTreeMin + +#define gainTablAddLin _SCOTCHgainTablAddLin +#define gainTablAddLog _SCOTCHgainTablAddLog +#define gainTablCheck _SCOTCHgainTablCheck +#ifdef SCOTCH_DEBUG_GAIN1 /* If not already redefined as accelerated macro */ +#define gainTablDel _SCOTCHgainTablDel +#endif /* SCOTCH_DEBUG_GAIN1 */ +#define gainTablExit _SCOTCHgainTablExit +#define gainTablFree _SCOTCHgainTablFree +#define gainTablFrst _SCOTCHgainTablFrst +#define gainTablInit _SCOTCHgainTablInit +#define gainTablNext _SCOTCHgainTablNext + +#define geomExit _SCOTCHgeomExit +#define geomInit _SCOTCHgeomInit + +#define graphInit _SCOTCHgraphInit +#define graphExit _SCOTCHgraphExit +#define graphFree _SCOTCHgraphFree +#define graphLoad _SCOTCHgraphLoad +#define graphLoad2 _SCOTCHgraphLoad2 +#define graphSave _SCOTCHgraphSave +#define graphBand _SCOTCHgraphBand +#define graphBase _SCOTCHgraphBase +#define graphCheck _SCOTCHgraphCheck +#define graphCoarsen _SCOTCHgraphCoarsen +#define graphInduceList _SCOTCHgraphInduceList +#define graphInducePart _SCOTCHgraphInducePart +#define graphMatch _SCOTCHgraphMatch +#define graphMatchInit _SCOTCHgraphMatchInit +#define graphGeomLoadChac _SCOTCHgraphGeomLoadChac +#define graphGeomLoadHabo _SCOTCHgraphGeomLoadHabo +#define graphGeomLoadMmkt _SCOTCHgraphGeomLoadMmkt +#define graphGeomLoadScot _SCOTCHgraphGeomLoadScot +#define graphGeomSaveChac _SCOTCHgraphGeomSaveChac +#define graphGeomSaveScot _SCOTCHgraphGeomSaveScot +#define graphGeomSaveMmkt _SCOTCHgraphGeomSaveMmkt +#define graphPtscotch _SCOTCHgraphPtscotch + +#define hallOrderHdHalmd _SCOTCHhallOrderHdHalmd +#define hallOrderHfR2hamdf4 _SCOTCHhallOrderHfR2hamdf4 +#define hallOrderHxBuild _SCOTCHhallOrderHxBuild +#define hallOrderHxTree _SCOTCHhallOrderHxTree + +#define hdgraphorderststratab _SCOTCHhdgraphorderststratab +#define hdgraphInit _SCOTCHhdgraphInit +#define hdgraphExit _SCOTCHhdgraphExit +#define hdgraphCheck _SCOTCHhdgraphCheck +#define hdgraphFold _SCOTCHhdgraphFold +#define hdgraphFold2 _SCOTCHhdgraphFold2 +#define hdgraphGather _SCOTCHhdgraphGather +#define hdgraphInduceList _SCOTCHhdgraphInduceList +#define hdgraphOrderNd _SCOTCHhdgraphOrderNd +#define hdgraphOrderSi _SCOTCHhdgraphOrderSi +#define hdgraphOrderSq _SCOTCHhdgraphOrderSq +#define hdgraphOrderSq2 _SCOTCHhdgraphOrderSq2 +#define hdgraphOrderSt _SCOTCHhdgraphOrderSt + +#define hgraphorderststratab _SCOTCHhgraphorderststratab +#define hgraphInit _SCOTCHhgraphInit +#define hgraphExit _SCOTCHhgraphExit +#define hgraphFree _SCOTCHhgraphFree +#define hgraphInduceList _SCOTCHhgraphInduceList +#define hgraphCheck _SCOTCHhgraphCheck +#define hgraphOrderBl _SCOTCHhgraphOrderBl +#define hgraphOrderCp _SCOTCHhgraphOrderCp +#define hgraphOrderGp _SCOTCHhgraphOrderGp +#define hgraphOrderHd _SCOTCHhgraphOrderHd +#define hgraphOrderHf _SCOTCHhgraphOrderHf +#define hgraphOrderHxFill _SCOTCHhgraphOrderHxFill +#define hgraphOrderKp _SCOTCHhgraphOrderKp +#define hgraphOrderNd _SCOTCHhgraphOrderNd +#define hgraphOrderSi _SCOTCHhgraphOrderSi +#define hgraphOrderSt _SCOTCHhgraphOrderSt +#define hgraphUnhalo _SCOTCHhgraphUnhalo + +#define hmeshorderststratab _SCOTCHhmeshorderststratab +#define hmeshExit _SCOTCHhmeshExit +#define hmeshBase _SCOTCHhmeshBase +#define hmeshCheck _SCOTCHhmeshCheck +#define hmeshInducePart _SCOTCHhmeshInducePart +#define hmeshHgraph _SCOTCHhmeshHgraph +#define hmeshMesh _SCOTCHhmeshMesh +#define hmeshOrderBl _SCOTCHhmeshOrderBl +#define hmeshOrderCp _SCOTCHhmeshOrderCp +#define hmeshOrderGp _SCOTCHhmeshOrderGp +#define hmeshOrderGr _SCOTCHhmeshOrderGr +#define hmeshOrderHd _SCOTCHhmeshOrderHd +#define hmeshOrderHf _SCOTCHhmeshOrderHf +#define hmeshOrderHxFill _SCOTCHhmeshOrderHxFill +#define hmeshOrderNd _SCOTCHhmeshOrderNd +#define hmeshOrderSi _SCOTCHhmeshOrderSi +#define hmeshOrderSt _SCOTCHhmeshOrderSt + +#define kdgraphmapststratab _SCOTCHkdgraphmapststratab +#define kdgraphInit _SCOTCHkdgraphInit +#define kdgraphExit _SCOTCHkdgraphExit +#define kdgraphGather _SCOTCHkdgraphGather +#define kdgraphMapRb _SCOTCHkdgraphMapRb +#define kdgraphMapRbAdd2 _SCOTCHkdgraphMapRbAdd2 +#define kdgraphMapRbAddBoth _SCOTCHkdgraphMapRbAddBoth +#define kdgraphMapRbAddOne _SCOTCHkdgraphMapRbAddOne +#define kdgraphMapRbAddPart _SCOTCHkdgraphMapRbAddPart +#define kdgraphMapRbMap _SCOTCHkdgraphMapRbMap +#define kdgraphMapRbPart _SCOTCHkdgraphMapRbPart +#define kdgraphMapSt _SCOTCHkdgraphMapSt + +#define kgraphmapststratab _SCOTCHkgraphmapststratab +#define kgraphInit _SCOTCHkgraphInit +#define kgraphExit _SCOTCHkgraphExit +#define kgraphCheck _SCOTCHkgraphCheck +#define kgraphBand _SCOTCHkgraphBand +#define kgraphCost _SCOTCHkgraphCost +#define kgraphFron _SCOTCHkgraphFron +#define kgraphFrst _SCOTCHkgraphFrst +#define kgraphMapBd _SCOTCHkgraphMapBd +#define kgraphMapCp _SCOTCHkgraphMapCp +#define kgraphMapDf _SCOTCHkgraphMapDf +#define kgraphMapEx _SCOTCHkgraphMapEx +#define kgraphMapFm _SCOTCHkgraphMapFm +#define kgraphMapMl _SCOTCHkgraphMapMl +#define kgraphMapRb _SCOTCHkgraphMapRb +#define kgraphMapRbMap _SCOTCHkgraphMapRbMap +#define kgraphMapRbBgraph _SCOTCHkgraphMapRbBgraph +#define kgraphMapRbPart _SCOTCHkgraphMapRbPart +#define kgraphMapRbVfloBuild _SCOTCHkgraphMapRbVfloBuild +#define kgraphMapRbVfloMerge _SCOTCHkgraphMapRbVfloMerge +#define kgraphMapRbVfloSplit _SCOTCHkgraphMapRbVfloSplit +#define kgraphMapSt _SCOTCHkgraphMapSt +#define kgraphStoreInit _SCOTCHkgraphStoreInit +#define kgraphStoreExit _SCOTCHkgraphStoreExit +#define kgraphStoreSave _SCOTCHkgraphStoreSave +#define kgraphStoreUpdt _SCOTCHkgraphStoreUpdt + +#define listInit _SCOTCHlistInit +#define listExit _SCOTCHlistExit +#define listAlloc _SCOTCHlistAlloc +#define listFree _SCOTCHlistFree +#define listLoad _SCOTCHlistLoad +#define listSave _SCOTCHlistSave +#define listSort _SCOTCHlistSort +#define listCopy _SCOTCHlistCopy + +#define mapInit _SCOTCHmapInit +#define mapInit2 _SCOTCHmapInit2 +#define mapExit _SCOTCHmapExit +#define mapAlloc _SCOTCHmapAlloc +#define mapBuild _SCOTCHmapBuild +#define mapCopy _SCOTCHmapCopy +#define mapFree _SCOTCHmapFree +#define mapFrst _SCOTCHmapFrst +#define mapLoad _SCOTCHmapLoad +#define mapMerge _SCOTCHmapMerge +#define mapResize _SCOTCHmapResize +#define mapResize2 _SCOTCHmapResize2 +#define mapSave _SCOTCHmapSave +#define mapTerm _SCOTCHmapTerm + +#define meshInit _SCOTCHmeshInit +#define meshExit _SCOTCHmeshExit +#define meshFree _SCOTCHmeshFree +#define meshLoad _SCOTCHmeshLoad +#define meshSave _SCOTCHmeshSave +#define meshBase _SCOTCHmeshBase +#define meshGraph _SCOTCHmeshGraph +#define meshCoarsen _SCOTCHmeshCoarsen +#define meshInduceList _SCOTCHmeshInduceList +#define meshInducePart _SCOTCHmeshInducePart +#define meshInduceSepa _SCOTCHmeshInduceSepa +#define meshCheck _SCOTCHmeshCheck +#define meshGeomLoadHabo _SCOTCHmeshGeomLoadHabo +#define meshGeomLoadScot _SCOTCHmeshGeomLoadScot +#define meshGeomSaveScot _SCOTCHmeshGeomSaveScot + +#define orderInit _SCOTCHorderInit +#define orderExit _SCOTCHorderExit +#define orderLoad _SCOTCHorderLoad +#define orderSave _SCOTCHorderSave +#define orderSaveMap _SCOTCHorderSaveMap +#define orderSaveTree _SCOTCHorderSaveTree +#define orderCheck _SCOTCHorderCheck +#define orderPeri _SCOTCHorderPeri +#define orderRang _SCOTCHorderRang +#define orderTree _SCOTCHorderTree + +#define parsermethtokentab _SCOTCHparsermethtokentab +#define parserparamcurr _SCOTCHparserparamcurr +#define parserstratcurr _SCOTCHparserstratcurr +#define parserstrattab _SCOTCHparserstrattab + +#define stratdummy _SCOTCHstratdummy +#define stratInit _SCOTCHstratInit +#define stratExit _SCOTCHstratExit +#define stratSave _SCOTCHstratSave +#define stratCondEval _SCOTCHstratCondEval +#define stratCondExit _SCOTCHstratCondExit +#define stratCondSave _SCOTCHstratCondSave +#define stratParserInit _SCOTCHstratParserInit +#define stratParserInput _SCOTCHstratParserInput +#define stratParserLex _SCOTCHstratParserLex +#define stratParserRemain _SCOTCHstratParserRemain +#define stratParserSelect _SCOTCHstratParserSelect +#define stratParserError _SCOTCHstratParserError +#define stratParserParse _SCOTCHstratParserParse +#define stratParserParse2 _SCOTCHstratParserParse2 +#define stratTestEval _SCOTCHstratTestEval +#define stratTestExit _SCOTCHstratTestExit +#define stratTestSave _SCOTCHstratTestSave + +#define threadLaunch _SCOTCHthreadLaunch +#define threadReduce _SCOTCHthreadReduce +#define threadScan _SCOTCHthreadScan + +#define vdgraphseparateststratab _SCOTCHvdgraphseparateststratab +#define vdgraphCheck _SCOTCHvdgraphCheck +#define vdgraphExit _SCOTCHvdgraphExit +#define vdgraphGatherAll _SCOTCHvdgraphGatherAll +#define vdgraphInit _SCOTCHvdgraphInit +#define vdgraphSeparateBd _SCOTCHvdgraphSeparateBd +#define vdgraphSeparateDf _SCOTCHvdgraphSeparateDf +#define vdgraphSeparateMl _SCOTCHvdgraphSeparateMl +#define vdgraphSeparateSq _SCOTCHvdgraphSeparateSq +#define vdgraphSeparateSt _SCOTCHvdgraphSeparateSt +#define vdgraphSeparateZr _SCOTCHvdgraphSeparateZr +#define vdgraphStoreExit _SCOTCHvdgraphStoreExit +#define vdgraphStoreInit _SCOTCHvdgraphStoreInit +#define vdgraphStoreSave _SCOTCHvdgraphStoreSave +#define vdgraphStoreUpdt _SCOTCHvdgraphStoreUpdt +#define vdgraphZero _SCOTCHvdgraphZero + +#define vgraphseparateststratab _SCOTCHvgraphseparateststratab +#define vgraphInit _SCOTCHvgraphInit +#define vgraphExit _SCOTCHvgraphExit +#define vgraphCheck _SCOTCHvgraphCheck +#define vgraphZero _SCOTCHvgraphZero +#define vgraphSeparateBd _SCOTCHvgraphSeparateBd +#define vgraphSeparateDf _SCOTCHvgraphSeparateDf +#define vgraphSeparateEs _SCOTCHvgraphSeparateEs +#define vgraphSeparateFm _SCOTCHvgraphSeparateFm +#define vgraphSeparateGg _SCOTCHvgraphSeparateGg +#define vgraphSeparateGp _SCOTCHvgraphSeparateGp +#define vgraphSeparateMl _SCOTCHvgraphSeparateMl +#define vgraphSeparateMt _SCOTCHvgraphSeparateMt +#define vgraphSeparateSt _SCOTCHvgraphSeparateSt +#define vgraphSeparateTh _SCOTCHvgraphSeparateTh +#define vgraphSeparateVw _SCOTCHvgraphSeparateVw +#define vgraphSeparateZr _SCOTCHvgraphSeparateZr +#define vgraphStoreInit _SCOTCHvgraphStoreInit +#define vgraphStoreExit _SCOTCHvgraphStoreExit +#define vgraphStoreSave _SCOTCHvgraphStoreSave +#define vgraphStoreUpdt _SCOTCHvgraphStoreUpdt + +#define vmeshseparateststratab _SCOTCHvmeshseparateststratab +#define vmeshExit _SCOTCHvmeshExit +#define vmeshCheck _SCOTCHvmeshCheck +#define vmeshZero _SCOTCHvmeshZero +#define vmeshSeparateFm _SCOTCHvmeshSeparateFm +#define vmeshSeparateGg _SCOTCHvmeshSeparateGg +#define vmeshSeparateGr _SCOTCHvmeshSeparateGr +#define vmeshSeparateMl _SCOTCHvmeshSeparateMl +#define vmeshSeparateSt _SCOTCHvmeshSeparateSt +#define vmeshSeparateZr _SCOTCHvmeshSeparateZr +#define vmeshStoreInit _SCOTCHvmeshStoreInit +#define vmeshStoreExit _SCOTCHvmeshStoreExit +#define vmeshStoreSave _SCOTCHvmeshStoreSave +#define vmeshStoreUpdt _SCOTCHvmeshStoreUpdt + +#define wgraphpartststratab _SCOTCHwgraphpartststratab +#define wgraphAlloc _SCOTCHwgraphAlloc +#define wgraphInit _SCOTCHwgraphInit +#define wgraphExit _SCOTCHwgraphExit +#define wgraphCheck _SCOTCHwgraphCheck +#define wgraphZero _SCOTCHwgraphZero +#define wgraphPartFm _SCOTCHwgraphPartFm +#define wgraphPartGg _SCOTCHwgraphPartGg +#define wgraphPartGp _SCOTCHwgraphPartGp +#define wgraphPartMl _SCOTCHwgraphPartMl +#define wgraphPartRb _SCOTCHwgraphPartRb +#define wgraphPartSt _SCOTCHwgraphPartSt +#define wgraphPartZr _SCOTCHwgraphPartZr +#define wgraphStoreInit _SCOTCHwgraphStoreInit +#define wgraphStoreExit _SCOTCHwgraphStoreExit +#define wgraphStoreSave _SCOTCHwgraphStoreSave +#define wgraphStoreUpdt _SCOTCHwgraphStoreUpdt +#endif /* SCOTCH_RENAME */ diff --git a/scotch_6.0.3/src/libscotch/order.c b/scotch_6.0.3/src/libscotch/order.c new file mode 100644 index 00000000..373e3a76 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/order.c @@ -0,0 +1,275 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : order.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles generic orderings. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 oct 1996 **/ +/** to 27 aug 1998 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 26 dec 2004 **/ +/** # Version 5.0 : from : 25 jul 2007 **/ +/** to 25 jul 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ORDER + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This routine initializes an ordering +** with respect to a given source graph. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +orderInit ( +Order * restrict const ordeptr, +const Gnum baseval, +const Gnum vnodnbr, +Gnum * restrict const peritab) +{ + ordeptr->flagval = ORDERNONE; + ordeptr->baseval = baseval; + ordeptr->vnodnbr = vnodnbr; + ordeptr->treenbr = /* Initialize a simple blocking */ + ordeptr->cblknbr = 1; + ordeptr->cblktre.typeval = ORDERCBLKOTHR; + ordeptr->cblktre.vnodnbr = vnodnbr; + ordeptr->cblktre.cblknbr = 0; + ordeptr->cblktre.cblktab = NULL; + ordeptr->peritab = peritab; + + if (ordeptr->peritab == NULL) { /* Inverse permutation must be allocated */ + ordeptr->flagval |= ORDERFREEPERI; /* Flag it so it will be freed */ + if ((ordeptr->peritab = (Gnum *) memAlloc (vnodnbr * sizeof (Gnum))) == NULL) { + errorPrint ("orderInit: out of memory"); + return (1); + } + } + +#ifdef SCOTCH_DEBUG_ORDER2 + memSet (ordeptr->peritab, ~0, vnodnbr * sizeof (Gnum)); +#endif /* SCOTCH_DEBUG_ORDER2 */ + + return (0); +} + +/* This routine frees the contents +** of the given ordering. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +void +orderExit ( +Order * restrict const ordeptr) +{ + if (ordeptr->cblktre.cblktab != NULL) /* Free column block tree */ + orderExit2 (ordeptr->cblktre.cblktab, ordeptr->cblktre.cblknbr); + + if ((ordeptr->peritab != NULL) && ((ordeptr->flagval & ORDERFREEPERI) != 0)) /* If peritab is group leader */ + memFree (ordeptr->peritab); /* Free group leader */ + +#ifdef SCOTCH_DEBUG_ORDER2 + memSet (ordeptr, ~0, sizeof (Order)); +#endif /* SCOTCH_DEBUG_ORDER2 */ +} + +static +void +orderExit2 ( +OrderCblk * restrict const cblktab, +const Gnum cblknbr) +{ + Gnum cblknum; + + for (cblknum = 0; cblknum < cblknbr; cblknum ++) { + if (cblktab[cblknum].cblktab != NULL) + orderExit2 (cblktab[cblknum].cblktab, cblktab[cblknum].cblknbr); + } + memFree (cblktab); +} + +/* This routine computes the inverse permutation +** of the given permutation, according to the +** direct and inverse base values. +** It returns: +** - VOID : in all cases. +*/ + +void +orderPeri ( +const Gnum * restrict const permtab, /* Permutation to invert */ +const Gnum permbas, /* Permutation base value */ +const Gnum permnbr, /* Number of permutation indices */ +Gnum * restrict const peritab, /* Array of inverse permutation */ +const Gnum peribas) /* Base value of inverse permutation */ +{ + Gnum permnum; + + for (permnum = 0; permnum < permnbr; permnum ++) + peritab[permtab[permnum] - permbas] = permnum + peribas; +} + +/* This routine computes the column block +** range array of the given ordering. +** It returns: +** - VOID : in all cases. +*/ + +void +orderRang ( +const Order * restrict const ordeptr, /* Ordering */ +Gnum * restrict const rangtab) /* Column block range array [+1] */ +{ + Gnum * rangptr; + Gnum ordenum; + + rangptr = rangtab; /* Set beginning of range array */ + ordenum = ordeptr->baseval; /* Set initial number */ + orderRang2 (&rangptr, &ordenum, &ordeptr->cblktre); + *rangptr = ordenum; /* Set end of range array */ +} + +static +void +orderRang2 ( +Gnum ** restrict const rangppt, +Gnum * restrict const ordeppt, +const OrderCblk * restrict const cblkptr) +{ + Gnum cblknum; +#ifdef SCOTCH_DEBUG_ORDER2 + Gnum * restrict rangtmp; + + if (cblkptr->vnodnbr < 1) + errorPrint ("orderRang2: internal error (1)"); +#endif /* SCOTCH_DEBUG_ORDER2 */ + + if (cblkptr->cblktab == NULL) { /* If leaf of column block tree */ + *(*rangppt) ++ = *ordeppt; /* Set beginning of column block */ + *ordeppt += cblkptr->vnodnbr; /* Advance by column block size */ + } + else { +#ifdef SCOTCH_DEBUG_ORDER2 + rangtmp = *rangppt; +#endif /* SCOTCH_DEBUG_ORDER2 */ + for (cblknum = 0; cblknum < cblkptr->cblknbr; cblknum ++) + orderRang2 (rangppt, ordeppt, &cblkptr->cblktab[cblknum]); +#ifdef SCOTCH_DEBUG_ORDER2 + if ((*ordeppt - *rangtmp) != cblkptr->vnodnbr) + errorPrint ("orderRang2: internal error (2)"); +#endif /* SCOTCH_DEBUG_ORDER2 */ + } +} + +/* This routine computes the separator tree +** array of the given ordering. +** It returns: +** - VOID : in all cases. +*/ + +void +orderTree ( +const Order * restrict const ordeptr, /* Ordering */ +Gnum * restrict const treetab) /* Column block separator tree array */ +{ + Gnum cblanum; + + cblanum = ordeptr->cblknbr + ordeptr->baseval - 1; /* Set number of last column block */ + orderTree2 (treetab - ordeptr->baseval, &cblanum, &ordeptr->cblktre, -1); + +#ifdef SCOTCH_DEBUG_ORDER2 + if (cblanum != ordeptr->baseval - 1) + errorPrint ("orderTree: internal error"); +#endif /* SCOTCH_DEBUG_ORDER2 */ +} + +static +void +orderTree2 ( +Gnum * restrict const treetax, /* Based access to tree table */ +Gnum * restrict const cblaptr, /* Pointer to current number of last column block, in descending order */ +const OrderCblk * restrict const cblkptr, /* Current column block tree node */ +Gnum cbfanum) /* Current number of ancestor separator column block */ +{ +#ifdef SCOTCH_DEBUG_ORDER2 + if (cblkptr->vnodnbr < 1) + errorPrint ("orderTree2: internal error (1)"); +#endif /* SCOTCH_DEBUG_ORDER2 */ + + if (cblkptr->cblktab == NULL) /* If leaf of column block tree */ + treetax[(*cblaptr) --] = cbfanum; /* Set its ancestor */ + else { /* Node has sub-nodes */ + Gnum cblknum; + + cblknum = cblkptr->cblknbr - 1; /* Assume all column blocks will be scanned */ + if ((cblkptr->cblknbr == 3) && /* If node is a nested dissection node */ + (cblkptr->typeval == ORDERCBLKNEDI)) { /* With a non-empty separator */ + Gnum cblanum; + + cblanum = *cblaptr; /* Save number of last column block of separator */ + orderTree2 (treetax, cblaptr, &cblkptr->cblktab[cblknum], cbfanum); /* Scan separator apart */ + cbfanum = cblanum; /* Separator becomes most recent ancestor of parts */ + cblknum = 1; /* Only scan the two parts, not the separator */ + } + + for ( ; cblknum >= 0; cblknum --) { + orderTree2 (treetax, cblaptr, &cblkptr->cblktab[cblknum], cbfanum); +#ifdef SCOTCH_DEBUG_ORDER2 + if (*cblaptr < -1) + errorPrint ("orderTree2: internal error (2)"); +#endif /* SCOTCH_DEBUG_ORDER2 */ + } + } +} diff --git a/scotch_6.0.3/src/libscotch/order.h b/scotch_6.0.3/src/libscotch/order.h new file mode 100644 index 00000000..167ffc90 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/order.h @@ -0,0 +1,133 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : order.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data **/ +/** declarations for the generic ordering **/ +/** structure. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 oct 1996 **/ +/** to : 21 aug 1998 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 28 dec 2004 **/ +/** # Version 5.0 : from : 25 jul 2007 **/ +/** to 25 jul 2007 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +#define ORDER_H + +/* +** The defines. +*/ + +/*+ Ordering option flags. +*/ + +#define ORDERNONE 0x0000 /* No options set */ +#define ORDERFREEPERI 0x0001 /* Free inverse permutation array */ + +/*+ Column block separation tree cell flags. + The ORDERCBLKNEDI value must correspond + to a single bit and be equal to the + DORDERCBLKNEDI value. +*/ + +#define ORDERCBLKOTHR 0x0000 /*+ Other ordering node +*/ +#define ORDERCBLKNEDI 0x0001 /*+ Nested dissection separator node +*/ + +/* +** The type and structure definitions. +*/ + +/*+ Column-block tree node. Each node + defines a column block, which is either + a separator or a leaf built by nested + dissection, or a super-variable built + by minimum-degree algorithms. Column + blocks are given in ascending order + within sub-arrays, for proper infix + traversal. +*/ + +typedef struct OrderCblk_ { + int typeval; /*+ Type of tree node +*/ + Gnum vnodnbr; /*+ Number of node vertices in subtree +*/ + Gnum cblknbr; /*+ Number of descendent column blocks +*/ + struct OrderCblk_ * cblktab; /*+ Sub-array of column-blocks +*/ +} OrderCblk; + +/*+ Ordering structure. A block ordering is + defined by its inverse permutation peritab + and by the tree of permuted ordering blocks, + which, once flattened, defines the blocks + of the ordering. For the sake of consistency + between orderings that have been produced + either from graphs or meshes, all ordering + values are based from baseval. +*/ + +typedef struct Order_ { + int flagval; /*+ Flag value +*/ + Gnum baseval; /*+ Base value for structures +*/ + Gnum vnodnbr; /*+ Number of node vertices +*/ + Gnum treenbr; /*+ Number of column block tree nodes +*/ + Gnum cblknbr; /*+ Number of column blocks +*/ + OrderCblk cblktre; /*+ Root of column block tree +*/ + Gnum * peritab; /*+ Inverse permutation array [vnodnbr] +*/ +} Order; + +/* +** The function prototypes. +*/ + +#ifndef ORDER +#define static +#endif + +int orderInit (Order * const, const Gnum, const Gnum, Gnum * const); +void orderExit (Order * const); +static void orderExit2 (OrderCblk * const, const Gnum); +int orderLoad (Order * restrict const, const Gnum * restrict const, FILE * restrict const); +int orderSave (const Order * restrict const, const Gnum * restrict const, FILE * restrict const); +int orderSaveMap (const Order * const, const Gnum * restrict const, FILE * restrict const); +int orderSaveTree (const Order * const, const Gnum * restrict const, FILE * restrict const); +void orderPeri (const Gnum * const, const Gnum, const Gnum, Gnum * const, const Gnum); +void orderRang (const Order * const, Gnum * const); +static void orderRang2 (Gnum ** const, Gnum * const, const OrderCblk * const); +void orderTree (const Order * restrict const, Gnum * restrict const); +static void orderTree2 (Gnum * restrict const, Gnum * restrict const, const OrderCblk * restrict const, Gnum); +int orderCheck (const Order * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/order_check.c b/scotch_6.0.3/src/libscotch/order_check.c new file mode 100644 index 00000000..045c995f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/order_check.c @@ -0,0 +1,178 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : order_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module checks the consistency of **/ +/** orderings. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 dec 2001 **/ +/** to 20 nov 2003 **/ +/** # Version 5.0 : from : 26 jul 2007 **/ +/** to 26 jul 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ORDER_CHECK + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This routine checks the consistency +** of the given ordering. +** It returns: +** - 0 : if ordering data are consistent. +** - !0 : on error. +*/ + +static +int +orderCheck2 ( +const OrderCblk * restrict const cblkptr, +Gnum * const cblknbr, +Gnum * const treenbr) +{ + if (cblkptr->vnodnbr < 1) { + errorPrint ("orderCheck2: invalid number of vertex nodes (1)"); + return (1); + } + + if (cblkptr->cblktab != NULL) { /* If node has sons */ + Gnum vnodnbr; + Gnum cblknum; + + if (cblkptr->cblknbr <= 0) { + errorPrint ("orderCheck2: invalid number of column blocks (1)"); + return (1); + } + *cblknbr += cblkptr->cblknbr - 1; + *treenbr += cblkptr->cblknbr; + for (cblknum = vnodnbr = 0; cblknum < cblkptr->cblknbr; cblknum ++) { + vnodnbr += cblkptr->cblktab[cblknum].vnodnbr; + if (orderCheck2 (&cblkptr->cblktab[cblknum], cblknbr, treenbr) != 0) + return (1); + } + if (vnodnbr != cblkptr->vnodnbr) { + errorPrint ("orderCheck2: invalid number of vertex nodes (2)"); + return (1); + } + } + else if (cblkptr->cblknbr != 0) { + errorPrint ("orderCheck2: invalid number of column blocks (2)"); + return (1); + } + + return (0); +} + +int +orderCheck ( +const Order * restrict const ordeptr) +{ + Gnum * restrict permtab; + Gnum * restrict permtax; + Gnum treenbr; + Gnum cblknbr; + Gnum vertnnd; + Gnum vertnum; + + if (ordeptr->vnodnbr != ordeptr->cblktre.vnodnbr) { + errorPrint ("orderCheck: invalid vertex count"); + return (1); + } + if ((ordeptr->cblknbr < 0) || (ordeptr->cblknbr > ordeptr->treenbr)) { + errorPrint ("orderCheck: invalid column block count (1)"); + return (1); + } + + if ((permtab = (Gnum *) memAlloc (ordeptr->vnodnbr * sizeof (Gnum))) == NULL) { + errorPrint ("orderCheck: out of memory"); + return (1); + } + memSet (permtab, ~0, ordeptr->cblktre.vnodnbr * sizeof (Gnum)); + permtax = permtab - ordeptr->baseval; + vertnnd = ordeptr->baseval + ordeptr->vnodnbr; + + for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { + if ((ordeptr->peritab[vertnum] < ordeptr->baseval) || /* If index not in range */ + (ordeptr->peritab[vertnum] >= vertnnd)) { + errorPrint ("orderCheck: invalid index"); + memFree (permtab); + return (1); + } + if (permtax[ordeptr->peritab[vertnum]] != ~0) { /* If index already used */ + errorPrint ("orderCheck: duplicate index"); + memFree (permtab); + return (1); + } + permtax[ordeptr->peritab[vertnum]] = vertnum; /* Set who updated index */ + } + for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { + if (permtab[vertnum] == ~0) { /* If index not used */ + errorPrint ("orderCheck: missing index"); + memFree (permtab); + return (1); + } + } + + memFree (permtab); + + treenbr = /* Assume there is just a root node */ + cblknbr = 1; + if (orderCheck2 (&ordeptr->cblktre, &cblknbr, &treenbr) != 0) + return (1); + if (cblknbr != ordeptr->cblknbr) { + errorPrint ("orderCheck: invalid number of column blocks"); + return (1); + } + if (treenbr != ordeptr->treenbr) { + errorPrint ("orderCheck: invalid number of tree nodes"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/order_io.c b/scotch_6.0.3/src/libscotch/order_io.c new file mode 100644 index 00000000..e10bc533 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/order_io.c @@ -0,0 +1,303 @@ +/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : order_io.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module handles generic orderings. **/ +/** **/ +/** DATES : # Version 3.2 : from : 19 oct 1996 **/ +/** to 27 aug 1998 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 28 jun 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to 27 feb 2008 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ORDER_IO + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "order.h" + +/************************************/ +/* */ +/* These routines handle orderings. */ +/* */ +/************************************/ + +/* This routine loads an ordering. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +orderLoad ( +Order * restrict const ordeptr, +const Gnum * restrict const vlbltab, +FILE * restrict const stream) +{ + Gnum * restrict permtab; + Gnum vertnum; + + if (vlbltab != NULL) { + errorPrint ("orderLoad: vertex labels not yet supported"); + return (1); + } + + if ((permtab = memAlloc (ordeptr->vnodnbr * sizeof (Gnum))) == NULL) { + errorPrint ("orderLoad: out of memory"); + return (1); + } + + if (intLoad (stream, &ordeptr->vnodnbr) != 1) { + errorPrint ("orderLoad: bad input (1)"); + memFree (permtab); + return (1); + } + + if (vlbltab == NULL) { /* If ordering does not have label array */ + for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { + Gnum vertval; + + if ((intLoad (stream, &vertval) != 1) || /* Read item data */ + (intLoad (stream, &permtab[vertnum]) != 1)) { + errorPrint ("orderLoad: bad input (2)"); + memFree (permtab); + return (1); + } + if (vertval != (vertnum + ordeptr->baseval)) { /* Read item data */ + errorPrint ("orderLoad: bad input (3)"); + memFree (permtab); + return (1); + } + } + } + + orderPeri (permtab, ordeptr->baseval, ordeptr->vnodnbr, ordeptr->peritab, ordeptr->baseval); /* Compute inverse permutation */ + + memFree (permtab); + return (0); +} + +/* This routine saves an ordering. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +orderSave ( +const Order * restrict const ordeptr, +const Gnum * restrict const vlbltab, +FILE * restrict const stream) +{ + const Gnum * restrict vlbltax; + Gnum * restrict permtab; + Gnum vertnum; + + vlbltax = (vlbltab != NULL) ? (vlbltab - ordeptr->baseval) : NULL; + + if ((permtab = memAlloc (ordeptr->vnodnbr * sizeof (Gnum))) == NULL) { + errorPrint ("orderSave: out of memory"); + return (1); + } + + if (fprintf (stream, GNUMSTRING "\n", + (Gnum) ordeptr->vnodnbr) == EOF) { + errorPrint ("orderSave: bad output (1)"); + memFree (permtab); + return (1); + } + + orderPeri (ordeptr->peritab, ordeptr->baseval, ordeptr->vnodnbr, permtab, ordeptr->baseval); /* Compute direct permutation */ + + if (vlbltax != NULL) { /* If ordering has label array */ + for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) vlbltax[vertnum + ordeptr->baseval], + (Gnum) vlbltax[permtab[vertnum]]) == EOF) { + errorPrint ("orderSave: bad output (2)"); + memFree (permtab); + return (1); + } + } + } + else { + for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) (vertnum + ordeptr->baseval), + (Gnum) permtab[vertnum]) == EOF) { + errorPrint ("orderSave: bad output (3)"); + memFree (permtab); + return (1); + } + } + } + + memFree (permtab); + return (0); +} + +/* This routine saves the column block +** mapping data of the given ordering. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +orderSaveMap ( +const Order * restrict const ordeptr, +const Gnum * restrict const vlbltab, +FILE * const stream) +{ + const Gnum * restrict vlbltax; + const Gnum * restrict peritax; + Gnum * restrict rangtab; + Gnum * restrict cblktax; + Gnum vnodnnd; + Gnum vnodnum; + Gnum cblknum; + int o; + + if (fprintf (stream, GNUMSTRING "\n", + (Gnum) ordeptr->vnodnbr) == EOF) { + errorPrint ("orderSaveMap: bad output (1)"); + return (1); + } + + if (memAllocGroup ((void **) (void *) + &rangtab, (size_t) ((ordeptr->vnodnbr + 1) * sizeof (Gnum)), + &cblktax, (size_t) ( ordeptr->vnodnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("orderSaveMap: out of memory"); + return (1); + } + cblktax -= ordeptr->baseval; + + orderRang (ordeptr, rangtab); + peritax = ordeptr->peritab - ordeptr->baseval; + for (vnodnum = ordeptr->baseval, vnodnnd = vnodnum + ordeptr->vnodnbr, cblknum = 0; + vnodnum < vnodnnd; vnodnum ++) { + if (vnodnum >= rangtab[cblknum + 1]) + cblknum ++; + cblktax[peritax[vnodnum]] = cblknum; + } + + vlbltax = (vlbltab != NULL) ? (vlbltab - ordeptr->baseval) : NULL; + for (vnodnum = ordeptr->baseval, o = 0; vnodnum < vnodnnd; vnodnum ++) { + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) ((vlbltax != NULL) ? vlbltax[vnodnum] : vnodnum), + (Gnum) cblktax[vnodnum]) == EOF) { + errorPrint ("orderSaveMap: bad output (2)"); + o = 1; + break; + } + } + + memFree (rangtab); /* Free memory group leader */ + return (o); +} + +/* This routine saves the separator +** tree data of the given ordering. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +orderSaveTree ( +const Order * restrict const ordeptr, +const Gnum * restrict const vlbltab, +FILE * const stream) +{ + const Gnum * restrict vlbltax; + const Gnum * restrict peritax; + Gnum * restrict rangtab; + Gnum * restrict treetab; + Gnum * restrict cblktax; + Gnum vnodnnd; + Gnum vnodnum; + Gnum cblknum; + int o; + + if (fprintf (stream, GNUMSTRING "\n", + (Gnum) ordeptr->vnodnbr) == EOF) { + errorPrint ("orderSaveTree: bad output (1)"); + return (1); + } + + if (memAllocGroup ((void **) (void *) + &rangtab, (size_t) ((ordeptr->vnodnbr + 1) * sizeof (Gnum)), + &treetab, (size_t) ( ordeptr->vnodnbr * sizeof (Gnum)), + &cblktax, (size_t) ( ordeptr->vnodnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("orderSaveTree: out of memory"); + return (1); + } + cblktax -= ordeptr->baseval; + + orderRang (ordeptr, rangtab); + orderTree (ordeptr, treetab); + peritax = ordeptr->peritab - ordeptr->baseval; + for (vnodnum = ordeptr->baseval, vnodnnd = vnodnum + ordeptr->vnodnbr, cblknum = 0; + vnodnum < vnodnnd; vnodnum ++) { + if (vnodnum >= rangtab[cblknum + 1]) + cblknum ++; + cblktax[peritax[vnodnum]] = treetab[cblknum]; + } + + vlbltax = (vlbltab != NULL) ? (vlbltab - ordeptr->baseval) : NULL; + for (vnodnum = ordeptr->baseval, o = 0; vnodnum < vnodnnd; vnodnum ++) { + if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", + (Gnum) ((vlbltax != NULL) ? vlbltax[vnodnum] : vnodnum), + (Gnum) cblktax[vnodnum]) == EOF) { + errorPrint ("orderSaveMap: bad output (2)"); + o = 1; + break; + } + } + + memFree (rangtab); /* Free memory group leader */ + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/parser.c b/scotch_6.0.3/src/libscotch/parser.c new file mode 100644 index 00000000..e0edc9ee --- /dev/null +++ b/scotch_6.0.3/src/libscotch/parser.c @@ -0,0 +1,642 @@ +/* Copyright 2004,2007,2008,2010,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parser.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a static mapper. **/ +/** This module is the strategy lexical and **/ +/** syntactic analyzer. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 nov 1995 **/ +/** to 02 may 1996 **/ +/** # Version 3.2 : from : 07 oct 1996 **/ +/** to 19 oct 1996 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 10 sep 2001 **/ +/** # Version 4.0 : from : 20 dec 2001 **/ +/** to 02 feb 2004 **/ +/** # Version 5.0 : from : 20 feb 2008 **/ +/** to 20 feb 2008 **/ +/** # Version 5.1 : from : 22 oct 2008 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 01 jun 2012 **/ +/** to 30 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define PARSER + +#include "module.h" +#include "common.h" + +#undef INTEGER /* In case someone defined them */ +#undef DOUBLE + +#include "parser.h" +#include "parser_yy.h" + +/* +** The static and global variables. +*/ + +static StratTab stratdummytab = { NULL, NULL, NULL }; /* Dummy strategy table for the dummy empty object */ +Strat stratdummy = { &stratdummytab, STRATNODEEMPTY }; /* Dummy empty object for offset computations */ + +/**************************/ +/* */ +/* The strategy routines. */ +/* */ +/**************************/ + +/* This routine parses the given strategy +** string and builds the corresponding +** strategy tree. +** It returns: +** - !NULL : pointer to the strategy. +** - NULL : on error. +*/ + +Strat * +stratInit ( +const StratTab * const strattab, /*+ Pointer to strategy parsing table +*/ +const char * const string) /*+ Strategy string to parse +*/ +{ +#ifdef SCOTCH_DEBUG_PARSER1 + if ((strattab == NULL) || (string == NULL)) { + errorPrint ("stratInit: invalid parameter"); + return (NULL); + } +#endif /* SCOTCH_DEBUG_PARSER1 */ + + return (stratParserParse (strattab, string)); /* Parse strategy string */ +} + +/* This routine frees a strategy structure. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +stratExit ( +Strat * const strat) +{ + StratParamTab * paratab; /* Table of method parameters */ + byte * paraofft; /* Offset of parameter within method structure */ + unsigned int i; + int o; + + if (strat == NULL) /* If node does not exist, abort */ + return (0); + + o = 0; /* Assume everything will be all right */ + switch (strat->type) { /* Recursively free sub-strategies */ + case STRATNODECONCAT : + o = stratExit (strat->data.concat.strat[0]); + o |= stratExit (strat->data.concat.strat[1]); + break; + case STRATNODECOND : + o = stratTestExit (strat->data.cond.test); + o |= stratExit (strat->data.cond.strat[0]); + if (strat->data.cond.strat[1] != NULL) + o |= stratExit (strat->data.cond.strat[1]); + break; + case STRATNODESELECT : + o = stratExit (strat->data.select.strat[0]); + o |= stratExit (strat->data.select.strat[1]); + break; + case STRATNODEEMPTY : /* Empty strategy node */ + if (strat == &stratdummy) /* If node is empty dummy node */ + return (0); /* Return without freeing it */ + break; + case STRATNODEMETHOD : /* Method strategy node */ + paratab = strat->tabl->paratab; /* Free the method parameters */ + for (i = 0; paratab[i].name != NULL; i ++) { + if ((paratab[i].meth == strat->data.method.meth) && /* For all parameters of that method */ + (paratab[i].type == STRATPARAMSTRAT)) { /* Which are non-deprecated strategy parameters */ + paraofft = (byte *) &strat->data.method.data + /* Compute parameter offset within method */ + (paratab[i].dataofft - + paratab[i].database); + o |= stratExit (*((Strat **) paraofft)); /* Perform recursion */ + } + } + break; +#ifdef SCOTCH_DEBUG_PARSER2 + default : + errorPrint ("stratExit: invalid strategy node"); + o = 1; + break; +#endif /* SCOTCH_DEBUG_PARSER2 */ + } + + memFree (strat); /* Free strategy structure itself */ + return (o); /* Return output code */ +} + +/* This routine displays the given +** strategy structure. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +stratSave ( +const Strat * const strat, +FILE * const stream) +{ + unsigned int paraflag; /* Flag set if method has parameters */ + StratParamTab * paratab; /* Pointer to method parameter table */ + byte * paraofft; /* Offset of parameter within method structure */ + unsigned int i; + int o; + + o = 0; + switch (strat->type) { /* Recursively view sub-strategies */ + case STRATNODECOND : + if ((fprintf (stream, "(/(") == EOF) || + (stratTestSave (strat->data.cond.test, stream) != 0) || + (fprintf (stream, ")?(") == EOF) || + (stratSave (strat->data.cond.strat[0], stream) != 0)) + o = 1; + if ((o == 0) && (strat->data.cond.strat[1] != NULL)) { + if ((fprintf (stream, "):(") == EOF) || + (stratSave (strat->data.cond.strat[1], stream) != 0)) + o = 1; + } + if (o == 0) + o = (fprintf (stream, ");)") == EOF); + break; + case STRATNODECONCAT : + if ((stratSave (strat->data.concat.strat[0], stream) != 0) || + (stratSave (strat->data.concat.strat[1], stream) != 0)) + o = 1; + break; + case STRATNODESELECT : + if ((fprintf (stream, "(") == EOF) || + (stratSave (strat->data.select.strat[0], stream) != 0) || + (fprintf (stream, "|") == EOF) || + (stratSave (strat->data.select.strat[1], stream) != 0) || + (fprintf (stream, ")") == EOF)) + o = 1; + case STRATNODEEMPTY : + break; + case STRATNODEMETHOD : + if (fprintf (stream, "%s", strat->tabl->methtab[strat->data.method.meth].name) == EOF) { /* Print method name */ + o = 1; + break; + } + paraflag = 0; /* No method parameters seen yet */ + paratab = strat->tabl->paratab; + for (i = 0; paratab[i].name != NULL; i ++) { + if ((paratab[i].meth == strat->data.method.meth) && /* For all parameters of that method */ + ((paratab[i].type & STRATPARAMDEPRECATED) == 0)) { /* Which are not deprecated */ + paraofft = (byte*) &strat->data.method.data + /* Compute parameter offset within method */ + (paratab[i].dataofft - + paratab[i].database); + if (fprintf (stream, "%c%s=", /* Open or continue parameter list */ + ((paraflag ++ == 0) ? '{' : ','), + paratab[i].name) == EOF) { + o = 1; + break; + } + switch (paratab[i].type) { /* Print parameter value */ + case STRATPARAMCASE : /* Case value */ + o = (fprintf (stream, "%c", /* Print corresponding character */ + ((char *) paratab[i].datasltr)[*((unsigned int *) paraofft)]) == EOF); + break; + case STRATPARAMINT : /* Integer value */ + o = (fprintf (stream, INTSTRING, *((INT *) paraofft)) == EOF); + break; + case STRATPARAMDOUBLE : /* Double value */ + o = (fprintf (stream, "%g", *((double *) paraofft)) == EOF); + break; + case STRATPARAMSTRAT : /* Strategy */ + o = stratSave (*((Strat **) paraofft), stream); /* Perform recursion */ + break; + case STRATPARAMSTRING : /* String value */ + o = (fprintf (stream, "%s", (char *) paraofft) == EOF); + break; +#ifdef SCOTCH_DEBUG_PARSER2 + default : + errorPrint ("stratSave: invalid parameter type"); + return (1); +#endif /* SCOTCH_DEBUG_PARSER2 */ + } + } + if (o != 0) /* If an error has occured */ + break; /* Abort the loop */ + } + if ((o == 0) && (paraflag != 0)) /* If there is a parameter list */ + o |= (fprintf (stream, "}") == EOF); /* Close it */ + break; +#ifdef SCOTCH_DEBUG_PARSER2 + default : + errorPrint ("stratSave: invalid strategy node"); + return (1); +#endif /* SCOTCH_DEBUG_PARSER2 */ + } + if (o != 0) { + errorPrint ("stratSave: bad output"); + } + + return (o); +} + +/*****************************************/ +/* */ +/* These routines handle strategy tests. */ +/* */ +/*****************************************/ + +/* This routine evaluates the +** given condition. +** It returns: +** - 0 : on success; eval updated. +** - !0 : on error. +*/ + +int +stratTestEval ( +const StratTest * restrict const test, +StratTest * restrict const eval, /*+ Place where to return final value +*/ +const void * restrict const data) /*+ Pointer to data structure where to read variables from +*/ +{ + StratTest val[2]; /* Temporary evaluation variables */ + StratTestType sign; /* Sign of comparison */ + int o; + +#ifdef SCOTCH_DEBUG_PARSER1 + if ((test == NULL) || (eval == NULL) || (data == NULL)) { + errorPrint ("stratTestEval: invalid parameter"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER1 */ + + o = 0; /* Assume no error */ + switch (test->typetest) { + case STRATTESTNOT : /* Not operator */ + o = stratTestEval (test->data.test[0], eval, data); +#ifdef SCOTCH_DEBUG_PARSER2 + if ((o == 0) && (eval->typenode != STRATPARAMLOG)) { + errorPrint ("stratTestEval: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + eval->data.val.vallog = 1 - eval->data.val.vallog; + break; + case STRATTESTAND : /* And operator */ + o = stratTestEval (test->data.test[0], eval, data); +#ifdef SCOTCH_DEBUG_PARSER2 + if ((o == 0) && (eval->typenode != STRATPARAMLOG)) { + errorPrint ("stratTestEval: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + if ((o == 0) && (eval->data.val.vallog == 1)) { + o = stratTestEval (test->data.test[1], eval, data); +#ifdef SCOTCH_DEBUG_PARSER2 + if (eval->typenode != STRATPARAMLOG) { + errorPrint ("stratTestEval: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + } + break; + case STRATTESTOR : /* Or operator */ + o = stratTestEval (test->data.test[0], eval, data); +#ifdef SCOTCH_DEBUG_PARSER2 + if ((o == 0) && (eval->typenode != STRATPARAMLOG)) { + errorPrint ("stratTestEval: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + if ((o == 0) && (eval->data.val.vallog == 0)) { + o = stratTestEval (test->data.test[1], eval, data); +#ifdef SCOTCH_DEBUG_PARSER2 + if (eval->typenode != STRATPARAMLOG) { + errorPrint ("stratTestEval: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + } + break; + case STRATTESTLT : /* Less-than operator */ + case STRATTESTEQ : /* Equal-to operator */ + case STRATTESTGT : /* Greater-than operator */ + o = stratTestEval (test->data.test[0], &val[0], data); + o |= stratTestEval (test->data.test[1], &val[1], data); + o |= stratTestEvalCast (&val[0], &val[1]); + if (o != 0) + break; + sign = STRATTESTNBR; /* In case of error */ + switch (val[0].typenode) { + case STRATPARAMDOUBLE : + sign = (val[0].data.val.valdbl < val[1].data.val.valdbl) ? STRATTESTLT : ((val[0].data.val.valdbl > val[1].data.val.valdbl) ? STRATTESTGT : STRATTESTEQ); + break; + case STRATPARAMINT : + sign = (val[0].data.val.valint < val[1].data.val.valint) ? STRATTESTLT : ((val[0].data.val.valint > val[1].data.val.valint) ? STRATTESTGT : STRATTESTEQ); + break; +#ifdef SCOTCH_DEBUG_PARSER2 + default : + errorPrint ("stratTestEval: internal error (6)"); + o = 1; + break; +#endif /* SCOTCH_DEBUG_PARSER2 */ + } + eval->typenode = STRATPARAMLOG; /* Build test result */ + eval->data.val.vallog = (sign == test->typetest); + break; + case STRATTESTADD : /* Addition operator */ + o = stratTestEval (test->data.test[0], &val[0], data); + o |= stratTestEval (test->data.test[1], &val[1], data); + o |= stratTestEvalCast (&val[0], &val[1]); + if (o != 0) + break; + if (val[0].typenode == STRATPARAMDOUBLE) + eval->data.val.valdbl = val[0].data.val.valdbl + val[1].data.val.valdbl; + else + eval->data.val.valint = val[0].data.val.valint + val[1].data.val.valint; + eval->typenode = val[0].typenode; + break; + case STRATTESTSUB : /* Subtraction operator */ + o = stratTestEval (test->data.test[0], &val[0], data); + o |= stratTestEval (test->data.test[1], &val[1], data); + o |= stratTestEvalCast (&val[0], &val[1]); + if (o != 0) + break; + if (val[0].typenode == STRATPARAMDOUBLE) + eval->data.val.valdbl = val[0].data.val.valdbl - val[1].data.val.valdbl; + else + eval->data.val.valint = val[0].data.val.valint - val[1].data.val.valint; + eval->typenode = val[0].typenode; + break; + case STRATTESTMUL : /* Multiplication operator */ + o = stratTestEval (test->data.test[0], &val[0], data); + o |= stratTestEval (test->data.test[1], &val[1], data); + o |= stratTestEvalCast (&val[0], &val[1]); + if (o != 0) + break; + if (val[0].typenode == STRATPARAMDOUBLE) + eval->data.val.valdbl = val[0].data.val.valdbl * val[1].data.val.valdbl; + else + eval->data.val.valint = val[0].data.val.valint * val[1].data.val.valint; + eval->typenode = val[0].typenode; + break; + case STRATTESTMOD : /* Modulus operator */ + o = stratTestEval (test->data.test[0], &val[0], data); + o |= stratTestEval (test->data.test[1], &val[1], data); + o |= stratTestEvalCast (&val[0], &val[1]); + if (o != 0) + break; + if (val[0].typenode == STRATPARAMDOUBLE) + eval->data.val.valdbl = fmod (val[0].data.val.valdbl, val[1].data.val.valdbl); + else + eval->data.val.valint = val[0].data.val.valint % val[1].data.val.valint; + eval->typenode = val[0].typenode; + break; + case STRATTESTVAL : /* Constant value */ + *eval = *test; /* Copy value */ + break; + case STRATTESTVAR : /* Variable */ + switch (test->typenode) { + case STRATPARAMDOUBLE : + eval->data.val.valdbl = *((double *) ((byte *) data + test->data.var.datadisp)); + break; + case STRATPARAMINT : + eval->data.val.valint = *((INT *) ((byte *) data + test->data.var.datadisp)); + break; +#ifdef SCOTCH_DEBUG_PARSER1 + default : + errorPrint ("stratTestEval: internal error (7)"); + o = 1; + break; +#endif /* SCOTCH_DEBUG_PARSER1 */ + } + eval->typenode = test->typenode; + break; +#ifdef SCOTCH_DEBUG_PARSER1 + default : + errorPrint ("stratTestEval: invalid condition type (%u)", test->typetest); + o = 1; + break; +#endif /* SCOTCH_DEBUG_PARSER1 */ + } + eval->typetest = STRATTESTVAL; + + return (o); +} + +/* This routine casts the type of one +** of the two input values so as to +** get the same type for both values. +** It returns: +** - VOID : in all cases; +*/ + +static +int +stratTestEvalCast ( +StratTest * const test0, +StratTest * const test1) +{ +#ifdef SCOTCH_DEBUG_PARSER2 + if (((test0->typenode != STRATPARAMINT) && (test0->typenode != STRATPARAMDOUBLE)) || + ((test1->typenode != STRATPARAMINT) && (test1->typenode != STRATPARAMDOUBLE))) { + errorPrint ("stratTestEvalCast: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + if (test0->typenode != test1->typenode) { /* If value types differ */ + if (test0->typenode == STRATPARAMDOUBLE) { + test1->typenode = STRATPARAMDOUBLE; + test1->data.val.valdbl = (double) test1->data.val.valint; + } + else { + test0->typenode = STRATPARAMDOUBLE; + test0->data.val.valdbl = (double) test0->data.val.valint; + } + } + + return (0); +} + +/* This routine fres the given +** strategy condition. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +stratTestExit ( +StratTest * const test) +{ + int o; /* Output condition flag */ + +#ifdef SCOTCH_DEBUG_PARSER1 + if (test == NULL) { + errorPrint ("stratTestExit: invalid parameter"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER1 */ + + o = 0; + switch (test->typetest) { + case STRATTESTNOT : /* Not operator */ + o = stratTestExit (test->data.test[0]); /* Free the son */ + break; + case STRATTESTAND : /* And operator */ + case STRATTESTOR : /* Or operator */ + case STRATTESTLT : /* Less-than operator */ + case STRATTESTEQ : /* Equal-to operator */ + case STRATTESTGT : /* Greater-than operator */ + case STRATTESTMOD : /* Modulus operator */ + case STRATTESTMUL : /* Multiplication operator */ + case STRATTESTADD : /* Addition operator */ + case STRATTESTSUB : /* Subtraction operator */ + o = stratTestExit (test->data.test[0]); /* Free the sons */ + o |= stratTestExit (test->data.test[1]); + break; + case STRATTESTVAL : /* Constant value */ + case STRATTESTVAR : /* Variable */ + break; +#ifdef SCOTCH_DEBUG_PARSER1 + default : + errorPrint ("stratTestExit: invalid condition type (%u)", test->typetest); + o = 1; + break; +#endif /* SCOTCH_DEBUG_PARSER1 */ + } + + memFree (test); /* Free the structure */ + return (o); +} + +/* This routine displays the +** given strategy condition. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static char strattestsaveop[STRATTESTNBR] = "|&!=><+-*%##"; +static char * strattestsavepa[2][2] = { { "(", ")" }, { "", "" } }; + +int +stratTestSave ( +const StratTest * const test, +FILE * const stream) +{ + int i; + int o; + +#ifdef SCOTCH_DEBUG_PARSER1 + if ((test == NULL) || (stream == NULL)) { + errorPrint ("stratTestSave: invalid parameter"); + return (1); + } +#endif /* SCOTCH_DEBUG_PARSER1 */ + + o = 0; /* Assume no error */ + switch (test->typetest) { + case STRATTESTNOT : /* Not operator */ + if ((fprintf (stream, "!(") == EOF) || + (stratTestSave (test->data.test[0], stream) != 0) || + (fprintf (stream, ")") == EOF)) + o = 1; + break; + case STRATTESTAND : /* And operator */ + case STRATTESTOR : /* Or operator */ + case STRATTESTEQ : /* Equal-to operator */ + case STRATTESTGT : /* Greater-than operator */ + case STRATTESTLT : /* Less-than operator */ + case STRATTESTADD : /* Addition operator */ + case STRATTESTSUB : /* Subtraction operator */ + case STRATTESTMUL : /* Multiplication operator */ + case STRATTESTMOD : /* Modulus operator */ + i = (test->data.test[0]->typetest < test->typetest) ? 1 : 0; + fprintf (stream, "%s", strattestsavepa[i][0]); + o = stratTestSave (test->data.test[0], stream); + fprintf (stream, "%s", strattestsavepa[i][1]); + if (o == 0) { + fprintf (stream, "%c", strattestsaveop[test->typetest]); + i = (test->data.test[1]->typetest < test->typetest) ? 1 : 0; + fprintf (stream, "%s", strattestsavepa[i][0]); + stratTestSave (test->data.test[1], stream); + fprintf (stream, "%s", strattestsavepa[i][1]); + } + break; + case STRATTESTVAL : /* Constant value */ + switch (test->typenode) { + case STRATPARAMDOUBLE : + o = (fprintf (stream, "%lf", test->data.val.valdbl) == EOF); + break; + case STRATPARAMINT : + o = (fprintf (stream, INTSTRING, (INT) test->data.val.valint) == EOF); + break; +#ifdef SCOTCH_DEBUG_PARSER2 + default : + errorPrint ("stratTestSave: invalid value type"); + o = 1; +#endif /* SCOTCH_DEBUG_PARSER2 */ + } + break; + case STRATTESTVAR : /* Variable */ + for (i = 0; test->data.var.datatab->condtab[i].name != NULL; i ++) { + if ((test->data.var.datatab->condtab[i].dataofft - + test->data.var.datatab->condtab[i].database) == test->data.var.datadisp) + break; + } + if (test->data.var.datatab->condtab[i].name == NULL) { + errorPrint ("stratTestSave: invalid variable displacement"); + return (1); + } + o = (fprintf (stream, "%s", test->data.var.datatab->condtab[i].name) == EOF); + break; +#ifdef SCOTCH_DEBUG_PARSER2 + default : + errorPrint ("stratTestSave: invalid condition type (%u)", test->typetest); + o = 1; +#endif /* SCOTCH_DEBUG_PARSER2 */ + } + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/parser.h b/scotch_6.0.3/src/libscotch/parser.h new file mode 100644 index 00000000..e10f2361 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/parser.h @@ -0,0 +1,232 @@ +/* Copyright 2004,2007,2008,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parser.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the declarations for **/ +/** the strategy lexical and syntactic **/ +/** analyzer. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 nov 1995 **/ +/** to 02 may 1996 **/ +/** # Version 3.2 : from : 07 oct 1996 **/ +/** to 19 oct 1996 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 20 dec 2001 **/ +/** to 11 jun 2004 **/ +/** # Version 5.1 : from : 20 feb 2008 **/ +/** to 20 feb 2008 **/ +/** # Version 6.0 : from : 30 sep 2014 **/ +/** to 30 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#define PARSERSTRINGLEN 256 /*+ Length of parser strings +*/ + +/* +** The type definitions. +*/ + +/*+ Strategy node types. +*/ + +typedef enum StratNodeType_ { + STRATNODECONCAT, /*+ Concatenation node +*/ + STRATNODECOND, /*+ Condition node +*/ + STRATNODEEMPTY, /*+ Empty strategy +*/ + STRATNODEMETHOD, /*+ Method +*/ + STRATNODESELECT, /*+ Selection node +*/ + STRATNODENBR /*+ Number of strategy nodes +*/ +} StratNodeType; + +/*+ Method and graph parameter types. +*/ + +typedef int StratParamType; /*+ Same type as enum +*/ + +#define STRATPARAMCASE 0 /*+ Character; TRICK: FIRST +*/ +#define STRATPARAMDOUBLE 1 /*+ Double floating-point +*/ +#define STRATPARAMINT 2 /*+ Integer +*/ +#define STRATPARAMLOG 3 /*+ Logical value +*/ +#define STRATPARAMSTRAT 4 /*+ Strategy +*/ +#define STRATPARAMSTRING 5 /*+ String of characters +*/ + +#define STRATPARAMDEPRECATED 8 /*+ Indicates deprecated parameter; can be merged with the above +*/ + +/*+ Test types, ordered by ascending priority, + for proper writing of parentheses. Initial + value should be zero for proper indexing. +*/ + +typedef enum StratTestType_ { + STRATTESTOR = 0, /*+ Or operator +*/ + STRATTESTAND, /*+ And operator +*/ + STRATTESTNOT, /*+ Not operator +*/ + STRATTESTEQ, /*+ Equal-to operator +*/ + STRATTESTGT, /*+ Greater-than operator +*/ + STRATTESTLT, /*+ Less-than operator +*/ + STRATTESTADD, /*+ Addition operator +*/ + STRATTESTSUB, /*+ Subtraction operator +*/ + STRATTESTMUL, /*+ Multiplication operator +*/ + STRATTESTMOD, /*+ Modulus operator +*/ + STRATTESTVAL, /*+ Constant value +*/ + STRATTESTVAR, /*+ Variable +*/ + STRATTESTNBR /*+ Number of test nodes +*/ +} StratTestType; + +/*+ Method characteristics. +*/ + +typedef struct StratMethodTab_ { + int meth; /*+ Method number in method table +*/ + char * name; /*+ Method name +*/ + int (* func) (); /*+ Pointer to bipartitioning method +*/ + void * data; /*+ Pointer to default parameters +*/ +} StratMethodTab; + +/*+ Method parameter characteristics. +*/ + +typedef struct StratParamTab_ { + int meth; /*+ Method number in method table +*/ + StratParamType type; /*+ Parameter type +*/ + char * name; /*+ Parameter name +*/ + byte * database; /*+ Pointer to data base in method +*/ + byte * dataofft; /*+ Pointer to data offset in method +*/ + void * datasltr; /*+ Pointer to data selector +*/ +} StratParamTab; + +/*+ Strategy characteristics. +*/ + +typedef struct StratTab_ { + StratMethodTab * methtab; /*+ Pointer to method table +*/ + StratParamTab * paratab; /*+ Pointer to parameter table +*/ + StratParamTab * condtab; /*+ Pointer to condition table +*/ +} StratTab; + +/*+ Concatenation strategy node. +*/ + +typedef struct StratNodeConcat_ { /*+ Concatenation node +*/ + struct Strat_ * strat[2]; /*+ Pointers to the two strategies to combine +*/ +} StratNodeConcat; + +/*+ Condition and test strategy nodes. +*/ + +typedef union StratTestVal_ { /*+ Constant value +*/ + double valdbl; /*+ Double value +*/ + INT valint; /*+ Integer value +*/ + int vallog; /*+ Logical value +*/ +} StratTestVal; + +typedef struct StratTestVar_ { /*+ Condition variable +*/ + const StratTab * datatab; /*+ Pointer to data parameter table +*/ + int datadisp; /*+ Displacement with respect to beginning +*/ +} StratTestVar; + +typedef struct StratTest_ { /*+ Test node +*/ + StratTestType typetest; /*+ Test type +*/ + StratParamType typenode; /*+ Node type +*/ + union { + struct StratTest_ * test[2]; /*+ Logical/relational branches +*/ + StratTestVal val; /*+ Value +*/ + StratTestVar var; /*+ Variable +*/ + } data; +} StratTest; + +typedef struct StratNodeCond_ { /*+ Test node +*/ + StratTest * test; /*+ Test condition +*/ + struct Strat_ * strat[2]; /*+ Then/else strategies +*/ +} StratNodeCond; + +/*+ Data structure of the empty strategy operator node. +*/ + +typedef struct StratNodeEmpty_ { /*+ Empty node +*/ + byte dummy; /*+ Dummy data +*/ +} StratNodeEmpty; + +/*+ Data structure of the empty strategy operator node. +*/ + +typedef double StratNodeMethodData[10]; /*+ Reserved padded space for method data */ + +typedef struct StratNodeMethod_ { /*+ Method node +*/ + int meth; /*+ Index in method table +*/ + StratNodeMethodData data; /*+ Method data +*/ +} StratNodeMethod; + +/*+ Data structure of the selection strategy operator node. +*/ + +typedef struct StratNodeSelect_ { /*+ Selection node +*/ + struct Strat_ * strat[2]; /*+ Pointers to the two strategies to test +*/ +} StratNodeSelect; + +/*+ The strategy node data structure. +*/ + +typedef struct Strat_ { + const StratTab * tabl; /*+ Pointer to parsing strategy table +*/ + StratNodeType type; /*+ Method type +*/ + union { /*+ Method data +*/ + double padding; /*+ Padding for double alignment +*/ + StratNodeConcat concat; /*+ Concatenation node data +*/ + StratNodeCond cond; /*+ Condition node data +*/ + StratNodeEmpty empty; /*+ Empty node data +*/ + StratNodeMethod method; /*+ Method node data +*/ + StratNodeSelect select; /*+ Selection node data +*/ + } data; +} Strat; + +/* +** The external declarations. +*/ + +extern Strat stratdummy; /*+ Dummy empty strategy node +*/ + +/* +** The function prototypes. +*/ + +#ifndef PARSER +#define static +#endif + +Strat * stratInit (const StratTab * const , const char * const); +int stratExit (Strat * const); +int stratSave (const Strat * const, FILE * const); + +int stratTestEval (const StratTest * const, StratTest * const, const void * const); +static int stratTestEvalCast (StratTest * const, StratTest * const); +int stratTestExit (StratTest * const); +int stratTestSave (const StratTest * const, FILE * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/parser_ll.h b/scotch_6.0.3/src/libscotch/parser_ll.h new file mode 100644 index 00000000..4b14324f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/parser_ll.h @@ -0,0 +1,67 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parser_ll.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a static mapper. **/ +/** These lines are the declarations for **/ +/** the strategy strings lexical parser. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 nov 1995 **/ +/** to 13 jun 1996 **/ +/** # Version 3.2 : from : 03 oct 1996 **/ +/** to 19 oct 1996 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 20 dec 2001 **/ +/** to 20 dec 2001 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef PARSER_LL +#define static +#endif + +void stratParserInit (const char * const); +static int stratParserInput (void); +int stratParserLex (void); +const char * stratParserRemain (void); +void stratParserSelect (unsigned int); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/parser_ll.l b/scotch_6.0.3/src/libscotch/parser_ll.l new file mode 100644 index 00000000..82450f1c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/parser_ll.l @@ -0,0 +1,264 @@ +%{ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parser_ll.l **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the lexical parser **/ +/** which processes strategy strings. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 nov 1995 **/ +/** to 23 aug 1996 **/ +/** # Version 3.2 : from : 24 sep 1996 **/ +/** to 05 jun 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 11 sep 2001 **/ +/** # Version 4.0 : from : 20 dec 2001 **/ +/** to 23 dec 2001 **/ +/** # Version 5.1 : from : 09 jun 2009 **/ +/** to 24 jul 2011 **/ +/** **/ +/** NOTES : # In order for flex to read its input **/ +/** with getc() instead of fread, we set **/ +/** YY_ALWAYS_INTERACTIVE to 1. This may **/ +/** not always work with future releases. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define PARSER_LL + +#include "module.h" +#include "common.h" + +#undef INTEGER /* In case someone defined them */ +#undef DOUBLE + +#include "parser.h" +#include "parser_ll.h" +#include "parser_yy.h" +#include "parser_ly.h" /*+ Definitions produced by yacc +*/ + +/* Assume no interactive parsing. */ + +#ifdef X_OSDOS /* Available only with MKS LEX */ +#ifdef YY_INTERACTIVE +#undef YY_INTERACTIVE +#endif /* YY_INTERACTIVE */ +#define YY_INTERACTIVE 0 +#endif /* X_OSDOS */ + +#ifdef FLEX_SCANNER +#define YY_ALWAYS_INTERACTIVE 1 /* Set the parser as interactive and read one char at a time */ +#define YY_INPUT(buf,result,max_size) { int c = stratParserInput (); result = (c == 0) ? YY_NULL : ((buf)[0] = c, 1); } +#else /* FLEX_SCANNER */ +#undef getc /* Redirect I/O functions */ +#define getc yygetc +#undef yygetc +#define yygetc(stream) stratParserInput () +#endif /* FLEX_SCANNER */ + +#define YY_NO_UNPUT /* No prototype for yyunput as not defined */ +#define YY_SKIP_YYWRAP /* No prototype for yywrap as defined as macro */ +#define yywrap() (1) /* Always return end-of-file on end-of-string */ + +/* +** The static variables. +*/ + +static const char * stratparserstringptr; /* Pointer to the string to parse */ + +%} + +IDENT [A-Za-z][0-9A-Za-z]* +INTEGER [0-9]+ +FLOAT [0-9]+(\.[0-9]+)?([Ee][-+]?[0-9]+)? +STRING \"[^\"]*\" + +%s lstrat +%s lparam +%s lparamcase +%s lparamdouble +%s lparamint +%s lparamstring +%s ltest + +%% +[0-9A-Za-z] { + strncpy (yylval.STRING, yytext, PARSERSTRINGLEN); + yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; + return (METHODNAME); + } + +{IDENT} { + strncpy (yylval.STRING, yytext, PARSERSTRINGLEN); + yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; + return (PARAMNAME); + } + +[0-9A-Za-z] { + yylval.CASEVAL = yytext[0]; + return (VALCASE); + } + +({FLOAT}|{INTEGER}) { + yylval.DOUBLE = atof (yytext); + return (VALDOUBLE); + } + +{INTEGER} { + yylval.INTEGER = (INT) atol (yytext); + return (VALINT); + } +{FLOAT} { + yylval.INTEGER = (INT) atof (yytext); /* FLOAT is put after so that INTEGER can be matched */ + return (VALINT); + } + +{STRING} { + yytext[yyleng - 1] = '\0'; /* Remove the heading and trailing \" */ + strncpy (yylval.STRING, yytext + 1, PARSERSTRINGLEN); + yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; + return (VALSTRING); + } + +{INTEGER} { + yylval.INTEGER = (INT) atol (yytext); + return (VALINT); + } +{FLOAT} { + yylval.DOUBLE = atof (yytext); + return (VALDOUBLE); + } +{IDENT} { + strncpy (yylval.STRING, yytext, PARSERSTRINGLEN); + yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; + return (PARAMNAME); + } + +[ \t\n]* ; +. return (yytext[0]); + +%% + +/*******************************************/ +/* */ +/* These routines handle data input to the */ +/* lexical analyzer. */ +/* */ +/*******************************************/ + +/* This routine initializes the +** lexical analyzer. +** It returns: +** - VOID : in all cases. +*/ + +void +stratParserInit ( +const char * const string) /*+ Strategy string to parse +*/ +{ +#ifdef FLEX_SCANNER + yyrestart (yyin); /* (Re-)initialize the parser */ +#endif /* FLEX_SCANNER */ + + stratParserSelect (VALSTRAT); /* Begin with a strategy */ + stratparserstringptr = string; /* Point to beginning of string */ +} + +/* This routine reads a single character +** from the input string. +** It returns: +** - 0 : if end of string reached. +** - !0 : character from string. +*/ + +static +int +stratParserInput () +{ + if (*stratparserstringptr == '\0') /* If end-of-string reached */ + return (0); /* Return end-of-file token */ + else /* Else return the character */ + return ((int) (unsigned char) *stratparserstringptr ++); +} + +/* This routine returns the pointer to the +** remaining part of the string. +*/ + +const char * +stratParserRemain () +{ + return (stratparserstringptr); +} + +/* This routine selects the sub-parser +** to parse the input. +** It returns: +** - VOID : in all cases. +*/ + +void +stratParserSelect ( +unsigned int type) +{ + switch (type) { + case VALCASE : + BEGIN lparamcase; + break; + case VALDOUBLE : + BEGIN lparamdouble; + break; + case VALINT : + BEGIN lparamint; + break; + case VALSTRING : + BEGIN lparamstring; + break; + case VALPARAM : + BEGIN lparam; + break; + case VALSTRAT : + BEGIN lstrat; + break; + case VALTEST : + BEGIN ltest; + break; + } +} diff --git a/scotch_6.0.3/src/libscotch/parser_yy.h b/scotch_6.0.3/src/libscotch/parser_yy.h new file mode 100644 index 00000000..d574187c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/parser_yy.h @@ -0,0 +1,87 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parser_yy.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a static mapper. **/ +/** These lines are the declarations for **/ +/** the strategy strings syntactic parser. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 nov 1995 **/ +/** to 30 may 1996 **/ +/** # Version 3.2 : from : 03 oct 1996 **/ +/** to 19 oct 1996 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 20 dec 2001 **/ +/** to 21 dec 2001 **/ +/** # Version 5.1 : from : 09 jun 2009 **/ +/** to 07 aug 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/* Change some function names. */ + +#if ((defined SCOTCH_RENAME_PARSER) || (defined yylex)) /* If prefix renaming */ +#define scotchyyparse stratParserParse2 /* Parser function name */ +#define scotchyyerror stratParserError /* Error processing routine */ +#ifndef yylval +#define yylval scotchyylval /* It should be Yacc/Bison's job to redefine it! */ +#endif /* yylval */ +#else /* SCOTCH_RENAME_PARSER */ +#define yylex stratParserLex /* Lexical analyzer */ +#define yyparse stratParserParse2 /* Parser function name */ +#define yyerror stratParserError /* Error processing routine */ +#endif /* SCOTCH_RENAME_PARSER */ + +/* +** The function prototypes. +*/ + +#ifndef PARSER_YY +#define static +#endif + +int yylex (void); + +Strat * stratParserParse (const StratTab * const, const char * const); +int stratParserParse2 (void); +static int stratParserError (const char * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/parser_yy.y b/scotch_6.0.3/src/libscotch/parser_yy.y new file mode 100644 index 00000000..089279b8 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/parser_yy.y @@ -0,0 +1,819 @@ +%{ +/* Copyright 2004,2007,2008,2011,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parser_yy.y **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the syntactic parser **/ +/** which processes strategy strings. **/ +/** **/ +/** DATES : # Version 3.1 : from : 07 nov 1995 **/ +/** to 13 jun 1996 **/ +/** # Version 3.2 : from : 24 sep 1996 **/ +/** to 27 feb 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 20 dec 2001 **/ +/** to 11 jun 2004 **/ +/** # Version 5.1 : from : 30 oct 2007 **/ +/** to 24 jul 2011 **/ +/** # Version 6.0 : from : 30 sep 2014 **/ +/** to 30 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define PARSER_YY + +#include "module.h" +#include "common.h" + +#undef INTEGER /* In case someone defined them */ +#undef DOUBLE + +#include "parser.h" +#include "parser_ll.h" +#include "parser_yy.h" + +/* #define SCOTCH_DEBUG_PARSER3 */ +#ifdef SCOTCH_DEBUG_PARSER3 +extern int yydebug; +#define YYDEBUG 1 +#endif /* SCOTCH_DEBUG_PARSER3 */ + +/* +** The static and global definitions. +** See also at the end of this file. +*/ + +static const StratTab * parserstrattab; /* Pointer to parsing tables */ +static Strat * parserstratcurr = NULL; /* Pointer to current strategy node */ +static StratParamTab * parserparamcurr = NULL; /* Pointer to current parameter */ + +extern unsigned int parsermethtokentab[]; /* Pre-definition for stupid compilers */ + +%} + +%union { + char CASEVAL; /* Case value */ + StratTest * TEST; /* Test type */ + StratTestType TESTOP; /* Relational type */ + double DOUBLE; /* Double-precision */ + INT INTEGER; /* Integer */ + char STRING[PARSERSTRINGLEN]; /* Character string */ + struct { + const StratTab * tabl; /* Current tables */ + Strat * strat; /* Current method */ + StratParamTab * param; /* Current parameter */ + } SAVE; /* Parameter type */ + Strat * STRAT; /* Strategy tree */ +} + +%token METHODNAME +%token PARAMNAME +%token VALCASE VALDOUBLE VALINT VALSTRING +%token VALSTRAT VALPARAM VALTEST + +%type TEST TESTOR TESTAND TESTNOT +%type TESTREL TESTEXPR1 TESTEXPR2 TESTEXPR3 +%type TESTEXPR4 TESTVAL TESTVAR +%type TESTRELOP TESTEXPR1OP TESTEXPR2OP TESTEXPR3OP +%type VALCASE +%type VALDOUBLE VALSDOUBLE +%type VALINT VALSINT +%type VALSTRING +%type STRATCONCAT STRATTEST STRATTESTELSE STRATEMPTY +%type STRATGROUP STRATMETHOD STRATSELECT +%type METHODNAME PARAMNAME + +%start STRAT + +%% + +/* +** These rules define the strategy grammar. +*/ + +STRAT : STRATSELECT + { + parserstratcurr = ($1); /* Save pointer to root of tree */ + } + ; + +STRATSELECT : STRATSELECT '|' STRATEMPTY + { + Strat * strat; + + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (2)"); + stratExit ($1); + stratExit ($3); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODESELECT; + strat->data.select.strat[0] = ($1); + strat->data.select.strat[1] = ($3); + + ($$) = strat; + } + | STRATEMPTY + ; + +STRATEMPTY : STRATCONCAT + | + { + Strat * strat; + + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (3)"); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODEEMPTY; + + ($$) = strat; + } + ; + +STRATCONCAT : STRATCONCAT STRATTEST + { + Strat * strat; + + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (4)"); + stratExit ($1); + stratExit ($2); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODECONCAT; + strat->data.concat.strat[0] = ($1); + strat->data.concat.strat[1] = ($2); + + ($$) = strat; + } + | STRATTEST + ; + +STRATTEST : + { + stratParserSelect (VALTEST); /* Parse parameter tokens */ + } + '/' TEST + { + stratParserSelect (VALSTRAT); /* Parse strategy tokens */ + } + '?' STRATSELECT STRATTESTELSE ';' + { + Strat * strat; + + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (1)"); + stratExit ($6); + if (($7) != NULL) + stratExit ($7); + stratTestExit ($3); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODECOND; + strat->data.cond.test = ($3); + strat->data.cond.strat[0] = ($6); + strat->data.cond.strat[1] = ($7); + + ($$) = strat; + } + | STRATGROUP + ; + +STRATTESTELSE : ':' STRATSELECT + { + ($$) = ($2); + } + | + { + ($$) = NULL; + } + ; + +STRATGROUP : '(' STRATSELECT ')' + { + ($$) = ($2); + } + | STRATMETHOD + ; + +STRATMETHOD : METHODNAME + { + Strat * strat; + int meth; + int methlen; + StratMethodTab * methtab; + int i, j; + + meth = + methlen = 0; /* No method recognized yet */ + methtab = parserstrattab->methtab; /* Point to the method table */ + for (i = 0; methtab[i].name != NULL; i ++) { + if ((strncasecmp (($1), /* Find longest matching code name */ + methtab[i].name, + j = strlen (methtab[i].name)) == 0) && + (j > methlen)) { + meth = methtab[i].meth; + methlen = j; + } + } + if (methlen == 0) { /* If method name not known */ + errorPrint ("stratParserParse: invalid method name \"%s\", before \"%s\"", + ($1), stratParserRemain ()); + YYABORT; + } + if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { + errorPrint ("stratParserParse: out of memory (5)"); + YYABORT; + } + + strat->tabl = parserstrattab; + strat->type = STRATNODEMETHOD; + strat->data.method.meth = meth; /* Set method type */ + if (methtab[meth].data != NULL) /* If default values exist */ + memcpy (&strat->data.method.data, /* Set values to default */ + methtab[meth].data, + sizeof (StratNodeMethodData)); + + parserstratcurr = strat; /* Structure available for parameter processing */ + } + METHODPARAM + { + StratParamTab * paratab; + int i; + + paratab = parserstrattab->paratab; /* Point to the parameter table */ + for (i = 0; paratab[i].name != NULL; i ++) { + if ((paratab[i].meth == parserstratcurr->data.method.meth) && /* If a strategy parameter found for this method */ + (paratab[i].type == STRATPARAMSTRAT)) { + if (*((Strat **) ((byte *) &parserstratcurr->data.method.data + /* And this parameter has not been set */ + (paratab[i].dataofft - paratab[i].database))) == NULL) + errorPrintW ("stratParserParse: strategy parameter \"%s\" of method \"%s\" not set, before \"%s\"", + paratab[i].name, parserstrattab->methtab[parserstratcurr->data.method.meth].name, stratParserRemain ()); + } + } + + ($$) = parserstratcurr; /* Return current structure */ + parserstratcurr = NULL; /* No current structure */ + } + ; + +METHODPARAM : + { + stratParserSelect (VALPARAM); /* Parse parameter tokens */ + } + '{' PARAMLIST + { + stratParserSelect (VALSTRAT); /* Parse strategy tokens */ + } + '}' + | /* No parameters at all */ + ; + +PARAMLIST : PARAMLIST ',' PARAMPARAM + | PARAMPARAM + ; + +PARAMPARAM : PARAMNAME + { + int para; + int paralen; + StratParamTab * paratab; + int i, j; + + para = + paralen = 0; /* No parameter recognized yet */ + paratab = parserstrattab->paratab; /* Point to the parameter table */ + for (i = 0; paratab[i].name != NULL; i ++) { + if ((paratab[i].meth == parserstratcurr->data.method.meth) && + (strncasecmp (($1), /* Find longest matching parameter name */ + paratab[i].name, + j = strlen (paratab[i].name)) == 0) && + (j > paralen)) { + para = i; + paralen = j; + } + } + if (paralen == 0) { + errorPrint ("stratParserParse: invalid method parameter name \"%s\", before \"%s\"", + ($1), stratParserRemain ()); + YYABORT; + } + + ($$).tabl = parserstrattab; /* Save current strategy tables */ + parserparamcurr = ¶tab[para]; /* Save current parameter value */ + stratParserSelect (parsermethtokentab[parserparamcurr->type & ~STRATPARAMDEPRECATED]); /* Get non-deprecated type */ + if (parserparamcurr->type == STRATPARAMSTRAT) /* If parameter is a strategy */ + parserstrattab = (StratTab *) parserparamcurr->datasltr; /* Use new strategy tables */ + } + '=' PARAMVAL + { + stratParserSelect (VALPARAM); /* Go-on reading parameters */ + parserstrattab = ($2).tabl; /* Restore current strategy tables */ + } + ; + +PARAMVAL : VALCASE + { + char c; /* Character read */ + char * p; /* Pointer to selector string */ + int i; /* Index in selector string */ + + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ + c = ($1); /* First, use char as is */ + for (p = (char *) parserparamcurr->datasltr, i = 0; + (*p != '\0') && (*p != c); + p ++, i ++) ; + if (*p == '\0') { /* Char was not found */ + c = tolower (c); /* Convert char to lower case */ + for (p = (char *) parserparamcurr->datasltr, i = 0; + (*p != '\0') && (*p != c); + p ++, i ++) ; + if (*p == '\0') { + errorPrint ("stratParserParse: invalid method parameter switch \"%s=%c\", before \"%s\"", + parserparamcurr->name, ($1), stratParserRemain ()); + YYABORT; + } + } + +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (int)) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (1)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + *((int *) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database))) = i; + } + } + | VALSDOUBLE + { + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (double)) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (2)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + *((double *) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database))) = ($1); + } + } + | VALSINT + { + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (INT)) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (3)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + *((INT *) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database))) = (INT) ($1); + } + } + | VALSTRING + { + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + strlen ($1) + 1) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (4)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + strcpy ((char *) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database)), + ($1)); + } + } + | + { + ($$).strat = parserstratcurr; + ($$).param = parserparamcurr; + parserstratcurr = NULL; + parserparamcurr = NULL; + } + STRATSELECT + { + parserstratcurr = ($1).strat; /* Restore current method */ + parserparamcurr = ($1).param; /* Restore current parameter */ + + if ((parserparamcurr->type & STRATPARAMDEPRECATED) == 0) { /* If parameter is not deprecated */ +#ifdef SCOTCH_DEBUG_PARSER2 + if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (Strat *)) > sizeof (StratNodeMethodData)) { + errorPrint ("stratParserParse: internal error (5)"); + YYABORT; + } +#endif /* SCOTCH_DEBUG_PARSER2 */ + + *((Strat **) ((byte *) &parserstratcurr->data.method.data + + (parserparamcurr->dataofft - + parserparamcurr->database))) = ($2); + } + } + | error + { + errorPrint ("stratParserParse: invalid value for parameter \"%s\" of method \"%s\", before \"%s\"", + parserparamcurr->name, parserstratcurr->tabl->methtab[parserstratcurr->data.method.meth].name, stratParserRemain ()); + YYABORT; + } + ; + +TEST : TESTOR + ; + +TESTOR : TESTOR '|' TESTAND + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (6)"); + stratTestExit ($1); + stratTestExit ($3); + YYABORT; + } + + test->typetest = STRATTESTOR; + test->typenode = STRATPARAMLOG; + test->data.test[0] = ($1); + test->data.test[1] = ($3); + + ($$) = test; + } + | TESTAND + ; + +TESTAND : TESTAND '&' TESTNOT + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (7)"); + stratTestExit ($1); + stratTestExit ($3); + YYABORT; + } + + test->typetest = STRATTESTAND; + test->typenode = STRATPARAMLOG; + test->data.test[0] = ($1); + test->data.test[1] = ($3); + + ($$) = test; + } + | TESTNOT + ; + +TESTNOT : '!' TESTNOT + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (8)"); + stratTestExit ($2); + YYABORT; + } + + test->typetest = STRATTESTNOT; + test->typenode = STRATPARAMLOG; + test->data.test[0] = ($2); + + ($$) = test; + } + | '(' TESTOR ')' + { + ($$) = ($2); + } + | TESTREL + ; + +TESTREL : TESTEXPR1 TESTRELOP TESTEXPR1 + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (9)"); + stratTestExit ($1); + stratTestExit ($3); + YYABORT; + } + test->typetest = ($2); + test->typenode = STRATPARAMLOG; + test->data.test[0] = ($1); + test->data.test[1] = ($3); + + ($$) = test; + } + ; + +TESTRELOP : '<' + { + ($$) = STRATTESTLT; + } + | '=' + { + ($$) = STRATTESTEQ; + } + | '>' + { + ($$) = STRATTESTGT; + } + ; + +TESTEXPR1 : TESTEXPR1 TESTEXPR1OP TESTEXPR2 + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (10)"); + stratTestExit ($1); + stratTestExit ($3); + YYABORT; + } + test->typetest = ($2); + test->data.test[0] = ($1); + test->data.test[1] = ($3); + + ($$) = test; + } + | TESTEXPR2 + ; + +TESTEXPR1OP : '+' + { + ($$) = STRATTESTADD; + } + | '-' + { + ($$) = STRATTESTSUB; + } + ; + +TESTEXPR2 : TESTEXPR2 TESTEXPR2OP TESTEXPR3 + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + stratTestExit ($1); + stratTestExit ($3); + errorPrint ("stratParserParse: out of memory (11)"); + YYABORT; + } + test->typetest = ($2); + test->data.test[0] = ($1); + test->data.test[1] = ($3); + + ($$) = test; + } + | TESTEXPR3 + ; + +TESTEXPR2OP : '*' + { + ($$) = STRATTESTMUL; + } + ; + +TESTEXPR3 : TESTEXPR3 TESTEXPR3OP TESTEXPR4 + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (12)"); + stratTestExit ($1); + stratTestExit ($3); + YYABORT; + } + test->typetest = ($2); + test->data.test[0] = ($1); + test->data.test[1] = ($3); + + ($$) = test; + } + | TESTEXPR4 + ; + +TESTEXPR3OP : '%' + { + ($$) = STRATTESTMOD; + } + ; + +TESTEXPR4 : '(' TESTEXPR1 ')' + { + ($$) = ($2); + } + | TESTVAL + | TESTVAR + ; + +TESTVAL : VALSDOUBLE + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (13)"); + YYABORT; + } + + test->typetest = STRATTESTVAL; + test->typenode = STRATPARAMDOUBLE; + test->data.val.valdbl = ($1); + + ($$) = test; + } + | VALSINT + { + StratTest * test; + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (14)"); + YYABORT; + } + + test->typetest = STRATTESTVAL; + test->typenode = STRATPARAMINT; + test->data.val.valint = ($1); + + ($$) = test; + } + ; + +TESTVAR : PARAMNAME + { + StratTest * test; + StratParamTab * condtab; + int para; + int paralen; + int i, j; + + para = + paralen = 0; /* No parameter recognized yet */ + condtab = parserstrattab->condtab; /* Point to parameter table */ + for (i = 0; condtab[i].name != NULL; i ++) { + if ((strncasecmp (($1), /* Find longest matching parameter name */ + condtab[i].name, + j = strlen (condtab[i].name)) == 0) && + (j > paralen)) { + para = i; + paralen = j; + } + } + if (paralen == 0) { + errorPrint ("stratParserParse: invalid graph parameter name \"%s\", before \"%s\"", + ($1), stratParserRemain ()); + YYABORT; + } + + if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { + errorPrint ("stratParserParse: out of memory (15)"); + YYABORT; + } + + test->typetest = STRATTESTVAR; + test->typenode = condtab[para].type; + test->data.var.datatab = parserstrattab; + test->data.var.datadisp = condtab[para].dataofft - + condtab[para].database; + + ($$) = test; + } + ; + +VALSDOUBLE : TESTEXPR1OP VALDOUBLE + { + ($$) = (($1) == STRATTESTSUB) ? - ($2) : ($2); + } + | VALDOUBLE + ; + +VALSINT : TESTEXPR1OP VALINT + { + ($$) = (($1) == STRATTESTSUB) ? - ($2) : ($2); + } + | VALINT + ; + +%% + +/* +** The static and global definitions (bis). +** These are put at the end of the file because +** the token values that they use are not yet +** defined in the first section of the file. +*/ + +unsigned int parsermethtokentab[] = { /* Table for parameter/token type conversion */ + VALCASE, + VALDOUBLE, + VALINT, + -1, /* No logical parameters */ + VALSTRAT, + VALSTRING, + -1 /* One more value to detect array overflow */ + }; + +/************************************/ +/* */ +/* These routines drive the parser. */ +/* */ +/************************************/ + +/* This routine is the entry point for +** the strategy parser. +** It returns: +** - !NULL : pointer to the strategy. +** - NULL : on error. +*/ + +Strat * +stratParserParse ( +const StratTab * const strattab, /*+ Pointer to parsing tables +*/ +const char * const string) /*+ Strategy string to parse +*/ +{ + yyclearin; /* Reset the parser state */ + +#ifdef SCOTCH_DEBUG_PARSER3 + yydebug = 1; /* Set debugging if needed */ +#endif /* SCOTCH_DEBUG_PARSER3 */ + + stratParserInit (string); /* Initialize the lexical parser */ + parserstrattab = strattab; /* Point to the parsing tables */ + parserstratcurr = NULL; /* Clear up the temporary strategy pointer */ + + if (stratParserParse2 () != 0) { /* Parse the strategy string */ + if (parserstratcurr != NULL) + stratExit (parserstratcurr); + return (NULL); + } + + return (parserstratcurr); /* Return strategy pointer */ +} + +/* This routine displays the parser error message. +** It returns: +** - 1 : in all cases. +*/ + +static +int +stratParserError ( +const char * const errstr) +{ + errorPrint ("stratParserParse: invalid strategy string, before \"%s\"", stratParserRemain ()); + return (1); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph.c b/scotch_6.0.3/src/libscotch/vdgraph.c new file mode 100644 index 00000000..a175cd41 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph.c @@ -0,0 +1,137 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the distributed **/ +/** separator handling routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 07 feb 2006 **/ +/** to 13 mar 2006 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "vdgraph.h" + +/*************************************/ +/* */ +/* These routines handle distributed */ +/* separator graphs. */ +/* */ +/*************************************/ + +/* This routine initializes a distributed +** separator graph structure. As for the Dgraph +** structure, in order to avoid collective +** communication whenever possible, the allocation +** of send and receive index arrays is not performed +** in the routine itself, but rather delegated to +** subsequent routines such as dgraphBuild. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +vdgraphInit ( +Vdgraph * restrict const grafptr, /* Distributed separator graph structure */ +MPI_Comm proccomm) /* Communicator to be used for all communications */ +{ + memSet (grafptr, 0, sizeof (Vdgraph)); /* Clear public and private graph fields */ + + grafptr->s.proccomm = proccomm; /* Set private fields */ + MPI_Comm_size (proccomm, &grafptr->s.procglbnbr); /* Get communicator data */ + MPI_Comm_rank (proccomm, &grafptr->s.proclocnum); + + return (0); +} + +/* This routine frees the contents +** of the given distributed active graph. +** It returns: +** - VOID : in all cases. +*/ + +void +vdgraphExit ( +Vdgraph * const grafptr) +{ + if (grafptr->partgsttax != NULL) + memFree (grafptr->partgsttax + grafptr->s.baseval); + if (grafptr->fronloctab != NULL) + memFree (grafptr->fronloctab); + + dgraphExit (&grafptr->s); /* Free distributed source graph and its private data (flagval may be corrupted afterwards) */ + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + memSet (grafptr, ~0, sizeof (Vdgraph)); +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ +} + +/* This routine moves all of the graph +** vertices to the first part. +** It returns: +** - VOID : in all cases. +*/ + +void +vdgraphZero ( +Vdgraph * const grafptr) +{ + memSet (grafptr->partgsttax + grafptr->s.baseval, 0, grafptr->s.vertgstnbr * sizeof (GraphPart)); /* Set all local and ghost vertices to part 0 */ + + grafptr->compglbloaddlt = grafptr->s.veloglbsum; + grafptr->compglbload[0] = grafptr->s.veloglbsum; /* No frontier vertices */ + grafptr->compglbload[1] = + grafptr->compglbload[2] = 0; + grafptr->compglbsize[0] = grafptr->s.vertglbnbr; + grafptr->compglbsize[1] = + grafptr->compglbsize[2] = 0; + grafptr->complocload[0] = grafptr->s.velolocsum; + grafptr->complocload[1] = + grafptr->complocload[2] = 0; + grafptr->complocsize[0] = grafptr->s.vertlocnbr; + grafptr->complocsize[1] = + grafptr->complocsize[2] = 0; +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph.h b/scotch_6.0.3/src/libscotch/vdgraph.h new file mode 100644 index 00000000..78f25fd9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph.h @@ -0,0 +1,100 @@ +/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for distributed vertex separation **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 06 feb 2006 **/ +/** to : 29 apr 2006 **/ +/** # Version 5.1 : from : 07 nov 2007 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Active graph structure. +*/ + +typedef struct Vdgraph_ { + Dgraph s; /*+ Source distributed graph +*/ + GraphPart * partgsttax; /*+ Based local part array: 0,1: part; 2: separator +*/ + Gnum compglbloaddlt; /*+ Load difference between both parts +*/ + Gnum compglbload[3]; /*+ Global loads of both parts and of separator; TRICK: before compglbsize[] +*/ + Gnum compglbsize[3]; /*+ Number of vertices in parts; compglbsize[2] is fronglbnbr, the separator +*/ + Gnum complocload[3]; /*+ Local loads of both parts and of separator; TRICK: before complocsize[] +*/ + Gnum complocsize[3]; /*+ Number of vertices in parts; complocsize[2] is fronlocnbr, the separator +*/ + Gnum * fronloctab; /*+ Array of local frontier vertex numbers +*/ + Gnum levlnum; /*+ Nested dissection or coarsening level +*/ +} Vdgraph; + +/*+ The graph separator storing structure. +*/ + +typedef struct VdgraphStore_ { + Gnum fronglbnbr; /*+ Number of frontier nodes +*/ + Gnum compglbloaddlt; /*+ Difference from the average +*/ + Gnum compglbload[2]; /*+ Load in both parts +*/ + Gnum compglbsize0; /*+ Number of vertices in part 0 +*/ + Gnum complocsize0; /*+ Number of vertices in parts +*/ + Gnum fronlocnbr; /*+ Number of local frontier vertices +*/ + byte * datatab; /*+ Variable-sized data array +*/ +} VdgraphStore; + +/* +** The function prototypes. +*/ + +#ifndef VDGRAPH +#define static +#endif + +int vdgraphInit (Vdgraph * restrict const, MPI_Comm); +void vdgraphExit (Vdgraph * const); +void vdgraphZero (Vdgraph * const); +int vdgraphCheck (const Vdgraph * const); +#ifdef VGRAPH_H +int vdgraphGatherAll (const Vdgraph * restrict const, Vgraph * restrict); +#endif /* VGRAPH_H */ + +int vdgraphStoreInit (const Vdgraph * const, VdgraphStore * const); +void vdgraphStoreExit (VdgraphStore * const); +void vdgraphStoreSave (const Vdgraph * const , VdgraphStore * const); +void vdgraphStoreUpdt (Vdgraph * const, const VdgraphStore * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vdgraph_check.c b/scotch_6.0.3/src/libscotch/vdgraph_check.c new file mode 100644 index 00000000..dacf5297 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_check.c @@ -0,0 +1,272 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the distributed **/ +/** separator graph consistency checking **/ +/** routine. **/ +/** **/ +/** DATES : # Version 5.0 : from : 07 feb 2006 **/ +/** to 01 mar 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "vdgraph.h" + +/*************************/ +/* */ +/* These routines handle */ +/* separator graphs. */ +/* */ +/*************************/ + +/* This routine checks the consistency +** of the given distributed separator graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +vdgraphCheck ( +const Vdgraph * const grafptr) +{ + Dgraph grafdat; /* Dummy graph for ghost edge array */ + MPI_Comm proccomm; /* Graph communicator */ + Gnum vertnum; /* Number of current vertex */ + Gnum fronnum; /* Number of frontier vertex */ + Gnum complocload[3]; + Gnum complocsize[3]; + Gnum commcut[3]; + GraphPart * restrict partgsttax; + Gnum reduloctab[11]; /* Arrays for reductions */ + Gnum reduglbtab[11]; + int cheklocval; /* Local consistency flag */ + int chekglbval; /* Global consistency flag */ + + proccomm = grafptr->s.proccomm; + if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize */ + errorPrint ("vdgraphCheck: communication error (1)"); + return (1); + } + + cheklocval = 0; /* Assume everything is all right */ + + if ((grafptr->compglbload[0] + grafptr->compglbload[1] + grafptr->compglbload[2]) != grafptr->s.veloglbsum) { + errorPrint ("vdgraphCheck: invalid global load sum"); + cheklocval = 1; + } + + if (grafptr->compglbloaddlt != (grafptr->compglbload[0] - grafptr->compglbload[1])) { + errorPrint ("vdgraphCheck: invalid global balance"); + cheklocval |= 2; + } + + if ((grafptr->compglbsize[0] + grafptr->compglbsize[1] + grafptr->compglbsize[2]) != grafptr->s.vertglbnbr) { + errorPrint ("vdgraphCheck: invalid global size sum"); + cheklocval |= 4; + } + + if ((grafptr->complocsize[0] + grafptr->complocsize[1] + grafptr->complocsize[2]) != grafptr->s.vertlocnbr) { + errorPrint ("vdgraphCheck: invalid local size sum"); + cheklocval |= 8; + } + + if ((grafptr->complocsize[2] < 0) || + (grafptr->complocsize[2] > grafptr->s.vertlocnbr)) { + errorPrint ("vdgraphCheck: invalid number of local frontier vertices"); + cheklocval |= 16; + } + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertlocnnd; vertnum ++) { + if (grafptr->partgsttax[vertnum] > 2) { + errorPrint ("vdgraphCheck: invalid local part array"); + cheklocval |= 32; + break; + } + } + + for (fronnum = 0; fronnum < grafptr->complocsize[2]; fronnum ++) { + Gnum vertnum; + + vertnum = grafptr->fronloctab[fronnum]; + if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->s.vertlocnnd)) { + errorPrint ("vdgraphCheck: invalid vertex index in frontier array"); + cheklocval |= 64; + break; + } + if (grafptr->partgsttax[vertnum] != 2) { + errorPrint ("vdgraphCheck: invalid vertex in frontier array"); + cheklocval |= 64; + break; + } + } + + grafdat = grafptr->s; /* Copy minimal distributed graph data */ + if (dgraphGhst (&grafdat) != 0) { /* Create ghost edge array if did not exist */ + errorPrint ("vdgraphCheck: cannot compute ghost edge array"); + cheklocval |= 128; + } + + if ((partgsttax = memAlloc (grafdat.vertgstnbr * sizeof (byte))) == NULL) { + errorPrint ("vdgraphCheck: out of memory"); + cheklocval |= 256; + } + + reduloctab[0] = grafptr->compglbload[0]; + reduloctab[1] = - grafptr->compglbload[0]; + reduloctab[2] = grafptr->compglbload[1]; + reduloctab[3] = - grafptr->compglbload[1]; + reduloctab[4] = grafptr->compglbload[2]; + reduloctab[5] = - grafptr->compglbload[2]; + reduloctab[6] = grafptr->compglbsize[2]; + reduloctab[7] = - grafptr->compglbsize[2]; + reduloctab[8] = grafptr->levlnum; + reduloctab[9] = - grafptr->levlnum; + reduloctab[10] = cheklocval; + + if (MPI_Allreduce (reduloctab, reduglbtab, 11, GNUM_MPI, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphCheck: communication error (2)"); + return (1); + } + + if (reduglbtab[10] != 0) { /* Return from previous errors */ + if (partgsttax != NULL) + memFree (partgsttax); + return (1); + } + + if ((reduglbtab[1] != - reduglbtab[0]) || + (reduglbtab[3] != - reduglbtab[2]) || + (reduglbtab[5] != - reduglbtab[4]) || + (reduglbtab[7] != - reduglbtab[6]) || + (reduglbtab[9] != - reduglbtab[8])) { + errorPrint ("vdgraphCheck: inconsistent global graph data"); + return (1); + } + + memCpy (partgsttax, grafptr->partgsttax + grafptr->s.baseval, grafptr->s.vertlocnbr); /* Copy local part data */ + dgraphHaloSync (&grafdat, partgsttax, GRAPHPART_MPI); /* Spread yet unbased halo part data across neighboring processes */ + partgsttax -= grafptr->s.baseval; + + complocload[0] = + complocload[1] = + complocload[2] = 0; + complocsize[0] = + complocsize[1] = + complocsize[2] = 0; + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertlocnnd; vertnum ++) { + int partnum; /* Part of current vertex */ + Gnum edgenum; /* Number of current edge */ + + partnum = (int) partgsttax[vertnum]; + + complocload[partnum] += (grafptr->s.veloloctax == NULL) ? 1 : grafptr->s.veloloctax[vertnum]; + complocsize[partnum] ++; + + commcut[0] = + commcut[1] = + commcut[2] = 0; + for (edgenum = grafptr->s.vertloctax[vertnum]; edgenum < grafptr->s.vendloctax[vertnum]; edgenum ++) { + if (grafdat.edgegsttax[edgenum] < grafptr->s.vertlocnnd) /* Check only for local ends, as ghost part might be inaccurate */ + commcut[partgsttax[grafdat.edgegsttax[edgenum]]] ++; + } + if (partnum != 2) { + if (commcut[1 - partnum] != 0) { + errorPrint ("vdgraphCheck: vertex should be in separator (%ld)", (long) vertnum); + cheklocval = 1; + break; + } + } + } + if (grafptr->s.edgegsttax != grafdat.edgegsttax) /* If ghost edge array was allocated here, free it manually */ + memFree (grafdat.edgegsttax + grafptr->s.baseval); + if (grafptr->s.procsidtab != grafdat.procsidtab) /* The same for procsidtab */ + memFree (grafdat.procsidtab); + memFree (partgsttax + grafptr->s.baseval); + + if ((cheklocval == 0) && + ((complocsize[0] != grafptr->complocsize[0]) || + (complocsize[1] != grafptr->complocsize[1]) || + (complocsize[2] != grafptr->complocsize[2]))) { + errorPrint ("vgraphCheck: invalid local part sizes"); + cheklocval = 1; + } + + reduloctab[0] = complocload[0]; + reduloctab[1] = complocload[1]; + reduloctab[2] = complocload[2]; + reduloctab[3] = complocsize[0]; + reduloctab[4] = complocsize[1]; + reduloctab[5] = complocsize[2]; + reduloctab[6] = cheklocval; + + if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphCheck: communication error (3)"); + return (1); + } + if (reduglbtab[6] != 0) /* Return from previous errors */ + return (1); + + if ((grafptr->compglbload[0] != reduglbtab[0]) || + (grafptr->compglbload[1] != reduglbtab[1]) || + (grafptr->compglbload[2] != reduglbtab[2])) { + errorPrint ("vdgraphCheck: invalid global part loads"); + cheklocval = 1; + } + if ((grafptr->compglbsize[0] != reduglbtab[3]) || + (grafptr->compglbsize[1] != reduglbtab[4]) || + (grafptr->compglbsize[2] != reduglbtab[5])) { + errorPrint ("vgraphCheck: invalid global part sizes"); + cheklocval = 1; + } + + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphCheck: communication error (4)"); + return (1); + } + + return (chekglbval); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph_gather_all.c b/scotch_6.0.3/src/libscotch/vdgraph_gather_all.c new file mode 100644 index 00000000..3be32cac --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_gather_all.c @@ -0,0 +1,223 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_gather_all.c **/ +/** **/ +/** AUTHORS : Cedric CHEVALIER **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the routine which **/ +/** builds a centralized Vgraph on all **/ +/** processes by gathering the pieces of a **/ +/** distributed Vdgraph. **/ +/** **/ +/** DATES : # Version 5.0 : from : 29 apr 2006 **/ +/** to 01 mar 2008 **/ +/** # Version 5.1 : from : 18 apr 2009 **/ +/** to 30 jul 2010 **/ +/** **/ +/** NOTES : # The definitions of MPI_Gather and **/ +/** MPI_Gatherv indicate that elements in **/ +/** the receive array should not be **/ +/** written more than once. Great care **/ +/** should be taken to enforce this rule, **/ +/** especially when the number of **/ +/** vertices in the centralized graph is **/ +/** smaller than the number of **/ +/** processes. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "graph.h" +#include "vgraph.h" +#include "dgraph.h" +#include "vdgraph.h" + +/* This function gathers on all processes +** the pieces of a distributed Vdgraph to +** build a centralized Vgraph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +vdgraphGatherAll ( +const Vdgraph * restrict const dgrfptr, /* Distributed graph */ +Vgraph * restrict cgrfptr) /* Centralized graph */ +{ + int * restrict froncnttab; /* Count array for gather operations */ + int * restrict frondsptab; /* Displacement array for gather operations */ + int fronlocnbr; /* Also int to enforce MPI standard */ + int cheklocval; +#ifdef SCOTCH_DEBUG_VDGRAPH1 + int chekglbval; +#endif /* SCOTCH_DEBUG_VDGRAPH1 */ + int procnum; + + cheklocval = 0; +#ifdef SCOTCH_DEBUG_VDGRAPH1 + if (cgrfptr == NULL) /* Centralized graphs should be provided by all */ + cheklocval = 1; + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphGatherAll: communication error (1)"); + return (1); + } + if (chekglbval != 0) { + errorPrint ("vdgraphGatherAll: centralized graphs should be provided on every process"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH1 */ + + if (dgraphGatherAll (&dgrfptr->s, &cgrfptr->s) != 0) { + errorPrint ("vdgraphGatherAll: cannot build centralized graph"); + return (1); + } + + cgrfptr->parttax = NULL; /* In case of error */ + cgrfptr->frontab = NULL; + if (((cgrfptr->parttax = (GraphPart *) memAlloc (cgrfptr->s.vertnbr * sizeof (GraphPart))) == NULL) || + ((cgrfptr->parttax -= cgrfptr->s.baseval, + cgrfptr->frontab = (Gnum *) memAlloc (cgrfptr->s.vertnbr * sizeof (Gnum))) == NULL)) { + errorPrint ("vdgraphGatherAll: out of memory (1)"); +#ifndef SCOTCH_DEBUG_VDGRAPH1 + vgraphExit (cgrfptr); + return (1); + } +#else /* SCOTCH_DEBUG_VDGRAPH1 */ + cheklocval = 1; + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphGatherAll: communication error (2)"); + return (1); + } + if (chekglbval != 0) { + vgraphExit (cgrfptr); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH1 */ + + cgrfptr->levlnum = dgrfptr->levlnum; /* Set level of separation graph as level of halo graph */ + + if (dgrfptr->partgsttax == NULL) { /* If distributed graph does not have a part array yet */ + vgraphZero (cgrfptr); + return (0); + } + + if (memAllocGroup ((void **) (void *) /* Allocate tempory arrays to gather separator vertices */ + &froncnttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), + &frondsptab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), NULL) == NULL) { + errorPrint ("vdgraphGatherAll: out of memory (2)"); +#ifndef SCOTCH_DEBUG_VDGRAPH1 + vgraphExit (cgrfptr); + return (1); + } +#else /* SCOTCH_DEBUG_VDGRAPH1 */ + cheklocval = 1; + } + if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphGatherAll: communication error (3)"); + return (1); + } + if (chekglbval != 0) { + if (froncnttab != NULL) + memFree (froncnttab); + vgraphExit (cgrfptr); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH1 */ + + if (commAllgatherv (dgrfptr->partgsttax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GRAPHPART_MPI, /* Get parttax of distributed graph */ + cgrfptr->parttax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GRAPHPART_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphGatherAll: communication error (4)"); + return (1); + } + + fronlocnbr = (int) dgrfptr->complocsize[2]; + if (MPI_Allgather (&fronlocnbr, 1, MPI_INT, /* Compute how separator vertices are distributed */ + froncnttab, 1, MPI_INT, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphGatherAll: communication error (5)"); + return (1); + } + frondsptab[0] = 0; /* Offset 0 for first process */ + for (procnum = 1; procnum < dgrfptr->s.procglbnbr; procnum ++) /* Adjust index sub-arrays for all processes except the first one */ + frondsptab[procnum] = frondsptab[procnum - 1] + froncnttab[procnum - 1]; + + if (MPI_Allgatherv (dgrfptr->fronloctab, fronlocnbr, GNUM_MPI, /* Gather separator vertices */ + cgrfptr->frontab, froncnttab, frondsptab, GNUM_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphGatherAll: communication error (6)"); + return (1); + } + + for (procnum = 1; procnum < dgrfptr->s.procglbnbr; procnum ++) { /* Adjust index sub-arrays for all processes except the first one */ + Gnum vertnum; + Gnum vertnnd; + + for (vertnum = (Gnum) frondsptab[procnum], vertnnd = vertnum + (Gnum) froncnttab[procnum]; + vertnum < vertnnd; vertnum ++) + cgrfptr->frontab[vertnum] += (Gnum) dgrfptr->s.procdsptab[procnum] - dgrfptr->s.baseval; + } + + memFree (froncnttab); /* Free group leader */ + + for (procnum = 0; procnum < dgrfptr->s.proclocnum; procnum ++) /* Desynchronize random generators across processes */ + cheklocval = intRandVal (2); + intPerm (cgrfptr->frontab, dgrfptr->compglbsize[2]); /* Compute permutation of frontier array to have different solutions on every process */ + + cgrfptr->compload[0] = dgrfptr->compglbload[0]; /* Update other fields */ + cgrfptr->compload[1] = dgrfptr->compglbload[1]; + cgrfptr->compload[2] = dgrfptr->compglbload[2]; + cgrfptr->comploaddlt = dgrfptr->compglbloaddlt; + cgrfptr->compsize[0] = dgrfptr->compglbsize[0]; + cgrfptr->compsize[1] = dgrfptr->compglbsize[1]; + cgrfptr->fronnbr = dgrfptr->compglbsize[2]; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (vgraphCheck (cgrfptr) != 0) { + errorPrint ("vdgraphGatherAll: internal error"); + vgraphExit (cgrfptr); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_bd.c b/scotch_6.0.3/src/libscotch/vdgraph_separate_bd.c new file mode 100644 index 00000000..e5a4fb2e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_bd.c @@ -0,0 +1,199 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_bd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : This module computes a separator of the **/ +/** given distributed separator graph by **/ +/** creating a band graph of given witdh **/ +/** around the current separator, computing **/ +/** an improved separator of the band **/ +/** graph, and projecting back the obtained **/ +/** separator in the original graph. **/ +/** **/ +/** DATES : # Version 5.0 : from : 04 mar 2006 **/ +/** to : 07 nov 2007 **/ +/** # Version 5.1 : from : 11 nov 2007 **/ +/** to : 01 mar 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH_SEPARATE_BD + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "dgraph.h" +#include "vdgraph.h" +#include "vdgraph_separate_bd.h" +#include "vdgraph_separate_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes a distributed band graph +** of given width around the current separator and +** applies distributed separation routines to it. +** The distributed graph is not guaranteed to be +** balanced at at all. +** It returns: +** - 0 : if the distributed band graph could be computed. +** - !0 : on error. +*/ + +int +vdgraphSeparateBd ( +Vdgraph * const grafptr, /*+ Distributed graph +*/ +const VdgraphSeparateBdParam * const paraptr) /*+ Method parameters +*/ +{ + Vdgraph bandgrafdat; /* Vertex separator band graph structure */ + Gnum bandvertancnnd; /* End of local vertex array, without anchors */ + Gnum bandvertlocnbr1; /* Number of band graph vertices in part 1 except anchor 1 */ + Gnum bandvertlocnum; + Gnum bandvertlocancadj; /* Flag set when anchor(s) represent unexistent vertices */ + Gnum bandvertglbancadj; /* Global adjustment of anchor vertices */ + Gnum complocsizeadj0; + Gnum complocsizeadj1; + Gnum reduloctab[3]; + Gnum reduglbtab[3]; + Gnum * restrict edloloctax; /* Save value for edge loads while we pretend we don't have them */ + Gnum fronlocnum; + + if (grafptr->compglbsize[2] == 0) /* If no frontier to base on */ + return (0); /* Then do nothing */ + if (paraptr->distmax < 1) /* If distance is 0 (or less) */ + return (0); /* Then do nothing */ + + edloloctax = grafptr->s.edloloctax; /* Fake no edge loads on original graph as we do not need them */ + grafptr->s.edloloctax = NULL; + if (dgraphBand (&grafptr->s, grafptr->complocsize[2], grafptr->fronloctab, grafptr->partgsttax, + grafptr->complocload[0] + grafptr->complocload[2], grafptr->complocload[1], paraptr->distmax, + &bandgrafdat.s, &bandgrafdat.fronloctab, &bandgrafdat.partgsttax, + NULL, &bandvertlocnbr1, &bandvertlocancadj) != 0) { + grafptr->s.edloloctax = edloloctax; + errorPrint ("vdgraphSeparateBd: cannot create band graph"); + return (1); + } + grafptr->s.edloloctax = edloloctax; /* Restore edge loads, if any */ + + bandgrafdat.complocsize[0] = bandgrafdat.s.vertlocnbr - (bandvertlocnbr1 + 1) - grafptr->complocsize[2]; /* Add 1 for anchor vertex 1 */ + bandgrafdat.complocsize[1] = bandvertlocnbr1 + 1; /* Add 1 for anchor vertex 1 */ + complocsizeadj0 = grafptr->complocsize[0] - bandgrafdat.complocsize[0]; + complocsizeadj1 = grafptr->complocsize[1] - bandgrafdat.complocsize[1]; + reduloctab[0] = bandgrafdat.complocsize[0]; + reduloctab[1] = bandgrafdat.complocsize[1]; + reduloctab[2] = bandvertlocancadj; /* Sum increases in size and load */ + if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 3, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateBd: communication error (1)"); + return (1); + } + bandvertglbancadj = reduglbtab[2]; + bandgrafdat.compglbload[0] = grafptr->compglbload[0] + bandvertglbancadj; /* All loads are kept in band graph */ + bandgrafdat.compglbload[1] = grafptr->compglbload[1] + bandvertglbancadj; + bandgrafdat.compglbload[2] = grafptr->compglbload[2]; + bandgrafdat.compglbloaddlt = grafptr->compglbloaddlt; /* Balance is not changed by anchor vertices */ + bandgrafdat.complocload[0] = grafptr->complocload[0] + bandvertlocancadj; + bandgrafdat.complocload[1] = grafptr->complocload[1] + bandvertlocancadj; + bandgrafdat.complocload[2] = grafptr->complocload[2]; + bandgrafdat.compglbsize[0] = reduglbtab[0]; + bandgrafdat.compglbsize[1] = reduglbtab[1]; + bandgrafdat.compglbsize[2] = grafptr->compglbsize[2]; /* All separator vertices are kept in band graph */ + bandgrafdat.complocsize[2] = grafptr->complocsize[2]; + bandgrafdat.levlnum = grafptr->levlnum; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (vdgraphCheck (&bandgrafdat) != 0) { + errorPrint ("vdgraphSeparateBd: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + + if (vdgraphSeparateSt (&bandgrafdat, paraptr->strat) != 0) { /* Separate distributed band graph */ + errorPrint ("vdgraphSeparateBd: cannot separate band graph"); + vdgraphExit (&bandgrafdat); + return (1); + } + + bandvertancnnd = bandgrafdat.s.vertlocnnd - 2; + reduloctab[0] = ((bandgrafdat.partgsttax[bandvertancnnd] == 0) && /* Check if anchor vertices remain in their parts */ + (bandgrafdat.partgsttax[bandvertancnnd + 1] == 1)) ? 0 : 1; + reduloctab[1] = bandgrafdat.complocsize[0] + complocsizeadj0; + reduloctab[2] = bandgrafdat.complocsize[1] + complocsizeadj1; + if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 3, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateBd: communication error (2)"); + return (1); + } + if (reduglbtab[0] != 0) { /* If at least one anchor changed of part */ + vdgraphExit (&bandgrafdat); /* Then keep original partition */ + return (0); + } + + grafptr->compglbload[0] = bandgrafdat.compglbload[0] - bandvertglbancadj; + grafptr->compglbload[1] = bandgrafdat.compglbload[1] - bandvertglbancadj; + grafptr->compglbload[2] = bandgrafdat.compglbload[2]; + grafptr->compglbloaddlt = bandgrafdat.compglbloaddlt; + grafptr->compglbsize[0] = reduglbtab[1]; + grafptr->compglbsize[1] = reduglbtab[2]; + grafptr->compglbsize[2] = bandgrafdat.compglbsize[2]; + grafptr->complocload[0] = bandgrafdat.complocload[0] - bandvertlocancadj; + grafptr->complocload[1] = bandgrafdat.complocload[1] - bandvertlocancadj; + grafptr->complocload[2] = bandgrafdat.complocload[2]; + grafptr->complocsize[0] = reduloctab[1]; + grafptr->complocsize[1] = reduloctab[2]; + grafptr->complocsize[2] = bandgrafdat.complocsize[2]; + for (fronlocnum = 0; fronlocnum < bandgrafdat.complocsize[2]; fronlocnum ++) /* Project back separator */ + grafptr->fronloctab[fronlocnum] = bandgrafdat.s.vnumloctax[bandgrafdat.fronloctab[fronlocnum]]; + for (bandvertlocnum = bandgrafdat.s.baseval; bandvertlocnum < bandvertancnnd; bandvertlocnum ++) /* For all vertices except anchors */ + grafptr->partgsttax[bandgrafdat.s.vnumloctax[bandvertlocnum]] = bandgrafdat.partgsttax[bandvertlocnum]; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (vdgraphCheck (grafptr) != 0) { + errorPrint ("vdgraphSeparateBd: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + + vdgraphExit (&bandgrafdat); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_bd.h b/scotch_6.0.3/src/libscotch/vdgraph_separate_bd.h new file mode 100644 index 00000000..5ed218f1 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_bd.h @@ -0,0 +1,68 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_bd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the band vertex separation **/ +/** routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.0 : from : 04 mar 2006 **/ +/** to : 04 mar 2006 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VdgraphSeparateBdParam_ { + INT distmax; /*+ Width of band surrounding the separator +*/ + Strat * strat; /*+ Separation strategy used on the band garph +*/ +} VdgraphSeparateBdParam; + +/* +** The function prototypes. +*/ + +#ifndef VDGRAPH_SEPARATE_BD +#define static +#endif + +int vdgraphSeparateBd (Vdgraph * const, const VdgraphSeparateBdParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_df.c b/scotch_6.0.3/src/libscotch/vdgraph_separate_df.c new file mode 100644 index 00000000..6c97f000 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_df.c @@ -0,0 +1,372 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_df.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a separator of the **/ +/** given distributed separator graph by **/ +/** applying a diffusion method to what is **/ +/** assumed to be a distributed band graph. **/ +/** **/ +/** DATES : # Version 5.1 : from : 05 nov 2007 **/ +/** to : 09 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH_SEPARATE_DF + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "vdgraph.h" +#include "vdgraph_separate_df.h" + +/* +** The static variables. +*/ + +static const Gnum vdgraphseparatedfloadone = 1; + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes a distributed separator +** by diffusion across what is assumed to be a +** distributed band graph. +** It returns: +** - 0 : if the separator could be computed. +** - !0 : on error. +*/ + +int +vdgraphSeparateDf ( +Vdgraph * const grafptr, /*+ Distributed graph +*/ +const VdgraphSeparateDfParam * const paraptr) /*+ Method parameters +*/ +{ + float * restrict ielsloctax; /* Inverse of degree array */ + float * restrict difogsttax; /* Old diffusion value array */ + float * restrict difngsttax; /* New diffusion value array */ + const Gnum * restrict edgegsttax; + Gnum fronlocnum; + float compglbavg; + Gnum complocload1; + Gnum complocload2; + Gnum complocsize1; + const Gnum * restrict velolocbax; + Gnum velolocmsk; + float vanclocval[2]; + float valolocval[2]; /* Fraction of load to remove from anchor vertices at each step */ + Gnum vanclocnnd; + Gnum vertlocnum; + Gnum reduloctab[4]; /* Local degree of both anchor vertices, minus edges to other anchors, and their loads */ + Gnum reduglbtab[4]; + Gnum passnum; + float cdifval; + float cremval; + Gnum psepval; /* Separator part */ + int ovflval; /* Overflow flag value */ + + if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present */ + errorPrint ("vdgraphSeparateDf: cannot compute ghost edge array"); + return (1); + } + + reduloctab[0] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 2] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 2] - (grafptr->s.procglbnbr - 1); + reduloctab[1] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 1] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 1] - (grafptr->s.procglbnbr - 1); + if (grafptr->s.veloloctax == NULL) + reduloctab[2] = + reduloctab[3] = 1; + else { + reduloctab[2] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 2]; + reduloctab[3] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 1]; + } + + if (memAllocGroup ((void **) (void *) + &ielsloctax, (size_t) (grafptr->s.vertlocnbr * sizeof (float)), + &difogsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), + &difngsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), NULL) == NULL) { + errorPrint ("vdgraphSeparateDf: out of memory"); + reduloctab[0] = -1; + } + else { + ielsloctax -= grafptr->s.baseval; + difogsttax -= grafptr->s.baseval; + difngsttax -= grafptr->s.baseval; + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 4, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateDf: communication error (1)"); + return (1); + } + + if (reduglbtab[0] < 0) { /* If memory error */ + if (ielsloctax != NULL) + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + } + if ((reduglbtab[0] == 0) || /* If graph is too small to have any usable anchors, leave partition as is */ + (reduglbtab[1] == 0)) { + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + return (0); + } + + psepval = paraptr->partval & 1; /* Coerce part in the {0,1} range */ + compglbavg = (float) (grafptr->compglbload[0] + grafptr->compglbload[1]) * 0.5F; + vanclocval[0] = (float) grafptr->compglbload[0]; + if (vanclocval[0] < (compglbavg * (1.0F - (float) paraptr->deltval))) /* Enforce balance constraint */ + vanclocval[0] = compglbavg * (1.0F - (float) paraptr->deltval); + else if (vanclocval[0] > (compglbavg * (1.0F + (float) paraptr->deltval))) + vanclocval[0] = compglbavg * (1.0F + (float) paraptr->deltval); + vanclocval[1] = (float) (grafptr->compglbload[0] + grafptr->compglbload[1]) - vanclocval[0]; + valolocval[0] = (float) reduglbtab[2]; /* Compute values to remove from anchor vertices */ + valolocval[1] = (float) reduglbtab[3]; + if (vanclocval[0] < valolocval[0]) /* If anchor in part 0 too large to reduce imbalance */ + psepval = 1; /* Separator must be taken from part 1 to stick to anchor 0 */ + else if (vanclocval[1] < valolocval[1]) /* Else if anchor in part 1 too large to reduce imbalance */ + psepval = 0; /* It is from part 0 that separator must be extracted */ + vanclocval[psepval] += (float) grafptr->compglbload[2]; /* Aggregate separator to proper part */ + vanclocval[0] = - vanclocval[0]; /* Part 0 holds negative values */ + vanclocval[1] -= VDGRAPHSEPARATEDFEPSILON; /* Slightly tilt value to add to part 1 */ + + for (vertlocnum = grafptr->s.baseval, vanclocnnd = grafptr->s.vertlocnnd - 2; /* Do not account for anchor vertices in diffusion computations */ + vertlocnum < vanclocnnd; vertlocnum ++) { +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if ((grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]) == 0) { + errorPrint ("vdgraphSeparateDf: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + ielsloctax[vertlocnum] = 1.0F / (float) (grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]); + difogsttax[vertlocnum] = 0.0F; + } + ielsloctax[vanclocnnd] = 1.0F / (float) reduglbtab[0]; + ielsloctax[vanclocnnd + 1] = 1.0F / (float) reduglbtab[1]; + difogsttax[vanclocnnd] = vanclocval[0] * ielsloctax[vanclocnnd]; /* Load anchor vertices for first pass */ + difogsttax[vanclocnnd + 1] = vanclocval[1] * ielsloctax[vanclocnnd + 1]; + difngsttax[vanclocnnd] = /* In case of isolated anchors, do not risk overflow because of NaN */ + difngsttax[vanclocnnd + 1] = 0.0F; + + if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { /* Perform initial diffusion (and build communication structures) */ + errorPrint ("vdgraphSeparateDf: cannot propagate diffusion data (1)"); + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + return (1); + } + + ovflval = 0; + cdifval = paraptr->cdifval; + cremval = paraptr->cremval; + edgegsttax = grafptr->s.edgegsttax; + for (passnum = 0; ; ) { /* For all passes */ + if (ovflval == 0) { /* If no overflow occured */ + Gnum vertlocnum; + float * diftgsttax; /* Temporary swap value */ + float veloval; + + veloval = 1.0F; /* Assume no vertex loads */ + for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { + Gnum edgelocnum; + Gnum edgelocnnd; + float diffval; + + diffval = 0.0F; + for (edgelocnum = grafptr->s.vertloctax[vertlocnum], edgelocnnd = grafptr->s.vendloctax[vertlocnum]; + edgelocnum < edgelocnnd; edgelocnum ++) + diffval += difogsttax[edgegsttax[edgelocnum]]; + + diffval *= cdifval; + diffval += (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; + + if (grafptr->s.veloloctax != NULL) + veloval = (float) grafptr->s.veloloctax[vertlocnum]; + if (diffval >= 0.0F) { + diffval = (diffval - veloval) * ielsloctax[vertlocnum]; + if (diffval <= 0.0F) + diffval = +VDGRAPHSEPARATEDFEPSILON; + } + else { + diffval = (diffval + veloval) * ielsloctax[vertlocnum]; + if (diffval >= 0.0F) + diffval = -VDGRAPHSEPARATEDFEPSILON; + } + if (isnan (diffval)) { /* If overflow occured */ + ovflval = 1; /* We are in state of overflow */ + goto abort; /* Exit this loop without swapping arrays */ + } + difngsttax[vertlocnum] = diffval; + } + for ( ; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { /* For the two local anchor vertices */ + Gnum edgelocnum; + Gnum edgelocnnd; + float diffval; + + diffval = 0.0F; + edgelocnum = grafptr->s.vertloctax[vertlocnum] + grafptr->s.procglbnbr - 1; /* Skip links to other anchors */ + edgelocnnd = grafptr->s.vendloctax[vertlocnum]; + if (edgelocnum == edgelocnnd) /* If isolated anchor */ + continue; /* Barrel is empty */ + + for ( ; edgelocnum < edgelocnnd; edgelocnum ++) + diffval += difogsttax[edgegsttax[edgelocnum]]; + + diffval *= cdifval; + diffval += vanclocval[vertlocnum - vanclocnnd] + (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; + if (diffval >= 0.0F) { + diffval = (diffval - valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; + if (diffval <= 0.0F) + diffval = +VDGRAPHSEPARATEDFEPSILON; + } + else { + diffval = (diffval + valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; + if (diffval >= 0.0F) + diffval = -VDGRAPHSEPARATEDFEPSILON; + } + if (isnan (diffval)) { /* If overflow occured */ + ovflval = 1; /* We are in state of overflow */ + goto abort; /* Exit this loop without swapping arrays */ + } + difngsttax[vertlocnum] = diffval; + } + + diftgsttax = (float *) difngsttax; /* Swap old and new diffusion arrays */ + difngsttax = (float *) difogsttax; /* Casts to prevent IBM compiler from yelling */ + difogsttax = (float *) diftgsttax; + } +abort : /* If overflow occured, resume here */ + if (++ passnum >= paraptr->passnbr) /* If maximum number of passes reached */ + break; /* Exit main loop */ + + if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { + errorPrint ("vdgraphSeparateDf: cannot propagate diffusion data (2)"); + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + return (1); + } + } + + for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) /* Pre-set parts without separator */ + grafptr->partgsttax[vertlocnum] = (difogsttax[vertlocnum] <= 0.0F) ? 0 : 1; + grafptr->partgsttax[vanclocnnd] = 0; /* Set up parts in case anchors are isolated */ + grafptr->partgsttax[vanclocnnd + 1] = 1; + + if (grafptr->s.veloloctax != NULL) { + velolocbax = grafptr->s.veloloctax; + velolocmsk = ~((Gnum) 0); + } + else { + velolocbax = &vdgraphseparatedfloadone; + velolocmsk = 0; + } + + memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ + + if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (grafptr->partgsttax + grafptr->s.baseval), GRAPHPART_MPI) != 0) { + errorPrint ("vdgraphSeparateDf: cannot propagate part data"); + return (1); + } + + for (vertlocnum = grafptr->s.baseval, fronlocnum = complocsize1 = complocload1 = complocload2 = 0; + vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { + Gnum partval; + GraphPart partend; + Gnum veloval; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (grafptr->partgsttax[vertlocnum] > 1) { + errorPrint ("vdgraphSeparateDf: internal error (2)"); + break; /* Do not break upcoming collective communications */ + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + partend = grafptr->partgsttax[vertlocnum] ^ 1; + partval = (Gnum) grafptr->partgsttax[vertlocnum]; + veloval = velolocbax[vertlocnum & velolocmsk]; + complocsize1 += partval; /* Here, part is 0 or 1 only */ + complocload1 += partval * veloval; + if (partval == psepval) { /* Only vertices of aggregated part can be in separator */ + Gnum edgelocnum; + + for (edgelocnum = grafptr->s.vertloctax[vertlocnum]; + edgelocnum < grafptr->s.vendloctax[vertlocnum]; edgelocnum ++) { +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (grafptr->partgsttax[edgegsttax[edgelocnum]] > 2) { + errorPrint ("vdgraphSeparateDf: internal error (3)"); + vertlocnum = grafptr->s.vertlocnnd; + break; /* Do not break upcoming collective communications */ + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + if (grafptr->partgsttax[edgegsttax[edgelocnum]] == partend) { /* If end vertex is in other part (and not in separator) */ + grafptr->fronloctab[fronlocnum ++] = vertlocnum; /* Record it as member of the separator */ + grafptr->partgsttax[vertlocnum] = 2; + complocload2 += veloval; + break; /* No need to go further */ + } + } + } + } + grafptr->complocload[0] = grafptr->s.velolocsum - complocload1; + grafptr->complocload[1] = complocload1; + grafptr->complocload[2] = complocload2; + grafptr->complocload[psepval] -= complocload2; + grafptr->complocsize[0] = grafptr->s.vertlocnbr - complocsize1; + grafptr->complocsize[1] = complocsize1; + grafptr->complocsize[psepval] -= fronlocnum; + grafptr->complocsize[2] = fronlocnum; + + if (MPI_Allreduce (&grafptr->complocload[0], &grafptr->compglbload[0], 6, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { /* TRICK: all arrays */ + errorPrint ("vdgraphSeparateDf: communication error (2)"); + return (1); + } + grafptr->compglbloaddlt = grafptr->compglbload[0] - grafptr->compglbload[1]; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (vdgraphCheck (grafptr) != 0) { + errorPrint ("vdgraphSeparateDf: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + +if (grafptr->s.proclocnum == 0) +fprintf (stderr, "BROL " GNUMSTRING "," GNUMSTRING "," GNUMSTRING "(" GNUMSTRING ")\n", + (Gnum) grafptr->compglbload[0], + (Gnum) grafptr->compglbload[1], + (Gnum) grafptr->compglbload[2], + (Gnum) grafptr->compglbloaddlt); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_df.h b/scotch_6.0.3/src/libscotch/vdgraph_separate_df.h new file mode 100644 index 00000000..4c430ae0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_df.h @@ -0,0 +1,83 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_df.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the parallel diffusion separation **/ +/** routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.1 : from : 05 nov 2007 **/ +/** to : 07 nov 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Small non-zero float value. +*/ + +#define VDGRAPHSEPARATEDFEPSILON (1.0F / (float) (GNUMMAX)) + +/*+ Sign masking operator. +*/ + +#define VDGRAPHSEPARATEDFGNUMSGNMSK(i) ((Gnum) 0 - (((Gunum) (i)) >> (sizeof (Gnum) * 8 - 1))) + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VdgraphSeparateDfParam_ { + INT partval; /*+ Part to aggregate to separator +*/ + INT passnbr; /*+ Number of passes to do +*/ + double cdifval; /*+ Coefficient of diffused load +*/ + double cremval; /*+ Coefficient of remaining load +*/ + double deltval; /*+ Maximum imbalance ratio +*/ +} VdgraphSeparateDfParam; + +/* +** The function prototypes. +*/ + +#ifndef VDGRAPH_SEPARATE_DF +#define static +#endif + +int vdgraphSeparateDf (Vdgraph * const, const VdgraphSeparateDfParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_ml.c b/scotch_6.0.3/src/libscotch/vdgraph_separate_ml.c new file mode 100644 index 00000000..4170669c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_ml.c @@ -0,0 +1,827 @@ +/* Copyright 2007-2010,2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_ml.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : This module contains the multi-level **/ +/** separation strategy. **/ +/** **/ +/** DATES : # Version 5.0 : from : 07 mar 2006 **/ +/** to : 01 mar 2008 **/ +/** # Version 5.1 : from : 14 dec 2008 **/ +/** to : 26 aug 2010 **/ +/** # Version 6.0 : from : 11 sep 2012 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH_SEPARATE_ML + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "vdgraph.h" +#include "vdgraph_separate_ml.h" +#include "vdgraph_separate_st.h" + +/*********************************************/ +/* */ +/* The coarsening and uncoarsening routines. */ +/* */ +/*********************************************/ + +/* This routine builds a coarser graph from the +** Dgraph that is given on input. The coarser +** Dgraphs differ at this stage from classical +** active Dgraphs as their internal gains are not +** yet computed. +** It returns: +** - 0 : if the coarse Dgraph has been built. +** - 1 : if threshold achieved or on error. +*/ + +static +int +vdgraphSeparateMlCoarsen ( +Vdgraph * restrict const finegrafptr, /*+ Finer graph +*/ +Vdgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ +DgraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to based multinode table to build +*/ +const VdgraphSeparateMlParam * const paraptr) /*+ Method parameters +*/ +{ + int foldval; + + switch (paraptr->foldval) { + case 0 : + foldval = DGRAPHCOARSENNONE; + break; + case 1 : + foldval = DGRAPHCOARSENFOLD; + break; + case 2 : + foldval = DGRAPHCOARSENFOLDDUP; + break; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + default : + errorPrint ("vdgraphSeparateMlCoarsen: invalid parameter"); + return (1); +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + } + if ((finegrafptr->s.vertglbnbr / finegrafptr->s.procglbnbr) > paraptr->foldmax) /* If no need to fold */ + foldval = DGRAPHCOARSENNONE; + + *coarmultptr = NULL; /* Let the routine create the multinode array */ + dgraphInit (&coargrafptr->s, finegrafptr->s.proccomm); /* Re-use fine graph communicator */ + if (dgraphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, paraptr->passnbr, + paraptr->coarnbr, paraptr->coarrat, foldval) != 0) + return (1); /* Return if coarsening failed */ + + coargrafptr->fronloctab = NULL; + coargrafptr->partgsttax = NULL; /* Do not allocate partition data yet */ + + if (coargrafptr->s.procglbnbr == 0) { /* Not a owner graph */ + coargrafptr->s.vertlocnbr = 0; /* Set it to zero for vrcvdattab allocation */ + return (0); + } + + coargrafptr->levlnum = finegrafptr->levlnum + 1; /* Graph level is coarsening level */ + if (coargrafptr->s.vertlocnbr <= finegrafptr->s.vertlocnbr) /* If (folded) coarser graph is smaller */ + coargrafptr->fronloctab = finegrafptr->fronloctab; /* Re-use frontier array for coarser graph */ + else { /* Else allocate new private frontier array */ + if ((coargrafptr->fronloctab = memAlloc (coargrafptr->s.vertlocnbr * sizeof (Gnum))) == NULL) { + errorPrint ("vdgraphSeparateMlCoarsen: out of memory"); + dgraphExit (&coargrafptr->s); /* Only free Dgraph since fronloctab not allocated */ + memFree (*coarmultptr); /* Free un-based array */ + return (1); + } + } + + *coarmultptr -= coargrafptr->s.baseval; /* Base the multinode array */ + + return (0); +} + +/* This routine is the reduction-loc operator which +** returns in inout[2] the rank of the process which +** holds the best partition. +** It returns: +** - void : in all cases. +*/ + +static +void +vdgraphSeparateMlOpBest ( +const Gnum * const in, /* First operand */ +Gnum * const inout, /* Second and output operand */ +const int * const len, /* Number of instances ; should be 1, not used */ +const MPI_Datatype * const typedat) /* MPI datatype ; not used */ +{ + inout[5] |= in[5]; /* Memory error flag */ + + if (inout[0] == 1) { /* Handle cases when at least one of them is erroneous */ + if (in[0] == 1) { + if (inout[1] > in[1]) { /* To enforce commutativity, always keep smallest process number */ + inout[1] = in[1]; + inout[2] = in[2]; + } + return; + } + + inout[0] = in[0]; /* Validity flag */ + inout[1] = in[1]; /* Lead process rank */ + inout[2] = in[2]; /* Lead process color */ + inout[3] = in[3]; /* Separator size */ + inout[4] = in[4]; /* Parts imbalance */ + return; + } + else if (in[0] == 1) + return; + + if ((in[3] < inout[3]) || /* Select best partition */ + ((in[3] == inout[3]) && + ((in[4] < inout[4]) || + ((in[4] == inout[4]) && (in[1] < inout[1]))))) { + inout[1] = in[1]; + inout[2] = in[2]; + inout[3] = in[3]; + inout[4] = in[4]; + } +} + +/* This routine packs the neighbor data to be sent +** to one of the neighbors by part number. +** It returns: +** - void : in all cases. +*/ + +static +void +vdgraphSeparateMlPack ( +Gnum * restrict const dataloctab, +const Gnum datalocidx, +Gnum * restrict ssndcnttab) +{ + Gnum finevertsndnbr0; + Gnum finevertsndnbr1; + Gnum finevertsndnbr2; + Gnum datalocnbr; + + finevertsndnbr0 = ssndcnttab[0]; + finevertsndnbr1 = ssndcnttab[1]; + finevertsndnbr2 = ssndcnttab[2]; + datalocnbr = finevertsndnbr0 + finevertsndnbr1 + finevertsndnbr2; + + if (datalocnbr <= datalocidx) { /* If arrays do not overlap */ + Gnum * restrict datadsttab = dataloctab + datalocidx; + const Gnum * restrict const datasrctab = dataloctab + datalocidx * 2; + Gnum datasrcnum; + Gnum partidxtab[3]; + + partidxtab[0] = 0; + partidxtab[1] = finevertsndnbr0; + partidxtab[2] = finevertsndnbr0 + finevertsndnbr1; + for (datasrcnum = 0, datalocnbr <<= 1; datasrcnum < datalocnbr; ) { /* Work on pairs of Gnum's */ + Gnum finevertglbnum; + Gnum finepartval; + + finevertglbnum = datasrctab[datasrcnum ++]; + finepartval = datasrctab[datasrcnum ++]; + datadsttab[partidxtab[finepartval] ++] = finevertglbnum; + } + } + else { /* Arrays do overlap */ + Gnum datadstnum; + Gnum datasrcnum; + Gnum datasrcnnd; + Gnum datasrcnxt; + + datadstnum = datalocidx; + for (datasrcnum = datalocidx << 1, datasrcnnd = datasrcnum + (finevertsndnbr0 << 1), datasrcnxt = datasrcnnd; /* Work on pairs of Gnum's */ + datasrcnum < datasrcnnd; ) { + Gnum finevertglbnum; + Gnum finepartval; + + finevertglbnum = dataloctab[datasrcnum ++]; + finepartval = dataloctab[datasrcnum ++]; + if (finepartval != 0) { + Gnum finevertglbtmp; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if ((finepartval < 1) || (finepartval > 2)) { + errorPrint ("vdgraphSeparateMlPack: internal error (1)"); + return; + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + while (dataloctab[datasrcnxt + 1] != 0) { /* Find first vertex of part zero in next block */ + datasrcnxt += 2; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (datasrcnxt >= ((datalocidx + datalocnbr) << 1)) { + errorPrint ("vdgraphSeparateMlPack: internal error (2)"); + return; + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + } + + finevertglbtmp = dataloctab[datasrcnxt]; + dataloctab[datasrcnxt ++] = finevertglbnum; + dataloctab[datasrcnxt ++] = finepartval; + finevertglbnum = finevertglbtmp; + } + dataloctab[datadstnum ++] = finevertglbnum; + } + + for (datasrcnnd += finevertsndnbr1 << 1, datasrcnxt = datasrcnnd; /* Work on pairs of Gnum's */ + datasrcnum < datasrcnnd; ) { + Gnum finevertglbnum; + Gnum finepartval; + + finevertglbnum = dataloctab[datasrcnum ++]; + finepartval = dataloctab[datasrcnum ++]; + if (finepartval != 1) { + Gnum finevertglbtmp; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (finepartval != 2) { + errorPrint ("vdgraphSeparateMlPack: internal error (3)"); + return; + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + while (dataloctab[datasrcnxt + 1] != 1) { /* Find first vertex of part one in next block */ + datasrcnxt += 2; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (datasrcnxt >= ((datalocidx + datalocnbr) << 1)) { + errorPrint ("vdgraphSeparateMlPack: internal error (4)"); + return; + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + } + + finevertglbtmp = dataloctab[datasrcnxt]; + dataloctab[datasrcnxt ++] = finevertglbnum; + dataloctab[datasrcnxt ++] = finepartval; + finevertglbnum = finevertglbtmp; + } + dataloctab[datadstnum ++] = finevertglbnum; + } + + for (datasrcnnd += finevertsndnbr2 << 1; datasrcnum < datasrcnnd; ) { /* Work on pairs of Gnum's */ + Gnum finevertglbnum; + + finevertglbnum = dataloctab[datasrcnum]; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (dataloctab[datasrcnum + 1] != 2) { + errorPrint ("vdgraphSeparateMlPack: internal error (5)"); + return; + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + datasrcnum += 2; + dataloctab[datadstnum ++] = finevertglbnum; + } + } +} + +/* This routine propagates the separation of the +** coarser graph back to the finer graph, according +** to the multinode table of collapsed vertices. +** After the separation is propagated, it finishes +** to compute the parameters of the finer graph that +** were not computed at the coarsening stage. +** It returns: +** - 0 : if coarse graph data has been propagated to the fine graph. +** - !0 : on error. +*/ + +static +int +vdgraphSeparateMlUncoarsen ( +Vdgraph * restrict finegrafptr, /*+ Finer graph +*/ +const Vdgraph * restrict const coargrafptr, /*+ Coarser graph +*/ +const DgraphCoarsenMulti * restrict const coarmulttax) /*+ Based multinode array +*/ +{ + Gnum coarvertnum; + Gnum finevertlocadj; + Gnum finecomplocload0; + Gnum finecomplocload2; + Gnum finecomplocsize1; + Gnum finecomplocsize2; + Gnum * restrict srcvdattab; + Gnum * ssnddattab; /* TRICK: holds vrcvcnttab, vsnddsptab, vrcvdsptab */ + Gnum * vrcvdattab; /* TRICK: overlaps with vsnddattab before packing [norestrict:async] */ + Gnum * vsnddattab; /* [norestrict:async] */ + int * vrcvcnttab; + int * vsndcnttab; + int * vrcvdsptab; + int * vsnddsptab; + int vrcvdspnum; + int vsnddspnum; + Gnum vrcvdatnum; + MPI_Datatype besttypedat; /* Data type for finding best bipartition */ + MPI_Op bestoperdat; /* Handle of MPI operator for finding best bipartition */ + Gnum reduloctab[6]; + Gnum reduglbtab[6]; + int procnum; + const Gnum * restrict fineveloglbtax; + GraphPart * restrict finepartglbtax; + + Gnum * restrict const finefronloctab = finegrafptr->fronloctab; + + reduloctab[5] = 0; /* Assume everything is fine */ + if (finegrafptr->partgsttax == NULL) { /* If partition array not yet allocated */ + if (dgraphGhst (&finegrafptr->s) != 0) { /* Create ghost edge array and compute vertgstnbr */ + errorPrint ("vdgraphSeparateMlUncoarsen: cannot compute ghost edge array"); + reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ + } + else if ((finegrafptr->partgsttax = (GraphPart *) memAlloc (finegrafptr->s.vertgstnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("vdgraphSeparateMlUncoarsen: out of memory (1)"); + reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ + } + else + finegrafptr->partgsttax -= finegrafptr->s.baseval; + } + + if (coargrafptr == NULL) { /* If coarser graph not provided */ +#ifdef SCOTCH_DEBUG_BDGRAPH1 /* Communication cannot be overlapped by a useful one */ + if (MPI_Allreduce (&reduloctab[5], &reduglbtab[5], 1, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateMlUncoarsen: communication error (1)"); + return (1); + } +#else /* SCOTCH_DEBUG_BDGRAPH1 */ + reduglbtab[5] = reduloctab[5]; +#endif /* SCOTCH_DEBUG_BDGRAPH1 */ + if (reduglbtab[5] != 0) + return (1); + + vdgraphZero (finegrafptr); /* Assign all vertices to part 0 */ + + return (0); + } + + if (memAllocGroup ((void **) (void *) + &vsndcnttab, (size_t) (finegrafptr->s.procglbnbr * sizeof (int)), /* TRICK: srcvdattab after ssnddattab, after vsndcnttab */ + &ssnddattab, (size_t) (finegrafptr->s.procglbnbr * 3 * sizeof (Gnum)), /* TRICK: ssnddattab is vrcvcnttab, vsnddsptab, vrcvdsptab */ + &srcvdattab, (size_t) (finegrafptr->s.procglbnbr * 3 * sizeof (Gnum)), + &vsnddattab, (size_t) (coargrafptr->s.vertlocnbr * 2 * sizeof (Gnum)), /* TRICK: vsnddattab overlaps with vrcvdattab */ + &vrcvdattab, (size_t) (MAX ((coargrafptr->s.vertlocnbr * 2), finegrafptr->s.vertlocnbr) * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("vdgraphSeparateMlUncoarsen: out of memory (2)"); + reduloctab[5] = 1; + } + + if (coargrafptr->s.procglbnbr <= 0) { /* If unused folded coargrafptr */ + reduloctab[0] = 1; /* Set it as invalid */ + reduloctab[1] = 0; /* Useless rank */ + reduloctab[2] = 1; /* Color is not the one of folded */ + reduloctab[3] = /* Prevent Valgrind from yelling */ + reduloctab[4] = 0; + } + else { + reduloctab[0] = ((coargrafptr->compglbsize[0] == 0) || /* Empty separated parts are deemed invalid */ + (coargrafptr->compglbsize[1] == 0)) ? 1 : 0; + reduloctab[1] = finegrafptr->s.proclocnum; /* Set rank and color key according to coarse graph (sub)communicator */ + reduloctab[2] = finegrafptr->s.prockeyval; + reduloctab[3] = coargrafptr->compglbsize[2]; + reduloctab[4] = coargrafptr->compglbloaddlt; + } + + if ((MPI_Type_contiguous (6, GNUM_MPI, &besttypedat) != MPI_SUCCESS) || + (MPI_Type_commit (&besttypedat) != MPI_SUCCESS) || + (MPI_Op_create ((MPI_User_function *) vdgraphSeparateMlOpBest, 1, &bestoperdat) != MPI_SUCCESS)) { + errorPrint ("vdgraphSeparateMlUncoarsen: communication error (2)"); + return (1); + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 1, besttypedat, bestoperdat, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateMlUncoarsen: communication error (3)"); + return (1); + } + + if ((MPI_Op_free (&bestoperdat) != MPI_SUCCESS) || + (MPI_Type_free (&besttypedat) != MPI_SUCCESS)) { + errorPrint ("vdgraphSeparateMlUncoarsen: communication error (4)"); + return (1); + } + + if (reduglbtab[5] != 0) { /* If memory error, return */ + if (vsndcnttab != NULL) /* Partgsttax will be freed at the above level */ + memFree (vsndcnttab); + return (1); + } + + if (reduglbtab[0] == 1) { /* If all possible partitions are invalid */ +#ifdef SCOTCH_DEBUG_BDGRAPH2 + errorPrintW ("vdgraphSeparateMlUncoarsen: no valid partition"); +#endif /* SCOTCH_DEBUG_BDGRAPH2 */ + return (1); /* All invalid partitions will lead to low method be applied at upper level */ + } + + finevertlocadj = finegrafptr->s.procvrttab[finegrafptr->s.proclocnum] - finegrafptr->s.baseval; + fineveloglbtax = (finegrafptr->s.veloloctax != NULL) ? (finegrafptr->s.veloloctax - finevertlocadj) : NULL; /* Array can be indexed with global vertex numbers */ + finepartglbtax = finegrafptr->partgsttax - finevertlocadj; + + finegrafptr->complocload[0] = + finegrafptr->complocload[1] = + finegrafptr->complocload[2] = + finegrafptr->complocsize[0] = + finegrafptr->complocsize[1] = + finegrafptr->complocsize[2] = 0; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + memSet (finegrafptr->partgsttax + finegrafptr->s.baseval, 3, finegrafptr->s.vertgstnbr * sizeof (GraphPart)); /* Mark all vertices as unvisited */ +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + + memSet (vsndcnttab, 0, ((byte *) srcvdattab) - ((byte *) vsndcnttab)); /* TRICK: Assume process has nothing to send in vsndcnttab and ssnddattab */ + + if (reduglbtab[2] == (Gnum) coargrafptr->s.prockeyval) { /* If we belong to the group of the lead process, we must browse and send local data */ + Gnum fineveloval; + Gnum finevertsndnbr1; + Gnum finevertsndnbr2; + Gnum finevertglbmin; + Gnum finevertglbmax; + Gnum finevertglbnnd; + Gnum vsnddatnbr; + Gnum vsnddatnum; + Gnum vsnddattmp; + + const GraphPart * restrict const coarpartgsttax = coargrafptr->partgsttax; + + fineveloval = 1; /* Assume no vertex loads */ + finevertglbmin = finegrafptr->s.procvrttab[finegrafptr->s.proclocnum]; + finevertglbmax = finegrafptr->s.procvrttab[finegrafptr->s.proclocnum + 1]; + finecomplocload0 = + finecomplocload2 = + finecomplocsize1 = + finecomplocsize2 = 0; + for (coarvertnum = coargrafptr->s.baseval, vsnddatnbr = 0; + coarvertnum < coargrafptr->s.vertlocnnd; coarvertnum ++) { + Gnum finevertglbnum; + GraphPart coarpartval; + + coarpartval = coarpartgsttax[coarvertnum]; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if ((coarpartval < 0) || (coarpartval > 2)) { + errorPrint ("vdgraphSeparateMlUncoarsen: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + + finevertglbnum = coarmulttax[coarvertnum].vertglbnum[0]; + while (1) { /* Loop on both fine vertices of multinode */ + Gnum finepartval; + + finepartval = (Gnum) coarpartval; + if ((finevertglbnum >= finevertglbmin) && (finevertglbnum < finevertglbmax)) { /* Vertex is a local one */ +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (finepartglbtax[finevertglbnum] != 3) { + errorPrint ("vdgraphSeparateMlUncoarsen: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + finepartglbtax[finevertglbnum] = coarpartval; + + finecomplocsize1 += finepartval & 1; /* One extra vertex created in part 1 if (coarpartval == 1) */ + if (fineveloglbtax != NULL) + fineveloval = fineveloglbtax[finevertglbnum]; + if (coarpartval == 2) { + finecomplocload2 += fineveloval; + finefronloctab[finecomplocsize2 ++] = finevertglbnum - finevertlocadj; + } + else + finecomplocload0 += fineveloval & (finepartval - 1); + } + else { /* Non local vertex */ + vsnddattab[vsnddatnbr ++] = finevertglbnum; /* Store index and part */ + vsnddattab[vsnddatnbr ++] = finepartval; + } + + if (finevertglbnum == coarmulttax[coarvertnum].vertglbnum[1]) /* If single-vertex multinode or both vertices processed */ + break; + finevertglbnum = coarmulttax[coarvertnum].vertglbnum[1]; /* Process second multinode */ + } + } + + finegrafptr->complocload[0] = finecomplocload0; /* Account for local vertices already processed */ + finegrafptr->complocload[2] = finecomplocload2; + finegrafptr->complocsize[1] = finecomplocsize1; + finegrafptr->complocsize[2] = finecomplocsize2; + + intSort2asc1 ((void *) vsnddattab, vsnddatnbr >> 1); /* Sort vertices to send by ascending global numbers */ + + finevertsndnbr1 = + finevertsndnbr2 = 0; + for (vsnddatnum = vsnddattmp = 0, procnum = 0, finevertglbnnd = finegrafptr->s.procvrttab[1]; + vsnddatnum < vsnddatnbr; ) { + Gnum finevertglbnum; + Gnum finepartval; + + finevertglbnum = vsnddattab[vsnddatnum]; + finepartval = vsnddattab[vsnddatnum + 1]; + if (finevertglbnum >= finevertglbnnd) { + Gnum finevertsndnbr; + + finevertsndnbr = (vsnddatnum - vsnddattmp) >> 1; + finevertsndnbr2 >>= 1; + vsndcnttab[procnum] = (int) finevertsndnbr; + ssnddattab[3 * procnum] = finevertsndnbr - finevertsndnbr1 - finevertsndnbr2; + ssnddattab[3 * procnum + 1] = finevertsndnbr1; + ssnddattab[3 * procnum + 2] = finevertsndnbr2; + vdgraphSeparateMlPack (vsnddattab, vsnddattmp >> 1, ssnddattab + (3 * procnum)); + + do + finevertglbnnd = finegrafptr->s.procvrttab[(++ procnum) + 1]; + while (finevertglbnum >= finevertglbnnd); + + vsnddattmp = vsnddatnum; /* Set startpoint for new neighbor */ + finevertsndnbr1 = + finevertsndnbr2 = 0; + } + + vsnddatnum += 2; + finevertsndnbr1 += finepartval & 1; /* Count number of vertices in part 1 */ + finevertsndnbr2 += finepartval & 2; /* Count twice number of vertices in part 2 */ + } + finevertsndnbr2 >>= 1; /* Complete data for last receiver process */ + vsndcnttab[procnum] = (int) ((vsnddatnum - vsnddattmp) >> 1); + ssnddattab[3 * procnum] = ((vsnddatnum - vsnddattmp) >> 1) - finevertsndnbr1 - finevertsndnbr2; + ssnddattab[3 * procnum + 1] = finevertsndnbr1; + ssnddattab[3 * procnum + 2] = finevertsndnbr2; + vdgraphSeparateMlPack (vsnddattab, (Gnum) vsnddattmp >> 1, ssnddattab + (3 * procnum)); + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if ((ssnddattab[3 * finegrafptr->s.proclocnum] != 0) || /* One should never send something to itself */ + (ssnddattab[3 * finegrafptr->s.proclocnum + 1] != 0) || + (ssnddattab[3 * finegrafptr->s.proclocnum + 2] != 0)) { + errorPrint ("vdgraphSeparateMlUncoarsen: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + } + + if (MPI_Alltoall (ssnddattab, 3, GNUM_MPI, srcvdattab, 3, GNUM_MPI, finegrafptr->s.proccomm) != MPI_SUCCESS) { /* Exchange sizes */ + errorPrint ("vdgraphSeparateMlUncoarsen: communication error (2)"); + return (1); + } + + vrcvcnttab = (int *) ssnddattab; /* TRICK: re-use ssnddattab */ + vsnddsptab = vrcvcnttab + finegrafptr->s.procglbnbr; + vrcvdsptab = vrcvcnttab + finegrafptr->s.procglbnbr * 2; + for (procnum = 0, vsnddspnum = vrcvdspnum = 0; procnum < finegrafptr->s.procglbnbr; procnum ++) { /* Compute size of data to exchange */ + vrcvcnttab[procnum] = (int) (srcvdattab[3 * procnum] + srcvdattab[3 * procnum + 1] + srcvdattab[3 * procnum + 2]); + vrcvdsptab[procnum] = vrcvdspnum; + vsnddsptab[procnum] = vsnddspnum; + vrcvdspnum += vrcvcnttab[procnum]; + vsnddspnum += vsndcnttab[procnum]; + } + + if (MPI_Alltoallv (vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, /* Exchange data */ + vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateMlUncoarsen: communication error (3)"); + return (1); + } + + finecomplocload0 = finegrafptr->complocload[0]; + finecomplocload2 = finegrafptr->complocload[2]; + finecomplocsize1 = finegrafptr->complocsize[1]; + finecomplocsize2 = finegrafptr->complocsize[2]; + for (procnum = 0, vrcvdatnum = 0; /* Process partition data per process number */ + procnum < finegrafptr->s.procglbnbr; procnum ++) { + Gnum vrcvdatnnd; + + vrcvdatnnd = vrcvdatnum + srcvdattab[3 * procnum]; + if (fineveloglbtax != NULL) { + for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { + Gnum finevertglbnum; + + finevertglbnum = vrcvdattab[vrcvdatnum]; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (finepartglbtax[finevertglbnum] != 3) { + errorPrint ("vdgraphSeparateMlUncoarsen: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + finepartglbtax[finevertglbnum] = 0; + finecomplocload0 += fineveloglbtax[finevertglbnum]; + } + } + else { + finecomplocload0 += srcvdattab[3 * procnum]; + for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (finepartglbtax[vrcvdattab[vrcvdatnum]] != 3) { + errorPrint ("vdgraphSeparateMlUncoarsen: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + finepartglbtax[vrcvdattab[vrcvdatnum]] = 0; + } + } + + finecomplocsize1 += srcvdattab[3 * procnum + 1]; + vrcvdatnnd = vrcvdatnum + srcvdattab[3 * procnum + 1]; + for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (finepartglbtax[vrcvdattab[vrcvdatnum]] != 3) { + errorPrint ("vdgraphSeparateMlUncoarsen: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + finepartglbtax[vrcvdattab[vrcvdatnum]] = 1; + } + + vrcvdatnnd = vrcvdatnum + srcvdattab[3 * procnum + 2]; + if (fineveloglbtax != NULL) { + for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { + Gnum finevertglbnum; + + finevertglbnum = vrcvdattab[vrcvdatnum]; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (finepartglbtax[finevertglbnum] != 3) { + errorPrint ("vdgraphSeparateMlUncoarsen: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + finefronloctab[finecomplocsize2 ++] = finevertglbnum - finevertlocadj; + finepartglbtax[finevertglbnum] = 2; + finecomplocload2 += fineveloglbtax[finevertglbnum]; + } + } + else { + finecomplocload2 += srcvdattab[3 * procnum + 2]; + for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { + Gnum finevertglbnum; + + finevertglbnum = vrcvdattab[vrcvdatnum]; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (finepartglbtax[finevertglbnum] != 3) { + errorPrint ("vdgraphSeparateMlUncoarsen: internal error (9)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + finefronloctab[finecomplocsize2 ++] = finevertglbnum - finevertlocadj; + finepartglbtax[finevertglbnum] = 2; + } + } + } + + finegrafptr->complocload[0] = finecomplocload0; + finegrafptr->complocload[1] = finegrafptr->s.velolocsum - finecomplocload0 - finecomplocload2; + finegrafptr->complocload[2] = finecomplocload2; + finegrafptr->complocsize[0] = finegrafptr->s.vertlocnbr - finecomplocsize1 - finecomplocsize2; + finegrafptr->complocsize[1] = finecomplocsize1; + finegrafptr->complocsize[2] = finecomplocsize2; + + memFree (vsndcnttab); /* Free group leader */ + + reduloctab[0] = finegrafptr->complocload[0]; + reduloctab[1] = finegrafptr->complocload[1]; + reduloctab[2] = finegrafptr->complocload[2]; + reduloctab[3] = finegrafptr->complocsize[0]; + reduloctab[4] = finegrafptr->complocsize[1]; + reduloctab[5] = finegrafptr->complocsize[2]; + + if (MPI_Allreduce (reduloctab, reduglbtab, 6, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateMlUncoarsen: communication error (4)"); + return (1); + } + + finegrafptr->compglbload[0] = reduglbtab[0]; + finegrafptr->compglbload[1] = reduglbtab[1]; + finegrafptr->compglbload[2] = reduglbtab[2]; + finegrafptr->compglbsize[0] = reduglbtab[3]; + finegrafptr->compglbsize[1] = reduglbtab[4]; + finegrafptr->compglbsize[2] = reduglbtab[5]; + finegrafptr->compglbloaddlt = reduglbtab[0] - reduglbtab[1]; + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (vdgraphCheck (finegrafptr) != 0) { + errorPrint ("vdgraphSeparateMlUncoarsen: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + + return (0); +} + +/* This routine recursively performs the +** separation recursion. +** It returns: +** - 0 : if separator could be computed. +** - !0 : on error. +*/ + +static +int +vdgraphSeparateMl2 ( +Vdgraph * restrict const grafptr, /* Vertex-separation graph */ +const VdgraphSeparateMlParam * const paraptr) /* Method parameters */ +{ + Vdgraph coargrafdat; + DgraphCoarsenMulti * restrict coarmulttax; + int o; + + if (grafptr->s.procglbnbr <= 1) { /* No need to stay parallel */ + if (((o = vdgraphSeparateMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ + ((o = vdgraphSeparateSt (grafptr, paraptr->stratseq)) != 0)) { +#ifdef SCOTCH_DEBUG_VDGRAPH2 + errorPrintW ("vdgraphSeparateMl2: cannot apply sequential strategy"); +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + } + return (o); + } + + coarmulttax = NULL; /* Assume multinode array is not allocated */ + if (vdgraphSeparateMlCoarsen (grafptr, &coargrafdat, &coarmulttax, paraptr) == 0) { + o = (coargrafdat.s.procglbnbr == 0) ? 0 : vdgraphSeparateMl2 (&coargrafdat, paraptr); /* Apply recursion on coarsened graph if it exists */ + + if ((o == 0) && + ((o = vdgraphSeparateMlUncoarsen (grafptr, &coargrafdat, coarmulttax)) == 0) && + ((o = vdgraphSeparateSt (grafptr, paraptr->stratasc)) != 0)) { /* Apply ascending strategy if uncoarsening worked */ +#ifdef SCOTCH_DEBUG_VDGRAPH2 + errorPrintW ("vdgraphSeparateMl2: cannot apply ascending strategy"); +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + } + + if (coargrafdat.fronloctab == grafptr->fronloctab) /* If coarse graph shares fronloctab with fine graph */ + coargrafdat.fronloctab = NULL; /* Prevent fronloctab of fine graph from being freed */ + vdgraphExit (&coargrafdat); + + if (coarmulttax != NULL) /* If multinode array has been allocated */ + memFree (coarmulttax + grafptr->s.baseval); /* Free array */ + + if (o == 0) /* If multi-level failed, apply low strategy as fallback */ + return (o); + } + + if (((o = vdgraphSeparateMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ + ((o = vdgraphSeparateSt (grafptr, paraptr->stratlow)) != 0)) { /* Apply low strategy */ +#ifdef SCOTCH_DEBUG_VDGRAPH2 + errorPrintW ("vdgraphSeparateMl2: cannot apply low strategy"); +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + } + + return (o); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the muti-level separation. +** It returns: +** - 0 : if separator could be computed. +** - 1 : on error. +*/ + +int +vdgraphSeparateMl ( +Vdgraph * const grafptr, /*+ Vertex-separation graph +*/ +const VdgraphSeparateMlParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum levlnum; /* Save value for graph level */ + int o; + + levlnum = grafptr->levlnum; /* Save graph level */ + grafptr->levlnum = 0; /* Initialize coarsening level */ + o = vdgraphSeparateMl2 (grafptr, paraptr); /* Perform multi-level separation */ + grafptr->levlnum = levlnum; /* Restore graph level */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_ml.h b/scotch_6.0.3/src/libscotch/vdgraph_separate_ml.h new file mode 100644 index 00000000..f2d61e6e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_ml.h @@ -0,0 +1,83 @@ +/* Copyright 2007-2009, 2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_ml.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the sequential vertex separation **/ +/** routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.0 : from : 07 feb 2006 **/ +/** to : 03 aug 2007 **/ +/** # Version 5.1 : from : 14 dec 2008 **/ +/** to : 29 may 2009 **/ +/** # Version 6.0 : from : 28 sep 2014 **/ +/** to : 28 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VdgraphSeparateMlParam_ { + INT passnbr; /*+ Number of coarsening passes to go +*/ + INT foldmax; /*+ Maximum number of vertices per processor to do folding +*/ + int foldval; /*+ Type of folding +*/ + INT coarnbr; /*+ Minimum number of vertices +*/ + double coarrat; /*+ Coarsening ratio +*/ + Strat * stratlow; /*+ Strategy at lowest level +*/ + Strat * stratasc; /*+ Strategy at ascending levels +*/ + Strat * stratseq; /*+ Strategy when running on a single processor +*/ +} VdgraphSeparateMlParam; + +/* +** The function prototypes. +*/ + +#ifndef VDGRAPH_SEPARATE_ML +#define static +#endif + +static int vdgraphSeparateMlCoarsen (Vdgraph * const, Vdgraph * const, DgraphCoarsenMulti * restrict * const, const VdgraphSeparateMlParam * const); +static int vdgraphSeparateMlUncoarsen (Vdgraph *, const Vdgraph * const, const DgraphCoarsenMulti * restrict const); +static void vdgraphSeparateMlOpBest (const Gnum * const, Gnum * const, const int * const, const MPI_Datatype * const); +int vdgraphSeparateMl (Vdgraph * const, const VdgraphSeparateMlParam * const); +static int vdgraphSeparateMl2 (Vdgraph * const, const VdgraphSeparateMlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_sq.c b/scotch_6.0.3/src/libscotch/vdgraph_separate_sq.c new file mode 100644 index 00000000..79476ada --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_sq.c @@ -0,0 +1,276 @@ +/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_sq.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a separator of the **/ +/** given distributed separator graph by **/ +/** moving all (interesting) vertices of **/ +/** the given graph to every processor, **/ +/** running a sequential vertex separation **/ +/** computing, and projecting back the **/ +/** best result obtained. **/ +/** **/ +/** DATES : # Version 5.1 : from : 15 feb 2006 **/ +/** to 30 jul 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH_SEPARATE_SQ + +#include "module.h" +#include "common.h" +#include "comm.h" +#include "parser.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_st.h" +#include "dgraph.h" +#include "vdgraph.h" +#include "vdgraph_separate_sq.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine is the reduction-loc operator which +** returns in inout[2] the rank of the process which +** holds the best partition. +** It returns: +** - void : in all cases. +*/ + +static +void +vdgraphSeparateSqOpBest ( +const Gnum * const in, /* First operand */ +Gnum * const inout, /* Second and output operand */ +const int * const len, /* Number of instances; should be 1, not used */ +const MPI_Datatype * const typedat) /* MPI datatype; not used */ +{ + if (inout[3] == 1) { /* Handle cases when at least one of them is erroneous */ + if (in[3] == 1) + return; + + inout[0] = in[0]; + inout[1] = in[1]; + inout[2] = in[2]; + inout[3] = in[3]; + return; + } + else if (in[3] == 1) + return; + + if ((in[0] < inout[0]) || /* Select best partition */ + ((in[0] == inout[0]) && + ((in[1] < inout[1]) || + ((in[1] == inout[1]) && (in[2] < inout[2]))))) { + inout[0] = in[0]; + inout[1] = in[1]; + inout[2] = in[2]; + } +} + +/* This routine computes a partition of the +** given distributed graph by gathering as many +** copies of the graph as there are processes +** sharing the distributed graph, running a +** sequential algorithm on them, and collecting +** the best solution found. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vdgraphSeparateSq ( +Vdgraph * const dgrfptr, /*+ Distributed graph +*/ +const VdgraphSeparateSqParam * const paraptr) /*+ Method parameters +*/ +{ + Vgraph cgrfdat; /* Centralized vertex separator graph structure */ + Gnum reduloctab[7]; /* Local array for best separator data (7 for Bcast) */ + Gnum reduglbtab[4]; /* Global array for best separator data */ + MPI_Datatype besttypedat; /* Data type for finding best separator */ + MPI_Op bestoperdat; /* Handle of MPI operator for finding best separator */ + int bestprocnum; /* Rank of process holding best partition */ + Gnum * restrict vnumloctax; + Gnum vertlocnum; + Gnum complocsize1; + Gnum complocload1; + Gnum complocload2; + Gnum fronlocnbr; + int o; + + if ((MPI_Type_contiguous (4, GNUM_MPI, &besttypedat) != MPI_SUCCESS) || + (MPI_Type_commit (&besttypedat) != MPI_SUCCESS) || + (MPI_Op_create ((MPI_User_function *) vdgraphSeparateSqOpBest, 1, &bestoperdat) != MPI_SUCCESS)) { + errorPrint ("vdgraphSeparateSq: communication error (1)"); + return (1); + } + + reduloctab[0] = /* In case of error, maximum frontier size */ + reduloctab[1] = GNUMMAX; /* And maximum load imbalance */ + reduloctab[2] = dgrfptr->s.proclocnum; + reduloctab[3] = 0; /* Assume sequential separation went fine */ + + vnumloctax = dgrfptr->s.vnumloctax; /* No need for vertex number array when centralizing graph */ + dgrfptr->s.vnumloctax = NULL; + o = vdgraphGatherAll (dgrfptr, &cgrfdat); + dgrfptr->s.vnumloctax = vnumloctax; /* Restore vertex number array */ + if (o != 0) { + errorPrint ("vdgraphSeparateSq: cannot build centralized graph"); + return (1); + } + + if (vgraphSeparateSt (&cgrfdat, paraptr->strat) != 0) { /* Separate centralized graph */ + errorPrint ("vdgraphSeparateSq: cannot separate centralized graph"); + reduloctab[3] = 1; + } + else { /* Fill local array with local separator data */ + reduloctab[0] = ((cgrfdat.fronnbr != 0) || ((cgrfdat.compload[0] != 0) && (cgrfdat.compload[1] != 0))) + ? cgrfdat.fronnbr + : (cgrfdat.fronnbr + cgrfdat.s.vertnbr); /* Partitions with empty separators unwanted if they are completely unbalanced */ + reduloctab[1] = cgrfdat.comploaddlt; + } + + if (MPI_Allreduce (reduloctab, reduglbtab, 1, besttypedat, bestoperdat, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateSq: communication error (2)"); + return (1); + } +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (MPI_Allreduce (&reduglbtab[3], &reduloctab[3], 1, GNUM_MPI, MPI_SUM, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateSq: communication error (3)"); + return (1); + } + if ((reduloctab[3] != 0) && (reduloctab[3] != dgrfptr->s.procglbnbr)) { + errorPrint ("vdgraphSeparateSq: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + + if ((MPI_Op_free (&bestoperdat) != MPI_SUCCESS) || + (MPI_Type_free (&besttypedat) != MPI_SUCCESS)) { + errorPrint ("vdgraphSeparateSq: communication error (4)"); + return (1); + } + + if (reduglbtab[3] != 0) { /* If none of the sequential methods succeeded */ + vgraphExit (&cgrfdat); + return (1); + } + + bestprocnum = (int) reduglbtab[2]; + if (dgrfptr->s.proclocnum == bestprocnum) { /* If process holds best partition */ + reduloctab[0] = cgrfdat.compload[0]; /* Global values to share */ + reduloctab[1] = cgrfdat.compload[1]; + reduloctab[2] = cgrfdat.compload[2]; + reduloctab[3] = cgrfdat.comploaddlt; + reduloctab[4] = cgrfdat.compsize[0]; + reduloctab[5] = cgrfdat.compsize[1]; + reduloctab[6] = cgrfdat.fronnbr; + } + if (MPI_Bcast (reduloctab, 7, GNUM_MPI, bestprocnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateSq: communication error (5)"); + return (1); + } + dgrfptr->compglbload[0] = reduloctab[0]; + dgrfptr->compglbload[1] = reduloctab[1]; + dgrfptr->compglbload[2] = reduloctab[2]; + dgrfptr->compglbloaddlt = reduloctab[3]; + dgrfptr->compglbsize[0] = reduloctab[4]; + dgrfptr->compglbsize[1] = reduloctab[5]; + dgrfptr->compglbsize[2] = reduloctab[6]; + + if (commScatterv (cgrfdat.parttax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GRAPHPART_MPI, /* No base for sending as procdsptab holds based values */ + dgrfptr->partgsttax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GRAPHPART_MPI, + bestprocnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { + errorPrint ("vdgraphSeparateSq: communication error (6)"); + return (1); + } + + complocsize1 = + complocload1 = + complocload2 = 0; + for (vertlocnum = dgrfptr->s.baseval, fronlocnbr = 0; + vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { + int partval; + Gnum partval1; + + partval = dgrfptr->partgsttax[vertlocnum]; + partval1 = partval & 1; + complocsize1 += partval1; /* Superscalar update */ + if (partval == 2) /* Build local frontier */ + dgrfptr->fronloctab[fronlocnbr ++] = vertlocnum; + if (dgrfptr->s.veloloctax != NULL) { + Gnum partval2; + Gnum veloval; + + veloval = dgrfptr->s.veloloctax[vertlocnum]; + partval2 = (partval >> 1) & 1; + complocload1 += (-partval1) & veloval; /* Superscalar update */ + complocload2 += (-partval2) & veloval; /* Superscalar update */ + } + } + dgrfptr->complocsize[0] = dgrfptr->s.vertlocnbr - fronlocnbr - complocsize1; + dgrfptr->complocsize[1] = complocsize1; + dgrfptr->complocsize[2] = fronlocnbr; + if (dgrfptr->s.veloloctax != NULL) { + dgrfptr->complocload[0] = dgrfptr->s.velolocsum - complocload1 - complocload2; + dgrfptr->complocload[1] = complocload1; + dgrfptr->complocload[2] = complocload2; + } + else { + dgrfptr->complocload[0] = dgrfptr->complocsize[0]; + dgrfptr->complocload[1] = dgrfptr->complocsize[1]; + dgrfptr->complocload[2] = fronlocnbr; + } + + vgraphExit (&cgrfdat); + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (vdgraphCheck (dgrfptr) != 0) { + errorPrint ("vdgraphSeparateSq: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_sq.h b/scotch_6.0.3/src/libscotch/vdgraph_separate_sq.h new file mode 100644 index 00000000..e62f7251 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_sq.h @@ -0,0 +1,69 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_sq.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the sequential vertex separation **/ +/** routine for distributed graphs. **/ +/** **/ +/** DATES : # Version 5.0 : from : 15 feb 2006 **/ +/** to : 01 mar 2006 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VdgraphSeparateSqParam_ { + Strat * strat; /*+ Sequential separation strategy used +*/ +} VdgraphSeparateSqParam; + +/* +** The function prototypes. +*/ + +#ifndef VDGRAPH_SEPARATE_SQ +#define static +#endif + +int vdgraphSeparateSq (Vdgraph * const, const VdgraphSeparateSqParam * const); + +static void vdgraphSeparateSqOpBest (const Gnum * const, Gnum * const, const int * const, const MPI_Datatype * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_st.c b/scotch_6.0.3/src/libscotch/vdgraph_separate_st.c new file mode 100644 index 00000000..732f2316 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_st.c @@ -0,0 +1,342 @@ +/* Copyright 2007-2009,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_st.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : This module contains the global **/ +/** distributed separation strategy and **/ +/** method tables. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 feb 2006 **/ +/** to 01 aug 2007 **/ +/** # Version 5.1 : from : 05 nov 2007 **/ +/** to 26 may 2009 **/ +/** # Version 6.0 : from : 01 may 2014 **/ +/** to 30 sep 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH_SEPARATE_ST + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_st.h" +#include "dgraph.h" +#include "dgraph_coarsen.h" +#include "vdgraph.h" +#include "vdgraph_separate_bd.h" +#include "vdgraph_separate_df.h" +#include "vdgraph_separate_ml.h" +#include "vdgraph_separate_sq.h" +#include "vdgraph_separate_st.h" +#include "vdgraph_separate_zr.h" + +/* +** The static and global variables. +*/ + +static Vdgraph vdgraphdummy; /* Dummy distributed separator graph for offset computations */ + +static union { + VdgraphSeparateBdParam param; + StratNodeMethodData padding; +} vdgraphseparatedefaultbd = { { 3, &stratdummy } }; + +static union { + VdgraphSeparateDfParam param; + StratNodeMethodData padding; +} vdgraphseparatedefaultdf = { { 0, 300, 1.0, 0.0, 0.2 } }; + +static union { + VdgraphSeparateMlParam param; + StratNodeMethodData padding; +} vdgraphseparatedefaultml = { { 5, 1000, 2, 10000, 0.8L, &stratdummy, &stratdummy, &stratdummy } }; + +static union { + VdgraphSeparateSqParam param; + StratNodeMethodData padding; +} vdgraphseparatedefaultsq = { { &stratdummy } }; + + +static StratMethodTab vdgraphseparatestmethtab[] = { /* Distributed graph separation methods array */ + { VDGRAPHSEPASTMETHBD, "b", vdgraphSeparateBd, &vdgraphseparatedefaultbd }, + { VDGRAPHSEPASTMETHDF, "d", vdgraphSeparateDf, &vdgraphseparatedefaultdf }, + { VDGRAPHSEPASTMETHML, "m", vdgraphSeparateMl, &vdgraphseparatedefaultml }, + { VDGRAPHSEPASTMETHSQ, "q", vdgraphSeparateSq, &vdgraphseparatedefaultsq }, + { VDGRAPHSEPASTMETHZR, "z", vdgraphSeparateZr, NULL }, + { -1, NULL, NULL, NULL } }; + + +static StratParamTab vdgraphseparatestparatab[] = { /* Distributed graph separation method parameter list */ + { VDGRAPHSEPASTMETHBD, STRATPARAMINT, "width", + (byte *) &vdgraphseparatedefaultbd.param, + (byte *) &vdgraphseparatedefaultbd.param.distmax, + NULL }, + { VDGRAPHSEPASTMETHBD, STRATPARAMSTRAT, "strat", + (byte *) &vdgraphseparatedefaultbd.param, + (byte *) &vdgraphseparatedefaultbd.param.strat, + (void *) &vdgraphseparateststratab }, + { VDGRAPHSEPASTMETHDF, STRATPARAMINT, "part", + (byte *) &vdgraphseparatedefaultdf.param, + (byte *) &vdgraphseparatedefaultdf.param.partval, + NULL }, + { VDGRAPHSEPASTMETHDF, STRATPARAMINT, "pass", + (byte *) &vdgraphseparatedefaultdf.param, + (byte *) &vdgraphseparatedefaultdf.param.passnbr, + NULL }, + { VDGRAPHSEPASTMETHDF, STRATPARAMDOUBLE, "bal", + (byte *) &vdgraphseparatedefaultdf.param, + (byte *) &vdgraphseparatedefaultdf.param.deltval, + NULL }, + { VDGRAPHSEPASTMETHDF, STRATPARAMDOUBLE, "dif", + (byte *) &vdgraphseparatedefaultdf.param, + (byte *) &vdgraphseparatedefaultdf.param.cdifval, + NULL }, + { VDGRAPHSEPASTMETHDF, STRATPARAMDOUBLE, "rem", + (byte *) &vdgraphseparatedefaultdf.param, + (byte *) &vdgraphseparatedefaultdf.param.cremval, + NULL }, + { VDGRAPHSEPASTMETHML, STRATPARAMSTRAT, "asc", + (byte *) &vdgraphseparatedefaultml.param, + (byte *) &vdgraphseparatedefaultml.param.stratasc, + (void *) &vdgraphseparateststratab }, + { VDGRAPHSEPASTMETHML, STRATPARAMSTRAT, "low", + (byte *) &vdgraphseparatedefaultml.param, + (byte *) &vdgraphseparatedefaultml.param.stratlow, + (void *) &vdgraphseparateststratab }, + { VDGRAPHSEPASTMETHML, STRATPARAMSTRAT, "seq", + (byte *) &vdgraphseparatedefaultml.param, + (byte *) &vdgraphseparatedefaultml.param.stratseq, + (void *) &vdgraphseparateststratab }, + { VDGRAPHSEPASTMETHML, STRATPARAMINT, "pass", + (byte *) &vdgraphseparatedefaultml.param, + (byte *) &vdgraphseparatedefaultml.param.passnbr, + NULL }, + { VDGRAPHSEPASTMETHML, STRATPARAMINT, "vert", + (byte *) &vdgraphseparatedefaultml.param, + (byte *) &vdgraphseparatedefaultml.param.coarnbr, + NULL }, + { VDGRAPHSEPASTMETHML, STRATPARAMINT, "dvert", + (byte *) &vdgraphseparatedefaultml.param, + (byte *) &vdgraphseparatedefaultml.param.foldmax, + NULL }, + { VDGRAPHSEPASTMETHML, STRATPARAMCASE, "fold", + (byte *) &vdgraphseparatedefaultml.param, + (byte *) &vdgraphseparatedefaultml.param.foldval, + (void *) "nfd" }, + { VDGRAPHSEPASTMETHML, STRATPARAMDOUBLE, "rat", + (byte *) &vdgraphseparatedefaultml.param, + (byte *) &vdgraphseparatedefaultml.param.coarrat, + NULL }, + { VDGRAPHSEPASTMETHML, STRATPARAMDEPRECATED | STRATPARAMINT, "dlevl", NULL, NULL, NULL }, /* Wait until MUMPS 5.0 */ + { VDGRAPHSEPASTMETHML, STRATPARAMDEPRECATED | STRATPARAMINT, "proc", NULL, NULL, NULL }, + { VDGRAPHSEPASTMETHSQ, STRATPARAMSTRAT, "strat", + (byte *) &vdgraphseparatedefaultsq.param, + (byte *) &vdgraphseparatedefaultsq.param.strat, + (void *) &vgraphseparateststratab }, + { VDGRAPHSEPASTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab vdgraphseparatestcondtab[] = { /* Distributed graph condition parameter table */ + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &vdgraphdummy, + (byte *) &vdgraphdummy.s.edgeglbnbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &vdgraphdummy, + (byte *) &vdgraphdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &vdgraphdummy, + (byte *) &vdgraphdummy.s.veloglbsum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "proc", + (byte *) &vdgraphdummy, + (byte *) &vdgraphdummy.s.procglbnbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "rank", + (byte *) &vdgraphdummy, + (byte *) &vdgraphdummy.s.proclocnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vert", + (byte *) &vdgraphdummy, + (byte *) &vdgraphdummy.s.vertglbnbr, + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab vdgraphseparateststratab = { /* Strategy tables for distributed vertex separation methods */ + vdgraphseparatestmethtab, + vdgraphseparatestparatab, + vdgraphseparatestcondtab }; + +/*******************************************/ +/* */ +/* This is the generic separation routine. */ +/* */ +/*******************************************/ + +/* This routine computes the separation of the +** given distributed graph according to the given +** strategy. +** All distributed vertex separation routines must +** be collective, that is, they must all return +** the same success or failure return value on all +** of the processors onto which they are run. Else, +** the behavior of the software is unpredictable. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +vdgraphSeparateSt ( +Vdgraph * restrict const grafptr, /*+ Distributed separation graph +*/ +const Strat * restrict const strat) /*+ Separation strategy +*/ +{ + StratTest val; + VdgraphStore savetab[2]; /* Results of the two strategies */ + Gnum compglbload2; /* Saved global separator load */ + int o; +#ifdef SCOTCH_DEBUG_VDGRAPH2 + MPI_Comm proccommold; /* Save area for old communicator */ +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (sizeof (Gnum) != sizeof (INT)) { + errorPrint ("vdgraphSeparateSt: invalid type specification for parser variables"); + return (1); + } + if (sizeof (VdgraphSeparateSqParam) > sizeof (StratNodeMethodData)) { + errorPrint ("vdgraphSeparateSt: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ +#ifdef SCOTCH_DEBUG_VDGRAPH1 + if ((strat->tabl != &vdgraphseparateststratab) && + (strat != &stratdummy)) { + errorPrint ("vdgraphSeparateSt: invalid parameter (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VDGRAPH1 */ + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + o = vdgraphSeparateSt (grafptr, strat->data.concat.strat[0]); /* Apply first strategy */ + if (o == 0) /* If it worked all right */ + o |= vdgraphSeparateSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ + break; + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if ((val.typetest != STRATTESTVAL) || + (val.typenode != STRATPARAMLOG)) { + errorPrint ("vdgraphSeparateSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = vdgraphSeparateSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = vdgraphSeparateSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + break; + case STRATNODESELECT : /* TODO: Can be multithreaded! */ + if (((vdgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ + ((vdgraphStoreInit (grafptr, &savetab[1])) != 0)) { + errorPrint ("vdgraphSeparateSt: out of memory"); + vdgraphStoreExit (&savetab[0]); + return (1); + } + + vdgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */ + if (vdgraphSeparateSt (grafptr, strat->data.select.strat[0]) != 0) { /* If first strategy didn't work */ + vdgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ + vdgraphStoreSave (grafptr, &savetab[0]); /* Save it as result */ + } + else { /* First strategy worked */ + vdgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ + vdgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ + } + if (vdgraphSeparateSt (grafptr, strat->data.select.strat[1]) != 0) /* If second strategy didn't work */ + vdgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition as its result */ + + compglbload2 = grafptr->s.veloglbsum - savetab[0].compglbload[0] - savetab[0].compglbload[1]; /* Compute saved separator load */ + if ( (compglbload2 < grafptr->compglbload[2]) || /* If first strategy is better */ + ((compglbload2 == grafptr->compglbload[2]) && + (abs (savetab[0].compglbloaddlt) < abs (grafptr->compglbloaddlt)))) + vdgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ + + vdgraphStoreExit (&savetab[0]); /* Free both save areas */ + vdgraphStoreExit (&savetab[1]); + break; +#ifdef SCOTCH_DEBUG_VDGRAPH1 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_VDGRAPH1 */ + default : +#endif /* SCOTCH_DEBUG_VDGRAPH1 */ +#ifdef SCOTCH_DEBUG_VDGRAPH2 + proccommold = grafptr->s.proccomm; /* Create new communicator to isolate method communications */ + MPI_Comm_dup (proccommold, &grafptr->s.proccomm); +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ + o = strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data); +#ifdef SCOTCH_DEBUG_VDGRAPH2 + MPI_Comm_free (&grafptr->s.proccomm); /* Restore old communicator */ + grafptr->s.proccomm = proccommold; +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ +#ifdef SCOTCH_DEBUG_VDGRAPH1 + break; + default : + errorPrint ("vdgraphSeparateSt: invalid parameter (2)"); + return (1); +#endif /* SCOTCH_DEBUG_VDGRAPH1 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_st.h b/scotch_6.0.3/src/libscotch/vdgraph_separate_st.h new file mode 100644 index 00000000..5981a82e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_st.h @@ -0,0 +1,80 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_st.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the global distributed sepa- **/ +/** ration strategy and method tables. **/ +/** **/ +/** DATES : # Version 5.0 : from : 16 feb 2006 **/ +/** to 08 mar 2006 **/ +/** # Version 5.1 : from : 05 nov 2007 **/ +/** to 05 nov 2007 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum VdgraphSeparateStMethodType_ { + VDGRAPHSEPASTMETHBD = 0, /*+ Band strategy +*/ + VDGRAPHSEPASTMETHDF, /*+ Diffusion method +*/ + VDGRAPHSEPASTMETHML, /*+ Multilevel strategy +*/ + VDGRAPHSEPASTMETHSQ, /*+ Sequential strategy +*/ + VDGRAPHSEPASTMETHZR, /*+ Zero method +*/ + VDGRAPHSEPASTMETHNBR /*+ Number of methods +*/ +} VdgraphSeparateStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab vdgraphseparateststratab; + +/* +** The function prototypes. +*/ + +#ifndef VDGRAPH_SEPARATE_ST +#define static +#endif + +int vdgraphSeparateSt (Vdgraph * const, const Strat * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_zr.c b/scotch_6.0.3/src/libscotch/vdgraph_separate_zr.c new file mode 100644 index 00000000..8d3fac00 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_zr.c @@ -0,0 +1,80 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_zr.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module moves all of the vertices **/ +/** of the distributed separator graph to **/ +/** the first subdomain. **/ +/** **/ +/** DATES : # Version 5.0 : from : 07 feb 2006 **/ +/** to 07 feb 2006 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH_SEPARATE_ZR + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "vdgraph.h" +#include "vdgraph_separate_zr.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine moves all of the graph vertices +** to the first part of the partition. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vdgraphSeparateZr ( +Vdgraph * const grafptr) /*+ Active graph +*/ +{ + if (grafptr->compglbload[0] != grafptr->s.veloglbsum) /* If not all vertices already in part zero */ + vdgraphZero (grafptr); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vdgraph_separate_zr.h b/scotch_6.0.3/src/libscotch/vdgraph_separate_zr.h new file mode 100644 index 00000000..304bf467 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_separate_zr.h @@ -0,0 +1,57 @@ +/* Copyright 2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_separate_zr.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the move-all-to-first-subdomain **/ +/** distributed separation method. **/ +/** **/ +/** DATES : # Version 5.0 : from : 07 feb 2006 **/ +/** to 07 feb 2006 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef VDGRAPH_SEPARATE_ZR +#define static +#endif + +int vdgraphSeparateZr (Vdgraph * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vdgraph_store.c b/scotch_6.0.3/src/libscotch/vdgraph_store.c new file mode 100644 index 00000000..473518e1 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vdgraph_store.c @@ -0,0 +1,167 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vdgraph_store.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the save data **/ +/** structure handling routines for **/ +/** distributed separation graphs. **/ +/** **/ +/** DATES : # Version 4.0 : from : 08 mar 2006 **/ +/** to : 01 mar 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VDGRAPH_STORE + +#include "module.h" +#include "common.h" +#include "dgraph.h" +#include "vdgraph.h" + +/**********************************/ +/* */ +/* Store graph handling routines. */ +/* */ +/**********************************/ + +/* This routine builds a save structure +** for the given active graph. +** It returns: +** - 0 : if allocation succeeded. +** - !0 : on error. +*/ + +int +vdgraphStoreInit ( +const Vdgraph * restrict const grafptr, +VdgraphStore * restrict const storptr) +{ + Gnum savsize; + + savsize = grafptr->s.vertlocnbr * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ + + if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ + errorPrint ("vdgraphStoreInit: out of memory"); + return (1); + } + + return (0); +} + +/* This routine frees a save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +vdgraphStoreExit ( +VdgraphStore * const storptr) +{ + memFree (storptr->datatab); +#ifdef SCOTCH_DEBUG_VDGRAPH2 + storptr->datatab = NULL; +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ +} + +/* This routine saves partition data from the +** given active graph to the given save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +vdgraphStoreSave ( +const Vdgraph * const grafptr, +VdgraphStore * const storptr) +{ + byte * partloctab; /* Pointer to part data save area */ + byte * fronloctab; /* Pointer to frontier data save area */ + + storptr->fronglbnbr = grafptr->compglbsize[2]; /* Save partition parameters */ + storptr->compglbloaddlt = grafptr->compglbloaddlt; + storptr->compglbload[0] = grafptr->compglbload[0]; + storptr->compglbload[1] = grafptr->compglbload[1]; + storptr->compglbsize0 = grafptr->compglbsize[0]; + storptr->complocsize0 = grafptr->complocsize[0]; + storptr->fronlocnbr = grafptr->complocsize[2]; + + fronloctab = storptr->datatab; /* Compute data offsets within save structure */ + partloctab = fronloctab + grafptr->complocsize[2] * sizeof (Gnum); + + memCpy (fronloctab, grafptr->fronloctab, grafptr->complocsize[2] * sizeof (Gnum)); + memCpy (partloctab, grafptr->partgsttax + grafptr->s.baseval, grafptr->s.vertlocnbr * sizeof (GraphPart)); +} + +/* This routine updates partition data of the +** given active graph, using the given save graph. +** It returns: +** - VOID : in all cases. +*/ + +void +vdgraphStoreUpdt ( +Vdgraph * const grafptr, +const VdgraphStore * const storptr) +{ + byte * fronloctab; /* Pointer to frontier data save area */ + byte * partloctab; /* Pointer to part data save area */ + + grafptr->compglbload[0] = storptr->compglbload[0]; /* Load partition parameters */ + grafptr->compglbload[1] = storptr->compglbload[1]; + grafptr->compglbload[2] = grafptr->s.veloglbsum - (storptr->compglbload[0] + storptr->compglbload[1]); + grafptr->compglbloaddlt = storptr->compglbloaddlt; + grafptr->compglbsize[0] = storptr->compglbsize0; + grafptr->compglbsize[1] = grafptr->s.vertglbnbr - (storptr->compglbsize0 + storptr->fronglbnbr); + grafptr->compglbsize[2] = storptr->fronglbnbr; + grafptr->complocsize[0] = storptr->complocsize0; + grafptr->complocsize[1] = grafptr->s.vertlocnbr - (storptr->complocsize0 + storptr->fronlocnbr); + grafptr->complocsize[2] = storptr->fronlocnbr; + + fronloctab = storptr->datatab; /* Compute data offsets within save structure */ + partloctab = fronloctab + grafptr->complocsize[2] * sizeof (Gnum); + + memCpy (grafptr->fronloctab, fronloctab, grafptr->complocsize[2] * sizeof (Gnum)); + memCpy (grafptr->partgsttax + grafptr->s.baseval, partloctab, grafptr->s.vertlocnbr * sizeof (GraphPart)); + +#ifdef SCOTCH_DEBUG_VDGRAPH2 + if (vdgraphCheck (grafptr) != 0) + errorPrint ("vdgraphStoreUpdt: inconsistent graph data"); +#endif /* SCOTCH_DEBUG_VDGRAPH2 */ +} diff --git a/scotch_6.0.3/src/libscotch/vgraph.c b/scotch_6.0.3/src/libscotch/vgraph.c new file mode 100644 index 00000000..121ae202 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph.c @@ -0,0 +1,107 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the separator **/ +/** handling routines. **/ +/** **/ +/** DATES : # Version 3.2 : from : 24 aug 1996 **/ +/** to 03 nov 1997 **/ +/** # Version 4.0 : from : 12 dec 2001 **/ +/** to 08 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "vgraph.h" + +/*************************/ +/* */ +/* These routines handle */ +/* separator graphs. */ +/* */ +/*************************/ + +/* This routine frees the contents +** of the given active graph. +** It returns: +** - VOID : in all cases. +*/ + +void +vgraphExit ( +Vgraph * const grafptr) +{ + if (grafptr->parttax != NULL) + memFree (grafptr->parttax + grafptr->s.baseval); + if (grafptr->frontab != NULL) + memFree (grafptr->frontab); + + graphFree (&grafptr->s); /* Free source graph */ + +#ifdef SCOTCH_DEBUG_VGRAPH2 + memSet (grafptr, ~0, sizeof (Vgraph)); +#endif /* SCOTCH_DEBUG_VGRAPH2 */ +} + +/* This routine moves all of the graph +** vertices to the first part. +** It returns: +** - VOID : in all cases. +*/ + +void +vgraphZero ( +Vgraph * const grafptr) +{ + memSet (grafptr->parttax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ + + grafptr->compload[0] = grafptr->s.velosum; /* No frontier vertices */ + grafptr->compload[1] = + grafptr->compload[2] = 0; + grafptr->comploaddlt = grafptr->s.velosum; + grafptr->compsize[0] = grafptr->s.vertnbr; + grafptr->compsize[1] = + grafptr->fronnbr = 0; +} diff --git a/scotch_6.0.3/src/libscotch/vgraph.h b/scotch_6.0.3/src/libscotch/vgraph.h new file mode 100644 index 00000000..88b85871 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph.h @@ -0,0 +1,98 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for vertex separation routines. **/ +/** **/ +/** DATES : # Version 3.2 : from : 24 aug 1996 **/ +/** to : 17 oct 1997 **/ +/** # Version 3.3 : from : 13 mar 1999 **/ +/** to : 13 mar 1999 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to : 07 jan 2002 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +#define VGRAPH_H + +/* +** The type and structure definitions. +*/ + +/*+ Active graph structure. +*/ + +typedef struct Vgraph_ { + Graph s; /*+ Source graph +*/ + GraphPart * parttax; /*+ Based part array: 0,1: part; 2: separator +*/ + Gnum compload[3]; /*+ Size of both parts and separator +*/ + Gnum comploaddlt; /*+ Load difference between both parts +*/ + Gnum compsize[2]; /*+ Number of vertices in parts (separator is fronnbr) +*/ + Gnum fronnbr; /*+ Number of frontier vertices; TRICK: compsize[2] +*/ + Gnum * frontab; /*+ Array of frontier vertex numbers +*/ + Gnum levlnum; /*+ Nested dissection or coarsening level +*/ +} Vgraph; + +/*+ The graph separator storing structure. +*/ + +typedef struct VgraphStore_ { + Gnum fronnbr; /*+ Number of frontier nodes +*/ + Gnum comploaddlt; /*+ Difference from the average +*/ + Gnum compload[2]; /*+ Load in both parts +*/ + Gnum compsize0; /*+ Number of vertices in part 0 +*/ + byte * datatab; /*+ Variable-sized data array +*/ +} VgraphStore; + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH +#define static +#endif + +void vgraphExit (Vgraph * const); +void vgraphZero (Vgraph * const); +int vgraphCheck (const Vgraph * const); + +int vgraphStoreInit (const Vgraph * const, VgraphStore * const); +void vgraphStoreExit (VgraphStore * const); +void vgraphStoreSave (const Vgraph * const , VgraphStore * const); +void vgraphStoreUpdt (Vgraph * const, const VgraphStore * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_check.c b/scotch_6.0.3/src/libscotch/vgraph_check.c new file mode 100644 index 00000000..b97c69bc --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_check.c @@ -0,0 +1,190 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the separator **/ +/** graph consistency checking routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 24 aug 1996 **/ +/** to 03 nov 1997 **/ +/** # Version 4.0 : from : 12 dec 2001 **/ +/** to 08 jan 2004 **/ +/** # Version 5.0 : from : 16 sep 2006 **/ +/** to : 16 sep 2006 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to : 09 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "vgraph.h" + +/*************************/ +/* */ +/* These routines handle */ +/* separator graphs. */ +/* */ +/*************************/ + +/* This routine checks the consistency +** of the given separator graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +vgraphCheck ( +const Vgraph * const grafptr) +{ + Gnum vertnum; /* Number of current vertex */ + Gnum fronnum; /* Number of frontier vertex */ + Gnum compload[3]; + Gnum compsize[3]; + Gnum commcut[3]; + + if (grafptr->comploaddlt != (grafptr->compload[0] - grafptr->compload[1])) { + errorPrint ("vgraphCheck: invalid balance"); + return (1); + } + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + if (grafptr->parttax[vertnum] > 2) { + errorPrint ("vgraphCheck: invalid part array"); + return (1); + } + } + + if ((grafptr->fronnbr < 0) || + (grafptr->fronnbr > grafptr->s.vertnbr)) { + errorPrint ("vgraphCheck: invalid number of frontier vertices"); + return (1); + } + for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { + Gnum vertnum; + + vertnum = grafptr->frontab[fronnum]; + if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->s.vertnnd)) { + errorPrint ("vgraphCheck: invalid vertex index in frontier array"); + return (1); + } + if (grafptr->parttax[vertnum] != 2) { + errorPrint ("vgraphCheck: invalid vertex in frontier array"); + return (1); + } + } + + compload[0] = + compload[1] = + compload[2] = 0; + compsize[0] = + compsize[1] = + compsize[2] = 0; + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + int partnum; /* Part of current vertex */ + Gnum edgenum; /* Number of current edge */ + + partnum = (int) grafptr->parttax[vertnum]; + + compload[partnum] += (grafptr->s.velotax == NULL) ? 1 : grafptr->s.velotax[vertnum]; + compsize[partnum] ++; + + commcut[0] = + commcut[1] = + commcut[2] = 0; + if ((grafptr->s.verttax[vertnum] < grafptr->s.baseval) || + (grafptr->s.verttax[vertnum] > grafptr->s.vendtax[vertnum])) { + errorPrint ("vgraphCheck: invalid graph structure (1)"); + return (1); + } + for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = grafptr->s.edgetax[edgenum]; + if ((vertend < grafptr->s.baseval) || + (vertend >= grafptr->s.vertnnd)) { + errorPrint ("vgraphCheck: invalid graph structure (2)"); + return (1); + } + commcut[grafptr->parttax[vertend]] ++; + } + +#ifdef SCOTCH_DEBUG_VGRAPH3 + if (partnum == 2) { + if ((commcut[0] == 0) || + (commcut[1] == 0)) + errorPrintW ("vgraphCheck: no-use separator vertex%s (%ld)", /* Warning only */ + ((grafptr->levlnum == 0) ? " at level 0" : ""), + (long) vertnum); + } + else { +#else + if (partnum != 2) { +#endif /* SCOTCH_DEBUG_VGRAPH3 */ + if (commcut[1 - partnum] != 0) { + errorPrint ("vgraphCheck: vertex should be in separator (%ld)", (long) vertnum); + return (1); + } + } + } + + if ((grafptr->compload[0] != compload[0]) || + (grafptr->compload[1] != compload[1]) || + (grafptr->compload[2] != compload[2])) { + errorPrint ("vgraphCheck: invalid part loads"); + return (1); + } + if (grafptr->comploaddlt != (grafptr->compload[0] - grafptr->compload[1])) { + errorPrint ("vgraphCheck: invalid balance"); + return (1); + } + if ((grafptr->compsize[0] != compsize[0]) || + (grafptr->compsize[1] != compsize[1]) || + (grafptr->fronnbr != compsize[2])) { + errorPrint ("vgraphCheck: invalid part sizes"); + return (1); + } + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_bd.c b/scotch_6.0.3/src/libscotch/vgraph_separate_bd.c new file mode 100644 index 00000000..69d31ada --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_bd.c @@ -0,0 +1,437 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_bd.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : This module builds a band graph around **/ +/** the frontier in order to decrease **/ +/** problem size for the strategy to be **/ +/** applied. **/ +/** **/ +/** DATES : # Version 5.0 : from : 18 oct 2004 **/ +/** to : 12 sep 2007 **/ +/** # Version 5.1 : from : 30 oct 2007 **/ +/** to : 09 nov 2008 **/ +/** **/ +/************************************************************/ + + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_BD + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_bd.h" +#include "vgraph_separate_st.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +int +vgraphSeparateBd ( +Vgraph * restrict const orggrafptr, /*+ Active graph +*/ +const VgraphSeparateBdParam * const paraptr) /*+ Method parameters +*/ +{ + VgraphSeparateBdQueue queudat; /* Neighbor queue */ + Gnum * restrict orgdisttax; /* Based access to distance array for original graph */ + Gnum orgdistmax; /* Maximum distance allowed */ +#define orgindxtax orgdisttax /* Recycle distance array as number indexing array */ + Vgraph bndgrafdat; /* Band graph structure */ + Gnum bndvertnbr; /* Number of regular vertices in band graph (without anchors) */ + Gnum bndvertnnd; + Gnum * restrict bndvnumtax; /* Band vertex number array, recycling queudat.qtab */ + Gnum bndcompsize1; /* Number of regular vertices in part 1 of band graph */ + Gnum bndcompload1; /* Load of regular vertices in part 1 */ + Gnum bndvlvlnum; /* Index of first band graph vertex to belong to the last layer */ + Gnum bndvertnum; + Gnum bndvelosum; /* Load of regular vertices in band graph */ + Gnum * restrict bndedgetax; + Gnum bndedgenbr; /* Upper bound on the number of edges, including anchor edges */ + Gnum bndeancnbr; /* Number of anchor edges */ + Gnum bndedgenum; + Gnum bndedgetmp; + Gnum bnddegrmax; + Gnum fronnum; + const Gnum * restrict const orgverttax = orggrafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const orgvendtax = orggrafptr->s.vendtax; + const Gnum * restrict const orgvelotax = orggrafptr->s.velotax; + const Gnum * restrict const orgedgetax = orggrafptr->s.edgetax; + + if (orggrafptr->fronnbr == 0) /* If no separator vertices, apply strategy to full graph */ + return (vgraphSeparateSt (orggrafptr, paraptr->stratorg)); + + orgdistmax = (Gnum) paraptr->distmax; + if (orgdistmax < 1) /* To simplify algorithm, always at least one layer of vertices around separator */ + orgdistmax = 1; + + if (memAllocGroup ((void **) (void *) + &queudat.qtab, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), /* TRICK: no need of "+ 2" for anchor vertices (see below) */ + &orgdisttax, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("vgraphSeparateBd: out of memory (1)"); + return (1); + } + memSet (orgdisttax, ~0, orggrafptr->s.vertnbr * sizeof (Gnum)); /* Initialize distance array */ + orgdisttax -= orggrafptr->s.baseval; + + vgraphSeparateBdQueueFlush (&queudat); /* Flush vertex queue */ + bndedgenbr = 0; /* Guess upper bound on the number of edges */ + bndvelosum = 0; + for (fronnum = 0; fronnum < orggrafptr->fronnbr; fronnum ++) { /* Enqueue separator vertices */ + Gnum orgvertnum; + + orgvertnum = orggrafptr->frontab[fronnum]; +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((orgvertnum < orggrafptr->s.baseval) || (orgvertnum >= orggrafptr->s.vertnnd)) { + errorPrint ("vgraphSeparateBd: internal error (1)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } + if (orgdisttax[orgvertnum] != ~0) { + errorPrint ("vgraphSeparateBd: internal error (2)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } + if (orggrafptr->parttax[orgvertnum] != 2) { + errorPrint ("vgraphSeparateBd: internal error (3)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + orgdisttax[orgvertnum] = 0; + vgraphSeparateBdQueuePut (&queudat, orgvertnum); + if (orgvelotax != NULL) + bndvelosum += orgvelotax[orgvertnum]; + } + + bndcompsize1 = 0; + bndcompload1 = 0; + do { /* Loop on vertices in queue */ + Gnum orgvertnum; + Gnum orgedgenum; + Gnum orgdistval; + + orgvertnum = vgraphSeparateBdQueueGet (&queudat); +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((orgvertnum < orggrafptr->s.baseval) || (orgvertnum >= orggrafptr->s.vertnnd)) { + errorPrint ("vgraphSeparateBd: internal error (4)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + bndedgenbr += orgvendtax[orgvertnum] - orgverttax[orgvertnum]; /* Exact or upper bound on number of edges, including anchor edge(s) */ + + orgdistval = orgdisttax[orgvertnum]; /* Get vertex distance */ + if (orgdistval >= orgdistmax) { /* If we belong to the farthest layer */ + bndedgenbr ++; /* One more anchor edge, for the opposite */ + continue; + } + + orgdistval ++; /* Distance of neighbors */ + for (orgedgenum = orgverttax[orgvertnum]; + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { + Gnum orgvertend; + Gnum orgpartval1; + + orgvertend = orgedgetax[orgedgenum]; + if (orgdisttax[orgvertend] == ~0) { /* If vertex not visited yet */ + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (orggrafptr->parttax[orgvertend] > 1) { + errorPrint ("vgraphSeparateBd: internal error (5)"); + memFree (queudat.qtab); /* Free group leader */ + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + orgpartval1 = orggrafptr->parttax[orgvertend] & 1; + orgdisttax[orgvertend] = orgdistval; /* Enqueue vertex */ + vgraphSeparateBdQueuePut (&queudat, orgvertend); + bndcompsize1 += orgpartval1; /* Count vertices in part 1 */ + if (orgvelotax != NULL) { + bndvelosum += orgvelotax[orgvertend]; + bndcompload1 += orgvelotax[orgvertend] * orgpartval1; + } + } + } + } while (! vgraphSeparateBdQueueEmpty (&queudat)); /* As long as queue is not empty */ + + bndvertnbr = queudat.head - queudat.qtab; /* Number of regular band graph vertices (withour anchors) is number of enqueued vertices */ + + if (orgvelotax == NULL) { + bndvelosum = bndvertnbr; + bndcompload1 = bndcompsize1; + } + + if ((bndcompsize1 >= orggrafptr->compsize[1]) || /* If either part has all of its vertices in band, use plain graph instead */ + ((bndvertnbr - bndcompsize1 - orggrafptr->fronnbr) >= orggrafptr->compsize[0])) { + memFree (queudat.qtab); /* Free group leader */ + return (vgraphSeparateSt (orggrafptr, paraptr->stratorg)); + } /* TRICK: since always at least one missing vertex per part, there is room for anchor vertices */ + + bndvertnnd = bndvertnbr + orggrafptr->s.baseval; + bndvnumtax = queudat.qtab - orggrafptr->s.baseval; /* TRICK: re-use queue array as vertex number array as vertices taken in queue order */ + for (bndvertnum = orggrafptr->s.baseval; bndvertnum < bndvertnnd; bndvertnum ++) { /* For vertices not belonging to last layer */ + Gnum orgvertnum; + + orgvertnum = bndvnumtax[bndvertnum]; /* Get distance index of vertex */ + if (orgindxtax[orgvertnum] >= paraptr->distmax) /* If vertex belongs to last layer */ + break; + orgindxtax[orgvertnum] = bndvertnum; + } + bndvlvlnum = bndvertnum; /* Get index of first vertex of last layer */ + for ( ; bndvertnum < bndvertnnd; bndvertnum ++) /* For vertices belonging to last layer */ + orgindxtax[bndvnumtax[bndvertnum]] = bndvertnum; + + memSet (&bndgrafdat, 0, sizeof (Vgraph)); + bndgrafdat.s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; + bndgrafdat.s.baseval = orggrafptr->s.baseval; + bndgrafdat.s.vertnbr = bndvertnbr + 2; /* "+ 2" for anchor vertices */ + bndgrafdat.s.vertnnd = bndvertnnd + 2; + + if (memAllocGroup ((void **) (void *) /* Do not allocate vnumtab but keep queudat.qtab instead */ + &bndgrafdat.s.verttax, (size_t) ((bndvertnbr + 3) * sizeof (Gnum)), + &bndgrafdat.s.velotax, (size_t) ((bndvertnbr + 2) * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("vgraphSeparateBd: out of memory (2)"); + memFree (queudat.qtab); + return (1); + } + bndgrafdat.s.verttax -= orggrafptr->s.baseval; /* Adjust base of arrays */ + bndgrafdat.s.vendtax = bndgrafdat.s.verttax + 1; /* Band graph is compact */ + bndgrafdat.s.velotax -= orggrafptr->s.baseval; + bndgrafdat.s.vnumtax = bndvnumtax; + bndgrafdat.s.velosum = orggrafptr->s.velosum; + bndgrafdat.s.velotax[bndvertnnd] = orggrafptr->compload[0] - (bndvelosum - orggrafptr->compload[2] - bndcompload1); /* Set loads of anchor vertices */ + bndgrafdat.s.velotax[bndvertnnd + 1] = orggrafptr->compload[1] - bndcompload1; + + if (((bndgrafdat.s.edgetax = (Gnum *) memAlloc (bndedgenbr * sizeof (Gnum))) == NULL) || + (bndgrafdat.s.edgetax -= orggrafptr->s.baseval, + ((bndgrafdat.parttax = (GraphPart *) memAlloc ((bndvertnbr + 2) * sizeof (GraphPart))) == NULL))) { + errorPrint ("vgraphSeparateBd: out of memory (3)"); + graphExit (&bndgrafdat.s); + memFree (queudat.qtab); + return (1); + } + bndgrafdat.parttax -= orggrafptr->s.baseval; /* From now on we should free a Vgraph and not a Graph */ + bndedgetax = bndgrafdat.s.edgetax; + + for (bndvertnum = bndedgenum = orggrafptr->s.baseval, bnddegrmax = 0; /* Fill index array for vertices not belonging to last level */ + bndvertnum < bndvlvlnum; bndvertnum ++) { + Gnum orgvertnum; + Gnum orgedgenum; + + orgvertnum = bndvnumtax[bndvertnum]; + bndgrafdat.s.verttax[bndvertnum] = bndedgenum; + bndgrafdat.s.velotax[bndvertnum] = (orgvelotax != NULL) ? orgvelotax[orgvertnum] : 1; + + for (orgedgenum = orgverttax[orgvertnum]; /* All edges of first levels are kept */ + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++, bndedgenum ++) { +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((bndedgenum >= (bndedgenbr + orggrafptr->s.baseval)) || + (orgindxtax[orgedgetax[orgedgenum]] < 0)) { + errorPrint ("vgraphSeparateBd: internal error (6)"); + vgraphExit (&bndgrafdat); + memFree (queudat.qtab); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + bndedgetax[bndedgenum] = orgindxtax[orgedgetax[orgedgenum]]; + } + bndgrafdat.parttax[bndvertnum] = orggrafptr->parttax[orgvertnum]; /* Copy part array */ + + if (bnddegrmax < (bndedgenum - bndgrafdat.s.verttax[bndvertnum])) + bnddegrmax = (bndedgenum - bndgrafdat.s.verttax[bndvertnum]); + } + bndeancnbr = 0; + for ( ; bndvertnum < bndvertnnd; bndvertnum ++) { /* Fill index array for vertices belonging to last level */ + Gnum orgvertnum; + Gnum orgedgenum; + GraphPart orgpartval; + Gnum bnddegrval; + + orgvertnum = bndvnumtax[bndvertnum]; + bndgrafdat.s.verttax[bndvertnum] = bndedgenum; + bndgrafdat.s.velotax[bndvertnum] = (orgvelotax != NULL) ? orgvelotax[orgvertnum] : 1; + + for (orgedgenum = orgverttax[orgvertnum]; /* Keep only band edges */ + orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { + Gnum bndvertend; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (bndedgenum >= (bndedgenbr + orggrafptr->s.baseval)) { + errorPrint ("vgraphSeparateBd: internal error (7)"); + vgraphExit (&bndgrafdat); + memFree (queudat.qtab); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + bndvertend = orgindxtax[orgedgetax[orgedgenum]]; + if (bndvertend != ~0) + bndedgetax[bndedgenum ++] = bndvertend; + } + orgpartval = orggrafptr->parttax[orgvertnum]; + bndgrafdat.parttax[bndvertnum] = orgpartval; /* Record part for vertices of last level */ + bnddegrval = bndedgenum - bndgrafdat.s.verttax[bndvertnum]; + if (bnddegrval < (orgvendtax[orgvertnum] - orgverttax[orgvertnum])) { /* If vertex is connected to rest of part */ + bndedgetax[bndedgenum ++] = bndvertnnd + (Gnum) orgpartval; /* Add anchor edge to proper anchor vertex */ + bndeancnbr ++; + bnddegrval ++; /* One more (anchor) edge added to this vertex */ + } + if (bnddegrmax < bnddegrval) + bnddegrmax = bnddegrval; + } + bndgrafdat.parttax[bndvertnnd] = 0; /* Set parts of anchor vertices */ + bndgrafdat.parttax[bndvertnnd + 1] = 1; + + bndgrafdat.s.verttax[bndvertnnd] = bndedgenum; /* Mark end of regular edge array and start of first anchor edge array */ + bndedgetmp = bndedgenum + bndeancnbr; +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((bndedgetmp - 1) >= (bndedgenbr + orggrafptr->s.baseval)) { + errorPrint ("vgraphSeparateBd: internal error (8)"); + vgraphExit (&bndgrafdat); + memFree (queudat.qtab); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + bndgrafdat.s.edgenbr = + bndgrafdat.s.edlosum = bndedgetmp - orggrafptr->s.baseval; /* Since edge load array not kept */ + bndgrafdat.s.verttax[bndvertnnd + 2] = bndedgetmp; /* Mark end of edge array with anchor vertices */ + for (bndvertnum = bndvlvlnum; bndvertnum < bndvertnnd; bndvertnum ++) { /* Fill anchor edge arrays */ + Gnum orgvertnum; + + orgvertnum = bndvnumtax[bndvertnum]; + if (bndgrafdat.s.verttax[bndvertnum + 1] > bndgrafdat.s.verttax[bndvertnum]) { /* If vertex is not isolated */ + Gnum bndvertend; + + bndvertend = bndedgetax[bndgrafdat.s.verttax[bndvertnum + 1] - 1]; /* Get last neighbor of its edge sub-array */ + + if (bndvertend >= bndvertnnd) { /* If it is an anchor */ + if (bndvertend == bndvertnnd) /* Add edge from proper anchor */ + bndedgetax[bndedgenum ++] = bndvertnum; + else + bndedgetax[-- bndedgetmp] = bndvertnum; + } + } + } + bndgrafdat.s.verttax[bndvertnnd + 1] = bndedgenum; /* Mark end of edge array of first anchor and start of second */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (bndedgenum != bndedgetmp) { + errorPrint ("vgraphSeparateBd: internal error (9)"); + vgraphExit (&bndgrafdat); + memFree (queudat.qtab); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + if (bnddegrmax < (bndgrafdat.s.verttax[bndvertnnd + 1] - bndgrafdat.s.verttax[bndvertnnd])) + bnddegrmax = (bndgrafdat.s.verttax[bndvertnnd + 1] - bndgrafdat.s.verttax[bndvertnnd]); + if (bnddegrmax < (bndgrafdat.s.verttax[bndvertnnd + 2] - bndgrafdat.s.verttax[bndvertnnd + 1])) + bnddegrmax = (bndgrafdat.s.verttax[bndvertnnd + 2] - bndgrafdat.s.verttax[bndvertnnd + 1]); + bndgrafdat.s.degrmax = bnddegrmax; + bndgrafdat.s.edgetax = (Gnum *) memRealloc ((void *) (bndgrafdat.s.edgetax + orggrafptr->s.baseval), bndgrafdat.s.edgenbr * sizeof (Gnum)) - orggrafptr->s.baseval; + + bndgrafdat.frontab = queudat.qtab + bndgrafdat.s.vertnbr; /* Recycle end of queue array and part of index array as band frontier array */ + for (fronnum = 0, bndvertnum = orggrafptr->s.baseval; /* Fill band frontier array with first vertex indices as they make the separator */ + fronnum < orggrafptr->fronnbr; fronnum ++, bndvertnum ++) + bndgrafdat.frontab[fronnum] = bndvertnum; + + bndgrafdat.compload[0] = orggrafptr->compload[0]; + bndgrafdat.compload[1] = orggrafptr->compload[1]; + bndgrafdat.compload[2] = orggrafptr->compload[2]; + bndgrafdat.comploaddlt = orggrafptr->comploaddlt; + bndgrafdat.compsize[0] = bndvertnbr - bndcompsize1 - orggrafptr->fronnbr + 1; /* "+ 1" for anchor vertices */ + bndgrafdat.compsize[1] = bndcompsize1 + 1; + bndgrafdat.fronnbr = orggrafptr->fronnbr; + bndgrafdat.levlnum = orggrafptr->levlnum; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((graphCheck (&bndgrafdat.s) != 0) || /* Check band graph consistency */ + (vgraphCheck (&bndgrafdat) != 0)) { + errorPrint ("vgraphSeparateBd: inconsistent band graph data"); + bndgrafdat.frontab = NULL; /* Do not free frontab as it is not allocated */ + vgraphExit (&bndgrafdat); + memFree (queudat.qtab); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + if (vgraphSeparateSt (&bndgrafdat, paraptr->stratbnd) != 0) { /* Apply strategy to band graph */ + errorPrint ("vgraphSeparateBd: cannot separate band graph"); + bndgrafdat.frontab = NULL; /* Do not free frontab as it is not allocated */ + vgraphExit (&bndgrafdat); + memFree (queudat.qtab); + return (1); + } + if ((bndgrafdat.parttax[bndvertnnd] != 0) || /* If band graph was too small and anchors changed parts, apply strategy on full graph */ + (bndgrafdat.parttax[bndvertnnd + 1] != 1)) { + bndgrafdat.frontab = NULL; /* Do not free frontab as it is not allocated */ + vgraphExit (&bndgrafdat); + memFree (queudat.qtab); + return (vgraphSeparateSt (orggrafptr, paraptr->stratorg)); + } + + orggrafptr->compload[0] = bndgrafdat.compload[0]; + orggrafptr->compload[1] = bndgrafdat.compload[1]; + orggrafptr->compload[2] = bndgrafdat.compload[2]; + orggrafptr->comploaddlt = bndgrafdat.comploaddlt; + orggrafptr->compsize[0] = orggrafptr->compsize[0] - (bndvertnbr - bndcompsize1 - orggrafptr->fronnbr) + bndgrafdat.compsize[0] - 1; /* "- 1" for anchors */ + orggrafptr->compsize[1] = orggrafptr->compsize[1] - bndcompsize1 + bndgrafdat.compsize[1] - 1; + orggrafptr->fronnbr = bndgrafdat.fronnbr; + + for (bndvertnum = bndgrafdat.s.baseval; bndvertnum < bndvertnnd; bndvertnum ++) /* Update part array of full graph */ + orggrafptr->parttax[bndvnumtax[bndvertnum]] = bndgrafdat.parttax[bndvertnum]; + for (fronnum = 0; fronnum < bndgrafdat.fronnbr; fronnum ++) /* Update frontier array of full graph */ + orggrafptr->frontab[fronnum] = bndgrafdat.s.vnumtax[bndgrafdat.frontab[fronnum]]; + + bndgrafdat.frontab = NULL; /* Do not free frontab as it is not allocated */ + vgraphExit (&bndgrafdat); /* Free band graph structures */ + memFree (queudat.qtab); + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vgraphCheck (orggrafptr) != 0) { + errorPrint ("vgraphSeparateBd: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_bd.h b/scotch_6.0.3/src/libscotch/vgraph_separate_bd.h new file mode 100644 index 00000000..e2028b2b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_bd.h @@ -0,0 +1,83 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_bd.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** : Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the separation graph banding **/ +/** module. **/ +/** **/ +/** DATES : Version 5.0 : from : 18 oct 2004 **/ +/** to : 16 sep 2006 **/ +/** Version 5.1 : from : 30 oct 2007 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VgraphSeparateBdParam_ { + Gnum distmax; /*+ Maximum distance to separator +*/ + Strat * stratbnd; /*+ Strategy for band graph +*/ + Strat * stratorg; /*+ Strategy for original graph +*/ +} VgraphSeparateBdParam; + +/*+ Neighbor queue. +*/ + +typedef struct VgraphSeparateBdQueue_ { + Gnum * head; /*+ Head of distance queue +*/ + Gnum * tail; /*+ Tail of distance queue +*/ + Gnum * qtab; /*+ Array of queue elements +*/ +} VgraphSeparateBdQueue; + +/* +** The function prototypes. +*/ + +int vgraphSeparateBd (Vgraph * restrict const, const VgraphSeparateBdParam * restrict const); + +/* +** The macro definitions. +*/ + +#define vgraphSeparateBdQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) +#define vgraphSeparateBdQueueEmpty(queue) ((queue)->head <= (queue)->tail) +#define vgraphSeparateBdQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) +#define vgraphSeparateBdQueueGet(queue) (* ((queue)->tail ++)) diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_df.c b/scotch_6.0.3/src/libscotch/vgraph_separate_df.c new file mode 100644 index 00000000..bb1f413f --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_df.c @@ -0,0 +1,287 @@ +/* Copyright 2007,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_df.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module computes a separator of **/ +/** a separation graph by using a diffusion **/ +/** scheme. **/ +/** **/ +/** NOTES : # This algorithm has been designed to **/ +/** work on band graphs only, for which **/ +/** the two anchor vertices are the two **/ +/** last vertices, the before-last as **/ +/** anchor of part 0, and the last as **/ +/** anchor of part 1. **/ +/** **/ +/** DATES : # Version 5.1 : from : 29 oct 2007 **/ +/** to 24 may 2008 **/ +/** # Version 6.0 : from : 24 dec 2013 **/ +/** to 24 dec 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_DF + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_df.h" + +/* +** The static variables. +*/ + +static const Gnum vgraphseparatedfloadone = 1; + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the separation. +** It returns: +** - 0 : if the separator could be computed. +** - 1 : on error. +*/ + +int +vgraphSeparateDf ( +Vgraph * restrict const grafptr, /*+ Active graph +*/ +const VgraphSeparateDfParam * const paraptr) /*+ Method parameters +*/ +{ + float * restrict edlstax; /* Degree array */ + float * restrict difotax; /* Old diffusion value array */ + float * restrict difntax; /* New diffusion value array */ + float * restrict difttax; /* Temporary swap value */ + float cdifval; + float cremval; + Gnum fronnum; + Gnum compload0avg; + Gnum compload2; + Gnum compsize1; + float veloval; + float vanctab[2]; + INT movenum; + INT passnum; + + const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + Gnum * restrict const frontab = grafptr->frontab; + GraphPart * restrict const parttax = grafptr->parttax; + + if (memAllocGroup ((void **) (void *) + &edlstax, (size_t) (grafptr->s.vertnbr * sizeof (float)), + &difotax, (size_t) (grafptr->s.vertnbr * sizeof (float)), + &difntax, (size_t) (grafptr->s.vertnbr * sizeof (float)), NULL) == NULL) { + errorPrint ("vgraphSeparateDf: out of memory"); + return (1); + } + edlstax -= grafptr->s.baseval; /* Base access to edlstax and diffusion arrays */ + difotax -= grafptr->s.baseval; + difntax -= grafptr->s.baseval; + + if (grafptr->s.edlotax == NULL) { /* If graph has no edge weights */ + Gnum vertnum; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) + edlstax[vertnum] = (float) (vendtax[vertnum] - verttax[vertnum]); + } + else { /* If graph has edge weights */ + Gnum vertnum; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum edgenum; + Gnum edlosum; + + for (edgenum = verttax[vertnum], edlosum = 0; + edgenum < vendtax[vertnum]; edgenum ++) + edlosum += grafptr->s.edlotax[edgenum]; + + edlstax[vertnum] = (float) edlosum; + } + } + + compload0avg = grafptr->compload[0] + grafptr->compload[2] / 2; + + passnum = 0; + do { + const Gnum * restrict velobax; + Gnum velomsk; + Gnum vertnum; + Gnum compload0; + Gnum compload1; + int rootval; /* Root part for separator vertices */ + + compload0 = compload0avg - grafptr->compload[2] / 2; + compload1 = grafptr->s.velosum - compload0avg - (grafptr->compload[2] + 1) / 2; + vanctab[0] = (float) (- compload0); /* Values to be injected to anchor vertices at every iteration */ + vanctab[1] = (float) compload1 - VGRAPHSEPARATEDFEPSILON; /* Slightly tilt value to add to part 1 */ + rootval = (paraptr->partval + passnum) & 1; /* Compute index of part which will receive separator vertices */ + if (rootval == 0) /* If separator must be aggregated to part 0 */ + vanctab[0] -= (float) grafptr->compload[2]; + else + vanctab[1] += (float) grafptr->compload[2]; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd - 2; vertnum ++) + difotax[vertnum] = 0.0F; + difotax[grafptr->s.vertnnd - 2] = vanctab[0] / edlstax[grafptr->s.vertnnd - 2]; /* Load anchor vertices for first move */ + difotax[grafptr->s.vertnnd - 1] = vanctab[1] / edlstax[grafptr->s.vertnnd - 1]; + + veloval = 1.0F; /* Assume no vertex loads */ + cdifval = paraptr->cdifval; + cremval = paraptr->cremval; + for (movenum = 0; movenum < paraptr->movenbr; movenum ++) { /* For all moves */ + Gnum vertnum; + Gnum vertnnd; + float vancval; /* Value to load vertex with if anchor */ + + vancval = 0.0F; /* At first vertices are not anchors */ + vertnum = grafptr->s.baseval; + vertnnd = grafptr->s.vertnnd - 2; + while (1) { + for ( ; vertnum < vertnnd; vertnum ++) { + Gnum edgenum; + Gnum edgennd; + float diffval; + + edgenum = verttax[vertnum]; + edgennd = vendtax[vertnum]; + diffval = 0.0F; + if (grafptr->s.edlotax != NULL) + for ( ; edgenum < edgennd; edgenum ++) + diffval += difotax[edgetax[edgenum]] * (float) grafptr->s.edlotax[edgenum]; + else + for ( ; edgenum < edgennd; edgenum ++) + diffval += difotax[edgetax[edgenum]]; + + if (grafptr->s.velotax != NULL) + veloval = (float) grafptr->s.velotax[vertnum]; + diffval *= cdifval; + diffval += difotax[vertnum] * cremval * edlstax[vertnum]; + if (diffval >= 0.0F) { + diffval -= veloval; + if (diffval <= 0.0F) + diffval = +VGRAPHSEPARATEDFEPSILON; + } + else { + diffval += veloval; + if (diffval >= 0.0F) + diffval = -VGRAPHSEPARATEDFEPSILON; + } + if (isnan (diffval)) /* If overflow occured */ + goto abort; /* Exit main loop without swapping arrays so as to keep last valid iteration */ + + difntax[vertnum] = diffval / edlstax[vertnum]; /* Prepare vertex for diffusion */ + } + if (vertnum == grafptr->s.vertnnd) /* If all vertices processed, exit intermediate infinite loop */ + break; + + vertnnd ++; /* Prepare to go only for one more run */ + vancval = vanctab[vertnum - grafptr->s.vertnnd + 2]; /* Load variable with anchor value */ + } + + difttax = difntax; /* Swap old and new diffusion arrays */ + difntax = difotax; + difotax = difttax; + } +abort : /* If overflow occured, resume here */ + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) /* Pre-set parts without separator */ + parttax[vertnum] = (difotax[vertnum] <= 0.0F) ? 0 : 1; + + if (grafptr->s.velotax != NULL) { + velobax = grafptr->s.velotax; + velomsk = ~((Gnum) 0); + } + else { + velobax = &vgraphseparatedfloadone; + velomsk = 0; + } + + veloval = 1.0F; /* Assume no vertex loads */ + for (vertnum = grafptr->s.baseval, fronnum = compsize1 = compload1 = compload2 = 0; + vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum partval; + GraphPart partend; + Gnum veloval; + + partend = parttax[vertnum] ^ 1; + partval = (Gnum) parttax[vertnum]; + veloval = velobax[vertnum & velomsk]; + compsize1 += partval; /* Here, part is 0 or 1 only */ + compload1 += partval * veloval; + if (partval == (Gnum) rootval) { /* Only vertices of aggregated part can be in separator */ + Gnum edgenum; + + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + if (parttax[edgetax[edgenum]] == partend) { /* If end vertex is in other part (and not in separator) */ + frontab[fronnum ++] = vertnum; /* Record it */ + parttax[vertnum] = 2; + compload2 += veloval; + break; /* No need to go further */ + } + } + } + } + grafptr->compload[0] = grafptr->s.velosum - compload1; + grafptr->compload[1] = compload1; + grafptr->compload[2] = compload2; + grafptr->compload[rootval] -= compload2; + grafptr->comploaddlt = grafptr->compload[0] - grafptr->compload[1]; + grafptr->compsize[0] = grafptr->s.vertnbr - compsize1; + grafptr->compsize[1] = compsize1; + grafptr->compsize[rootval] -= fronnum; + grafptr->fronnbr = fronnum; + } while (++ passnum < paraptr->passnbr); /* As long as not all passes performed */ + + memFree (edlstax + grafptr->s.baseval); /* Free group leader */ + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vgraphCheck (grafptr) != 0) { + errorPrint ("vgraphSeparateDf: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_df.h b/scotch_6.0.3/src/libscotch/vgraph_separate_df.h new file mode 100644 index 00000000..20ac5b83 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_df.h @@ -0,0 +1,79 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_df.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the diffusion vertex separation **/ +/** method. **/ +/** **/ +/** DATES : # Version 5.1 : from : 29 oct 2007 **/ +/** to 24 may 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/* Small non-zero float value. */ + +#define VGRAPHSEPARATEDFEPSILON (1.0F / (float) (GNUMMAX)) + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct VgraphSeparateDfParam_ { + INT partval; /*+ Part to aggregate to separator +*/ + INT movenbr; /*+ Number of moves to do +*/ + INT passnbr; /*+ Number of passes to do +*/ + double cdifval; /*+ Coefficient of diffused load +*/ + double cremval; /*+ Coefficient of remaining load +*/ +} VgraphSeparateDfParam; + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_DF +#define static +#endif + +int vgraphSeparateDf (Vgraph * restrict const, const VgraphSeparateDfParam * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_es.c b/scotch_6.0.3/src/libscotch/vgraph_separate_es.c new file mode 100644 index 00000000..1c9dcd73 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_es.c @@ -0,0 +1,767 @@ +/* Copyright 2004,2007,2008,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_es.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a matrix ordering software. **/ +/** This module computes the node separator **/ +/** of a graph based on the edge-separation **/ +/** module of "bgraph_bipart_st.c". **/ +/** **/ +/** DATES : # Version 3.2 : from : 17 oct 1996 **/ +/** to : 07 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 18 aug 2004 **/ +/** to 20 aug 2004 **/ +/** # Version 5.0 : from : 24 jan 2007 **/ +/** to 12 sep 2007 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to 09 nov 2008 **/ +/** **/ +/** NOTES : # This algorithm comes from: **/ +/** "Computing the Block Triangular form **/ +/** of a Sparse Matrix", A. Pothen and **/ +/** C.-J. Fan, ACM Trans. on Mathematical **/ +/** Software, 16 (4), pp 303-324, 1990. **/ +/** and from: **/ +/** "Implementations of $O(n^{1/2}\tau)$ **/ +/** assignment algorithms", I. Duff and **/ +/** T. Wieberg, ACM Trans. on Math. **/ +/** Software, 4, pp 267-287, 1988. **/ +/** **/ +/** # The choice of the separator to take, **/ +/** either HR u SC u VC or HR u SR u VC, **/ +/** is made regarding the size of the **/ +/** separator only, irrespective of its **/ +/** balance. This choice is made because **/ +/** else an imbalance ratio should be **/ +/** provided for this method, and because **/ +/** it is assumed that the edge biparti- **/ +/** tioning method is assumed to have **/ +/** reached suitable balance. When they **/ +/** are equal, the choice is biased **/ +/** towards SR, because the xC block is **/ +/** the one which has less vertices so **/ +/** removing more separator vertices from **/ +/** it would mean increasing imbalance. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_ES + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "vgraph.h" +#include "vgraph_separate_es.h" + +/*********************************************/ +/* */ +/* These routines compute a vertex separator */ +/* from an edge separator represented as a */ +/* bipartite graph, by minimum covering. */ +/* */ +/*********************************************/ + +/* This routine computes a vertex separator +** from an edge separator represented as a +** bipartite graph, by minimum covering. +** It returns: +** - 0 : if a separator could be computed. +** - !0 : on error. +*/ + +static +int +vgraphSeparateEsCover ( +const Graph * restrict const grafptr, /* Bipartite graph to cover */ +const Gnum partnbr, /* Number of vertices in first part */ +Gnum * const sepatab, /* Array of covering vertices */ +Gnum * const sepaptr) /* Pointer to size of the array */ +{ + Gnum * restrict levltax; /* Array of vertex level values */ + Gnum levlmax; /* Maximum level searched */ + Gnum * restrict listtab; /* List of reachable augmenting rows */ + Gnum listnbr; /* Number of items in list */ + Gnum * restrict matetax; /* Matching array */ + Gnum * queutab; /* Queue of (free) column nodes */ + Gnum * restrict queuhead; /* Head of queue */ + Gnum * restrict queutail; /* Tail of queue */ + VgraphSeparateEsTrav * restrict travtax; /* Array of traversal flag values */ + VgraphSeparateEsType * restrict typetax; /* Vertex type in the graph */ + Gnum loadcval; /* Load of subset (HR u SC u VC) */ + Gnum loadrval; /* Load of subset (HR u SR u VC) */ + Gnum sizecval; /* Load of subset (HR u SC u VC) */ + Gnum sizerval; /* Load of subset (HR u SR u VC) */ + Gnum vertnum; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (sizeof (VgraphSeparateEsType) > sizeof (VgraphSeparateEsTrav)) { /* Assert next trick will work */ + errorPrint ("vgraphSeparateEsCover: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + if (memAllocGroup ((void **) (void *) + &travtax, (size_t) (grafptr->vertnbr * sizeof (VgraphSeparateEsTrav)), /* TRICK: VgraphSeparateEsType should also fit */ + &matetax, (size_t) (grafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("vgraphSeparateEsCover: out of memory (1)"); + return (1); + } + if (memAllocGroup ((void **) (void *) + &queutab, (size_t) (partnbr * sizeof (Gnum)), + &levltax, (size_t) (grafptr->vertnbr * sizeof (Gnum)), + &listtab, (size_t) (grafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("vgraphSeparateEsCover: out of memory (2)"); + memFree (travtax); /* Not based yet */ + return (1); + } + travtax -= grafptr->baseval; + matetax -= grafptr->baseval; + levltax -= grafptr->baseval; + + memSet (matetax + (partnbr + grafptr->baseval), ~0, (grafptr->vertnbr - partnbr) * sizeof (Gnum)); + for (vertnum = grafptr->baseval; /* Compute a cheap matching */ + vertnum < (partnbr + grafptr->baseval); vertnum ++) { + Gnum edgenum; + Gnum matenum; + + for (edgenum = grafptr->verttax[vertnum], matenum = ~0; /* Search a matching end vertex */ + edgenum < grafptr->vendtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = grafptr->edgetax[edgenum]; + if (matetax[vertend] == ~0) { /* If an unmatched end vertex is found */ + matenum = vertend; + matetax[vertend] = vertnum; + break; + } + } + matetax[vertnum] = matenum; + } + + do { /* Matching augmentation loop */ + queuhead = /* Flush the data structures */ + queutail = queutab; + listnbr = 0; + memSet (levltax + grafptr->baseval, 0, grafptr->vertnbr * sizeof (Gnum)); + memSet (travtax + grafptr->baseval, 0, grafptr->vertnbr * sizeof (VgraphSeparateEsTrav)); + levlmax = ~0; + + for (vertnum = grafptr->baseval; /* Enqueue unmatched column nodes */ + vertnum < (partnbr + grafptr->baseval); vertnum ++) { + if (matetax[vertnum] == ~0) { + *queuhead ++ = vertnum; + levltax[vertnum] = 1; + } + } + + while (queuhead > queutail) { /* As long as there are free columns */ + Gnum vertcol; + + vertcol = *queutail ++; /* Get the free column vertex */ + if (levltax[vertcol] < levlmax) { + Gnum edgenum; + + travtax[vertcol] = VGRAPHSEPAESTRAVUSED; /* Column has been reached */ + + for (edgenum = grafptr->verttax[vertcol]; /* For all neighboring rows */ + edgenum < grafptr->vendtax[vertcol]; edgenum ++) { + Gnum vertrow; + + vertrow = grafptr->edgetax[edgenum]; + if (travtax[vertrow] == VGRAPHSEPAESTRAVFREE) { /* If row not yet reached yet */ + travtax[vertrow] = VGRAPHSEPAESTRAVUSED; /* Now it is */ + if (matetax[vertrow] == ~0) { /* If row is unmatched */ + listtab[listnbr ++] = vertrow; /* Put it in list */ + levlmax = levltax[vertcol]; /* Do not go any further */ + } + else { /* Row is matched */ + *queuhead ++ = matetax[vertrow]; /* Enqueue its matching column */ + levltax[matetax[vertrow]] = levltax[vertcol] + 1; + } + } + } + } + } + + if (listnbr <= 0) /* If no free rows could be reached */ + break; /* Then the matching is maximal */ + + while (-- listnbr >= 0) /* For all rows in list, try to augment the matching */ + vgraphSeparateEsCoverAugment (levltax, levlmax, matetax, travtax, grafptr->verttax, grafptr->vendtax, grafptr->edgetax, listtab[listnbr]); + } while (1); + + memFree (queutab); /* Free group leader of arrays no longer in use */ + typetax = (VgraphSeparateEsType *) travtax; /* TRICK: re-use traversal table as type table */ + + for (vertnum = grafptr->baseval; vertnum < (partnbr + grafptr->baseval); vertnum ++) /* Pre-set vertex types */ + typetax[vertnum] = VGRAPHSEPAESTYPESC; + for ( ; vertnum < grafptr->vertnnd; vertnum ++) + typetax[vertnum] = VGRAPHSEPAESTYPESR; + for (vertnum = grafptr->baseval; vertnum < (partnbr + grafptr->baseval); vertnum ++) /* For all column vertices */ + if (matetax[vertnum] == ~0) /* If vertex is unmatched */ + vgraphSeparateEsCoverCol (matetax, typetax, grafptr->verttax, grafptr->vendtax, grafptr->edgetax, vertnum); /* Find HC and HR */ + for ( ; vertnum < grafptr->vertnnd; vertnum ++) /* For all row vertices */ + if (matetax[vertnum] == ~0) /* If vertex is unmatched */ + vgraphSeparateEsCoverRow (matetax, typetax, grafptr->verttax, grafptr->vendtax, grafptr->edgetax, vertnum); /* Find VC and VR */ + + sizecval = /* Reset sizes */ + sizerval = 0; + if (grafptr->velotax != NULL) { /* If graph vertices are weighted */ + Gnum vertnum; + + loadcval = /* Reset loads */ + loadrval = 0; + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { /* Accumulate loads */ + VgraphSeparateEsType typeval; + Gnum veloval; + Gnum bitcval; + Gnum bitrval; + + typeval = typetax[vertnum]; + veloval = grafptr->velotax[vertnum]; + bitcval = (typeval >> VGRAPHSEPAESTYPEBITC) & 1; + bitrval = typeval >> VGRAPHSEPAESTYPEBITR; /* TRICK: highest bit so does not need mask */ + + loadcval += bitcval * veloval; /* Superscalar update */ + loadrval += bitrval * veloval; + sizecval += bitcval; + sizerval += bitrval; + } + } + else { /* Graph vertices are not weighted */ + Gnum vertnum; + + for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { /* Accumulate vertex sizes */ + sizecval += (typetax[vertnum] >> VGRAPHSEPAESTYPEBITC) & 1; /* Superscalar update */ + sizerval += typetax[vertnum] >> VGRAPHSEPAESTYPEBITR; /* TRICK: highest bit so does not need mask */ + } + loadcval = sizecval; /* Loads equal sizes */ + loadrval = sizerval; + } + + if (loadcval < loadrval) { /* If separator with SC is smaller */ + Gnum vertnum; + Gnum sepanum; + + *sepaptr = sizecval; + + for (vertnum = grafptr->baseval, sepanum = 0; + vertnum < grafptr->vertnnd; vertnum ++) { + if ((typetax[vertnum] & VGRAPHSEPAESTYPEHRSCVC) != 0) { +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((sepanum >= sizecval) || + ((typetax[vertnum] != VGRAPHSEPAESTYPEHR) && + (typetax[vertnum] != VGRAPHSEPAESTYPESC) && + (typetax[vertnum] != VGRAPHSEPAESTYPEVC))) { + errorPrint ("vgraphSeparateEsCover: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + sepatab[sepanum ++] = vertnum; + } + } +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (sepanum != sizecval) { + errorPrint ("vgraphSeparateEsCover: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + } + else { /* If separator with SR is smaller */ + Gnum vertnum; + Gnum sepanum; + + *sepaptr = sizerval; + + for (vertnum = grafptr->baseval, sepanum = 0; + vertnum < grafptr->vertnnd; vertnum ++) { + if ((typetax[vertnum] & VGRAPHSEPAESTYPEHRSRVC) != 0) { +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((sepanum >= sizerval) || + ((typetax[vertnum] != VGRAPHSEPAESTYPEHR) && + (typetax[vertnum] != VGRAPHSEPAESTYPESR) && + (typetax[vertnum] != VGRAPHSEPAESTYPEVC))) { + errorPrint ("vgraphSeparateEsCover: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + sepatab[sepanum ++] = vertnum; + } + } +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (sepanum != sizerval) { + errorPrint ("vgraphSeparateEsCover: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + } + + memFree (travtax + grafptr->baseval); /* Free group leader of remaining arrays */ + + return (0); +} + +/* This routine augments the current matching +** by performing a backtracking depth-first +** search from a free row vertex to a free +** column vertex, guided by the level values. +** It returns: +** - 0 : backtracking succeeded. +** - !0 : could not find a valid return path. +*/ + +static +int +vgraphSeparateEsCoverAugment ( +const Gnum * restrict const levltax, +const Gnum levlcur, /* Current backtracking level */ +Gnum * restrict const matetax, +VgraphSeparateEsTrav * restrict const travtax, +const Gnum * restrict const verttax, +const Gnum * restrict const vendtax, +const Gnum * restrict const edgetax, +const Gnum vertrow) /* Row vertex to backtrack from */ +{ + Gnum edgenum; + + travtax[vertrow] = VGRAPHSEPAESTRAVDRTY; /* Never re-use this row */ + + for (edgenum = verttax[vertrow]; edgenum < vendtax[vertrow]; edgenum ++) { + Gnum vertcol; + + vertcol = edgetax[edgenum]; /* Get column vertex */ + if ((travtax[vertcol] == VGRAPHSEPAESTRAVUSED) && /* If this column may be a backtracking path */ + (levltax[vertcol] == levlcur)) { /* At the proper distance from a free column */ + travtax[vertcol] = VGRAPHSEPAESTRAVDRTY; /* Never re-use this column */ + if ((levlcur == 1) || /* If we have (recursively) reached a free column vertex */ + (vgraphSeparateEsCoverAugment (levltax, levlcur - 1, matetax, travtax, verttax, vendtax, edgetax, matetax[vertcol]) == 0)) { + matetax[vertcol] = vertrow; /* Switch the edges of the augmenting path */ + matetax[vertrow] = vertcol; + return (0); /* Backtracking process is under way */ + } + } + } + + return (1); /* No improvement could be done */ +} + +/* Starting from unmatched column and row vertices, +** these routines perform depth-first traversals of +** the bipartite graph, following alternating paths. +** It is assumed that the matchings are sufficently +** large, so that the depth of the trees is small +** and the stack will not overflow. +** They return: +** - VOID : in all cases. +*/ + +static +void +vgraphSeparateEsCoverCol ( +const Gnum * restrict const matetax, +VgraphSeparateEsType * restrict const typetax, +const Gnum * restrict const verttax, +const Gnum * restrict const vendtax, +const Gnum * restrict const edgetax, +const Gnum vertcol) /* Column vertex index */ +{ + Gnum edgenum; + + if (typetax[vertcol] == VGRAPHSEPAESTYPEHC) /* If vertex already traversed */ + return; + + typetax[vertcol] = VGRAPHSEPAESTYPEHC; + + for (edgenum = verttax[vertcol]; edgenum < vendtax[vertcol]; edgenum ++) { + Gnum vertrow; + + vertrow = edgetax[edgenum]; + if (typetax[vertrow] == VGRAPHSEPAESTYPEHR) /* If end vertex already traversed */ + continue; /* Skip to next vertex */ + typetax[vertrow] = VGRAPHSEPAESTYPEHR; + if (matetax[vertrow] != ~0) /* If end vertex matched */ + vgraphSeparateEsCoverCol (matetax, typetax, verttax, vendtax, edgetax, matetax[vertrow]); + } +} + +static +void +vgraphSeparateEsCoverRow ( +const Gnum * restrict const matetax, +VgraphSeparateEsType * restrict const typetax, +const Gnum * restrict const verttax, +const Gnum * restrict const vendtax, +const Gnum * restrict const edgetax, +const Gnum vertrow) /* Row vertex index */ +{ + Gnum edgenum; + + if (typetax[vertrow] == VGRAPHSEPAESTYPEVR) /* If vertex already traversed */ + return; + + typetax[vertrow] = VGRAPHSEPAESTYPEVR; + + for (edgenum = verttax[vertrow]; edgenum < vendtax[vertrow]; edgenum ++) { + Gnum vertcol; + + vertcol = edgetax[edgenum]; + if (typetax[vertcol] == VGRAPHSEPAESTYPEVC) /* If end vertex already traversed */ + continue; /* Skip to next vertex */ + typetax[vertcol] = VGRAPHSEPAESTYPEVC; + if (matetax[vertcol] != ~0) /* If end vertex matched */ + vgraphSeparateEsCoverRow (matetax, typetax, verttax, vendtax, edgetax, matetax[vertcol]); + } +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine separates the given graph by first +** computing an edge separator, according to the +** given bipartitioning strategy, and then turning +** it into a vertex separator. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +vgraphSeparateEs ( +Vgraph * restrict const grafptr, /*+ Active graph +*/ +const VgraphSeparateEsParam * const paraptr) /*+ Method parameters +*/ +{ + Bgraph actgrafdat; /* Active graph structure */ + Graph bipgrafdat; /* Bipartite graph structure */ + + actgrafdat.s = grafptr->s; /* Initialize active graph */ + actgrafdat.s.flagval = grafptr->s.flagval & ~(GRAPHFREETABS | BGRAPHFREEPART | BGRAPHFREEFRON); + actgrafdat.s.vnumtax = NULL; + actgrafdat.s.vlbltax = NULL; + actgrafdat.veextax = NULL; /* No external gains */ + actgrafdat.parttax = grafptr->parttax; /* Inherit arrays from vertex separation graph */ + actgrafdat.frontab = grafptr->frontab; + bgraphInit2 (&actgrafdat, 1, 1, 1, 0, 0); /* Complete initialization and set all vertices to part 0 */ + + if (bgraphBipartSt (&actgrafdat, paraptr->strat) != 0) { /* Bipartition active subgraph */ + errorPrint ("vgraphSeparateEs: cannot bipartition active graph"); + return (1); + } + + grafptr->compload[0] = actgrafdat.compload0; /* Reset vertex counts */ + grafptr->compload[1] = actgrafdat.s.velosum - actgrafdat.compload0; + grafptr->compsize[0] = actgrafdat.compsize0; + grafptr->compsize[1] = actgrafdat.s.vertnbr - actgrafdat.compsize0; + + if (actgrafdat.fronnbr > 0) { /* If edge separator is not empty */ + if (paraptr->widtval == VGRAPHSEPAESWIDTHTHIN) { /* If thin vertex separator wanted */ + Gnum * restrict actvnumtax; + Gnum actfronnum; + Gnum bipvelosum; + Gnum bipedgenbr; /* Number of edges in bipartite graph (i.e. arcs) */ + Gnum bipedgenbr0; /* Number of edges adjacent to part 0 */ + Gnum bipedgenbr1; /* Number of edges adjacent to part 1 */ + Gnum bipvertnbr0; /* Number of vertices in part 0 */ + Gnum bipvertnbr1; /* Number of vertices in part 1 */ + Gnum bipvertnbrp; /* Number of vertices in part put in first place */ + Gnum bippartval; /* Part of bipartite graph to be put in first place */ + Gnum compsizep; /* Number of vertices to be removed from part p */ + Gnum compload01; /* Load of vertices to be removed from both parts */ + Gnum comploadp; /* Load of vertices to be removed from part p */ + + if ((actvnumtax = (Gnum *) memAlloc (actgrafdat.s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("vgraphSeparateEs: out of memory (1)"); + return (1); + } +#ifdef SCOTCH_DEBUG_VGRAPH2 + memSet (actvnumtax, ~0, actgrafdat.s.vertnbr * sizeof (Gnum)); +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + actvnumtax -= actgrafdat.s.baseval; + + bipedgenbr = 0; /* Initialize bipartite graph counts */ + bipvertnbr0 = + bipvertnbr1 = 0; + for (actfronnum = 0; actfronnum < actgrafdat.fronnbr; actfronnum ++) { /* For all frontier vertices */ + Gnum actvertnum; + int actpartval; + Gnum actedgenum; + + actvertnum = grafptr->frontab[actfronnum]; + actpartval = grafptr->parttax[actvertnum]; + + if (actpartval == 0) { /* Count separator edges only for nodes of one side and multply by 2 */ + for (actedgenum = actgrafdat.s.verttax[actvertnum]; + actedgenum < actgrafdat.s.vendtax[actvertnum]; actedgenum ++) + bipedgenbr += (actpartval ^ grafptr->parttax[actgrafdat.s.edgetax[actedgenum]]); + } + + actvnumtax[actvertnum] = actpartval * (bipvertnbr1 - bipvertnbr0) + bipvertnbr0; /* Count and number separator vertices on each side */ + bipvertnbr0 += actpartval ^ 1; /* Superscalar update */ + bipvertnbr1 += actpartval; + } + bipedgenbr *= 2; /* Count both sides of arcs */ + + bipgrafdat.flagval = GRAPHFREEVERT | GRAPHVERTGROUP; /* Initialize bipartite graph structure */ + bipgrafdat.baseval = 0; /* Base bipartite graph from 0 */ + bipgrafdat.vertnbr = + bipgrafdat.vertnnd = bipvertnbr0 + bipvertnbr1; + if (memAllocGroup ((void **) (void *) + &bipgrafdat.verttax, (size_t) ((bipgrafdat.vertnbr + 1) * sizeof (Gnum)), + &bipgrafdat.velotax, (size_t) ((actgrafdat.s.velotax != NULL) ? (bipgrafdat.vertnbr * sizeof (Gnum)) : 0), + &bipgrafdat.vnumtax, (size_t) (bipgrafdat.vertnbr * sizeof (Gnum)), + &bipgrafdat.edgetax, (size_t) (bipedgenbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("vgraphSeparateEs: out of memory (2)"); + memFree (actvnumtax + actgrafdat.s.baseval); + return (1); + } + bipgrafdat.vendtax = bipgrafdat.verttax + 1; + if (actgrafdat.s.velotax == NULL) + bipgrafdat.velotax = NULL; + bipgrafdat.vlbltax = NULL; + bipgrafdat.edgenbr = bipedgenbr; + bipgrafdat.edlotax = NULL; + bipgrafdat.edlosum = bipedgenbr; + bipgrafdat.degrmax = grafptr->s.degrmax; + + bippartval = (bipvertnbr0 <= bipvertnbr1) ? 0 : 1; /* Select smallest part to be placed first */ + if (bippartval == 0) { + bipvertnbrp = bipvertnbr0; + bipedgenbr0 = 0; + bipedgenbr1 = bipedgenbr / 2; + } + else { + bipvertnbrp = bipvertnbr1; + bipedgenbr0 = bipedgenbr / 2; + bipedgenbr1 = 0; + } + + bipvelosum = 0; + for (actfronnum = 0; actfronnum < actgrafdat.fronnbr; actfronnum ++) { /* For all frontier vertices */ + Gnum actvertnum; + int actpartval; + Gnum bipvertnum; + Gnum actedgenum; + + actvertnum = grafptr->frontab[actfronnum]; + actpartval = grafptr->parttax[actvertnum]; + + bipvertnum = (actpartval ^ bippartval) * bipvertnbrp + actvnumtax[actvertnum]; + + if (bipgrafdat.velotax != NULL) { + Gnum actveloval; + + actveloval = actgrafdat.s.velotax[actvertnum]; + bipvelosum += actveloval; + bipgrafdat.velotax[bipvertnum] = actveloval; + } + bipgrafdat.vnumtax[bipvertnum] = actvertnum; + bipgrafdat.verttax[bipvertnum] = actpartval * (bipedgenbr1 - bipedgenbr0) + bipedgenbr0; + + for (actedgenum = actgrafdat.s.verttax[actvertnum]; /* Count separator edges */ + actedgenum < actgrafdat.s.vendtax[actvertnum]; actedgenum ++) { + Gnum actvertend; + int actpartend; + + actvertend = actgrafdat.s.edgetax[actedgenum]; + actpartend = grafptr->parttax[actvertend]; + if (actpartend != actpartval) { + Gnum bipedgenum; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (actvnumtax[actvertend] == ~0) { + errorPrint ("vgraphSeparateEs: internal error (1)"); + graphExit (&bipgrafdat); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + bipedgenum = actpartval * (bipedgenbr1 - bipedgenbr0) + bipedgenbr0; + bipedgenbr0 += actpartval ^ 1; /* Superscalar update */ + bipedgenbr1 += actpartval; + bipgrafdat.edgetax[bipedgenum] = actvnumtax[actvertend] + (actpartend ^ bippartval) * bipvertnbrp; + } + } + } + bipgrafdat.verttax[bipgrafdat.vertnbr] = bipgrafdat.edgenbr; + bipgrafdat.velosum = (bipgrafdat.velotax != NULL) ? bipvelosum : bipgrafdat.vertnbr; + + memFree (actvnumtax + actgrafdat.s.baseval); + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (((bipedgenbr0 - bipedgenbr1) * bippartval + bipedgenbr1) != bipgrafdat.edgenbr) { + errorPrint ("vgraphSeparateEs: internal error (2)"); + graphExit (&bipgrafdat); + return (1); + } + if (graphCheck (&bipgrafdat) != 0) { + errorPrint ("vgraphSeparateEs: internal error (3)"); + graphExit (&bipgrafdat); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + if (vgraphSeparateEsCover (&bipgrafdat, bipvertnbrp, grafptr->frontab, &grafptr->fronnbr) != 0) { + errorPrint ("vgraphSeparateEs: cannot compute cover"); + graphExit (&bipgrafdat); + return (1); + } + + compsizep = 0; + if (actgrafdat.s.velotax != NULL) { /* If vertices are weighted */ + Gnum fronnum; + + compload01 = + comploadp = 0; + for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { + Gnum bipvertnum; + Gnum actvertnum; + Gnum actveloval; + + bipvertnum = grafptr->frontab[fronnum]; + actvertnum = bipgrafdat.vnumtax[bipvertnum]; + actveloval = actgrafdat.s.velotax[actvertnum]; + grafptr->frontab[fronnum] = actvertnum; /* Express vertices with respect to original graph */ + + grafptr->parttax[actvertnum] = 2; /* Write separator part for global renumbering */ + compload01 += actveloval; + if (bipvertnum < bipvertnbrp) { /* Update separator vertices */ + compsizep ++; /* Superscalar update */ + comploadp += actveloval; + } + } + } + else { /* Vertices are not weighted */ + Gnum fronnum; + + for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { + Gnum bipvertnum; + Gnum actvertnum; + + bipvertnum = grafptr->frontab[fronnum]; + actvertnum = bipgrafdat.vnumtax[bipvertnum]; + grafptr->frontab[fronnum] = actvertnum; /* Express vertices with respect to original graph */ + + grafptr->parttax[actvertnum] = 2; /* Write separator part for global renumbering */ + if (bipvertnum < bipvertnbrp) /* Update separator vertices */ + compsizep ++; /* Superscalar update */ + } + compload01 = grafptr->fronnbr; /* Loads are equivalent to sizes */ + comploadp = compsizep; + } + grafptr->compsize[bippartval] -= compsizep; + grafptr->compsize[bippartval ^ 1] -= grafptr->fronnbr - compsizep; + grafptr->compload[bippartval] -= comploadp; + grafptr->compload[bippartval ^ 1] -= compload01 - comploadp; + + graphExit (&bipgrafdat); + } + else { /* Fat separator wanted */ + Gnum compsize1; /* Number of vertices to be removed from part 1 */ + Gnum compload01; /* Load of vertices to be removed from both parts */ + Gnum compload1; /* Load of vertices to be removed from part 1 */ + + compsize1 = 0; + grafptr->fronnbr = actgrafdat.fronnbr; /* Keep separator as is */ + + if (actgrafdat.s.velotax != NULL) { /* If vertices are weighted */ + Gnum fronnum; + + compload01 = + compload1 = 0; + for (fronnum = 0; fronnum < actgrafdat.fronnbr; fronnum ++) { + Gnum vertnum; + Gnum veloval; + int partval; + + vertnum = grafptr->frontab[fronnum]; + partval = grafptr->parttax[vertnum]; + veloval = grafptr->s.velotax[vertnum]; + + compsize1 += partval; /* Superscalar update */ + compload01 += veloval; + compload1 += partval * veloval; + grafptr->parttax[vertnum] = 2; /* Write separator part for global renumbering */ + } + } + else { /* Vertices are not weighted */ + Gnum fronnum; + + for (fronnum = 0; fronnum < actgrafdat.fronnbr; fronnum ++) { + Gnum vertnum; + int partval; + + vertnum = grafptr->frontab[fronnum]; + partval = grafptr->parttax[vertnum]; + + compsize1 += partval; + grafptr->parttax[vertnum] = 2; /* Write separator part for global renumbering */ + } + + compload01 = actgrafdat.fronnbr; /* Loads are equivalent to sizes */ + compload1 = compsize1; + } + + grafptr->compsize[0] -= actgrafdat.fronnbr - compsize1; /* Update graph properties */ + grafptr->compsize[1] -= compsize1; + grafptr->compload[0] -= compload01 - compload1; + grafptr->compload[1] -= compload1; + } + } + + grafptr->comploaddlt = grafptr->compload[0] - grafptr->compload[1]; + grafptr->compload[2] = grafptr->s.velosum - grafptr->compload[0] - grafptr->compload[1]; + grafptr->fronnbr = grafptr->s.vertnbr - grafptr->compsize[0] - grafptr->compsize[1]; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vgraphCheck (grafptr) != 0) { + errorPrint ("vgraphSeparateEs: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_es.h b/scotch_6.0.3/src/libscotch/vgraph_separate_es.h new file mode 100644 index 00000000..deb54531 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_es.h @@ -0,0 +1,114 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_es.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the edge-separation-based node **/ +/** separation module. **/ +/** **/ +/** DATES : # Version 3.2 : from : 24 oct 1996 **/ +/** to : 07 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 18 aug 2004 **/ +/** to 19 aug 2004 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Separator type. +*/ + +typedef enum VgraphSeparateEsWidth_ { + VGRAPHSEPAESWIDTHTHIN, /*+ Thin vertex separator +*/ + VGRAPHSEPAESWIDTHFAT /*+ Fat vertex separator +*/ +} VgraphSeparateEsWidth; + +/*+ This structure holds the method parameters. +*/ + +typedef struct VgraphSeparateEsParam_ { + Strat * strat; /*+ Edge bipartitioning strategy used +*/ + VgraphSeparateEsWidth widtval; /*+ Separator width +*/ +} VgraphSeparateEsParam; + +/*+ These are the type of subgraphs vertices + belong to, used to represent the Dulmage- + Mendelsohn decomposition. + TRICK: item numbers have been carefully + chosen, so that one can easily sort out + vertices that belong to (HR u SC u VC) + and to (HR u SR u VC). +*/ + +typedef enum VgraphSeparateEsType_ { + VGRAPHSEPAESTYPEHC = 0x0000, + VGRAPHSEPAESTYPEVR = 0x0001, + VGRAPHSEPAESTYPEHRSCVC = 0x0002, /* Bit mask for testing */ + VGRAPHSEPAESTYPESC = 0x0003, + VGRAPHSEPAESTYPEHRSRVC = 0x0004, /* Bit mask for testing */ + VGRAPHSEPAESTYPESR = 0x0005, + VGRAPHSEPAESTYPEHR = 0x0006, + VGRAPHSEPAESTYPEVC = 0x0007 +} VgraphSeparateEsType; + +#define VGRAPHSEPAESTYPEBITC 1 /* Bit index for VGRAPHSEPAESTYPEHRSCVC */ +#define VGRAPHSEPAESTYPEBITR 2 /* Bit index for VGRAPHSEPAESTYPEHRSRVC */ + +/*+ Vertex traversal flag. +*/ + +typedef enum VgraphSeparateEsTrav_ { + VGRAPHSEPAESTRAVFREE = 0, /*+ Vertex not traversed +*/ + VGRAPHSEPAESTRAVUSED, /*+ Vertex traversed by search for free rows +*/ + VGRAPHSEPAESTRAVDRTY /*+ Vertex traversed by backtracking search for free columns +*/ +} VgraphSeparateEsTrav; + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_ES +#define static +#endif + +static int vgraphSeparateEsCover (const Graph * const, const Gnum, Gnum * const, Gnum * const); +static int vgraphSeparateEsCoverAugment (const Gnum * restrict const, const Gnum, Gnum * restrict const, VgraphSeparateEsTrav * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum); +static void vgraphSeparateEsCoverCol (const Gnum * restrict const, VgraphSeparateEsType * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum); +static void vgraphSeparateEsCoverRow (const Gnum * restrict const, VgraphSeparateEsType * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum); + +int vgraphSeparateEs (Vgraph * const, const VgraphSeparateEsParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_fm.c b/scotch_6.0.3/src/libscotch/vgraph_separate_fm.c new file mode 100644 index 00000000..2a3efda6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_fm.c @@ -0,0 +1,928 @@ +/* Copyright 2004,2007,2008,2010,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_fm.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module separates an active **/ +/** graph using a vertex-oriented version **/ +/** of our improved Fiduccia-Mattheyses **/ +/** heuristics, similar in principle to **/ +/** the algorithm of Ashcraft and Liu 1994. **/ +/** **/ +/** DATES : # Version 3.2 : from : 02 nov 1997 **/ +/** to 17 jul 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 31 dec 1998 **/ +/** # Version 4.0 : from : 07 jan 2002 **/ +/** to 18 aug 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to 22 may 2008 **/ +/** # Version 5.1 : from : 10 nov 2008 **/ +/** to 01 jun 2010 **/ +/** # Version 6.0 : from : 31 mar 2014 **/ +/** to 01 apr 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_FM + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_gg.h" +#include "vgraph_separate_fm.h" + +/* +** The static definitions. +*/ + +static VgraphSeparateFmVertex vexxdat; /* Dummy structure for computing offsets */ + +/*********************************/ +/* */ +/* Gain table handling routines. */ +/* */ +/*********************************/ + +/* This routine returns the vertex of best gain +** whose swap will keep the balance correct. +** It returns: +** - !NULL : pointer to the vertex gainlink. +** - NULL : if no more vertices available. +*/ + +static +GainLink * +vgraphSeparateFmTablGet ( +GainTabl * const tablptr, /* Gain table */ +const Gnum deltcur, /* Current imbalance */ +const Gnum deltmax, /* Maximum imbalance */ +const int partval) /* Current preferred */ +{ + const VgraphSeparateFmVertex * vexxptr; /* Pointer to vertex of current link */ + const GainLink * linkptr; /* Pointer to current gain link */ + const GainLink * linkbest; /* Pointer to best link found */ + const GainEntr * tablbest; /* Gain table entry of best link */ + Gnum gaincur; /* Separator gain of current link */ + Gnum gainbest; /* Separator gain of best link */ + + linkbest = NULL; /* Assume no candidate vertex found yet */ + tablbest = tablptr->tend; + gainbest = GAINMAX; + + for (linkptr = gainTablFrst (tablptr); /* Select candidate vertices */ + (linkptr != NULL) && (linkptr->tabl <= tablbest); + linkptr = gainTablNext (tablptr, linkptr)) { + int vertpart; /* Part of current vertex */ + + vertpart = 0; /* Assume we point to gainlink0 */ + vexxptr = (VgraphSeparateFmVertex *) linkptr; /* TRICK: gainlink0 is at beginning */ + if (vexxptr->veloval >= 0) { /* If in fact we point to gainlink1 */ + vertpart = 1; /* Then point to vertex structure */ + vexxptr = (VgraphSeparateFmVertex *) ((byte *) vexxptr - ((byte *) &vexxdat.gainlink1 - (byte *) &vexxdat)); + } + gaincur = vexxptr->compgain[vertpart]; /* Get separator gain and vertex balance */ + + if (gaincur == vexxptr->veloval) /* If vertex is isolated separator vertex */ + return ((GainLink *) linkptr); /* Select it immediatly */ + + if (abs (deltcur + (1 - 2 * vertpart) * (gaincur - 2 * vexxptr->veloval)) <= deltmax) { /* If vertex enforces balance */ + if ((gaincur < gainbest) || /* And if it gives better gain */ + ((gaincur == gainbest) && /* Or is in preferred part */ + (partval == vertpart))) { + linkbest = linkptr; /* Select it */ + tablbest = linkptr->tabl; + gainbest = gaincur; + } + } + } + + return ((GainLink *) linkbest); /* Return best link found */ +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +int +vgraphSeparateFm ( +Vgraph * restrict const grafptr, /*+ Active graph +*/ +const VgraphSeparateFmParam * const paraptr) /*+ Method parameters +*/ +{ + GainTabl * restrict tablptr; /* Pointer to gain tables */ + INT passnbr; /* Maximum number of passes to go */ + Gnum movenbr; /* Number of uneffective moves done */ + int moveflag; /* Flag set if useful moves made */ + Gnum savenbr; /* Position of current move */ + VgraphSeparateFmSave * restrict savetab; /* Pointer to move array */ + Gnum hashmax; /* Maximum number of elements in table */ + Gnum hashsiz; /* Size of hash and save tables */ + Gnum hashmsk; /* Mask for access to hash table */ + Gnum hashnbr; /* Number of elements in hash table */ + VgraphSeparateFmVertex * hashtab; /* Hash vertex table */ + GainLink lockdat; /* Double linked list of locked vertices */ + VgraphSeparateFmVertex * vexxptr; /* Pointer to current vertex */ + VgraphSeparateFmVertex * sepaptr; /* Pointer to current vertex in table */ + Gnum fronnum; /* Current index of frontier vertex */ + Gnum comploaddlt; /* Current load imbalance */ + Gnum comploaddltmat; /* Theoretical maximum unbalance */ + Gnum comploaddltmax; /* Largest unbalance allowed */ + Gnum comploaddltbst; /* Unbalance of best solution to date */ + Gnum compload2; /* Current load of separator */ + Gnum compload2bst; /* Separator load of best solution to date */ + Gnum mswpnum; /* Number of current move sweep */ + Gnum compsize1add; /* Number of vertices to add to counters */ + Gnum compsize1sub; + + const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + GraphPart * restrict const parttax = grafptr->parttax; + + comploaddltmat = (paraptr->deltrat > 0.0L) + ? MAX ((Gnum) ((grafptr->compload[0] + grafptr->compload[1]) * paraptr->deltrat), + ((2 * grafptr->s.velosum) / grafptr->s.vertnbr)) + : 0; + + if (grafptr->fronnbr == 0) { /* If no frontier defined */ + if (abs (grafptr->comploaddlt) <= comploaddltmat) /* If balance is achieved */ + return (0); /* This algorithm is useless */ + else { /* Imbalance must be fought */ + VgraphSeparateGgParam paradat; + + paradat.passnbr = 4; /* Use a standard algorithm */ + vgraphSeparateGg (grafptr, ¶dat); + if (grafptr->fronnbr == 0) /* If new partition has no frontier */ + return (0); /* This algorithm is still useless */ + } + } + + hashnbr = 16 * (grafptr->fronnbr + paraptr->movenbr + grafptr->s.degrmax) + 1; +#ifdef SCOTCH_DEBUG_VGRAPH2 + hashnbr /= 8; /* Ensure resizing routine will be called */ +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + if (hashnbr > grafptr->s.vertnbr) + hashnbr = grafptr->s.vertnbr; + for (hashsiz = 512; hashsiz < hashnbr; hashsiz <<= 1) ; /* Get upper power of two */ + hashmsk = hashsiz - 1; + hashmax = hashsiz >> 2; /* Use hash table at 1/4 of its capacity */ + + if (((tablptr = gainTablInit (GAINMAX, VGRAPHSEPAFMGAINBITS)) == NULL) || /* Use logarithmic array only */ + (memAllocGroup ((void **) (void *) + &hashtab, (size_t) (hashsiz * sizeof (VgraphSeparateFmVertex)), + &savetab, (size_t) (hashsiz * sizeof (VgraphSeparateFmSave)), NULL) == NULL)) { + errorPrint ("vgraphSeparateFm: out of memory (1)"); + if (tablptr != NULL) + gainTablExit (tablptr); + return (1); + } + memSet (hashtab, ~0, hashsiz * sizeof (VgraphSeparateFmVertex)); /* Set all vertex numbers to ~0 */ + + for (fronnum = 0, hashnbr = grafptr->fronnbr; /* Set initial gains */ + fronnum < hashnbr; fronnum ++) { + Gnum vertnum; + Gnum hashnum; + + vertnum = grafptr->frontab[fronnum]; +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (parttax[vertnum] != 2) { + errorPrint ("vgraphSeparateFm: vertex not in separator"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + for (hashnum = (vertnum * VGRAPHSEPAFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != ~0; hashnum = (hashnum + 1) & hashmsk) ; + + if (velotax != NULL) { /* If vertex loads present */ + Gnum edgenum; + Gnum veloval; + Gnum compgain0; + Gnum compgain01; + + for (edgenum = verttax[vertnum], compgain0 = compgain01 = 0; + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Gnum partend; + Gnum veloend; + + vertend = edgetax[edgenum]; + partend = (Gnum) parttax[vertend]; + veloend = velotax[vertend]; + + compgain0 += (partend & 1) * veloend; + compgain01 += (2 - (partend & 2)) * veloend; + } + veloval = velotax[vertnum]; + hashtab[hashnum].veloval = - veloval; /* TRICK: -veloval: stored value is opposite of load */ + hashtab[hashnum].compgain[0] = compgain0 - veloval; + hashtab[hashnum].compgain[1] = (compgain01 >> 1) - compgain0 - veloval; + } + else { /* No vertex loads */ + Gnum edgenum; + Gnum compgain0; + Gnum compgain2; + + for (edgenum = verttax[vertnum], compgain0 = compgain2 = 0; + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Gnum partend; + + vertend = edgetax[edgenum]; + partend = (Gnum) parttax[vertend]; + + compgain0 += (partend & 1); + compgain2 += (partend & 2); + } + hashtab[hashnum].veloval = -1; /* TRICK: -veloval */ + hashtab[hashnum].compgain[0] = compgain0 - 1; + hashtab[hashnum].compgain[1] = vendtax[vertnum] - verttax[vertnum] - (compgain2 >> 1) - compgain0 - 1; + } + hashtab[hashnum].partval = 2; + hashtab[hashnum].vertnum = vertnum; + + gainTablAdd (tablptr, &hashtab[hashnum].gainlink0, hashtab[hashnum].compgain[0]); /* Link both directions of separator vertex */ + gainTablAdd (tablptr, &hashtab[hashnum].gainlink1, hashtab[hashnum].compgain[1]); + } + + comploaddltmax = MAX (comploaddltmat, abs (grafptr->comploaddlt)); /* Set current maximum distance */ + comploaddltbst = grafptr->comploaddlt; + compload2bst = grafptr->compload[2]; + +#ifdef SCOTCH_DEBUG_VGRAPH3 + if (vgraphSeparateFmCheck (grafptr, hashtab, hashmsk, compload2bst, comploaddltbst) != 0) { + errorPrint ("vgraphSeparateFm: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH3 */ + + passnbr = paraptr->passnbr; /* Set remaining number of passes */ + savenbr = 0; /* For empty backtrack of first pass */ + mswpnum = -1; /* Will be incremented afterwards */ + lockdat.next = /* List of locked vertices is empty */ + lockdat.prev = &lockdat; + do { /* As long as there is improvement */ + Gnum comploadabsdltbst; + + while (savenbr -- > 0) { /* Delete exceeding moves */ + Gnum hashnum; + int partval; + + hashnum = savetab[savenbr].hashnum; + partval = savetab[savenbr].partval; + hashtab[hashnum].partval = partval; /* Restore vertex data */ + hashtab[hashnum].compgain[0] = savetab[savenbr].compgain[0]; + hashtab[hashnum].compgain[1] = savetab[savenbr].compgain[1]; + + if (hashtab[hashnum].gainlink0.next >= VGRAPHSEPAFMSTATELINK) { /* If vertex is linked */ + gainTablDel (tablptr, &hashtab[hashnum].gainlink0); /* Unlink it */ + gainTablDel (tablptr, &hashtab[hashnum].gainlink1); + hashtab[hashnum].gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Set it as free */ + } + if ((hashtab[hashnum].gainlink0.next == VGRAPHSEPAFMSTATEFREE) && (partval == 2)) { /* If vertex not locked and in separator */ + gainTablAdd (tablptr, &hashtab[hashnum].gainlink0, hashtab[hashnum].compgain[0]); /* Re-link it */ + gainTablAdd (tablptr, &hashtab[hashnum].gainlink1, hashtab[hashnum].compgain[1]); + } + } + compload2 = compload2bst; /* Restore best separator parameters */ + comploaddlt = comploaddltbst; + comploadabsdltbst = abs (comploaddltbst); + if (comploadabsdltbst > comploaddltmax) /* If the former state had a higher maximum imbalance ratio */ + comploaddltmax = comploadabsdltbst; /* Restore this maximum imbalance ratio */ + + mswpnum ++; /* Forget all recorded moves */ + +#ifdef SCOTCH_DEBUG_VGRAPH3 + if (vgraphSeparateFmCheck (grafptr, hashtab, hashmsk, compload2, comploaddlt) != 0) { + errorPrint ("vgraphSeparateFm: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH3 */ + + while (lockdat.next != &lockdat) { /* For all vertices in locked list */ + VgraphSeparateFmVertex * vexxptr; + + vexxptr = (VgraphSeparateFmVertex *) ((byte *) lockdat.next - ((byte *) &vexxdat.gainlink1 - (byte *) &vexxdat)); + lockdat.next = (GainLink *) vexxptr->gainlink1.next; /* Unlink vertex from list */ + + if (vexxptr->partval == 2) { /* If vertex belongs to separator */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vexxptr->gainlink0.next != VGRAPHSEPAFMSTATEUSED) { + errorPrint ("vgraphSeparateFm: linked non-used vertex"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + gainTablAdd (tablptr, &vexxptr->gainlink0, vexxptr->compgain[0]); /* Link it */ + gainTablAdd (tablptr, &vexxptr->gainlink1, vexxptr->compgain[1]); + } + else /* Vertex does not belong to separator */ + vexxptr->gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Set it as free for this run */ + } + lockdat.prev = &lockdat; /* Restore backward chaining */ + + moveflag = 0; /* No moves to date */ + movenbr = /* No uneffective moves yet */ + savenbr = 0; /* No recorded moves yet */ + while ((movenbr < paraptr->movenbr) && /* As long as we can find effective vertices */ + ((vexxptr = (VgraphSeparateFmVertex *) vgraphSeparateFmTablGet (tablptr, comploaddlt, comploaddltmax, (passnbr & 1))) != NULL)) { + Gnum comploadabsdlt; + int partval; /* Part of current vertex */ + Gnum vertnum; + Gnum edgenum; + + partval = 0; /* Assume we point to gainlink0 */ + if (vexxptr->veloval >= 0) { /* If in fact we point to gainlink1 */ + partval = 1; /* Then point to vertex structure */ + vexxptr = (VgraphSeparateFmVertex *) ((byte *) vexxptr - ((byte *) &vexxptr->gainlink1 - (byte *) vexxptr)); + } +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vexxptr->partval != 2) { + errorPrint ("vgraphSeparateFm: linked non-separator vertex (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + gainTablDel (tablptr, &vexxptr->gainlink0); /* Remove it from table */ + gainTablDel (tablptr, &vexxptr->gainlink1); + vexxptr->gainlink0.next = VGRAPHSEPAFMSTATESUCH; /* Mark it as used and avoid chaining */ + vexxptr->gainlink1.prev = &lockdat; /* Lock it */ + vexxptr->gainlink1.next = lockdat.next; + lockdat.next->prev = &vexxptr->gainlink1; + lockdat.next = &vexxptr->gainlink1; + + vertnum = vexxptr->vertnum; /* Get vertex number */ + compload2 += vexxptr->compgain[partval]; + comploaddlt -= (2 * partval - 1) * (vexxptr->compgain[partval] - 2 * vexxptr->veloval); /* TRICK: -veloval */ + + if (vexxptr->mswpnum != mswpnum) { /* If vertex data not yet recorded */ + vexxptr->mswpnum = mswpnum; + savetab[savenbr].hashnum = vexxptr - hashtab; + savetab[savenbr].partval = 2; + savetab[savenbr].compgain[0] = vexxptr->compgain[0]; + savetab[savenbr].compgain[1] = vexxptr->compgain[1]; + savenbr ++; /* One more move recorded */ + } + movenbr ++; /* One more move done */ + + sepaptr = NULL; /* No separator vertices to relink yet */ + for (edgenum = verttax[vertnum]; /* Update neighbors */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Gnum hashnum; + + vertend = edgetax[edgenum]; + for (hashnum = (vertend * VGRAPHSEPAFMHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + VgraphSeparateFmVertex * vexxend; /* Pointer to neighbor of current vertex */ + + vexxend = hashtab + hashnum; /* Point to neighbor */ + if (vexxend->vertnum == ~0) { /* If neighbor does not exist yet */ + if (parttax[vertend] == partval) /* If no use to create it */ + break; /* Skip to next vertex */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (parttax[vertend] != (1 - partval)) { + errorPrint ("vgraphSeparateFm: undeclared separator vertex"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + vexxend->vertnum = vertend; /* Set its number (TRICK: mswpnum assumed to be always -1) */ + vexxend->partval = 1 - partval; /* Vertex will be in separator */ + vexxend->veloval = - ((velotax != NULL) ? velotax[vertend] : 1); + vexxend->gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Vertex will be linked */ + hashnbr ++; /* One more vertex in hash table */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (hashnbr > hashmsk) { + errorPrint ("vgraphSeparateFm: hash table overflow"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + } + if (vexxend->vertnum == vertend) { /* If end vertex has been found */ + if (vexxend->partval == 2) { /* If already in separator or chained */ + if (vexxend->mswpnum != mswpnum) { /* If vertex data not yet recorded */ + vexxend->mswpnum = mswpnum; + savetab[savenbr].hashnum = hashnum; + savetab[savenbr].partval = 2; + savetab[savenbr].compgain[0] = vexxend->compgain[0]; + savetab[savenbr].compgain[1] = vexxend->compgain[1]; + savenbr ++; /* One more move recorded */ + } + vexxend->compgain[1 - partval] -= vexxptr->veloval; /* TRICK: -veloval */ + if (vexxend->gainlink0.next >= VGRAPHSEPAFMSTATELINK) { /* If vertex is linked */ + gainTablDel (tablptr, &vexxend->gainlink0); /* Unlink it temporarily */ + gainTablDel (tablptr, &vexxend->gainlink1); /* TRICK: gainlink1.next != NULL */ + vexxend->gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Mark separator vertex as temporarily unlinked */ + vexxend->gainlink0.prev = (GainLink *) sepaptr; /* Chain it for relinking */ + sepaptr = vexxend; + } + else if (vexxend->gainlink0.next == VGRAPHSEPAFMSTATEUSED) { + vexxend->gainlink0.next = VGRAPHSEPAFMSTATESUCH; /* Mark separator vertex as chained-used */ + vexxend->gainlink0.prev = (GainLink *) sepaptr; /* Chain it for relinking */ + sepaptr = vexxend; + } + } + else if (vexxend->partval == (1 - partval)) { /* Vertex is in other part */ + Gnum edgeend; + Gnum compgainp; /* Gain to be added to gain of part partval */ + + if (vexxend->mswpnum != mswpnum) { /* If vertex data not yet recorded */ + vexxend->mswpnum = mswpnum; + savetab[savenbr].hashnum = hashnum; + savetab[savenbr].partval = 1 - partval; + savetab[savenbr].compgain[0] = /* Vertex not in separator so gains are not relevant */ + savetab[savenbr].compgain[1] = 0; + savenbr ++; /* One more move recorded */ + } + + vexxend->partval = 2; /* Vertex will be in separator */ + vexxend->compgain[partval] = vexxend->veloval; /* Moved vertex still in separator */ + vexxend->compgain[1 - partval] = vexxend->veloval - vexxptr->veloval; /* TRICK: -veloval */ + + for (edgeend = verttax[vertend], compgainp = 0; + edgeend < vendtax[vertend]; edgeend ++) { + Gnum vertent; + Gnum hashnum; + + vertent = edgetax[edgeend]; + for (hashnum = (vertent * VGRAPHSEPAFMHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + VgraphSeparateFmVertex * vexxent; /* Pointer to neighbor of neighbor of current vertex */ + + vexxent = hashtab + hashnum; + if (vexxent->vertnum == ~0) { /* If neighbor does not exist */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (parttax[vertent] != (1 - partval)) { + errorPrint ("vgraphSeparateFm: broken separator (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + compgainp += (velotax != NULL) ? velotax[vertent] : 1; + break; /* Skip to next vertex */ + } + if (vexxent->vertnum == vertent) { /* If end vertex found */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vexxent->partval == partval) { + errorPrint ("vgraphSeparateFm: broken separator (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + if (vexxent->partval == 2) { /* If vertex is in separator (or is vexxptr) */ + if (vexxent->mswpnum != mswpnum) { /* If vertex data not yet recorded */ + vexxent->mswpnum = mswpnum; + savetab[savenbr].hashnum = hashnum; + savetab[savenbr].partval = 2; + savetab[savenbr].compgain[0] = vexxent->compgain[0]; + savetab[savenbr].compgain[1] = vexxent->compgain[1]; + savenbr ++; /* One more move recorded */ + } + + vexxent->compgain[partval] += vexxend->veloval; /* TRICK: -veloval */ + if (vexxent->gainlink0.next >= VGRAPHSEPAFMSTATELINK) { /* If not already chained */ + gainTablDel (tablptr, &vexxent->gainlink0); /* Unlink it temporarily */ + gainTablDel (tablptr, &vexxent->gainlink1); /* TRICK: gainlink1.next != NULL */ + vexxent->gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Mark separator vertex as temporarily unlinked */ + vexxent->gainlink0.prev = (GainLink *) sepaptr; /* Chain it */ + sepaptr = vexxent; + } + else if (vexxent->gainlink0.next == VGRAPHSEPAFMSTATEUSED) { + vexxent->gainlink0.next = VGRAPHSEPAFMSTATESUCH; /* Mark separator vertex as chained-used */ + vexxent->gainlink0.prev = (GainLink *) sepaptr; /* Chain it for relinking */ + sepaptr = vexxent; + } + } + else /* Vertex is in same part as vexxend */ + compgainp -= vexxent->veloval; /* TRICK: -veloval */ + break; + } + } + } + vexxend->compgain[partval] += compgainp; + if (vexxend->gainlink0.next == VGRAPHSEPAFMSTATEUSED) /* If vertex was already used */ + vexxend->gainlink0.next = VGRAPHSEPAFMSTATESUCH; /* Set it as separator-used-chained */ + vexxend->gainlink0.prev = (GainLink *) sepaptr; /* Chain it for relinking */ + sepaptr = vexxend; + } + break; /* If in same part, ignore */ + } + } + } + vexxptr->gainlink0.next = VGRAPHSEPAFMSTATEUSED; /* Mark it as used and not chained */ + vexxptr->partval = partval; /* Set vertex part last */ + while (sepaptr != NULL) { /* For all vertices in chain list */ + vexxptr = sepaptr; /* Unlink vertex from list */ + sepaptr = (VgraphSeparateFmVertex *) vexxptr->gainlink0.prev; +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vexxptr->partval != 2) { + errorPrint ("vgraphSeparateFm: linked non-separator vertex (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + if (vexxptr->gainlink0.next == VGRAPHSEPAFMSTATEFREE) { /* If vertex is not used */ + gainTablAdd (tablptr, &vexxptr->gainlink0, vexxptr->compgain[0]); /* Link it */ + gainTablAdd (tablptr, &vexxptr->gainlink1, vexxptr->compgain[1]); + } + else { + vexxptr->gainlink0.next = VGRAPHSEPAFMSTATEUSED; + if (vexxptr->compgain[partval] == vexxptr->veloval) { /* If immediate gain */ + vexxptr->gainlink1.next->prev = vexxptr->gainlink1.prev; /* Remove vertex from lock list */ + vexxptr->gainlink1.prev->next = vexxptr->gainlink1.next; + gainTablAdd (tablptr, &vexxptr->gainlink0, vexxptr->compgain[0]); /* Link it */ + gainTablAdd (tablptr, &vexxptr->gainlink1, vexxptr->compgain[1]); + } + } + } +#ifdef SCOTCH_DEBUG_VGRAPH3 + if (vgraphSeparateFmCheck (grafptr, hashtab, hashmsk, compload2, comploaddlt) != 0) { + errorPrint ("vgraphSeparateFm: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH3 */ + + if (hashnbr >= hashmax) { + if (vgraphSeparateFmResize (&hashtab, &hashmax, &hashmsk, &savetab, savenbr, tablptr, &lockdat) != 0) { + errorPrint ("vgraphSeparateFm: out of memory (2)"); + return (1); + } + } + + comploadabsdltbst = abs (comploaddltbst); + comploadabsdlt = abs (comploaddlt); + if ((comploadabsdlt < comploaddltmat) || /* Record move only if it is within bounds */ + (comploadabsdltbst > comploaddltmat)) { /* Or if we have always been out of bounds */ + if (compload2 < compload2bst) { /* If move improves the cost */ + compload2bst = compload2; /* This move was effective */ + comploaddltbst = comploaddlt; + movenbr = + savenbr = 0; + moveflag = 1; + mswpnum ++; + } else if (compload2 == compload2bst) { + if (comploadabsdlt < comploadabsdltbst) { + comploaddltbst = comploaddlt; /* This move was effective */ + movenbr = + savenbr = 0; + moveflag = 1; + mswpnum ++; + } + else if (comploadabsdlt == comploadabsdltbst) { + comploaddltbst = comploaddlt; /* Might be the opposite, so record */ + savenbr = 0; /* Forget backtracking */ + mswpnum ++; + } + } + } + + if (comploadabsdlt > comploaddltmax) /* If an isolated vertex unbalanced the partition */ + comploaddltmax = comploadabsdlt; /* Record that we degraded maximum load imbalance */ + else if (comploaddltmax > comploaddltmat) { /* Else if we must restrict distance bounds */ + Gnum comploaddlttmp; + + comploaddlttmp = comploaddltmax; /* Save old working compdeltmax value */ + comploaddltmax = MAX (comploaddltmat, comploadabsdlt); /* Restrict at most to the maximum */ + if ((comploadabsdltbst > comploaddltmat) && /* If we have never achieved balance yet */ + (comploaddltmax < comploaddlttmp)) { /* And if we have done something useful */ + compload2bst = compload2; /* Then record best move done */ + comploaddltbst = comploaddlt; + movenbr = /* Never set moveflag so as not to create an infinite loop */ + savenbr = 0; + mswpnum ++; + } + } + } + } while ((moveflag != 0) && /* As long as vertices are moved */ + (-- passnbr != 0)); /* And we are allowed to loop (TRICK for negative values) */ + + while (savenbr -- > 0) { /* Delete exceeding moves */ + Gnum hashnum; + int partval; + + hashnum = savetab[savenbr].hashnum; + partval = savetab[savenbr].partval; + hashtab[hashnum].partval = partval; /* Restore vertex part only for update computation */ + } + compload2 = compload2bst; /* Restore best separator parameters */ + comploaddlt = comploaddltbst; + compsize1add = /* Variables for superscalar update */ + compsize1sub = 0; + for (vexxptr = hashtab, fronnum = 0; /* Build new frontier */ + vexxptr < hashtab + (hashmax << 2); vexxptr ++) { /* From all vertices in table */ + Gnum vertnum; + + vertnum = vexxptr->vertnum; + if (vertnum != ~0) { /* If vertex slot is used */ + int partval; /* New part of current vertex */ + int partold; /* Old part of current vertex */ + + partval = vexxptr->partval; + partold = parttax[vexxptr->vertnum]; /* Get old part value from array */ + if (partval != partold) { /* If vertex part changed */ + parttax[vertnum] = partval; /* Set new part value */ + compsize1add += (partval & 1); /* Superscalar update */ + compsize1sub += (partold & 1); + } + if (partval == 2) /* If vertex belongs to cut */ + grafptr->frontab[fronnum ++] = vertnum; /* Add vertex to frontier */ + } + } + grafptr->compload[0] = ((grafptr->s.velosum - compload2) + comploaddlt) / 2; + grafptr->compload[1] = ((grafptr->s.velosum - compload2) - comploaddlt) / 2; + grafptr->compload[2] = compload2; + grafptr->comploaddlt = comploaddlt; + grafptr->compsize[1] = grafptr->compsize[1] + compsize1add - compsize1sub; + grafptr->compsize[0] = grafptr->s.vertnbr - grafptr->compsize[1] - fronnum; + grafptr->fronnbr = fronnum; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vgraphCheck (grafptr) != 0) { + errorPrint ("vgraphSeparateFm: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + memFree (hashtab); /* Free group leader */ + gainTablExit (tablptr); + + return (0); +} + +/* This routine doubles the size all of the arrays +** involved in handling the hash table and hash +** vertex arrays. +** It returns: +** - 0 : if resizing succeeded. +** - !0 : if out of memory. +*/ + +static +int +vgraphSeparateFmResize ( +VgraphSeparateFmVertex * restrict * hashtabptr, /*+ Pointer to hash vertex table +*/ +Gnum * const hashmaxptr, /*+ Pointer to maximum number of elements in table +*/ +Gnum * const hashmskptr, /*+ Pointer to hash table mask +*/ +VgraphSeparateFmSave * restrict * savetabptr, /*+ Pointer to move array +*/ +const Gnum savenbr, /*+ Current number of active slots in move array +*/ +GainTabl * const tablptr, /*+ Gain table +*/ +GainLink * const lockptr) +{ + VgraphSeparateFmVertex * restrict hashtab; /* Pointer to new hash table */ + VgraphSeparateFmSave * savetab; /* Pointer to new save array */ + VgraphSeparateFmSave * saveold; /* Pointer to translated old save array */ + Gnum savenum; + Gnum hashold; /* Size of old hash table (half of new) */ + Gnum hashsiz; + Gnum hashmax; + Gnum hashmsk; + Gnum hashsta; /* Start index of range of hash indices to move */ + Gnum hashend; /* End index of range of hash indices to move */ + Gnum hashnum; + + hashmax = *hashmaxptr << 1; /* Compute new sizes */ + hashold = *hashmaxptr << 2; + hashsiz = *hashmaxptr << 3; + hashmsk = hashsiz - 1; + + if (memReallocGroup ((void *) *hashtabptr, + &hashtab, (size_t) (hashsiz * sizeof (VgraphSeparateFmVertex)), + &savetab, (size_t) (hashsiz * sizeof (VgraphSeparateFmSave)), NULL) == NULL) { + errorPrint ("vgraphSeparateFmResize: out of memory"); + return (1); + } + + saveold = (VgraphSeparateFmSave *) ((byte *) hashtab + ((byte *) *savetabptr - (byte *) *hashtabptr)); + for (savenum = savenbr - 1; savenum >= 0; savenum --) { /* Move save array, in reverse order */ + savetab[savenum].compgain[1] = saveold[savenum].compgain[1]; + savetab[savenum].compgain[0] = saveold[savenum].compgain[0]; + savetab[savenum].partval = saveold[savenum].partval; + savetab[savenum].hashnum = hashtab[saveold[savenum].hashnum].vertnum; /* Temporarily translate from hash index to number */ + } + + *hashtabptr = hashtab; + *hashmaxptr = hashmax; + *hashmskptr = hashmsk; + *savetabptr = savetab; + + memSet (hashtab + hashold, ~0, hashold * sizeof (VgraphSeparateFmVertex)); + + gainTablFree (tablptr); /* Reset gain table */ + lockptr->next = /* Rebuild lock list */ + lockptr->prev = lockptr; + + for (hashsta = hashold - 1; hashtab[hashsta].vertnum != ~0; hashsta --) ; /* Start index of first segment to reconsider is last empty slot */ + hashend = hashold; /* First segment to reconsider ends at the end of the old array */ + while (hashend != hashsta) { /* For each of the two segments to consider */ + for (hashnum = hashsta; hashnum < hashend; hashnum ++) { /* Re-compute position of vertices in new table */ + Gnum vertnum; + + vertnum = hashtab[hashnum].vertnum; + if (vertnum != ~0) { /* If hash slot used */ + Gnum hashnew; + + for (hashnew = (vertnum * VGRAPHSEPAFMHASHPRIME) & hashmsk; ; hashnew = (hashnew + 1) & hashmsk) { + if (hashnew == hashnum) /* If hash slot is the same */ + break; /* There is nothing to do */ + if (hashtab[hashnew].vertnum == ~0) { /* If new slot is empty */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((hashnew > hashnum) && (hashnew < hashend)) { /* If vertex is not moved either before its old position or after the end of the segment */ + errorPrint ("vgraphSeparateFmResize: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + hashtab[hashnew] = hashtab[hashnum]; /* Copy data to new slot */ + hashtab[hashnum].mswpnum = ~0; /* TRICK: not tested at creation */ + hashtab[hashnum].vertnum = ~0; /* Make old slot empty */ + break; + } + } + + if (hashtab[hashnew].gainlink0.next >= VGRAPHSEPAFMSTATELINK) { /* If vertex was linked, re-link it */ + gainTablAdd (tablptr, &hashtab[hashnew].gainlink0, hashtab[hashnew].compgain[0]); + gainTablAdd (tablptr, &hashtab[hashnew].gainlink1, hashtab[hashnew].compgain[1]); + } + else if (hashtab[hashnew].gainlink0.next == VGRAPHSEPAFMSTATEUSED) { /* Re-lock used vertices */ + hashtab[hashnew].gainlink1.prev = lockptr; /* Lock it */ + hashtab[hashnew].gainlink1.next = lockptr->next; + lockptr->next->prev = &hashtab[hashnew].gainlink1; + lockptr->next = &hashtab[hashnew].gainlink1; + } + } + } + + hashend = hashsta; /* End of second segment to consider is start of first one */ + hashsta = 0; /* Start of second segment is beginning of array */ + } /* After second segment, hashsta = hashend = 0 and loop stops */ + + for (savenum = 0; savenum < savenbr; savenum ++) { + Gnum vertnum; + Gnum hashnum; + + vertnum = savetab[savenum].hashnum; /* Get vertex number temporarily saved */ + for (hashnum = (vertnum * VGRAPHSEPAFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != vertnum; hashnum = (hashnum + 1) & hashmsk) { +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (hashtab[hashnum].vertnum == ~0) { + errorPrint ("vgraphSeparateFmResize: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + } + savetab[savenum].hashnum = hashnum; /* Set new hash table index */ + } + + return (0); +} + +/* This routine checks the consistency of +** the hash structures. +** It returns: +** - 0 : in case of success. +** - !0 : in case of error. +*/ + +#ifdef SCOTCH_DEBUG_VGRAPH3 +static +int +vgraphSeparateFmCheck ( +const Vgraph * restrict const grafptr, +const VgraphSeparateFmVertex * restrict const hashtab, +const Gnum hashmsk, +const Gnum compload2, +const Gnum comploaddlt) +{ + Gnum hashnum; + Gnum comploadtmp[3]; + + const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const GraphPart * restrict const parttax = grafptr->parttax; + + comploadtmp[0] = grafptr->compload[0]; + comploadtmp[1] = grafptr->compload[1]; + comploadtmp[2] = grafptr->compload[2]; + for (hashnum = 0; hashnum <= hashmsk; hashnum ++) { /* For all vertex slots */ + Gnum vertnum; + int partval; + + vertnum = hashtab[hashnum].vertnum; + if (vertnum == ~0) /* If unallocated slot */ + continue; /* Skip to next slot */ + + if (hashtab[hashnum].veloval != - ((velotax == NULL) ? 1 : velotax[vertnum])) { + errorPrint ("vgraphSeparateFmCheck: invalid vertex load (1)"); + return (1); + } + partval = hashtab[hashnum].partval; + if ((partval < 0) || (partval > 2)) { + errorPrint ("vgraphSeparateFmCheck: invalid part value"); + return (1); + } + + if (partval != parttax[vertnum]) { + comploadtmp[parttax[vertnum]] += hashtab[hashnum].veloval; /* TRICK: -veloval */ + comploadtmp[partval] -= hashtab[hashnum].veloval; + } + + if (partval < 2) { /* If not separator vertex */ + if (hashtab[hashnum].gainlink0.next >= VGRAPHSEPAFMSTATELINK) { + errorPrint ("vgraphSeparateFmCheck: linked non-separator vertex"); + return (1); + } + } + else { /* Separator vertex */ + Gnum compload[3]; + Gnum edgenum; + + if (hashtab[hashnum].gainlink0.next == VGRAPHSEPAFMSTATEFREE) { + errorPrint ("vgraphSeparateFmCheck: free separator vertex"); + return (1); + } + + compload[0] = + compload[1] = + compload[2] = 0; + for (edgenum = verttax[vertnum]; /* For all element neighbors */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + Gnum hashnum; + int partend; + Gnum veloend; + + vertend = edgetax[edgenum]; + for (hashnum = (vertend * VGRAPHSEPAFMHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { + if (hashtab[hashnum].vertnum == vertend) { /* If end vertex found */ + partend = hashtab[hashnum].partval; + veloend = hashtab[hashnum].veloval; + + if (veloend != - ((velotax == NULL) ? 1 : velotax[vertend])) { + errorPrint ("vgraphSeparateFmCheck: invalid vertex load (2)"); + return (1); + } + break; + } + if (hashtab[hashnum].vertnum == ~0) { /* If element not present */ + partend = parttax[vertend]; + veloend = - ((velotax == NULL) ? 1 : velotax[vertend]); + break; + } + } + compload[partend] += veloend; + } + + if ((hashtab[hashnum].compgain[0] != (hashtab[hashnum].veloval - compload[1])) || + (hashtab[hashnum].compgain[1] != (hashtab[hashnum].veloval - compload[0]))) { + errorPrint ("vgraphSeparateFmCheck: invalid vertex gains"); + return (1); + } + } + } + if (compload2 != comploadtmp[2]) { + errorPrint ("vgraphSeparateFmCheck: invalid frontier load"); + return (1); + } + if (comploaddlt != (comploadtmp[0] - comploadtmp[1])) { + errorPrint ("vgraphSeparateFmCheck: invalid separator balance"); + return (1); + } + + return (0); +} +#endif /* SCOTCH_DEBUG_VGRAPH3 */ diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_fm.h b/scotch_6.0.3/src/libscotch/vgraph_separate_fm.h new file mode 100644 index 00000000..30c7adde --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_fm.h @@ -0,0 +1,134 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_fm.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the improved Fiduccia-Mattheyses **/ +/** graph separation routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 02 nov 1997 **/ +/** to 20 nov 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 28 dec 1998 **/ +/** # Version 4.0 : from : 13 dec 2001 **/ +/** to 18 aug 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Gain table subbits. +*/ + +#define VGRAPHSEPAFMGAINBITS 4 + +/*+ Prime number for hashing vertex numbers. +*/ + +#define VGRAPHSEPAFMHASHPRIME 17 /*+ Prime number for hashing +*/ + +/*+ Gain table vertex status. +*/ + +#define VGRAPHSEPAFMSTATEFREE ((GainLink *) 0) /*+ Vertex is free or separator-chained +*/ +#define VGRAPHSEPAFMSTATESUCH ((GainLink *) 1) /*+ Separator vertex is used and chained +*/ +#define VGRAPHSEPAFMSTATEUSED ((GainLink *) 2) /*+ Vertex already swapped once +*/ +#define VGRAPHSEPAFMSTATELINK ((GainLink *) 3) /*+ Currently in gain table if higher +*/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VgraphSeparateFmParam_ { + INT movenbr; /*+ Maximum number of uneffective moves that can be done +*/ + INT passnbr; /*+ Number of passes to be performed (-1 : infinite) +*/ + double deltrat; /*+ Maximum weight imbalance ratio +*/ +} VgraphSeparateFmParam; + +/*+ The hash vertex structure. For trick reasons, + one of the gain table data structures is followed + by a negative integer, and the other by a positive + one. Thus, one can deduce the value of the pointer + to the structure from a pointer to any of the gain + table data structures. + Moreover, some fields have special meaning: + - gainlink0.next: state of vertex (see + VGRAPHSEPAFMSTATEXXXX). + - gainlink0.prev: simple chaining for separator + vertices, if vertex is in chained state + (((vertpart == 2) && + (gainlink0.next == VGRAPHSEPAFMSTATEFREE)) || + (gainlink0.next == VGRAPHSEPAFMSTATESUCH)). + - gainlink1: double chained list of locked vertices, + if ((gainlink0.next == VGRAPHSEPAFMSTATESUCH) || + (gainlink0.next == VGRAPHSEPAFMSTATEUSED)). +*/ + +typedef struct VgraphSeparateFmVertex_ { + GainLink gainlink0; /*+ Gain link if moved to part 0; FIRST +*/ + Gnum veloval; /*+ TRICK: opposite of vertex load +*/ + GainLink gainlink1; /*+ Gain link if moved to part 1; TRICK: before vertpart +*/ + Gnum partval; /*+ Vertex part TRICK: same type as vertload +*/ + Gnum compgain[2]; /*+ Separator gain if moved to given part; TRICK: not first +*/ + Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ + Gnum vertnum; /*+ Number of vertex in hash table +*/ +} VgraphSeparateFmVertex; + +/*+ The move recording structure. +*/ + +typedef struct VgraphSeparateFmSave_ { + Gnum hashnum; /*+ Number of hash slot for saved vertex +*/ + int partval; /*+ Saved vertex part value +*/ + Gnum compgain[2]; /*+ Saved vertex gain +*/ +} VgraphSeparateFmSave; + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_FM +#define static +#endif + +int vgraphSeparateFm (Vgraph * const, const VgraphSeparateFmParam * const); + +static int vgraphSeparateFmResize (VgraphSeparateFmVertex * restrict * hashtabptr, Gnum * const, Gnum * const, VgraphSeparateFmSave * restrict *, const Gnum, GainTabl * const, GainLink * const); +#ifdef SCOTCH_DEBUG_VGRAPH3 +static int vgraphSeparateFmCheck (const Vgraph * const, const VgraphSeparateFmVertex * restrict const, const Gnum, const Gnum, const Gnum); +#endif /* SCOTCH_DEBUG_VGRAPH3 */ +static GainLink * vgraphSeparateFmTablGet (GainTabl * const, const Gnum, const Gnum, const int); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_gg.c b/scotch_6.0.3/src/libscotch/vgraph_separate_gg.c new file mode 100644 index 00000000..d25dd470 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_gg.c @@ -0,0 +1,304 @@ +/* Copyright 2004,2007,2008,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_gg.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module separates an active **/ +/** graph using a vertex-oriented version **/ +/** of the Greedy Graph Growing algorithm. **/ +/** **/ +/** DATES : # Version 3.2 : from : 10 nov 1997 **/ +/** to 15 jul 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 22 jan 2004 **/ +/** # Version 5.0 : from : 02 jan 2007 **/ +/** to 24 mar 2008 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to 09 nov 2008 **/ +/** # Version 6.0 : from : 04 feb 2012 **/ +/** to 04 feb 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_GG + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_gg.h" + +/* +** The static variables. +*/ + +static const Gnum vgraphseparateggloadone = 1; + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vgraphSeparateGg ( +Vgraph * restrict const grafptr, /*+ Separation graph +*/ +const VgraphSeparateGgParam * const paraptr) /*+ Method parameters +*/ +{ + GainTabl * restrict tablptr; /* Pointer to gain table */ + VgraphSeparateGgVertex * restrict vexxtax; /* Complementary vertex array */ + Gnum vertnum; /* Index of current vertex */ + Gnum * restrict permtab; /* Table for finding new roots */ + Gnum permnum; /* Current permutation index */ + Gnum fronnum; + INT passnum; + const Gnum * restrict velobax; /* Data for handling optional arrays */ + Gnum velomsk; /* Mask for handling optional arrays */ + Gnum comploaddlt; + Gnum compload2; + Gnum compsize1; + Gnum compsize2; + + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + const Gnum * restrict const edlotax = grafptr->s.edlotax; + GraphPart * restrict const parttax = grafptr->parttax; + Gnum * restrict const frontab = grafptr->frontab; + + if (((tablptr = gainTablInit (GAIN_LINMAX, VGRAPHSEPAGGSUBBITS)) == NULL) || /* Use logarithmic array only */ + ((vexxtax = (VgraphSeparateGgVertex *) memAlloc (grafptr->s.vertnbr * sizeof (VgraphSeparateGgVertex))) == NULL)) { + errorPrint ("vgraphSeparateGg: out of memory (1)"); + if (tablptr != NULL) + gainTablExit (tablptr); + return (1); + } + vexxtax -= grafptr->s.baseval; /* Base access to vexxtax */ + permtab = NULL; /* Do not allocate permutation array yet */ + + if (grafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ + velobax = &vgraphseparateggloadone; /* In case vertices not weighted (least often) */ + velomsk = 0; + } + else { + velobax = grafptr->s.velotax; + velomsk = ~((Gnum) 0); + } + + for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { /* For all passes */ + VgraphSeparateGgVertex * vexxptr; /* Pointer to current vertex to swap */ + + memSet (vexxtax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (VgraphSeparateGgVertex)); /* All vertices to part 0 */ + gainTablFree (tablptr); /* Reset gain table */ + permnum = 0; /* No permutation built yet */ + comploaddlt = grafptr->s.velosum; /* Reset separation parameters */ + compload2 = 0; + + vexxptr = vexxtax + (grafptr->s.baseval + intRandVal (grafptr->s.vertnbr)); /* Randomly select first root vertex */ + + do { /* Loop on root vertices */ + Gnum vertnum; /* Number of current vertex */ + Gnum veloval; /* Load of selected vertex */ + Gnum compgain2; + + vexxptr->gainlink.next = /* TRICK: allow deletion of root vertex */ + vexxptr->gainlink.prev = (GainLink *) vexxptr; +#ifdef SCOTCH_DEBUG_GAIN2 + vexxptr->gainlink.tabl = NULL; +#endif /* SCOTCH_DEBUG_GAIN2 */ + + vertnum = vexxptr - vexxtax; /* Get root vertex based number */ + if (velomsk == 0) { /* If vertices are not weighted */ + veloval = 1; + compgain2 = vendtax[vertnum] - verttax[vertnum] - 1; + } + else { /* Graph vertices are weighted */ + Gnum edgenum; + + veloval = velobax[vertnum]; + compgain2 = - veloval; + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) + compgain2 += velobax[edgetax[edgenum]]; + } + vexxptr->compgain2 = compgain2; /* Set root gain (root not in separator) */ + comploaddlt -= veloval; /* Move vertex from part 0 to separator */ + compload2 += veloval; + + do { /* While vertices can be retrieved */ + VgraphSeparateGgVertex * sepaptr; /* List of vertices in separator */ + Gnum veloval; /* Load of selected vertex */ + Gnum edgenum; + + vertnum = vexxptr - vexxtax; /* Get number of selected vertex */ + veloval = velobax[vertnum & velomsk]; + + if (comploaddlt < abs (comploaddlt - veloval)) { /* If swapping would cause imbalance */ + permnum = grafptr->s.vertnbr; /* Terminate swapping process */ + vexxptr = NULL; + break; + } + gainTablDel (tablptr, (GainLink *) vexxptr); /* Remove vertex from table */ + vexxptr->gainlink.next = VGRAPHSEPAGGSTATEPART1; /* Put vertex in part 1 */ + compload2 += vexxptr->compgain2; /* Update partition parameters */ + comploaddlt -= vexxptr->compgain2 + 2 * veloval; + + sepaptr = NULL; /* No separator vertices to relink yet */ + for (edgenum = verttax[vertnum]; /* (Re-)link neighbor vertices */ + edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; + VgraphSeparateGgVertex * vexxend; + + vertend = edgetax[edgenum]; /* Point to end vertex */ + vexxend = vexxtax + vertend; + if (vexxend->gainlink.next == VGRAPHSEPAGGSTATEPART0) { /* If end in part 0 */ + Gnum veloend; + Gnum edgtnum; + Gnum compgain2; + + vexxend->gainlink.next = VGRAPHSEPAGGSTATEPART2; /* Move vertex to separator */ + vexxend->gainlink.prev = (GainLink *) sepaptr; /* Chain vertex */ + sepaptr = vexxend; + + veloend = velobax[vertend & velomsk]; + compgain2 = - veloend; + for (edgtnum = verttax[vertend]; + edgtnum < vendtax[vertend]; edgtnum ++) { + Gnum vertent; + VgraphSeparateGgVertex * vexxent; + + vertent = edgetax[edgtnum]; /* Point to end vertex */ + vexxent = vexxtax + vertent; + if (vexxent->gainlink.next == VGRAPHSEPAGGSTATEPART0) + compgain2 += velobax[vertent & velomsk]; + else if (vexxent->gainlink.next >= VGRAPHSEPAGGSTATEPART2) { + vexxent->compgain2 -= veloend; + if (vexxent->gainlink.next >= VGRAPHSEPAGGSTATELINK) { + gainTablDel (tablptr, (GainLink *) vexxent); /* Unlink vertex */ + vexxent->gainlink.next = VGRAPHSEPAGGSTATEPART2; /* Chain vertex */ + vexxent->gainlink.prev = (GainLink *) sepaptr; + sepaptr = vexxent; + } + } + } + vexxend->compgain2 = compgain2; + } + } + while (sepaptr != NULL) { /* For all vertices in chain list */ + vexxptr = sepaptr; /* Unlink vertex from list */ + sepaptr = (VgraphSeparateGgVertex *) vexxptr->gainlink.prev; + gainTablAdd (tablptr, (GainLink *) vexxptr, vexxptr->compgain2); /* Relink it */ + } + } while ((vexxptr = (VgraphSeparateGgVertex *) gainTablFrst (tablptr)) != NULL); + + if (permnum == 0) { /* If permutation has not been built yet */ + if (permtab == NULL) { /* If permutation array not allocated yet */ + if ((permtab = (Gnum *) memAlloc (grafptr->s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("vgraphSeparateGg: out of memory (2)"); + memFree (vexxtax + grafptr->s.baseval); + gainTablExit (tablptr); + return (1); + } + intAscn (permtab, grafptr->s.vertnbr, grafptr->s.baseval); /* Initialize based permutation array */ + } + intPerm (permtab, grafptr->s.vertnbr); /* Build random permutation */ + } + for ( ; permnum < grafptr->s.vertnbr; permnum ++) { /* Find next root vertex */ + if (vexxtax[permtab[permnum]].gainlink.next == VGRAPHSEPAGGSTATEPART0) { + vexxptr = vexxtax + permtab[permnum ++]; + break; + } + } + } while (vexxptr != NULL); + + if ((passnum == 0) || /* If first try */ + ( (grafptr->compload[2] > compload2) || /* Or if better solution reached */ + ((grafptr->compload[2] == compload2) && + (abs (grafptr->comploaddlt) > abs (comploaddlt))))) { + Gnum vertnum; + + grafptr->comploaddlt = comploaddlt; /* Set graph parameters */ + grafptr->compload[2] = compload2; + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) /* Copy bipartition state */ + parttax[vertnum] = (vexxtax[vertnum].gainlink.next <= VGRAPHSEPAGGSTATEPART2) ? (GraphPart) (intptr_t) vexxtax[vertnum].gainlink.next : (GraphPart) 2; + } + } + + if (permtab != NULL) /* Free work arrays */ + memFree (permtab); + memFree (vexxtax + grafptr->s.baseval); + gainTablExit (tablptr); + + grafptr->compload[0] = (grafptr->s.velosum + grafptr->comploaddlt - grafptr->compload[2]) / 2; + grafptr->compload[1] = grafptr->s.velosum - grafptr->compload[2] - grafptr->compload[0]; + compsize1 = + compsize2 = 0; + for (vertnum = grafptr->s.baseval, fronnum = 0; + vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum partval; + + partval = (Gnum) parttax[vertnum]; + compsize1 += (partval & 1); /* Superscalar update */ + compsize2 += (partval >> 1); + if (partval == 2) /* If vertex belongs to frontier */ + frontab[fronnum ++] = vertnum; /* Record it in frontier array */ + } + grafptr->compsize[0] = grafptr->s.vertnbr - compsize1 - compsize2; + grafptr->compsize[1] = compsize1; + grafptr->fronnbr = compsize2; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vgraphCheck (grafptr) != 0) { + errorPrint ("vgraphSeparateGg: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_gg.h b/scotch_6.0.3/src/libscotch/vgraph_separate_gg.h new file mode 100644 index 00000000..622d02ab --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_gg.h @@ -0,0 +1,93 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_gg.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the greedy graph growing vertex **/ +/** separation method. **/ +/** **/ +/** DATES : # Version 3.2 : from : 14 nov 1997 **/ +/** to 15 jul 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 09 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ System-defined constants. +*/ + +#define VGRAPHSEPAGGSUBBITS 4 + +#define VGRAPHSEPAGGSTATEPART0 ((GainLink *) 0) /*+ Vertex in part 0 (initial state) +*/ +#define VGRAPHSEPAGGSTATEPART1 ((GainLink *) 1) /*+ Vertex in part 1 +*/ +#define VGRAPHSEPAGGSTATEPART2 ((GainLink *) 2) /*+ Vertex in part 2, chained +*/ +#define VGRAPHSEPAGGSTATELINK ((GainLink *) 3) /*+ Currently in gain table if higher +*/ + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct VgraphSeparateGgParam_ { + INT passnbr; /*+ Number of passes to do +*/ +} VgraphSeparateGgParam; + +/*+ The complementary vertex structure. For + trick reasons, the gain table data structure + must be the first field of the structure. +*/ + +typedef struct VgraphSeparateGgVertex_ { + GainLink gainlink; /*+ Gain link: FIRST +*/ + Gnum compgain2; /*+ Computation gain in separator +*/ +} VgraphSeparateGgVertex; + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_GG +#define static +#endif + +int vgraphSeparateGg (Vgraph * restrict const, const VgraphSeparateGgParam * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_gp.c b/scotch_6.0.3/src/libscotch/vgraph_separate_gp.c new file mode 100644 index 00000000..6ef68e6b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_gp.c @@ -0,0 +1,234 @@ +/* Copyright 2004,2007,2008,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_gp.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module separates an active **/ +/** graph using a vertex-oriented version **/ +/** of the Gibbs-Poole-Stockmeyer **/ +/** algorithm. **/ +/** **/ +/** DATES : # Version 4.0 : from : 15 may 2004 **/ +/** to 17 may 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to 12 sep 2007 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to 09 nov 2008 **/ +/** # Version 6.0 : from : 10 feb 2011 **/ +/** to 10 feb 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_GP + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_gp.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vgraphSeparateGp ( +Vgraph * restrict const grafptr, /*+ Separation graph +*/ +const VgraphSeparateGpParam * const paraptr) /*+ Method parameters +*/ +{ + VgraphSeparateGpQueue queudat; /* Vertex queue */ + VgraphSeparateGpVertex * restrict vexxtax; /* Complementary vertex array */ + Gnum rootnum; + Gnum vertnum; + Gnum fronnum; + Gnum compsize1; + Gnum compsize2; + Gnum compload2; + Gnum comploaddlt; + + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const velotax = grafptr->s.velotax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + GraphPart * restrict const parttax = grafptr->parttax; + Gnum * restrict const frontab = grafptr->frontab; + + if (grafptr->compload[0] != grafptr->s.velosum) /* If not all vertices already in part 0 */ + vgraphZero (grafptr); /* Move all graph vertices to part 0 */ + + if (memAllocGroup ((void **) (void *) + &queudat.queutab, (size_t) (grafptr->s.vertnbr * sizeof (Gnum)), + &vexxtax, (size_t) (grafptr->s.vertnbr * sizeof (VgraphSeparateGpVertex)), NULL) == NULL) { + errorPrint ("vgraphSeparateGp: out of memory"); + return (1); + } + memSet (vexxtax, 0, grafptr->s.vertnbr * sizeof (VgraphSeparateGpVertex)); /* Initialize pass numbers */ + vexxtax -= grafptr->s.baseval; + + compload2 = 0; /* All vertices to part 0 */ + comploaddlt = grafptr->s.velosum; + for (rootnum = grafptr->s.baseval; /* Loop on connected components */ + (rootnum < grafptr->s.vertnnd) && (comploaddlt > 0); rootnum ++) { + Gnum passnum; /* Pass number */ + Gnum diamnum; /* Number of current diameter vertex */ + Gnum diamval; /* Current diameter value */ + Gnum diamdeg; /* Degree of current diameter vertex */ + int diamflag; /* Flag set if improvement in diameter between passes */ + Gnum veloval; + + while (vexxtax[rootnum].passnum != 0) /* Find first unallocated vertex */ + rootnum ++; + + for (diamnum = rootnum, diamval = diamdeg = 0, diamflag = 1, passnum = 1; /* Start from root */ + (passnum < paraptr->passnbr) && (diamflag -- != 0); passnum ++) { /* Loop if improvements */ + vgraphSeparateGpQueueFlush (&queudat); /* Flush vertex queue */ + vgraphSeparateGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ + vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ + vexxtax[diamnum].distval = 0; + + do { /* Loop on vertices in queue */ + Gnum vertnum; + Gnum distval; + Gnum edgenum; + + vertnum = vgraphSeparateGpQueueGet (&queudat); /* Get vertex from queue */ + distval = vexxtax[vertnum].distval; /* Get vertex distance */ + + if ((distval > diamval) || /* If vertex increases diameter */ + ((distval == diamval) && /* Or is at diameter distance */ + ((vendtax[vertnum] - verttax[vertnum]) < diamdeg))) { /* With smaller degree */ + diamnum = vertnum; /* Set it as new diameter vertex */ + diamval = distval; + diamdeg = vendtax[vertnum] - verttax[vertnum]; + diamflag = 1; + } + + distval ++; /* Set neighbor distance */ + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* End vertex number */ + + vertend = edgetax[edgenum]; + if (vexxtax[vertend].passnum < passnum) { /* If vertex not yet queued */ + vgraphSeparateGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ + vexxtax[vertend].passnum = passnum; + vexxtax[vertend].distval = distval; + } + } + } while (! vgraphSeparateGpQueueEmpty (&queudat)); /* As long as queue is not empty */ + } + + vgraphSeparateGpQueueFlush (&queudat); /* Flush vertex queue */ + vgraphSeparateGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ + vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ + vexxtax[diamnum].distval = 0; + veloval = (velotax != NULL) ? velotax[diamnum] : 1; + parttax[diamnum] = 2; /* Move diameter vertex to separator */ + comploaddlt -= veloval; + compload2 += veloval; + + do { /* Loop on vertices in queue */ + Gnum vertnum; + Gnum veloval; + Gnum distval; + Gnum edgenum; + + vertnum = vgraphSeparateGpQueueGet (&queudat); /* Get vertex from queue */ + veloval = (velotax != NULL) ? velotax[vertnum] : 1; + distval = vexxtax[vertnum].distval + 1; + parttax[vertnum] = 1; /* Move selected vertex from separator to part 1 */ + comploaddlt -= veloval; + compload2 -= veloval; + + for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { + Gnum vertend; /* End vertex number */ + Gnum veloval; + + vertend = edgetax[edgenum]; + veloval = (velotax != NULL) ? velotax[vertend] : 1; + if (vexxtax[vertend].passnum < passnum) { /* If vertex not yet queued */ + vgraphSeparateGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ + vexxtax[vertend].passnum = passnum; + vexxtax[vertend].distval = distval; + parttax[vertend] = 2; /* Move neighbor vertex to separator */ + comploaddlt -= veloval; + compload2 += veloval; + } + } + } while ((comploaddlt > 0) && (! vgraphSeparateGpQueueEmpty (&queudat))); /* As long as balance not achieved and queue is not empty */ + } + grafptr->compload[0] = (grafptr->s.velosum + comploaddlt - compload2) / 2; + grafptr->compload[1] = grafptr->s.velosum - compload2 - grafptr->compload[0]; + grafptr->compload[2] = compload2; + grafptr->comploaddlt = comploaddlt; + + memFree (queudat.queutab); /* Free group leader */ + + compsize1 = + compsize2 = 0; + for (vertnum = grafptr->s.baseval, fronnum = 0; + vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum partval; + + partval = (Gnum) parttax[vertnum]; + compsize1 += (partval & 1); /* Superscalar update */ + compsize2 += (partval >> 1); + if (partval == 2) /* If vertex belongs to frontier */ + frontab[fronnum ++] = vertnum; /* Record it in frontier array */ + } + grafptr->compsize[0] = grafptr->s.vertnbr - compsize1 - compsize2; + grafptr->compsize[1] = compsize1; + grafptr->fronnbr = compsize2; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vgraphCheck (grafptr) != 0) { + errorPrint ("vgraphSeparateGp: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_gp.h b/scotch_6.0.3/src/libscotch/vgraph_separate_gp.h new file mode 100644 index 00000000..83883a56 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_gp.h @@ -0,0 +1,93 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_gp.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the Gibbs, Poole, and Stockmeyer **/ +/** graph separation algorithm. **/ +/** **/ +/** DATES : # Version 4.0 : from : 14 may 2004 **/ +/** to 17 may 2004 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct VgraphSeparateGpParam_ { + INT passnbr; /*+ Number of passes to do +*/ +} VgraphSeparateGpParam; + +/*+ Complementary vertex structure. +*/ + +typedef struct VgraphSeparateGpVertex_ { + Gnum passnum; /*+ Number of pass when vertex selected +*/ + Gnum distval; /*+ Current distance from diameter vertex +*/ +} VgraphSeparateGpVertex; + +/*+ Neighbor queue. +*/ + +typedef struct VgraphSeparateGpQueue_ { + Gnum headnum; /*+ Head of distance queue +*/ + Gnum tailnum; /*+ Tail of distance queue +*/ + Gnum * queutab; /*+ Array of queue elements +*/ +} VgraphSeparateGpQueue; + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_GP +#define static +#endif + +int vgraphSeparateGp (Vgraph * restrict const, const VgraphSeparateGpParam * restrict const); + +#undef static + +/* +** The macro definitions. +*/ + +#define vgraphSeparateGpQueueFlush(queue) ((queue)->headnum = (queue)->tailnum = 0) +#define vgraphSeparateGpQueueEmpty(queue) ((queue)->headnum <= (queue)->tailnum) +#define vgraphSeparateGpQueuePut(queue,vnum) ((queue)->queutab[(queue)->headnum ++] = (vnum)) +#define vgraphSeparateGpQueueGet(queue) ((queue)->queutab[(queue)->tailnum ++]) diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_ml.c b/scotch_6.0.3/src/libscotch/vgraph_separate_ml.c new file mode 100644 index 00000000..c5bb638c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_ml.c @@ -0,0 +1,247 @@ +/* Copyright 2004,2007,2009,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_ml.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module separates a separator **/ +/** graph using a multi-level scheme. **/ +/** **/ +/** DATES : # Version 3.2 : from : 28 oct 1997 **/ +/** to 05 nov 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 13 dec 2001 **/ +/** to 20 mar 2005 **/ +/** # Version 5.1 : from : 11 nov 2009 **/ +/** to 11 nov 2009 **/ +/** # Version 6.0 : from : 09 mar 2011 **/ +/** to 16 apr 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_ML + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "graph_coarsen.h" +#include "vgraph.h" +#include "vgraph_separate_ml.h" +#include "vgraph_separate_st.h" + +/*********************************************/ +/* */ +/* The coarsening and uncoarsening routines. */ +/* */ +/*********************************************/ + +/* This routine builds a coarser graph from the +** graph that is given on input. The coarser +** graphs differ at this stage from classical +** active graphs as their internal gains are not +** yet computed. +** It returns: +** - 0 : if the coarse graph has been built. +** - 1 : if threshold achieved or on error. +*/ + +static +int +vgraphSeparateMlCoarsen ( +const Vgraph * restrict const finegrafptr, /*+ Finer graph +*/ +Vgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ +GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ +const VgraphSeparateMlParam * const paraptr) /*+ Method parameters +*/ +{ + if (graphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, paraptr->coarnbr, paraptr->coarval, NULL, NULL, 0, NULL) != 0) + return (1); /* Return if coarsening failed */ + + coargrafptr->parttax = NULL; /* Do not allocate partition data yet */ + coargrafptr->frontab = finegrafptr->frontab; /* Re-use frontier array for coarser graph */ + coargrafptr->levlnum = finegrafptr->levlnum + 1; /* Graph level is coarsening level */ + + return (0); +} + +/* This routine propagates the separation of the +** coarser graph back to the finer graph, according +** to the multinode table of collapsed vertices. +** After the separation is propagated, it finishes +** to compute the parameters of the finer graph that +** were not computed at the coarsening stage. +** It returns: +** - 0 : if coarse graph data has been propagated to fine graph. +** - !0 : on error. +*/ + +static +int +vgraphSeparateMlUncoarsen ( +Vgraph * restrict const finegrafptr, /*+ Finer graph +*/ +const Vgraph * restrict const coargrafptr, /*+ Coarser graph +*/ +const GraphCoarsenMulti * restrict const coarmulttax) /*+ Multinode array +*/ +{ + Gnum coarvertnum; /* Number of current coarse vertex */ + Gnum finefronnbr; /* Number of frontier vertices in fine graph */ + + if (finegrafptr->parttax == NULL) { /* If partition array not yet allocated */ + if ((finegrafptr->parttax = (GraphPart *) memAlloc (finegrafptr->s.vertnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("vgraphSeparateMlUncoarsen: out of memory"); + return (1); /* Allocated data will be freed along with graph structure */ + } + finegrafptr->parttax -= finegrafptr->s.baseval; + } + + if (coargrafptr != NULL) { /* If coarser graph provided */ + GraphPart * restrict fineparttax; + Gnum finesize1; /* Number of vertices in fine part 1 */ + + const GraphPart * restrict const coarparttax = coargrafptr->parttax; + + finesize1 = coargrafptr->compsize[1]; /* Pre-allocate size */ + fineparttax = finegrafptr->parttax; + for (coarvertnum = coargrafptr->s.baseval, finefronnbr = 0; + coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { + GraphPart coarpartval; /* Value of current multinode part */ + + coarpartval = coarparttax[coarvertnum]; + fineparttax[coarmulttax[coarvertnum].vertnum[0]] = coarpartval; + if (coarpartval != 2) { /* If vertex is not in separator */ + if (coarmulttax[coarvertnum].vertnum[0] != + coarmulttax[coarvertnum].vertnum[1]) { + fineparttax[coarmulttax[coarvertnum].vertnum[1]] = coarpartval; + finesize1 += (Gnum) coarpartval; /* One extra vertex created in part 1 if (coarpartval == 1) */ + } + } + else { /* Vertex is in separator */ + finegrafptr->frontab[finefronnbr ++] = coarmulttax[coarvertnum].vertnum[0]; + if (coarmulttax[coarvertnum].vertnum[0] != + coarmulttax[coarvertnum].vertnum[1]) { + fineparttax[coarmulttax[coarvertnum].vertnum[1]] = coarpartval; + finegrafptr->frontab[finefronnbr ++] = coarmulttax[coarvertnum].vertnum[1]; /* One extra vertex in separator */ + } + } + } + + finegrafptr->fronnbr = finefronnbr; + finegrafptr->compload[0] = coargrafptr->compload[0]; + finegrafptr->compload[1] = coargrafptr->compload[1]; + finegrafptr->compload[2] = coargrafptr->compload[2]; + finegrafptr->comploaddlt = coargrafptr->comploaddlt; + finegrafptr->compsize[0] = finegrafptr->s.vertnbr - finefronnbr - finesize1; + finegrafptr->compsize[1] = finesize1; + } + else /* No coarse graph provided */ + vgraphZero (finegrafptr); /* Assign all vertices to part 0 */ + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vgraphCheck (finegrafptr) != 0) { + errorPrint ("vgraphSeparateMlUncoarsen: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + + return (0); +} + +/* This routine recursively performs the +** separation recursion. +** It returns: +** - 0 : if separator could be computed. +** - !0 : on error. +*/ + +static +int +vgraphSeparateMl2 ( +Vgraph * restrict const grafptr, /* Vertex-separation graph */ +const VgraphSeparateMlParam * const paraptr) /* Method parameters */ +{ + Vgraph coargrafdat; + GraphCoarsenMulti * restrict coarmulttax; + int o; + + if (vgraphSeparateMlCoarsen (grafptr, &coargrafdat, &coarmulttax, paraptr) == 0) { + if (((o = vgraphSeparateMl2 (&coargrafdat, paraptr)) == 0) && + ((o = vgraphSeparateMlUncoarsen (grafptr, &coargrafdat, coarmulttax)) == 0) && + ((o = vgraphSeparateSt (grafptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ + errorPrint ("vgraphSeparateMl2: cannot apply ascending strategy"); + coargrafdat.frontab = NULL; /* Prevent frontab of fine graph from being freed */ + vgraphExit (&coargrafdat); + } + else { /* Cannot coarsen due to lack of memory or error */ + if (((o = vgraphSeparateMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ + ((o = vgraphSeparateSt (grafptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ + errorPrint ("vgraphSeparateMl2: cannot apply low strategy"); + } + + return (o); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the muti-level separation. +** It returns: +** - 0 : if separator could be computed. +** - 1 : on error. +*/ + +int +vgraphSeparateMl ( +Vgraph * const grafptr, /*+ Vertex-separation graph +*/ +const VgraphSeparateMlParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum levlnum; /* Save value for graph level */ + int o; + + levlnum = grafptr->levlnum; /* Save graph level */ + grafptr->levlnum = 0; /* Initialize coarsening level */ + o = vgraphSeparateMl2 (grafptr, paraptr); /* Perform multi-level separation */ + grafptr->levlnum = levlnum; /* Restore graph level */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_ml.h b/scotch_6.0.3/src/libscotch/vgraph_separate_ml.h new file mode 100644 index 00000000..5314db80 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_ml.h @@ -0,0 +1,81 @@ +/* Copyright 2004,2007,2011,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_ml.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the multi-level vertex separation **/ +/** routines. **/ +/** **/ +/** DATES : # Version 3.2 : from : 28 oct 1997 **/ +/** to 13 sep 1998 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 01 oct 1998 **/ +/** # Version 4.0 : from : 13 dec 2001 **/ +/** to 02 feb 2004 **/ +/** # Version 6.0 : from : 16 apr 2011 **/ +/** to 25 sep 2013 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VgraphSeparateMlParam_ { + INT coarnbr; /*+ Minimum number of vertices +*/ + double coarval; /*+ Coarsening ratio +*/ + GraphCoarsenType coartype; /*+ Edge matching function type +*/ + Strat * stratlow; /*+ Strategy at lowest level +*/ + Strat * stratasc; /*+ Strategy at ascending levels +*/ +} VgraphSeparateMlParam; + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_ML +#define static +#endif + +static int vgraphSeparateMlCoarsen (const Vgraph * const, Vgraph * const, GraphCoarsenMulti * restrict * const, const VgraphSeparateMlParam * const); +static int vgraphSeparateMlUncoarsen (Vgraph * const, const Vgraph * const, const GraphCoarsenMulti * restrict const); + +int vgraphSeparateMl (Vgraph * const, const VgraphSeparateMlParam * const); +static int vgraphSeparateMl2 (Vgraph * const, const VgraphSeparateMlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_st.c b/scotch_6.0.3/src/libscotch/vgraph_separate_st.c new file mode 100644 index 00000000..b0a2312b --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_st.c @@ -0,0 +1,336 @@ +/* Copyright 2004,2007,2011-2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_st.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the global **/ +/** separation strategy and method tables. **/ +/** **/ +/** DATES : # Version 3.2 : from : 25 oct 1996 **/ +/** to 14 nov 1997 **/ +/** # Version 3.3 : from : 01 oct 1998 **/ +/** to 31 may 1999 **/ +/** # Version 4.0 : from : 06 jan 2002 **/ +/** to 28 mar 2006 **/ +/** # Version 5.0 : from : 12 sep 2006 **/ +/** to : 02 oct 2007 **/ +/** # Version 5.1 : from : 30 oct 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 09 mar 2011 **/ +/** to 01 may 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_ST + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "graph_coarsen.h" +#include "bgraph.h" +#include "bgraph_bipart_st.h" +#include "vgraph.h" +#include "vgraph_separate_bd.h" +#include "vgraph_separate_es.h" +#include "vgraph_separate_fm.h" +#include "vgraph_separate_gg.h" +#include "vgraph_separate_gp.h" +#include "vgraph_separate_ml.h" +#include "vgraph_separate_th.h" +#include "vgraph_separate_st.h" +#include "vgraph_separate_vw.h" +#include "vgraph_separate_zr.h" + +/* +** The static and global variables. +*/ + +static Vgraph vgraphdummy; /* Dummy separator graph for offset computations */ + +static union { + VgraphSeparateBdParam param; + StratNodeMethodData padding; +} vgraphseparatedefaultbd = { { 3, &stratdummy, &stratdummy } }; + +static union { + VgraphSeparateEsParam param; + StratNodeMethodData padding; +} vgraphseparatedefaultes = { { &stratdummy, VGRAPHSEPAESWIDTHTHIN } }; + +static union { + VgraphSeparateFmParam param; + StratNodeMethodData padding; +} vgraphseparatedefaultfm = { { 200, 1000, 0.1L } }; + +static union { + VgraphSeparateGgParam param; + StratNodeMethodData padding; +} vgraphseparatedefaultgg = { { 5 } }; + +static union { + VgraphSeparateGpParam param; + StratNodeMethodData padding; +} vgraphseparatedefaultgp = { { 9 } }; + +static union { + VgraphSeparateMlParam param; + StratNodeMethodData padding; +} vgraphseparatedefaultml = { { 100, 0.8L, GRAPHCOARHEM, &stratdummy, &stratdummy } }; + +static StratMethodTab vgraphseparatestmethtab[] = { /* Graph separation methods array */ + { VGRAPHSEPASTMETHBD, "b", vgraphSeparateBd, &vgraphseparatedefaultbd }, + { VGRAPHSEPASTMETHES, "e", vgraphSeparateEs, &vgraphseparatedefaultes }, + { VGRAPHSEPASTMETHFM, "f", vgraphSeparateFm, &vgraphseparatedefaultfm }, + { VGRAPHSEPASTMETHGG, "h", vgraphSeparateGg, &vgraphseparatedefaultgg }, + { VGRAPHSEPASTMETHGP, "g", vgraphSeparateGp, &vgraphseparatedefaultgp }, + { VGRAPHSEPASTMETHML, "m", vgraphSeparateMl, &vgraphseparatedefaultml }, + { VGRAPHSEPASTMETHVW, "v", vgraphSeparateVw, NULL }, + { VGRAPHSEPASTMETHZR, "z", vgraphSeparateZr, NULL }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab vgraphseparatestparatab[] = { /* Graph separation method parameter list */ + { VGRAPHSEPASTMETHBD, STRATPARAMSTRAT, "bnd", + (byte *) &vgraphseparatedefaultbd.param, + (byte *) &vgraphseparatedefaultbd.param.stratbnd, + (void *) &vgraphseparateststratab }, + { VGRAPHSEPASTMETHBD, STRATPARAMSTRAT, "org", + (byte *) &vgraphseparatedefaultbd.param, + (byte *) &vgraphseparatedefaultbd.param.stratorg, + (void *) &vgraphseparateststratab }, + { VGRAPHSEPASTMETHBD, STRATPARAMINT, "width", + (byte *) &vgraphseparatedefaultbd.param, + (byte *) &vgraphseparatedefaultbd.param.distmax, + NULL }, + { VGRAPHSEPASTMETHES, STRATPARAMSTRAT, "strat", + (byte *) &vgraphseparatedefaultes.param, + (byte *) &vgraphseparatedefaultes.param.strat, + (void *) &bgraphbipartststratab }, + { VGRAPHSEPASTMETHES, STRATPARAMCASE, "type", + (byte *) &vgraphseparatedefaultes.param, + (byte *) &vgraphseparatedefaultes.param.widtval, + (void *) "tf" }, + { VGRAPHSEPASTMETHFM, STRATPARAMINT, "move", + (byte *) &vgraphseparatedefaultfm.param, + (byte *) &vgraphseparatedefaultfm.param.movenbr, + NULL }, + { VGRAPHSEPASTMETHFM, STRATPARAMINT, "pass", + (byte *) &vgraphseparatedefaultfm.param, + (byte *) &vgraphseparatedefaultfm.param.passnbr, + NULL }, + { VGRAPHSEPASTMETHFM, STRATPARAMDOUBLE, "bal", + (byte *) &vgraphseparatedefaultfm.param, + (byte *) &vgraphseparatedefaultfm.param.deltrat, + NULL }, + { VGRAPHSEPASTMETHGG, STRATPARAMINT, "pass", + (byte *) &vgraphseparatedefaultgg.param, + (byte *) &vgraphseparatedefaultgg.param.passnbr, + NULL }, + { VGRAPHSEPASTMETHGP, STRATPARAMINT, "pass", + (byte *) &vgraphseparatedefaultgp.param, + (byte *) &vgraphseparatedefaultgp.param.passnbr, + NULL }, + { VGRAPHSEPASTMETHML, STRATPARAMSTRAT, "asc", + (byte *) &vgraphseparatedefaultml.param, + (byte *) &vgraphseparatedefaultml.param.stratasc, + (void *) &vgraphseparateststratab }, + { VGRAPHSEPASTMETHML, STRATPARAMSTRAT, "low", + (byte *) &vgraphseparatedefaultml.param, + (byte *) &vgraphseparatedefaultml.param.stratlow, + (void *) &vgraphseparateststratab }, + { VGRAPHSEPASTMETHML, STRATPARAMCASE, "type", + (byte *) &vgraphseparatedefaultml.param, + (byte *) &vgraphseparatedefaultml.param.coartype, + (void *) "hs" }, + { VGRAPHSEPASTMETHML, STRATPARAMINT, "vert", + (byte *) &vgraphseparatedefaultml.param, + (byte *) &vgraphseparatedefaultml.param.coarnbr, + NULL }, + { VGRAPHSEPASTMETHML, STRATPARAMDOUBLE, "rat", + (byte *) &vgraphseparatedefaultml.param, + (byte *) &vgraphseparatedefaultml.param.coarval, + NULL }, + { VGRAPHSEPASTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab vgraphseparatestcondtab[] = { /* Graph condition parameter table */ + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &vgraphdummy, + (byte *) &vgraphdummy.s.edgenbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &vgraphdummy, + (byte *) &vgraphdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &vgraphdummy, + (byte *) &vgraphdummy.s.velosum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vert", + (byte *) &vgraphdummy, + (byte *) &vgraphdummy.s.vertnbr, + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab vgraphseparateststratab = { /* Strategy tables for vertex separation methods */ + vgraphseparatestmethtab, + vgraphseparatestparatab, + vgraphseparatestcondtab }; + +/*******************************************/ +/* */ +/* This is the generic separation routine. */ +/* */ +/*******************************************/ + +/* This routine computes the separation of +** the given graph according to the given +** strategy. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +vgraphSeparateSt ( +Vgraph * restrict const grafptr, /*+ Separation graph +*/ +const Strat * restrict const strat) /*+ Separation strategy +*/ +{ + StratTest val; + VgraphStore savetab[2]; /* Results of the two strategies */ + Gnum compload2; /* Saved separator load */ + int o; + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (sizeof (Gnum) != sizeof (INT)) { + errorPrint ("vgraphSeparateSt: invalid type specification for parser variables"); + return (1); + } + if ((sizeof (VgraphSeparateFmParam) > sizeof (StratNodeMethodData)) || + (sizeof (VgraphSeparateGgParam) > sizeof (StratNodeMethodData)) || + (sizeof (VgraphSeparateGpParam) > sizeof (StratNodeMethodData)) || + (sizeof (VgraphSeparateMlParam) > sizeof (StratNodeMethodData))) { + errorPrint ("vgraphSeparateSt: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ +#ifdef SCOTCH_DEBUG_VGRAPH1 + if ((strat->tabl != &vgraphseparateststratab) && + (strat != &stratdummy)) { + errorPrint ("vgraphSeparateSt: invalid parameter (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VGRAPH1 */ + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + o = vgraphSeparateSt (grafptr, strat->data.concat.strat[0]); /* Apply first strategy */ + if (o == 0) /* If it worked all right */ + o |= vgraphSeparateSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ + break; + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_VGRAPH2 + if ((val.typetest != STRATTESTVAL) || + (val.typenode != STRATPARAMLOG)) { + errorPrint ("vgraphSeparateSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_VGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = vgraphSeparateSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = vgraphSeparateSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + break; + case STRATNODESELECT : + if (((vgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ + ((vgraphStoreInit (grafptr, &savetab[1])) != 0)) { + errorPrint ("vgraphSeparateSt: out of memory"); + vgraphStoreExit (&savetab[0]); + return (1); + } + + vgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */ + if (vgraphSeparateSt (grafptr, strat->data.select.strat[0]) != 0) { /* If first strategy didn't work */ + vgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ + vgraphStoreSave (grafptr, &savetab[0]); /* Save it as result */ + } + else { /* First strategy worked */ + vgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ + vgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ + } + if (vgraphSeparateSt (grafptr, strat->data.select.strat[1]) != 0) /* If second strategy didn't work */ + vgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition as its result */ + + compload2 = grafptr->s.velosum - savetab[0].compload[0] - savetab[0].compload[1]; /* Compute saved separator load */ + if ( (compload2 < grafptr->compload[2]) || /* If first strategy is better */ + ((compload2 == grafptr->compload[2]) && + (abs (savetab[0].comploaddlt) < abs (grafptr->comploaddlt)))) + vgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ + + vgraphStoreExit (&savetab[0]); /* Free both save areas */ + vgraphStoreExit (&savetab[1]); + break; +#ifdef SCOTCH_DEBUG_VGRAPH1 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_VGRAPH1 */ + default : +#endif /* SCOTCH_DEBUG_VGRAPH1 */ + return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_VGRAPH1 + default : + errorPrint ("vgraphSeparateSt: invalid parameter (2)"); + return (1); +#endif /* SCOTCH_DEBUG_VGRAPH1 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_st.h b/scotch_6.0.3/src/libscotch/vgraph_separate_st.h new file mode 100644 index 00000000..60c5c815 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_st.h @@ -0,0 +1,89 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_st.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the global separation **/ +/** strategy and method tables. **/ +/** **/ +/** DATES : # Version 3.2 : from : 24 oct 1996 **/ +/** to 14 nov 1997 **/ +/** # Version 3.3 : from : 31 may 1999 **/ +/** to 31 may 1999 **/ +/** # Version 4.0 : from : 06 jan 2002 **/ +/** to 19 aug 2004 **/ +/** # Version 5.0 : from : 12 sep 2006 **/ +/** to : 17 feb 2007 **/ +/** # Version 5.1 : from : 30 oct 2007 **/ +/** to : 30 oct 2007 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum VgraphSeparateStMethodType_ { + VGRAPHSEPASTMETHBD = 0, /*+ Banding strategy +*/ + VGRAPHSEPASTMETHES, /*+ Edge separation strategy +*/ + VGRAPHSEPASTMETHFM, /*+ Fiduccia-Mattheyses +*/ + VGRAPHSEPASTMETHGG, /*+ Greedy Graph Growing +*/ + VGRAPHSEPASTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ + VGRAPHSEPASTMETHML, /*+ Multi-level separation +*/ + VGRAPHSEPASTMETHVW, /*+ Partition viewer +*/ + VGRAPHSEPASTMETHZR, /*+ Zero method +*/ + VGRAPHSEPASTMETHNBR /*+ Number of methods +*/ +} VgraphSeparateStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab vgraphseparateststratab; + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_ST +#define static +#endif + +int vgraphSeparateSt (Vgraph * const, const Strat * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_th.c b/scotch_6.0.3/src/libscotch/vgraph_separate_th.c new file mode 100644 index 00000000..c3f53d4e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_th.c @@ -0,0 +1,111 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : separate_th.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module thins a vertex separator. **/ +/** **/ +/** DATES : # Version 3.3 : from : 17 oct 1998 **/ +/** to 17 oct 1998 **/ +/** # Version 4.0 : from : 12 dec 2001 **/ +/** to 06 jan 2002 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_TH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_th.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vgraphSeparateTh ( +Vgraph * const grafptr) +{ + Gnum fronnbr; /* Current number of frontier vertices */ + Gnum fronnum; /* Number of current frontier vertex */ + Gnum commcut[3]; /* Cut count array ([3] for halo) */ + + fronnbr = grafptr->fronnbr; /* Get current number of frontier vertices */ + for (fronnum = 0; fronnum < fronnbr; ) { + Gnum vertnum; + Gnum edgenum; + + vertnum = grafptr->frontab[fronnum]; /* Get vertex number */ + commcut[0] = + commcut[1] = + commcut[2] = 0; + for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) + commcut[grafptr->parttax[grafptr->s.edgetax[edgenum]]] ++; + + if (commcut[0] == 0) { + grafptr->parttax[vertnum] = 1; + grafptr->compload[1] += (grafptr->s.velotax == NULL) ? 1 : grafptr->s.velotax[vertnum]; + grafptr->compsize[1] ++; + grafptr->frontab[fronnum] = grafptr->frontab[-- fronnbr]; /* Replace frontier vertex by another */ + } + else if (commcut[1] == 0) { + grafptr->parttax[vertnum] = 0; + grafptr->compload[0] += (grafptr->s.velotax == NULL) ? 1 : grafptr->s.velotax[vertnum]; + grafptr->compsize[0] ++; + grafptr->frontab[fronnum] = grafptr->frontab[-- fronnbr]; /* Replace frontier vertex by another */ + } + else + fronnum ++; /* Keep vertex in separator */ + } + grafptr->fronnbr = fronnbr; /* Set new frontier parameters */ + grafptr->compload[2] = grafptr->s.velosum - (grafptr->compload[0] + grafptr->compload[1]); + grafptr->comploaddlt = grafptr->compload[0] - grafptr->compload[1]; + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_th.h b/scotch_6.0.3/src/libscotch/vgraph_separate_th.h new file mode 100644 index 00000000..19740b1d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_th.h @@ -0,0 +1,59 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_th.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the the separator thinner **/ +/** vertex separation method. **/ +/** **/ +/** DATES : # Version 3.3 : from : 17 oct 1998 **/ +/** to 17 oct 1998 **/ +/** # Version 4.0 : from : 12 dec 2001 **/ +/** to 01 jan 2002 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_TH +#define static +#endif + +int vgraphSeparateTh (Vgraph * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_vw.c b/scotch_6.0.3/src/libscotch/vgraph_separate_vw.c new file mode 100644 index 00000000..51baceb7 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_vw.c @@ -0,0 +1,111 @@ +/* Copyright 2004,2007,2010,2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_vw.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module outputs the state of the **/ +/** current partition on the form of a **/ +/** Scotch mapping file. **/ +/** **/ +/** DATES : # Version 4.0 : from : 18 may 2004 **/ +/** to 18 may 2004 **/ +/** # Version 5.1 : from : 11 aug 2010 **/ +/** to 11 aug 2010 **/ +/** # Version 6.0 : from : 10 oct 2013 **/ +/** to 10 oct 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_VW + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_vw.h" + +/* +** The static variables. +*/ + +static int vgraphseparatevwfilenum = 0; /* Number of file to output */ + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine outputs the mapping file. +** It returns: +** - 0 : if the file could be produced. +** - !0 : on error. +*/ + +int +vgraphSeparateVw ( +Vgraph * restrict const grafptr) /*+ Separation graph +*/ +{ + char nametab[64]; /* File name */ + FILE * restrict fileptr; + Gnum vertnum; /* Vertex number */ + + sprintf (nametab, "vgraphseparatevw_output_%08d.map", vgraphseparatevwfilenum ++); + if ((fileptr = fopen (nametab, "w+")) == NULL) { + errorPrint ("vgraphSeparateVw: cannot open partition file"); + return (1); + } + + fprintf (fileptr, GNUMSTRING "\n", /* Output size of mapping; test if failure later, in main loop */ + (Gnum) grafptr->s.vertnbr); + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + if (fprintf (fileptr, GNUMSTRING "\t%d\n", + (Gnum) ((grafptr->s.vnumtax != NULL) ? grafptr->s.vnumtax[vertnum] : vertnum), + (int) grafptr->parttax[vertnum]) <= 0) { + errorPrint ("vgraphSeparateVw: bad output"); + fclose (fileptr); + return (1); + } + } + + fclose (fileptr); + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_vw.h b/scotch_6.0.3/src/libscotch/vgraph_separate_vw.h new file mode 100644 index 00000000..6685c72d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_vw.h @@ -0,0 +1,59 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_vw.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the move-all-to-first-subdomain **/ +/** separation method. **/ +/** **/ +/** DATES : # Version 3.3 : from : 31 may 1999 **/ +/** to 31 may 1999 **/ +/** # Version 4.0 : from : 18 may 2004 **/ +/** to 18 may 2004 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_VW +#define static +#endif + +int vgraphSeparateVw (Vgraph * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_zr.c b/scotch_6.0.3/src/libscotch/vgraph_separate_zr.c new file mode 100644 index 00000000..7d365d81 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_zr.c @@ -0,0 +1,81 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_zr.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module moves all of the vertices **/ +/** to the first subdomain. **/ +/** **/ +/** DATES : # Version 3.3 : from : 31 may 1999 **/ +/** to 31 may 1999 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 29 may 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_SEPARATE_ZR + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_zr.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine moves all of the graph vertices +** to the first part of the partition. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vgraphSeparateZr ( +Vgraph * const grafptr) /*+ Active graph +*/ +{ + if (grafptr->compload[0] != grafptr->s.velosum) /* If not all vertices already in part zero */ + vgraphZero (grafptr); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vgraph_separate_zr.h b/scotch_6.0.3/src/libscotch/vgraph_separate_zr.h new file mode 100644 index 00000000..099f9f51 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_separate_zr.h @@ -0,0 +1,59 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_zr.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the move-all-to-first-subdomain **/ +/** separation method. **/ +/** **/ +/** DATES : # Version 3.3 : from : 31 may 1999 **/ +/** to 31 may 1999 **/ +/** # Version 4.0 : from : 19 dec 2001 **/ +/** to 01 jan 2002 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef VGRAPH_SEPARATE_ZR +#define static +#endif + +int vgraphSeparateZr (Vgraph * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vgraph_store.c b/scotch_6.0.3/src/libscotch/vgraph_store.c new file mode 100644 index 00000000..f9ea2fed --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vgraph_store.c @@ -0,0 +1,166 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_store.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the save data **/ +/** structure handling routines for separa- **/ +/** tion graphs. **/ +/** **/ +/** DATES : # Version 3.3 : from : 17 oct 1998 **/ +/** to 17 oct 1998 **/ +/** # Version 3.4 : from : 11 dec 2001 **/ +/** to : 11 dec 2001 **/ +/** # Version 4.0 : from : 01 jan 2002 **/ +/** to : 06 jan 2002 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VGRAPH_STORE + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "vgraph.h" + +/**********************************/ +/* */ +/* Store graph handling routines. */ +/* */ +/**********************************/ + +/* This routine builds a save structure +** for the given active graph. +** It returns: +** - 0 : if allocation succeeded. +** - !0 : on error. +*/ + +int +vgraphStoreInit ( +const Vgraph * restrict const grafptr, +VgraphStore * restrict const storptr) +{ + Gnum savsize; + + savsize = grafptr->s.vertnbr * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ + + if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ + errorPrint ("vgraphStoreInit: out of memory"); + return (1); + } + + return (0); +} + +/* This routine frees a save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +vgraphStoreExit ( +VgraphStore * const storptr) +{ + memFree (storptr->datatab); +#ifdef SCOTCH_DEBUG_VGRAPH2 + storptr->datatab = NULL; +#endif /* SCOTCH_DEBUG_VGRAPH2 */ +} + +/* This routine saves partition data from the +** given active graph to the given save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +vgraphStoreSave ( +const Vgraph * const grafptr, +VgraphStore * const storptr) +{ + byte * parttab; /* Pointer to part data save area */ + byte * frontab; /* Pointer to frontier data save area */ + + storptr->fronnbr = grafptr->fronnbr; /* Save partition parameters */ + storptr->comploaddlt = grafptr->comploaddlt; + storptr->compload[0] = grafptr->compload[0]; + storptr->compload[1] = grafptr->compload[1]; + storptr->compsize0 = grafptr->compsize[0]; + + frontab = storptr->datatab; /* Compute data offsets within save structure */ + parttab = frontab + grafptr->fronnbr * sizeof (Gnum); + + memCpy (frontab, grafptr->frontab, grafptr->fronnbr * sizeof (Gnum)); + memCpy (parttab, grafptr->parttax + grafptr->s.baseval, grafptr->s.vertnbr * sizeof (GraphPart)); +} + +/* This routine updates partition data of the +** given active graph, using the given save graph. +** It returns: +** - VOID : in all cases. +*/ + +void +vgraphStoreUpdt ( +Vgraph * const grafptr, +const VgraphStore * const storptr) +{ + byte * frontab; /* Pointer to frontier data save area */ + byte * parttab; /* Pointer to part data save area */ + + grafptr->compload[0] = storptr->compload[0]; /* Load partition parameters */ + grafptr->compload[1] = storptr->compload[1]; + grafptr->compload[2] = grafptr->s.velosum - (storptr->compload[0] + storptr->compload[1]); + grafptr->comploaddlt = storptr->comploaddlt; + grafptr->compsize[0] = storptr->compsize0; + grafptr->compsize[1] = grafptr->s.vertnbr - (storptr->compsize0 + storptr->fronnbr); + grafptr->fronnbr = storptr->fronnbr; + + frontab = storptr->datatab; /* Compute data offsets within save structure */ + parttab = frontab + grafptr->fronnbr * sizeof (Gnum); + + memCpy (grafptr->frontab, frontab, grafptr->fronnbr * sizeof (Gnum)); + memCpy (grafptr->parttax + grafptr->s.baseval, parttab, grafptr->s.vertnbr * sizeof (GraphPart)); + +#ifdef SCOTCH_DEBUG_VGRAPH2 + if (vgraphCheck (grafptr) != 0) + errorPrint ("vgraphStoreUpdt: inconsistent graph data"); +#endif /* SCOTCH_DEBUG_VGRAPH2 */ +} diff --git a/scotch_6.0.3/src/libscotch/vmesh.c b/scotch_6.0.3/src/libscotch/vmesh.c new file mode 100644 index 00000000..a12a99f9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh.c @@ -0,0 +1,108 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the separator **/ +/** handling routines. **/ +/** **/ +/** DATES : # Version 4.0 : from : 06 feb 2003 **/ +/** to 05 mar 2003 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to 09 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "vmesh.h" + +/*************************/ +/* */ +/* These routines handle */ +/* separator meshes. */ +/* */ +/*************************/ + +/* This routine frees the contents +** of the given active mesh. +** It returns: +** - VOID : in all cases. +*/ + +void +vmeshExit ( +Vmesh * const meshptr) +{ + if (meshptr->parttax != NULL) /* Free leader of group (parttab + frontab) */ + memFree (meshptr->parttax + meshptr->m.baseval); + + meshFree (&meshptr->m); /* Free source mesh */ + +#ifdef SCOTCH_DEBUG_VMESH2 + memSet (meshptr, ~0, sizeof (Vmesh)); +#endif /* SCOTCH_DEBUG_VMESH2 */ +} + +/* This routine moves all of the mesh +** elements to the first part. +** It returns: +** - VOID : in all cases. +*/ + +void +vmeshZero ( +Vmesh * const meshptr) +{ + memSet (meshptr->parttax + meshptr->m.baseval, 0, (meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (GraphPart)); + + meshptr->ecmpsize[0] = meshptr->m.velmnbr; + meshptr->ecmpsize[1] = 0; + meshptr->ncmpload[0] = meshptr->m.vnlosum; + meshptr->ncmpload[1] = + meshptr->ncmpload[2] = 0; + meshptr->ncmploaddlt = meshptr->m.vnlosum; + meshptr->ncmpsize[0] = meshptr->m.vnodnbr; + meshptr->ncmpsize[1] = + meshptr->fronnbr = 0; +} diff --git a/scotch_6.0.3/src/libscotch/vmesh.h b/scotch_6.0.3/src/libscotch/vmesh.h new file mode 100644 index 00000000..4d1e8d52 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh.h @@ -0,0 +1,95 @@ +/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for mesh vertex separation **/ +/** routines. **/ +/** **/ +/** DATES : # Version 4.0 : from : 10 sep 2002 **/ +/** to : 10 sep 2002 **/ +/** # Version 5.1 : from : 04 nov 2010 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ Active graph structure. +*/ + +typedef struct Vmesh_ { + Mesh m; /*+ Source mesh +*/ + GraphPart * parttax; /*+ Based part array: 0,1: part; 2: separator +*/ + Gnum ecmpsize[2]; /*+ Number of elements in each part (not in separator) +*/ + Gnum ncmpload[3]; /*+ Loads of nodes in both parts and separator +*/ + Gnum ncmploaddlt; /*+ Node load difference between both parts +*/ + Gnum ncmpsize[2]; /*+ Number of nodes in parts (separator is fronnbr) +*/ + Gnum fronnbr; /*+ Number of frontier nodes; TRICK: ncmpsize[2] +*/ + Gnum * frontab; /*+ Array of frontier node numbers +*/ + Gnum levlnum; /*+ Nested dissection or coarsening level +*/ +} Vmesh; + +/*+ The graph separator storing structure. +*/ + +typedef struct VmeshStore_ { + Gnum ecmpsize[2]; /*+ Number of elements in each part +*/ + Gnum ncmpload[3]; /*+ Loads of nodes in both parts and separator +*/ + Gnum ncmploaddlt; /*+ Node load difference between both parts +*/ + Gnum ncmpsize[2]; /*+ Number of nodes in parts (separator is fronnbr) +*/ + Gnum fronnbr; /*+ Number of frontier nodes; TRICK: ncmpsize[2] +*/ + byte * datatab; /*+ Variable-sized data array +*/ +} VmeshStore; + +/* +** The function prototypes. +*/ + +#ifndef VMESH +#define static +#endif + +void vmeshExit (Vmesh * const); +void vmeshZero (Vmesh * const); +int vmeshCheck (const Vmesh * const); + +int vmeshStoreInit (const Vmesh * const, VmeshStore * const); +void vmeshStoreExit (VmeshStore * const); +void vmeshStoreSave (const Vmesh * const , VmeshStore * const); +void vmeshStoreUpdt (Vmesh * const, const VmeshStore * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vmesh_check.c b/scotch_6.0.3/src/libscotch/vmesh_check.c new file mode 100644 index 00000000..dd245496 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_check.c @@ -0,0 +1,237 @@ +/* Copyright 2004,2007,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_check.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the consistency **/ +/** checker for separation meshes. **/ +/** **/ +/** DATES : # Version 4.0 : from : 21 mar 2003 **/ +/** to 11 may 2004 **/ +/** # Version 6.0 : from : 02 jun 2014 **/ +/** to 02 jun 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "vmesh.h" + +/*************************/ +/* */ +/* These routines handle */ +/* separator meshes. */ +/* */ +/*************************/ + +/* This routine checks the consistency +** of the given separator mesh. +** It returns: +** - 0 : if mesh data are consistent. +** - !0 : on error. +*/ + +int +vmeshCheck ( +const Vmesh * const meshptr) +{ + Gnum velmnum; /* Number of current element vertex */ + Gnum vnodnum; /* Number of current node vertex */ + Gnum fronnum; /* Number of current frontier vertex */ + int * restrict frontax; /* Frontier flag array */ + Gnum ecmpsize[2]; /* Elements never in separator */ + Gnum ncmpsize[3]; + Gnum ncmpload[3]; + int o; + + if ((meshptr->ecmpsize[0] + meshptr->ecmpsize[1]) > meshptr->m.velmnbr) { + errorPrint ("vmeshCheck: invalid element balance"); + return (1); + } + if (meshptr->ncmploaddlt != (meshptr->ncmpload[0] - meshptr->ncmpload[1])) { + errorPrint ("vmeshCheck: invalid node balance"); + return (1); + } + + ecmpsize[0] = + ecmpsize[1] = 0; + for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++) { + Gnum edgecut[3]; /* Array of cut edges */ + Gnum partnum; /* Part of current vertex */ + Gnum eelmnum; /* Number of current edge */ + + partnum = meshptr->parttax[velmnum]; + if ((partnum < 0) || (partnum > 1)) { + errorPrint ("vmeshCheck: invalid part array (1)"); + return (1); + } + ecmpsize[partnum] ++; + + if ((partnum != 0) && + (meshptr->m.verttax[velmnum] == meshptr->m.vendtax[velmnum])) { + errorPrint ("vmeshCheck: isolated element not in part 0"); + return (1); + } + + edgecut[0] = + edgecut[1] = + edgecut[2] = 0; + for (eelmnum = meshptr->m.verttax[velmnum]; + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) + edgecut[meshptr->parttax[meshptr->m.edgetax[eelmnum]]] ++; + + if (partnum == 2) { + if ((edgecut[0] != 0) || (edgecut[1] != 0)) { + errorPrint ("vmeshCheck: separator element not surrounded by separator nodes"); + return (1); + } + } + else { + if (edgecut[1 - partnum] != 0) { + errorPrint ("vmeshCheck: element should be in separator (%ld)", (long) velmnum); + return (1); + } + } + } + if ((meshptr->ecmpsize[0] != ecmpsize[0]) || + (meshptr->ecmpsize[1] != ecmpsize[1])) { + errorPrint ("vmeshCheck: invalid element parameters"); + return (1); + } + + ncmpload[0] = + ncmpload[1] = + ncmpload[2] = 0; + ncmpsize[0] = + ncmpsize[1] = + ncmpsize[2] = 0; + for (vnodnum = meshptr->m.vnodbas; vnodnum < meshptr->m.vnodnnd; vnodnum ++) { + Gnum edgecut[3]; /* Array of cut edges */ + Gnum partnum; /* Part of current vertex */ + Gnum enodnum; /* Number of current edge */ + + partnum = meshptr->parttax[vnodnum]; + if ((partnum < 0) || (partnum > 2)) { + errorPrint ("vmeshCheck: invalid part array (2)"); + return (1); + } + + ncmpsize[partnum] ++; + ncmpload[partnum] += (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; + + edgecut[0] = + edgecut[1] = + edgecut[2] = 0; + for (enodnum = meshptr->m.verttax[vnodnum]; + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) + edgecut[meshptr->parttax[meshptr->m.edgetax[enodnum]]] ++; + +#ifdef SCOTCH_DEBUG_VMESH3 + if (partnum == 2) { + if ((edgecut[0] == 0) || + (edgecut[1] == 0)) + errorPrint ("vmeshCheck: no-use separator vertex%s (%ld)", /* Warning only */ + ((meshptr->levlnum == 0) ? " at level 0" : ""), + (long) vnodnum); + } + else { +#else + if (partnum != 2) { +#endif /* SCOTCH_DEBUG_VMESH3 */ + if (edgecut[1 - partnum] != 0) { + errorPrint ("vmeshCheck: node should be in separator (%ld)", (long) vnodnum); + return (1); + } + } + } + if ((meshptr->ncmpload[0] != ncmpload[0]) || + (meshptr->ncmpload[1] != ncmpload[1]) || + (meshptr->ncmpload[2] != ncmpload[2]) || + (meshptr->ncmpsize[0] != ncmpsize[0]) || + (meshptr->ncmpsize[1] != ncmpsize[1]) || + (meshptr->fronnbr != ncmpsize[2])) { + errorPrint ("vmeshCheck: invalid node parameters"); + return (1); + } + + if ((meshptr->fronnbr < 0) || + (meshptr->fronnbr > meshptr->m.vnodnbr)) { + errorPrint ("vmeshCheck: invalid number of frontier vertices"); + return (1); + } + if ((frontax = memAlloc (meshptr->m.vnodnbr * sizeof (int))) == NULL) { + errorPrint ("vmeshCheck: out of memory"); + return (1); + } + memSet (frontax, 0, meshptr->m.vnodnbr * sizeof (int)); + frontax -= meshptr->m.vnodbas; + + o = 1; /* Assume failure when checking */ + for (fronnum = 0; fronnum < meshptr->fronnbr; fronnum ++) { + Gnum vnodnum; + + vnodnum = meshptr->frontab[fronnum]; + + if ((vnodnum < meshptr->m.vnodbas) || + (vnodnum >= meshptr->m.vnodnnd)) { + errorPrint ("vmeshCheck: invalid vertex in frontier array"); + goto fail; + } + if (meshptr->parttax[vnodnum] != 2) { + errorPrint ("vmeshCheck: invalid frontier array"); + goto fail; + } + if (frontax[vnodnum] != 0) { + errorPrint ("vmeshCheck: duplicate node in frontier array"); + goto fail; + } + frontax[vnodnum] = 1; + } + + o = 0; /* Everything turned well */ + +fail : + memFree (frontax + meshptr->m.vnodbas); + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_fm.c b/scotch_6.0.3/src/libscotch/vmesh_separate_fm.c new file mode 100644 index 00000000..4a6c58cf --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_fm.c @@ -0,0 +1,1247 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_fm.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module separates an active **/ +/** mesh using an element-oriented version **/ +/** of our improved Fiduccia-Mattheyses **/ +/** heuristics. **/ +/** **/ +/** DATES : # Version 4.0 : from : 26 feb 2003 **/ +/** to 06 may 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to 22 may 2008 **/ +/** # Version 5.1 : from : 12 nov 2008 **/ +/** to 12 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH_SEPARATE_FM + +/* #define SCOTCH_DEBUG_VMESH3 */ /* For intensive debugging */ + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "graph.h" +#include "mesh.h" +#include "vmesh.h" +#include "vmesh_separate_gg.h" +#include "vmesh_separate_fm.h" + +/* This routine resizes the hash arrays +** as well as the associated structures. +** In the group of allocated arrays, +** the element array must be put before +** the node array, because the element +** structure is larger than the node +** structure, such that the old and new +** node arrays can never overlap after +** the doubling in size of the element +** array. The same for the move array. +** It returns: +** - 0 : if resize succeeded. +** - !0 : in case of error. +*/ + +static +int +vmeshSeparateFmResize ( +GainTabl * restrict const tablptr, /*+ Pointer to gain table +*/ +VmeshSeparateFmElement * restrict * const helmptr, /*+ Pointer to pointer to element hash table +*/ +VmeshSeparateFmNode * restrict * const hnodptr, /*+ Pointer to pointer to node hash table +*/ +VmeshSeparateFmSave * restrict * const saveptr, /*+ Pointer to pointer to move array +*/ +const Gnum savenbr, /*+ Current number of items in save array +*/ +VmeshSeparateFmElement ** lockptr, /*+ Pointer to list of locked elements +*/ +VmeshSeparateFmElement ** sepaptr, /*+ Pointer to list of separator elements, if any +*/ +const Gnum hashold) /*+ Maximum number of vertices in hash structures +*/ +{ + Gnum hashsiz; /* Size of hash table */ + Gnum hashmsk; /* Mask for access to hash table */ + Gnum hashmax; /* Maximum number of objects in tables */ + VmeshSeparateFmSave * restrict movetab; /* Pointer to move array */ + VmeshSeparateFmElement * restrict helmtab; /* Element hash table */ + VmeshSeparateFmNode * hnodtab; /* Node hash table */ + size_t addradj; /* Address adjustment */ + Gnum helmold; + VmeshSeparateFmNode * hnodtld; + Gnum hnodold; + VmeshSeparateFmSave * restrict savetab; + Gnum savenum; + + hashmax = 2 * hashold; /* Set new number */ + hashsiz = 4 * hashmax; /* Set new size */ + hashmsk = hashsiz - 1; + + savetab = *saveptr; /* Point to old move array */ + for (savenum = 0; savenum < savenbr; savenum ++) { /* Turn hash indices into vertex indices */ + Gnum hertnum; + + hertnum = savetab[savenum].hertnum; + savetab[savenum].hertnum = (hertnum >= 0) ? (*helmptr)[hertnum].velmnum : (-1 - (*hnodptr)[-1 - hertnum].vnodnum); + } + + if (memReallocGroup ((void *) *helmptr, /* Get old group leader */ + &helmtab, (size_t) (hashsiz * sizeof (VmeshSeparateFmElement)), + &hnodtab, (size_t) (hashsiz * sizeof (VmeshSeparateFmNode)), + &movetab, (size_t) (hashmax * sizeof (VmeshSeparateFmSave)), NULL) == NULL) { + errorPrint ("vmeshSeparateFmResize: cannot resize arrays"); + return (1); /* If cannot reallocate */ + } +#ifdef SCOTCH_DEBUG_VMESH2 + if (((byte *) hnodtab - (byte *) helmtab) < ((byte *) (*saveptr) - (byte *) (*helmptr))) { /* If cannot simply copy node hash array */ + errorPrint ("vmeshSeparateFmResize: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + memMov (movetab, ((byte *) helmtab) + ((byte *) *saveptr - (byte *) *helmptr), savenbr * sizeof (VmeshSeparateFmSave)); /* Old array may have moved but arrays cannot overlap */ + + memSet (hnodtab, ~0, hashsiz * sizeof (VmeshSeparateFmNode)); /* Cannot overlap */ + hnodtld = (VmeshSeparateFmNode *) ((byte *) helmtab) + ((byte *) *hnodptr - (byte *) *helmptr); /* Point to old node array */ + for (hnodold = 0; hnodold < (hashold * 4); hnodold ++) { /* For all old allocated nodes */ + Gnum hnodnew; + + if (hnodtld[hnodold].vnodnum == ~0) /* If unallocated slot */ + continue; /* Skip to next slot */ + + for (hnodnew = (hnodtld[hnodold].vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; + hnodtab[hnodnew].vnodnum != ~0; hnodnew = (hnodnew + 1) & hashmsk) ; + hnodtab[hnodnew] = hnodtld[hnodold]; /* Move node data to new position */ + } + +/* TODO */ + fprintf (stderr, "hertnum no longer valid !\n"); + exit (1); + + addradj = (byte *) helmtab - (byte *) (*helmptr); /* Compute address difference */ + + gainTablFree (tablptr); /* Reset gain table */ + memSet (helmtab + hashold, ~0, hashold * 2 * sizeof (VmeshSeparateFmElement)); + for (helmold = 0; helmold < (hashold * 4); helmold ++) { /* For all old allocated elements */ + Gnum helmnew; + + if (helmtab[helmold].velmnum == ~0) /* If unallocated slot */ + continue; /* Skip to next slot */ + + for (helmnew = (helmtab[helmold].velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmnew = (helmnew + 1) & hashmsk) { + if (helmtab[helmnew].velmnum == ~0) { + helmtab[helmnew].velmnum = helmtab[helmold].velmnum; + helmtab[helmnew].vertpart = helmtab[helmold].vertpart; + helmtab[helmnew].ncmpcut2 = helmtab[helmold].ncmpcut2; + helmtab[helmnew].ncmpgain2 = helmtab[helmold].ncmpgain2; + helmtab[helmnew].ncmpgaindlt = helmtab[helmold].ncmpgaindlt; + helmtab[helmnew].mswpnum = helmtab[helmold].mswpnum; + helmtab[helmold].velmnum = ~0; /* Free old slot */ + helmtab[helmold].mswpnum = ~0; /* Reset sweep number */ + break; + } + if (helmtab[helmnew].velmnum != helmtab[helmold].velmnum) /* If element not found */ + continue; /* Go on searching */ + } + if (helmtab[helmold].gainlink.next >= VMESHSEPAFMSTATELINK) /* If element was linked */ + gainTablAdd (tablptr, (GainLink *) &helmtab[helmnew], helmtab[helmnew].ncmpgain2); /* Re-link it */ + else { /* Element may be chained in some list */ + helmtab[helmnew].gainlink.next = helmtab[helmold].gainlink.next; /* Save it */ + helmtab[helmnew].gainlink.prev = (GainLink *) ((byte *) helmtab[helmold].gainlink.prev + addradj); + } + } + + if (*lockptr != NULL) + *lockptr = (VmeshSeparateFmElement *) ((byte *) (*lockptr) + addradj); + if (sepaptr != NULL) { + if (*sepaptr != NULL) + *sepaptr = (VmeshSeparateFmElement *) ((byte *) (*sepaptr) + addradj); + } + + for (savenum = 0; savenum < savenbr; savenum ++) { /* Turn vertex indices back into hash indices */ + Gnum vertnum; + + vertnum = movetab[savenum].hertnum; /* Read vertex index */ + if (vertnum >= 0) { /* If element vertex */ + Gnum helmnum; + + for (helmnum = (vertnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmnum = (helmnum + 1) & hashmsk) { +#ifdef SCOTCH_DEBUG_VMESH2 + if (helmtab[helmnum].velmnum == ~0) { /* We should always find the elements */ + errorPrint ("vmeshSeparateFmResize: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (helmtab[helmnum].velmnum == vertnum) /* If element found */ + break; + } + movetab[savenum].hertnum = helmnum; /* Save element hash index */ + } + else { /* If node vertex */ + Gnum hnodnum; + + vertnum = -1 - vertnum; + for (hnodnum = (vertnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { +#ifdef SCOTCH_DEBUG_VMESH2 + if (hnodtab[hnodnum].vnodnum == ~0) { /* We should always find the nodes */ + errorPrint ("vmeshSeparateFmResize: internal error (3)"); + return (1); + } + if (hnodtab[hnodnum].vnodnum == vertnum) /* If element found */ + break; +#endif /* SCOTCH_DEBUG_VMESH2 */ + } + movetab[savenum].hertnum = -1 - hnodnum; /* Save node hash index */ + } + } + + fprintf (stderr, "########### vmeshSeparateFmResize (%ld) !!!\n", (long) hashold); + + return (0); +} + +/* This routine returns the vertex of best gain +** whose swap will keep the balance correct. +** It returns: +** - !NULL : pointer to the vertex. +** - NULL : if no more vertices available. +*/ + +static +VmeshSeparateFmElement * +vmeshSeparateFmTablGet ( +GainTabl * const tablptr, /*+ Gain table +*/ +const Gnum deltcur, /*+ Current imbalance +*/ +const Gnum deltmax) /*+ Maximum imbalance +*/ +{ + const VmeshSeparateFmElement * velmptr; + VmeshSeparateFmElement * vertbest; + Gnum gainbest; + const GainEntr * tablbest; + Gnum deltbest; + Gnum deltnew; + + tablbest = tablptr->tend; /* Assume no candidate vertex found yet */ + gainbest = GAINMAX; + vertbest = NULL; + deltbest = deltmax; + + for (velmptr = (VmeshSeparateFmElement *) gainTablFrst (tablptr); /* Select candidate vertices */ + (velmptr != NULL) && (velmptr->gainlink.tabl < tablbest); + velmptr = (VmeshSeparateFmElement *) gainTablNext (tablptr, &velmptr->gainlink)) { + deltnew = abs (deltcur + velmptr->ncmpgaindlt); + if (deltnew <= deltmax) { /* If vertex enforces balance */ + if ((velmptr->ncmpgain2 < gainbest) || /* And if it gives better gain */ + ((velmptr->ncmpgain2 == gainbest) && /* Or if it gives better load */ + (deltnew < deltbest))) { + tablbest = velmptr->gainlink.tabl; /* Select it */ + gainbest = velmptr->ncmpgain2; + vertbest = (VmeshSeparateFmElement *) velmptr; + deltbest = deltnew; + } + } + } + + return (vertbest); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine computes the +** separation of the given mesh. +** It returns: +** - 0 : if bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vmeshSeparateFm ( +Vmesh * restrict const meshptr, /*+ Node separation mesh +*/ +const VmeshSeparateFmParam * restrict const paraptr) /*+ Method parameters +*/ +{ + GainTabl * restrict tablptr; /* Pointer to gain table */ + long passnbr; /* Maximum number of passes to go */ + VmeshSeparateFmSave * restrict movetab; /* Pointer to move array */ + Gnum movenbr; /* Number of uneffective moves done */ + Gnum savenbr; /* Number of recorded backtrack moves */ + Gnum mswpnum; /* Current number of recording sweep */ + int moveflag; /* Flag set if useful moves made */ + Gnum fronnum; /* Current index in frontier array */ + Gnum vertnbr; + Gnum hashsiz; /* Size of hash table */ + Gnum hashmsk; /* Mask for access to hash table */ + Gnum hashmax; /* Maximum number of objects in tables */ + Gnum hashnbr; /* Estimated number of onjects in hash */ + Gnum helmnbr; /* Number of elements in hash table */ + Gnum helmnum; + Gnum hnodnum; + Gnum hnodnbr; /* Number of nodes in hash table */ + VmeshSeparateFmElement * restrict helmtab; /* Element hash table */ + VmeshSeparateFmNode * restrict hnodtab; /* Node hash table */ + VmeshSeparateFmElement * lockptr; /* Linked list of locked elements */ + VmeshSeparateFmElement * velmptr; /* Pointer to current element */ + Gnum ncmploaddltmat; /* Theoretical latgest imbalance allowed */ + Gnum ncmploaddltmax; /* Largest imbalance allowed */ + Gnum ncmploaddlt; /* Current imbalance */ + Gnum ncmpload2; /* Current size of separator */ + Gnum ncmpload2bst; + Gnum ncmploaddltbst; + Gnum ecmpload1; + Gnum ncmpload1; + Gnum ncmpsize1; + Gnum ncmpsize2; + + if (paraptr->deltrat > 0.0L) { + Gnum ncmploaddlttmp; + + ncmploaddltmat = (Gnum) (paraptr->deltrat * meshptr->m.vnlosum) + 1; + ncmploaddlttmp = (Gnum) (((float) meshptr->m.edgenbr * (float) meshptr->m.vnlosum) / + ((float) meshptr->m.velmnbr * (float) meshptr->m.vnodnbr)); + if (ncmploaddltmat < ncmploaddlttmp) + ncmploaddltmat = ncmploaddlttmp; + } + else + ncmploaddltmat = 0; + + ncmploaddltmat = (paraptr->deltrat > 0.0L) ? ((Gnum) (paraptr->deltrat * meshptr->m.vnlosum) + 1) : 0; + +/* printf ("FM Mbal=%ld\n", (long) ncmploaddltmat); */ + + if ((meshptr->fronnbr == 0) && /* If imbalance in graph with no frontier */ + (abs (meshptr->ncmploaddlt) > ncmploaddltmat)) { + VmeshSeparateGgParam paramdat; + + paramdat.passnbr = 3; + vmeshSeparateGg (meshptr, ¶mdat); /* Compute a balanced initial partition */ + } + + vertnbr = meshptr->m.velmnbr + meshptr->m.vnodnbr; + hashnbr = 2 * ((meshptr->fronnbr + paraptr->movenbr) * (1 + (Gnum) ((float) meshptr->m.edgenbr / (float) vertnbr))); + if (hashnbr > vertnbr) /* Set bound on hash table */ + hashnbr = vertnbr; + for (hashmax = 256; hashmax < hashnbr; hashmax <<= 1) ; /* Get upper power of two */ +/* TODO */ hashmax *= 4; + hashsiz = 4 * hashmax; + hashmsk = hashsiz - 1; + + if (((tablptr = gainTablInit (meshptr->m.vnlosum, VMESHSEPAFMGAINBITS)) == NULL) || + (memAllocGroup ((void **) (void *) + &helmtab, (size_t) (hashsiz * sizeof (VmeshSeparateFmElement)), + &hnodtab, (size_t) (hashsiz * sizeof (VmeshSeparateFmNode)), + &movetab, (size_t) (hashmax * sizeof (VmeshSeparateFmSave)), NULL) == NULL)) { + if (tablptr != NULL) { + errorPrint ("vmeshSeparateFm: out of memory (1)"); + gainTablExit (tablptr); + } + return (1); + } + + passnbr = paraptr->passnbr; /* Set remaining number of passes */ + ncmpload2 = meshptr->ncmpload[2]; /* Set current partition loads */ + ncmploaddlt = meshptr->ncmploaddlt; + + memSet (helmtab, ~0, (byte *) &hnodtab[hashsiz] - (byte *) helmtab); /* Set all vertex numbers to ~0 */ + + helmnbr = + hnodnbr = 0; + savenbr = 0; /* No recorded moves yet */ + lockptr = NULL; /* Set locked list as empty */ + for (fronnum = 0; fronnum < meshptr->fronnbr; fronnum ++) { /* Set initial gains */ + Gnum vnloval; + Gnum vnodnum; + Gnum enodnum; + Gnum hnodnum; + Gnum ecmpsize1; + + vnodnum = meshptr->frontab[fronnum]; +#ifdef SCOTCH_DEBUG_VMESH2 + if (meshptr->parttax[vnodnum] != 2) { + errorPrint ("vmeshSeparateFm: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; + + for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { + if (hnodtab[hnodnum].vnodnum == ~0) /* If node slot found */ + break; /* No need to go on */ +#ifdef SCOTCH_DEBUG_VMESH2 + if (hnodtab[hnodnum].vnodnum == vnodnum) { /* If node already present in frontier array */ + errorPrint ("vmeshSeparateFm: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + } + + hnodnbr ++; /* One more node in hash table */ + hnodtab[hnodnum].vnodnum = vnodnum; /* Insert node in hash table */ + hnodtab[hnodnum].vnloval = vnloval; + + if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) == 0) { /* If single node */ + int vnodpart; + + vnodpart = (ncmploaddlt > 0) ? 1 : 0; + ncmpload2 -= vnloval; /* Node cannot belong to the separator */ + ncmploaddlt += (1 - 2 * vnodpart) * vnloval; + hnodtab[hnodnum].vertpart = vnodpart; + hnodtab[hnodnum].ecmpsize0 = 0; + continue; /* No need to process elements of node vertex */ + } + + for (enodnum = meshptr->m.verttax[vnodnum], ecmpsize1 = 0; /* For all (at least one) element neighbors of node */ + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { + Gnum velmnum; + Gnum helmnum; + + velmnum = meshptr->m.edgetax[enodnum]; + for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmnum = (helmnum + 1) & hashmsk) { + if (helmtab[helmnum].velmnum == ~0) { /* If element not yet inserted */ + if (helmnbr >= hashmax) { /* If element hash table is full */ + if (vmeshSeparateFmResize (tablptr, &helmtab, &hnodtab, &movetab, savenbr, &lockptr, NULL, hashmax) != 0) { + errorPrint ("vmeshSeparateFm: cannot resize arrays (1)"); + memFree (helmtab); /* Free group leader */ + gainTablExit (tablptr); + return (1); + } + hashmax <<= 1; + hashsiz <<= 1; + hashmsk = (hashmsk << 1) | 1; +#ifdef SCOTCH_DEBUG_VMESH3 + if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { + errorPrint ("vmeshSeparateFm: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH3 */ + + for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; /* Re-compute position in table */ + helmtab[helmnum].velmnum != ~0; helmnum = (helmnum + 1) & hashmsk) ; + } + helmtab[helmnum].gainlink.prev = (GainLink *) lockptr; /* Link it */ + lockptr = &helmtab[helmnum]; + helmtab[helmnum].velmnum = velmnum; /* Insert it */ + helmtab[helmnum].vertpart = meshptr->parttax[velmnum] & 1; /* Separator elements to part 0 */ + helmnbr ++; + break; + } + if (helmtab[helmnum].velmnum == velmnum) /* If element already or newly inserted */ + break; /* It will already be processed later */ + } + ecmpsize1 += helmtab[helmnum].vertpart; /* Account for its (possibly modified) part */ + } + hnodtab[hnodnum].vertpart = 2; /* Assume node is in separator */ + hnodtab[hnodnum].ecmpsize0 = meshptr->m.vendtax[vnodnum] - + meshptr->m.verttax[vnodnum] - ecmpsize1; + if (hnodtab[hnodnum].ecmpsize0 == 0) { /* If all neighboring elements are in part 1 */ + ncmpload2 -= vnloval; /* Node moves from separator to part 1 too */ + ncmploaddlt -= vnloval; + hnodtab[hnodnum].vertpart = 1; + } + else if (ecmpsize1 == 0) { /* If all neighboring elements are in part 0 */ + ncmpload2 -= vnloval; /* Node moves from separator to part 0 too */ + ncmploaddlt += vnloval; + hnodtab[hnodnum].vertpart = 0; + } + } + for (velmptr = lockptr; velmptr != NULL; /* Process all frontier elements */ + velmptr = (VmeshSeparateFmElement *) velmptr->gainlink.prev) { + Gnum velmnum; + Gnum eelmnum; + Gnum ncmpcut2; + Gnum ncmpgain2; + Gnum ncmpgaindlt; + + velmnum = velmptr->velmnum; + ncmpcut2 = + ncmpgain2 = + ncmpgaindlt = 0; + for (eelmnum = meshptr->m.verttax[velmnum]; /* For all neighbors of element */ + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnodnum; + Gnum hnodnum; + Gnum vnoddeg; + + vnodnum = meshptr->m.edgetax[eelmnum]; + vnoddeg = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]; + for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { + if (hnodtab[hnodnum].vnodnum == vnodnum) { /* If node exists (can be in same part or separator) */ + int vnodpart; + Gnum vnloval; + + vnodpart = hnodtab[hnodnum].vertpart; + vnloval = hnodtab[hnodnum].vnloval; + if (vnodpart == 2) { /* If vertex is in separator */ + ncmpcut2 ++; /* One more node in separator */ + if ((hnodtab[hnodnum].ecmpsize0 - 1) == ((vnoddeg - 2) * velmptr->vertpart)) { /* If element is only neighbor in its part */ + ncmpgain2 -= vnloval; + ncmpgaindlt += vnloval * (2 * velmptr->vertpart - 1); + } + } + else { /* Vertex not in separator */ +#ifdef SCOTCH_DEBUG_VMESH2 + if (vnodpart != velmptr->vertpart) { /* Node should be in same part as element */ + errorPrint ("vmeshSeparateFm: internal error (4)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (vnoddeg <= 1) /* If element is node's sole neighbor */ + ncmpgaindlt += (vnloval * (2 * vnodpart - 1)) * 2; + else { + ncmpgain2 += vnloval; + ncmpgaindlt += (vnloval * (2 * vnodpart - 1)); + } + } + break; + } + if (hnodtab[hnodnum].vnodnum == ~0) { /* If node does not exist */ + int vnodpart; + Gnum vnloval; + + vnodpart = velmptr->vertpart; /* Get its part */ + vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; +#ifdef SCOTCH_DEBUG_VMESH2 + if (vnodpart != meshptr->parttax[vnodnum]) { /* Node should be in same part as element */ + errorPrint ("vmeshSeparateFm: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (vnoddeg > 1) { /* If node will move to separator */ + ncmpgain2 += vnloval; /* Increase size of separator */ + ncmpgaindlt += (2 * vnodpart - 1) * vnloval; /* Account for imbalance */ + } + else /* Node will move with element */ + ncmpgaindlt += (2 * vnodpart - 1) * 2 * vnloval; /* Double imbalance */ + break; + } + } + } + velmptr->ncmpcut2 = ncmpcut2; + velmptr->ncmpgain2 = ncmpgain2; + velmptr->ncmpgaindlt = ncmpgaindlt; + } + ncmploaddltmax = MAX (ncmploaddltmat, abs (ncmploaddlt)); /* Set current maximum imbalance after cleaning */ + +#ifdef SCOTCH_DEBUG_VMESH3 + if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { + errorPrint ("vmeshSeparateFm: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH3 */ + + mswpnum = 0; /* First sweep */ + ncmpload2bst = ncmpload2; /* Record best state */ + ncmploaddltbst = ncmploaddlt; + do { /* As long as there are improvements */ + VmeshSeparateFmElement * velmptr; + Gnum velmgain2; + Gnum velmgaindlt; + + while (lockptr != NULL) { /* For all elements in locked list */ + VmeshSeparateFmElement * velmptr; + + velmptr = lockptr; /* Unlink element from list */ + lockptr = (VmeshSeparateFmElement *) velmptr->gainlink.prev; + + velmptr->gainlink.next = VMESHSEPAFMSTATEFREE;/* Set it free anyway */ + if (velmptr->ncmpcut2 > 0) /* If element has nodes in separator */ + gainTablAdd (tablptr, (GainLink *) velmptr, velmptr->ncmpgain2); /* Put it in table */ + } + +/* fprintf (stderr, "LOOP %ld\t(%ld,\t%ld)\n", (long) passnbr, (long) ncmpload2bst, (long) ncmploaddltbst); */ + + moveflag = 0; /* No moves to date */ + movenbr = 0; /* No uneffective moves yet */ + while ((movenbr < paraptr->movenbr) && /* As long as we can find effective elements */ + ((velmptr = vmeshSeparateFmTablGet (tablptr, ncmploaddlt, ncmploaddltmax)) != NULL)) { + VmeshSeparateFmElement * sepaptr; /* Linked list of separator frontier elements */ + Gnum velmnum; /* Number of current element */ + Gnum velmpart; /* Old part of current element */ + Gnum eelmnum; + + gainTablDel (tablptr, &velmptr->gainlink); /* Remove it from table */ + velmptr->gainlink.next = VMESHSEPAFMSTATEUSED; /* Mark it as used */ + velmptr->gainlink.prev = (GainLink *) lockptr; /* Lock it */ + lockptr = velmptr; + + if (velmptr->mswpnum != mswpnum) { /* If element data not yet recorded */ + movetab[savenbr].hertnum = velmptr - helmtab; /* Record them */ + movetab[savenbr].data.elem.vertpart = velmptr->vertpart; + movetab[savenbr].data.elem.ncmpcut2 = velmptr->ncmpcut2; + movetab[savenbr].data.elem.ncmpgain2 = velmptr->ncmpgain2; + movetab[savenbr].data.elem.ncmpgaindlt = velmptr->ncmpgaindlt; + velmptr->mswpnum = mswpnum; + savenbr ++; /* One more move recorded */ + } + movenbr ++; /* One more assumed uneffective move performed */ + + velmgain2 = velmptr->ncmpgain2; /* Save old gains for this vertex */ + velmgaindlt = velmptr->ncmpgaindlt; + ncmpload2 += velmgain2; /* Account for gains */ + ncmploaddlt += velmgaindlt; + + velmnum = velmptr->velmnum; /* Move element to other part */ + velmpart = velmptr->vertpart; + velmptr->vertpart = velmpart ^ 1; + + sepaptr = NULL; /* No frontier elements to relink yet */ + for (eelmnum = meshptr->m.verttax[velmnum]; /* (Re-)link neighbors */ + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnoddeg; + Gnum vnodnum; + Gnum hnodnum; + Gnum enodnum; + Gnum vnloval; /* Load of current node */ + int vnodpartold; /* Old part of current node */ + int vnodpartnew; /* New part of current node */ + Gnum ecmpsize0old; + Gnum ecmpsize0new; + + vnodnum = meshptr->m.edgetax[eelmnum]; + vnoddeg = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]; + for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { + if (hnodtab[hnodnum].vnodnum == vnodnum) /* If node found */ + break; + if (hnodtab[hnodnum].vnodnum == ~0) { /* If node not yet inserted */ +#ifdef SCOTCH_DEBUG_VMESH2 + if (meshptr->parttax[vnodnum] != velmpart) { + errorPrint ("vmeshSeparateFm: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (hnodnbr >= hashmax) { /* If node hash table is full */ + if (vmeshSeparateFmResize (tablptr, &helmtab, &hnodtab, &movetab, savenbr, &lockptr, &sepaptr, hashmax) != 0) { + errorPrint ("vmeshSeparateFm: cannot resize arrays (2)"); + memFree (helmtab); /* Free group leader */ + gainTablExit (tablptr); + return (1); + } + hashmax <<= 1; + hashsiz <<= 1; + hashmsk = (hashmsk << 1) | 1; +#ifdef SCOTCH_DEBUG_VMESH3 + if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { + errorPrint ("vmeshSeparateFm: internal error (8)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH3 */ + for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; /* Re-compute positions in tables */ + helmtab[helmnum].velmnum != velmnum; helmnum = (helmnum + 1) & hashmsk) ; + velmptr = helmtab + helmnum; + for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; + hnodtab[hnodnum].vnodnum != ~0; hnodnum = (hnodnum + 1) & hashmsk) ; + } + + hnodtab[hnodnum].vnodnum = vnodnum; /* Insert node in hash table */ + hnodtab[hnodnum].vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; + hnodtab[hnodnum].ecmpsize0 = vnoddeg * (1 - velmpart); + hnodtab[hnodnum].vertpart = velmpart; /* Node belongs to old part */ + hnodnbr ++; /* One more node created */ + break; + } + } + + if (hnodtab[hnodnum].mswpnum != mswpnum) { /* If node data not yet recorded */ + movetab[savenbr].hertnum = -1 - hnodnum; + movetab[savenbr].data.node.vertpart = hnodtab[hnodnum].vertpart; + movetab[savenbr].data.node.ecmpsize0 = hnodtab[hnodnum].ecmpsize0; + hnodtab[hnodnum].mswpnum = mswpnum; + savenbr ++; /* One more move recorded */ + } + + vnloval = hnodtab[hnodnum].vnloval; + if (vnoddeg <= 1) { /* If node only has one neighbor */ +#ifdef SCOTCH_DEBUG_VMESH2 + if (hnodtab[hnodnum].vertpart != velmpart) { + errorPrint ("vmeshSeparateFm: internal error (9)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + hnodtab[hnodnum].vertpart = 1 - velmpart; /* Directly move node to other part */ + hnodtab[hnodnum].ecmpsize0 = velmpart; + continue; /* Skip to next node */ + } + + ecmpsize0old = hnodtab[hnodnum].ecmpsize0; + ecmpsize0new = + hnodtab[hnodnum].ecmpsize0 += (2 * velmpart - 1); /* One less neighbor element for this node */ +#ifdef SCOTCH_DEBUG_VMESH2 + if ((hnodtab[hnodnum].ecmpsize0 < 0) || + (hnodtab[hnodnum].ecmpsize0 > vnoddeg)) { + errorPrint ("vmeshSeparateFm: internal error (10)"); + return (1); + } + if (hnodtab[hnodnum].vertpart == (1 - velmpart)) { + errorPrint ("vmeshSeparateFm: internal error (11)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + vnodpartold = hnodtab[hnodnum].vertpart; /* Get old node part value */ + vnodpartnew = 2; /* Assume new node part */ + if (vnodpartold != vnodpartnew) /* If belonged to old part */ + hnodtab[hnodnum].vertpart = vnodpartnew; /* Move to separator */ + else if ((ecmpsize0old - 1) == (vnoddeg - 2) * velmpart) { + vnodpartnew = /* Belonged to separator and last element in this part */ + hnodtab[hnodnum].vertpart = 1 - velmpart; + } + + for (enodnum = meshptr->m.verttax[vnodnum]; /* For all element neighbors of node */ + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { + Gnum velmend; + Gnum helmend; + int vendpart; + Gnum ncmpcut2; + Gnum ncmpgain2; + Gnum ncmpgaindlt; + + velmend = meshptr->m.edgetax[enodnum]; + for (helmend = (velmend * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmend = (helmend + 1) & hashmsk) { + if (helmtab[helmend].velmnum == velmend) /* If element found */ + break; + if (helmtab[helmend].velmnum == ~0) { /* If element not yet inserted */ + Gnum ncmpgain2; + Gnum ncmpgaindlt; + +#ifdef SCOTCH_DEBUG_VMESH2 + if (vnodpartold == 2) { /* Elements neighboring the frontier should exist */ + errorPrint ("vmeshSeparateFm: internal error (12)"); + return (1); + } + if (vnodpartold != meshptr->parttax[velmend]) { /* Unexisting elements should be in same part as their neighboring nodes */ + errorPrint ("vmeshSeparateFm: internal error (13)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (helmnbr >= hashmax) { /* If element hash table is full */ + if (vmeshSeparateFmResize (tablptr, &helmtab, &hnodtab, &movetab, savenbr, &lockptr, &sepaptr, hashmax) != 0) { + errorPrint ("vmeshSeparateFm: cannot resize arrays (3)"); + memFree (helmtab); /* Free group leader */ + gainTablExit (tablptr); + return (1); + } + hashmax <<= 1; + hashsiz <<= 1; + hashmsk = (hashmsk << 1) | 1; +#ifdef SCOTCH_DEBUG_VMESH3 + if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { + errorPrint ("vmeshSeparateFm: internal error (14)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH3 */ + for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; /* Re-compute positions in tables */ + helmtab[helmnum].velmnum != velmnum; helmnum = (helmnum + 1) & hashmsk) ; + velmptr = helmtab + helmnum; + for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; + hnodtab[hnodnum].vnodnum != vnodnum; hnodnum = (hnodnum + 1) & hashmsk) ; + for (helmend = (velmend * VMESHSEPAFMHASHPRIME) & hashmsk; + helmtab[helmend].velmnum != ~0; helmend = (helmend + 1) & hashmsk) ; + } + + helmtab[helmend].gainlink.next = VMESHSEPAFMSTATEFREE; + helmtab[helmend].velmnum = velmend; + helmtab[helmend].vertpart = vnodpartold; + helmtab[helmend].ncmpcut2 = 0; + + if (meshptr->m.vnlotax == NULL) { + Gnum eelmend; + + ncmpgain2 = meshptr->m.vendtax[velmend] - meshptr->m.verttax[velmend]; + ncmpgaindlt = (2 * vnodpartold - 1) * ncmpgain2; + + for (eelmend = meshptr->m.verttax[velmend]; /* For all neighboring nodes */ + eelmend < meshptr->m.vendtax[velmend]; eelmend ++) { + Gnum vnodend; + + vnodend = meshptr->m.edgetax[eelmend]; + if ((meshptr->m.vendtax[vnodend] - meshptr->m.verttax[vnodend]) <= 1) { /* If node linked to element only */ + ncmpgain2 --; /* Node will directly move to other part */ + ncmpgaindlt += (2 * velmpart - 1); + } + } + } + else { + Gnum eelmend; + Gnum veloend; + + for (eelmend = meshptr->m.verttax[velmend], ncmpgain2 = ncmpgaindlt = veloend = 0; /* For all neighboring nodes */ + eelmend < meshptr->m.vendtax[velmend]; eelmend ++) { + Gnum vnodend; + Gnum vnloend; + + vnodend = meshptr->m.edgetax[eelmend]; + vnloend = meshptr->m.vnlotax[vnodend]; + veloend += vnloend; + if ((meshptr->m.vendtax[vnodend] - meshptr->m.verttax[vnodend]) <= 1) { /* If node linked to element only */ + ncmpgain2 -= vnloend; + ncmpgaindlt += vnloend * (2 * velmpart - 1); + } + } + ncmpgain2 += veloend; + ncmpgaindlt += (2 * vnodpartold - 1) * veloend; + } + helmtab[helmend].ncmpgain2 = ncmpgain2; + helmtab[helmend].ncmpgaindlt = ncmpgaindlt; + + helmnbr ++; + break; + } + } + + if (helmtab[helmend].mswpnum != mswpnum) { /* If element data not yet recorded */ + movetab[savenbr].hertnum = helmend; + movetab[savenbr].data.elem.vertpart = helmtab[helmend].vertpart; + movetab[savenbr].data.elem.ncmpcut2 = helmtab[helmend].ncmpcut2; + movetab[savenbr].data.elem.ncmpgain2 = helmtab[helmend].ncmpgain2; + movetab[savenbr].data.elem.ncmpgaindlt = helmtab[helmend].ncmpgaindlt; + helmtab[helmend].mswpnum = mswpnum; + savenbr ++; /* One more move recorded */ + } + + if (helmtab[helmend].gainlink.next != VMESHSEPAFMSTATEUSED) { /* If element available */ + if (helmtab[helmend].gainlink.next >= VMESHSEPAFMSTATELINK) /* If element linked */ + gainTablDel (tablptr, &helmtab[helmend].gainlink); /* Unlink element */ + helmtab[helmend].gainlink.next = VMESHSEPAFMSTATEUSED; /* Chain neighbor elements */ + helmtab[helmend].gainlink.prev = (GainLink *) sepaptr; + sepaptr = &helmtab[helmend]; + } + + vendpart = helmtab[helmend].vertpart; + ncmpcut2 = helmtab[helmend].ncmpcut2; /* Get element values */ + ncmpgain2 = helmtab[helmend].ncmpgain2; + ncmpgaindlt = helmtab[helmend].ncmpgaindlt; + if (vnodpartold != 2) { /* If node was in same part as the element */ + ncmpgain2 -= vnloval; + ncmpgaindlt -= (2 * vendpart - 1) * vnloval; + } + else { /* If node was in separator */ + ncmpcut2 --; + if ((ecmpsize0old - 1) == ((vnoddeg - 2) * vendpart)) { /* If element was the only one in its part */ + ncmpgain2 += vnloval; + ncmpgaindlt -= (2 * vendpart - 1) * vnloval; + } + } + if (vnodpartnew != 2) { /* If node is now in same part as the element */ + ncmpgain2 += vnloval; + ncmpgaindlt += (2 * vendpart - 1) * vnloval; + } + else { /* If node is now in separator */ + ncmpcut2 ++; + if ((ecmpsize0new - 1) == ((vnoddeg - 2) * vendpart)) { /* If element is the only one in its part */ + ncmpgain2 -= vnloval; + ncmpgaindlt += (2 * vendpart - 1) * vnloval; + } + } + helmtab[helmend].ncmpcut2 = ncmpcut2; /* Adjust element values */ + helmtab[helmend].ncmpgain2 = ncmpgain2; + helmtab[helmend].ncmpgaindlt = ncmpgaindlt; + } + } + velmptr->ncmpgain2 = - velmgain2; /* Set new gains of element */ + velmptr->ncmpgaindlt = - velmgaindlt; + + while (sepaptr != NULL) { /* As long as there are element to re-link */ + VmeshSeparateFmElement * velmptr; + + velmptr = sepaptr; /* Get element to re-link */ + sepaptr = (VmeshSeparateFmElement *) velmptr->gainlink.prev; + velmptr->gainlink.next = VMESHSEPAFMSTATEFREE; + if (velmptr->ncmpcut2 != 0) /* If element belongs to frontier */ + gainTablAdd (tablptr, (GainLink *) velmptr, velmptr->ncmpgain2); /* Re-link it */ + } + +#ifdef SCOTCH_DEBUG_VMESH3 + if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { + errorPrint ("vmeshSeparateFm: internal error (15)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH3 */ + + if (ncmpload2 < ncmpload2bst) { /* If move improves separator size */ + ncmpload2bst = ncmpload2; /* This move was effective */ + ncmploaddltbst = ncmploaddlt; + movenbr = + savenbr = 0; + moveflag = 1; + mswpnum ++; + } else if (ncmpload2 == ncmpload2bst) { + if (abs (ncmploaddlt) < abs (ncmploaddltbst)) { + ncmploaddltbst = ncmploaddlt; /* This move was effective */ + movenbr = + savenbr = 0; + moveflag = 1; + mswpnum ++; + } + else if (abs (ncmploaddlt) == abs (ncmploaddltbst)) { + ncmploaddltbst = ncmploaddlt; /* Might be the opposite, so record */ + savenbr = 0; /* Forget backtracking */ + mswpnum ++; + } + } + if (ncmploaddltmax > ncmploaddltmat) { /* If must restrict distance bounds */ + Gnum ncmploaddlttmp; + + ncmploaddlttmp = ncmploaddltmax; /* Save old working ncmpdltmax value */ + ncmploaddltmax = MAX (ncmploaddltmat, /* Restrict at most to maximum */ + abs (ncmploaddlt)); + if (ncmploaddltmax < ncmploaddlttmp) { /* If we have done something useful */ + ncmpload2bst = ncmpload2; /* Then record best move done */ + ncmploaddltbst = ncmploaddlt; + movenbr = + savenbr = 0; + mswpnum ++; + } + } + } + + while (savenbr > 0) { /* Delete exceeding moves */ + Gnum hertnum; + + hertnum = movetab[-- savenbr].hertnum; /* Get vertex hash number */ + if (hertnum >= 0) { /* If vertex is element */ + helmtab[hertnum].vertpart = movetab[savenbr].data.elem.vertpart; + helmtab[hertnum].ncmpcut2 = movetab[savenbr].data.elem.ncmpcut2; + helmtab[hertnum].ncmpgain2 = movetab[savenbr].data.elem.ncmpgain2; + helmtab[hertnum].ncmpgaindlt = movetab[savenbr].data.elem.ncmpgaindlt; + if (helmtab[hertnum].gainlink.next != VMESHSEPAFMSTATEUSED) { /* If element not already removed */ + if (helmtab[hertnum].gainlink.next >= VMESHSEPAFMSTATELINK) /* If vertex is still linked */ + gainTablDel (tablptr, &helmtab[hertnum].gainlink); /* Remove it from table */ + helmtab[hertnum].gainlink.next = VMESHSEPAFMSTATEUSED; + helmtab[hertnum].gainlink.prev = (GainLink *) lockptr; /* Lock it */ + lockptr = &helmtab[hertnum]; + } + } + else { /* Vertex is node */ + hertnum = -1 - hertnum; /* Get hash index */ + hnodtab[hertnum].vertpart = movetab[savenbr].data.node.vertpart; + hnodtab[hertnum].ecmpsize0 = movetab[savenbr].data.node.ecmpsize0; + } + } + ncmpload2 = ncmpload2bst; /* Restore best separator parameters */ + ncmploaddlt = ncmploaddltbst; + mswpnum ++; /* Forget all recorded moves */ + +#ifdef SCOTCH_DEBUG_VMESH3 + if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { + errorPrint ("vmeshSeparateFm: internal error (16)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH3 */ + } while ((moveflag != 0) && /* As long as vertices are moved */ + (-- passnbr != 0)); /* And we are allowed to loop (TRICK for negative values) */ + + ecmpload1 = 0; /* Assume no change in elements */ + for (helmnum = 0; helmnum < hashsiz; helmnum ++) { + Gnum velmnum; + + velmnum = helmtab[helmnum].velmnum; + if ((velmnum != ~0) && (helmtab[helmnum].vertpart != meshptr->parttax[velmnum])) { +#ifdef SCOTCH_DEBUG_VMESH2 + if ((helmtab[helmnum].vertpart < 0) || /* Separator elements should have been removed */ + (helmtab[helmnum].vertpart > 1)) { + errorPrint ("vmeshSeparateFm: internal error (17)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + ecmpload1 += helmtab[helmnum].vertpart - (meshptr->parttax[velmnum] & 1); + meshptr->parttax[velmnum] = helmtab[helmnum].vertpart; + } + } + meshptr->ecmpsize[1] += ecmpload1; /* No longer elements in separator */ + meshptr->ecmpsize[0] = meshptr->m.velmnbr - meshptr->ecmpsize[1]; + +#ifdef SCOTCH_DEBUG_VMESH2 + if ((meshptr->ecmpsize[0] + meshptr->ecmpsize[1]) != meshptr->m.velmnbr) { /* Separator elements should have been removed */ + errorPrint ("vmeshSeparateFm: internal error (18)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + ncmpsize1 = + ncmpsize2 = 0; + ncmpload1 = + ncmpload2 = 0; + for (hnodnum = 0, fronnum = 0; hnodnum < hashsiz; hnodnum ++) { + Gnum vnodnum; + + vnodnum = hnodtab[hnodnum].vnodnum; + if (vnodnum != ~0) { +#ifdef SCOTCH_DEBUG_VMESH2 + if ((hnodtab[hnodnum].vertpart < 0) || + (hnodtab[hnodnum].vertpart > 2)) { + errorPrint ("vmeshSeparateFm: internal error (19)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + if (hnodtab[hnodnum].vertpart == 2) /* If node belongs to separator */ + meshptr->frontab[fronnum ++] = vnodnum; /* Add it to separator array */ + if (hnodtab[hnodnum].vertpart != meshptr->parttax[vnodnum]) { + Gnum diffpart1; + Gnum diffpart2; + + diffpart1 = (hnodtab[hnodnum].vertpart & 1) - (meshptr->parttax[vnodnum] & 1); + diffpart2 = (hnodtab[hnodnum].vertpart >> 1) - (meshptr->parttax[vnodnum] >> 1); + ncmpsize1 += diffpart1; + ncmpsize2 += diffpart2; + ncmpload1 += hnodtab[hnodnum].vnloval * diffpart1; + ncmpload2 += hnodtab[hnodnum].vnloval * diffpart2; + meshptr->parttax[vnodnum] = hnodtab[hnodnum].vertpart; + } + } + } +#ifdef SCOTCH_DEBUG_VMESH2 + if ((meshptr->fronnbr + ncmpsize2) != fronnum) { + errorPrint ("vmeshSeparateFm: internal error (20)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + meshptr->ncmpload[1] += ncmpload1; + meshptr->ncmpload[2] += ncmpload2; + meshptr->ncmpload[0] = meshptr->m.vnlosum - meshptr->ncmpload[1] - meshptr->ncmpload[2]; + meshptr->ncmploaddlt = meshptr->ncmpload[0] - meshptr->ncmpload[1]; + meshptr->fronnbr = fronnum; + meshptr->ncmpsize[1] += ncmpsize1; + meshptr->ncmpsize[0] = meshptr->m.vnodnbr - fronnum - meshptr->ncmpsize[1]; + + memFree (helmtab); /* Free group leader */ + gainTablExit (tablptr); + +#ifdef SCOTCH_DEBUG_VMESH2 + if (vmeshCheck (meshptr) != 0) { + errorPrint ("vmeshSeparateFm: internal error (21)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + +/* printf ("FM Sepa\tsize=%ld\tload=%ld\tbal=%ld\n", (long) meshptr->fronnbr, (long) meshptr->ncmpload[2], (long) meshptr->ncmploaddlt); */ + + return (0); +} + +/* This routine checks the consistency of +** the hash structures. +** It returns: +** - 0 : in case of success. +** - !0 : in case of error. +*/ + +#ifdef SCOTCH_DEBUG_VMESH3 +static +int +vmeshSeparateFmCheck ( +const Vmesh * const meshptr, +const VmeshSeparateFmElement * restrict helmtab, +const VmeshSeparateFmNode * restrict hnodtab, +const Gnum hashmsk, +const Gnum ncmpload2, +const Gnum ncmploaddlt) +{ + Gnum vertnbr; + Gnum helmnum; + Gnum hnodnum; + Gnum ncmploadtmp[3]; + GraphPart * restrict parttax; + + vertnbr = meshptr->m.velmnbr + meshptr->m.vnodnbr; + if ((parttax = (GraphPart *) memAlloc (vertnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("vmeshSeparateFmCheck: out of memory"); + return (1); + } + memCpy (parttax, meshptr->parttax + meshptr->m.baseval, vertnbr * sizeof (GraphPart)); + parttax -= meshptr->m.baseval; + + ncmploadtmp[0] = meshptr->ncmpload[0]; + ncmploadtmp[1] = meshptr->ncmpload[1]; + ncmploadtmp[2] = meshptr->ncmpload[2]; + for (hnodnum = 0; hnodnum <= hashmsk; hnodnum ++) { /* For all node slots */ + Gnum vnodnum; + Gnum enodnum; + Gnum ecmpsize0; + int vnodpart; + + vnodnum = hnodtab[hnodnum].vnodnum; + if (vnodnum == ~0) /* If unallocated slot */ + continue; /* Skip to next slot */ + + if (hnodtab[hnodnum].vnloval != ((meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum])) { + errorPrint ("vmeshSeparateFmCheck: invalid node load"); + return (1); + } + if ((hnodtab[hnodnum].ecmpsize0 < 0) || + (hnodtab[hnodnum].ecmpsize0 > (meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]))) { + errorPrint ("vmeshSeparateFmCheck: invalid node neighbors in part 0"); + return (1); + } + vnodpart = hnodtab[hnodnum].vertpart; + if (vnodpart != meshptr->parttax[vnodnum]) { + ncmploadtmp[meshptr->parttax[vnodnum]] -= hnodtab[hnodnum].vnloval; + ncmploadtmp[vnodpart] += hnodtab[hnodnum].vnloval; + parttax[vnodnum] = vnodpart; + } + + ecmpsize0 = 0; + for (enodnum = meshptr->m.verttax[vnodnum]; /* For all element neighbors */ + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { + Gnum velmnum; + Gnum helmnum; + int velmpart; + + velmnum = meshptr->m.edgetax[enodnum]; + for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmnum = (helmnum + 1) & hashmsk) { + if (helmtab[helmnum].velmnum == velmnum) { /* If element found */ + velmpart = helmtab[helmnum].vertpart; + parttax[velmnum] = velmpart; + break; + } + if (helmtab[helmnum].velmnum == ~0) { /* If element not present */ + velmpart = meshptr->parttax[velmnum]; + break; + } + } + if (velmpart == 0) + ecmpsize0 ++; + } + + if (ecmpsize0 != hnodtab[hnodnum].ecmpsize0) { + errorPrint ("vmeshSeparateFmCheck: invalid node neighbor count"); + return (1); + } + } + if (ncmpload2 != ncmploadtmp[2]) { + errorPrint ("vmeshSeparateFmCheck: invalid frontier load"); + return (1); + } + if (ncmploaddlt != (ncmploadtmp[0] - ncmploadtmp[1])) { + errorPrint ("vmeshSeparateFmCheck: invalid separator balance"); + return (1); + } + + for (helmnum = 0; helmnum <= hashmsk; helmnum ++) { /* For all element slots */ + Gnum velmnum; + Gnum eelmnum; + Gnum ncmpcut2; + Gnum ncmpgain2; + Gnum ncmpgaindlt; + Gnum ncmpsize[3]; + int velmpart; + + velmnum = helmtab[helmnum].velmnum; + if (velmnum == ~0) /* If unallocated slot */ + continue; /* Skip to next slot */ + + ncmpcut2 = + ncmpgain2 = + ncmpgaindlt = 0; + ncmpsize[0] = + ncmpsize[1] = + ncmpsize[2] = 0; + velmpart = helmtab[helmnum].vertpart; + for (eelmnum = meshptr->m.verttax[velmnum]; /* For all node neighbors */ + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnodnum; + Gnum hnodnum; + int vnodpart; + Gnum vnloval; + + vnodnum = meshptr->m.edgetax[eelmnum]; + vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; + for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { + if (hnodtab[hnodnum].vnodnum == vnodnum) { /* If element found */ + vnodpart = hnodtab[hnodnum].vertpart; + if (vnodpart != 2) { + if (vnodpart != velmpart) { + errorPrint ("vmeshSeparateFmCheck: invalid separator node (1)"); + return (1); + } + if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum] - 1) == 0) + ncmpgaindlt += (2 * vnodpart - 1) * 2 * vnloval; + else { + ncmpgain2 += vnloval; + ncmpgaindlt += (2 * vnodpart - 1) * vnloval; + } + } + else if (((hnodtab[hnodnum].ecmpsize0 == 1) && (velmpart == 0)) || + ((hnodtab[hnodnum].ecmpsize0 == (meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum] - 1)) && (velmpart == 1))) { + ncmpgain2 -= vnloval; + ncmpgaindlt += (2 * velmpart - 1) * vnloval; + } + break; + } + if (hnodtab[hnodnum].vnodnum == ~0) { /* If element not present */ + vnodpart = meshptr->parttax[vnodnum]; + if (vnodpart != velmpart) { + errorPrint ("vmeshSeparateFmCheck: invalid separator node (2)"); + return (1); + } + if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) == 1) { + if (vnodpart == 2) { + errorPrint ("vmeshSeparateFmCheck: invalid separator node (3)"); + return (1); + } + ncmpgaindlt += (2 * vnodpart - 1) * 2 * vnloval; + } + else { + ncmpgain2 += vnloval; + ncmpgaindlt += (2 * vnodpart - 1) * vnloval; + } + break; + } + } + ncmpsize[vnodpart] ++; + } + if ((ncmpsize[0] != 0) && (ncmpsize[1] != 0)) { + errorPrint ("vmeshSeparateFmCheck: invalid element nodes"); + return (1); + } + if (ncmpsize[2] != helmtab[helmnum].ncmpcut2) { + errorPrint ("vmeshSeparateFmCheck: invalid element separator count"); + return (1); + } + if ((ncmpgain2 != helmtab[helmnum].ncmpgain2) || + (ncmpgaindlt != helmtab[helmnum].ncmpgaindlt)) { + errorPrint ("vmeshSeparateFmCheck: invalid element gains"); + return (1); + } + } + + memFree (parttax + meshptr->m.baseval); + + return (0); +} +#endif /* SCOTCH_DEBUG_VMESH3 */ diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_fm.h b/scotch_6.0.3/src/libscotch/vmesh_separate_fm.h new file mode 100644 index 00000000..e2598330 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_fm.h @@ -0,0 +1,138 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_fm.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the improved Fiduccia-Mattheyses **/ +/** mesh element separation routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 26 feb 2003 **/ +/** to 06 may 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Gain table subbits. +*/ + +#define VMESHSEPAFMGAINBITS 4 + +/*+ Prime number for hashing vertex numbers. +*/ + +#define VMESHSEPAFMHASHPRIME 11 /*+ Prime number for hashing +*/ + +/*+ Gain table vertex status. +*/ + +#define VMESHSEPAFMSTATEFREE ((GainLink *) 0) /*+ Element is free or separator-chained +*/ +#define VMESHSEPAFMSTATEUSED ((GainLink *) 1) /*+ Element already swapped +*/ +#define VMESHSEPAFMSTATELINK ((GainLink *) 2) /*+ Currently in gain table if higher +*/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VmeshSeparateFmParam_ { + INT movenbr; /*+ Maximum number of uneffective moves that can be done +*/ + INT passnbr; /*+ Number of passes to be performed (-1 : infinite) +*/ + double deltrat; /*+ Maximum weight imbalance ratio +*/ +} VmeshSeparateFmParam; + +/*+ The hash element structure. The goal + of both hash arrays is to record partition + data that supercedes the one contained in + the calling Vmesh structure, until the newly + computed partition is written back to the + Vmesh. +*/ + +typedef struct VmeshSeparateFmElement_ { + GainLink gainlink; /*+ Gain link if moved to other part; FIRST +*/ + Gnum velmnum; /*+ Number of vertex in hash table +*/ + int vertpart; /*+ Vertex part +*/ + Gnum ncmpcut2; /*+ Number of neighbor nodes in separator +*/ + Gnum ncmpgain2; /*+ Separator gain if moved to given part +*/ + Gnum ncmpgaindlt; /*+ Node load imbalance if element swapped +*/ + Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ +} VmeshSeparateFmElement; + +/*+ The hash node structure. +*/ + +typedef struct VmeshSeparateFmNode_ { + Gnum vnodnum; /*+ Number of vertex in hash table +*/ + Gnum vnloval; /*+ Vertex load +*/ + int vertpart; /*+ Vertex part +*/ + Gnum ecmpsize0; /*+ Number of element neighbors in part 0 +*/ + Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ +} VmeshSeparateFmNode; + +/*+ The move recording structure. +*/ + +typedef struct VmeshSeparateFmSave_ { + Gnum hertnum; /*+ Hash index of vertex, (helmnum) or (-1 - hnodnum) +*/ + union { /*+ Stored data to recover +*/ + struct { /*+ Recovery data for element +*/ + int vertpart; /*+ Vertex part +*/ + Gnum ncmpcut2; /*+ Number of neighbor nodes in separator +*/ + Gnum ncmpgain2; /*+ Separator gain if moved to given part +*/ + Gnum ncmpgaindlt; /*+ Node load imbalance if element swapped +*/ + } elem; + struct { /*+ Recovery data for node +*/ + int vertpart; /*+ Vertex part +*/ + Gnum ecmpsize0; /*+ Number of element neighbors in part 0 +*/ + } node; + } data; +} VmeshSeparateFmSave; + +/* +** The function prototypes. +*/ + +#ifndef VMESH_SEPARATE_FM +#define static +#endif + +int vmeshSeparateFm (Vmesh * restrict const, const VmeshSeparateFmParam * restrict const); + +static VmeshSeparateFmElement * vmeshSeparateFmTablGet (GainTabl * const, const Gnum, const Gnum); +static int vmeshSeparateFmResize (GainTabl * restrict const, VmeshSeparateFmElement * restrict * const, VmeshSeparateFmNode * restrict * const, VmeshSeparateFmSave * restrict * const, const Gnum, VmeshSeparateFmElement **, VmeshSeparateFmElement **, const Gnum); +#ifdef SCOTCH_DEBUG_VMESH3 +static int vmeshSeparateFmCheck (const Vmesh * const, const VmeshSeparateFmElement * restrict, const VmeshSeparateFmNode * restrict, const Gnum, const Gnum, const Gnum); +#endif /* SCOTCH_DEBUG_VMESH3 */ + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_gg.c b/scotch_6.0.3/src/libscotch/vmesh_separate_gg.c new file mode 100644 index 00000000..6f7ae38c --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_gg.c @@ -0,0 +1,495 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_gg.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module separates a node separation **/ +/** mesh using an element-oriented version **/ +/** of the Greedy Graph Growing algorithm. **/ +/** **/ +/** DATES : # Version 4.0 : from : 16 sep 2002 **/ +/** to 18 aug 2004 **/ +/** # Version 5.0 : from : 12 sep 2007 **/ +/** to 24 mar 2008 **/ +/** # Version 5.1 : from : 09 nov 2008 **/ +/** to 09 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH_SEPARATE_GG + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "graph.h" +#include "mesh.h" +#include "vmesh.h" +#include "vmesh_separate_gg.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vmeshSeparateGg ( +Vmesh * restrict const meshptr, /*+ Node separation mesh +*/ +const VmeshSeparateGgParam * restrict const paraptr) /*+ Method parameters +*/ +{ + GainTabl * restrict tablptr; /* Pointer to gain table */ + byte * restrict vexxtab; /* Start of auxiliary arrays */ + Gnum vexxsiz; /* Size of auxiliary arrays to be reset every pass */ + VmeshSeparateGgElem * restrict velxtax; /* Based auxiliary element array */ + VmeshSeparateGgNode * restrict vnoxtax; /* Based auxiliary node array */ + Gnum * restrict velitax; /* Array of sums of weights of isolated neighboring nodes of elements */ + Gnum * restrict velstax; /* Array of sums of weights of neighboring nodes of elements */ + Gnum velssiz; /* Size of element neighboring node load sum array */ + VmeshSeparateGgElem * sepaptr; /* Head of chained list of elements to re-link */ + Gnum * restrict permtab; /* Element permutation table for finding new roots */ + Gnum * permptr; /* Pointer to current permutation index */ + INT passnum; /* Number of current pass */ + Gnum ecmpsize0; /* Number of elements in part 0 */ + Gnum ncmploaddlt; /* Current imbalance of bipartition */ + Gnum ncmpload2; /* Current number of nodes in separator */ + Gnum vnodnum; + Gnum fronnum; + Gnum ncmpsize1; + Gnum ncmpsize2; + + if (meshptr->m.velmnbr == 0) { /* If only a single node or disconnected nodes */ + vmeshZero (meshptr); /* Don't bother with parts */ + return (0); + } + + velssiz = (meshptr->m.vnlotax == NULL) ? 0 : meshptr->m.velmnbr; /* Compute size of vetex load sum array */ + if (((tablptr = gainTablInit (GAINMAX, VMESHSEPAGGSUBBITS)) == NULL) || /* Use logarithmic array only */ + ((vexxtab = (byte *) memAllocGroup ((void **) (void *) + &velxtax, (size_t) (meshptr->m.velmnbr * sizeof (VmeshSeparateGgElem)), + &vnoxtax, (size_t) (meshptr->m.vnodnbr * sizeof (VmeshSeparateGgNode)), + &velitax, (size_t) (meshptr->m.velmnbr * sizeof (Gnum)), + &velstax, (size_t) (velssiz * sizeof (Gnum)), NULL)) == NULL)) { /* Indicates end of group allocated array */ + if (tablptr != NULL) + gainTablExit (tablptr); + errorPrint ("vmeshSeparateGg: out of memory (1)"); + return (1); + } + vexxsiz = (byte *) velitax - vexxtab; /* Size of arrays that must be reset at each pass */ + velxtax -= meshptr->m.velmbas; /* Base access to auxiliary arrays */ + vnoxtax -= meshptr->m.vnodbas; + velitax -= meshptr->m.velmbas; + + if (velssiz == 0) { /* If no vertex load array */ + Gnum velmnum; + + for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++) { + Gnum eelmnum; + Gnum velisum; + + for (eelmnum = meshptr->m.verttax[velmnum], velisum = 0; + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnodnum; + + vnodnum = meshptr->m.edgetax[eelmnum]; + if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) == 1) + velisum --; + } + velitax[velmnum] = velisum; + } + } + else { + Gnum velmnum; + + velstax -= meshptr->m.velmbas; + + for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++) { + Gnum eelmnum; + Gnum velisum; + Gnum velssum; + + for (eelmnum = meshptr->m.verttax[velmnum], velisum = velssum = 0; + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnodnum; + Gnum vnloval; + + vnodnum = meshptr->m.edgetax[eelmnum]; + vnloval = meshptr->m.vnlotax[vnodnum]; + velssum += vnloval; + if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) == 1) + velisum -= vnloval; + } + velitax[velmnum] = velisum; + velstax[velmnum] = velssum; + } + } + + permtab = NULL; /* Do not allocate permutation array yet */ + for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { /* For all passes */ + VmeshSeparateGgElem * velxptr; /* Pointer to selected element */ + + memSet (vexxtab, 0, vexxsiz); /* All vertices to part 0 */ + gainTablFree (tablptr); /* Reset gain table */ + permptr = NULL; /* No permutation built yet */ + ecmpsize0 = meshptr->m.velmnbr; /* All elements to part 0 */ + ncmpload2 = 0; /* Reset separation parameters */ + ncmploaddlt = meshptr->m.vnlosum; + + velxptr = (VmeshSeparateGgElem *) vexxtab + intRandVal (meshptr->m.velmnbr); /* Randomly select first root element vertex */ + + do { /* Loop on root element vertices */ + Gnum velmnum; /* Number of current element to process */ + + velxptr->gainlink.next = /* TRICK: allow deletion of root vertex */ + velxptr->gainlink.prev = (GainLink *) velxptr; + + velmnum = velxptr - velxtax; /* Get root element number */ + { + Gnum ncmpgain1; /* Gain (2->1) */ + Gnum ncmpgain2; /* Gain (0->2) */ + + ncmpgain2 = (meshptr->m.vnlotax == NULL) /* Set gains */ + ? meshptr->m.vendtax[velmnum] - meshptr->m.verttax[velmnum] + : velstax[velmnum]; + ncmpgain1 = velitax[velmnum]; + + velxptr->ncmpgain2 = ncmpgain1 + ncmpgain2; + velxptr->ncmpgaindlt = ncmpgain1 - ncmpgain2; + } + + do { /* While element vertices can be retrieved */ + Gnum eelmnum; /* Number of current element edge */ + + velmnum = velxptr - velxtax; /* Get based number of selected element */ + + if (ncmploaddlt < abs (ncmploaddlt + velxtax[velmnum].ncmpgaindlt)) { /* If swapping would cause imbalance */ + permptr = permtab + meshptr->m.velmnbr; /* Terminate swapping process */ + velxptr = NULL; + break; + } + ecmpsize0 --; /* One less element in part 0 */ + gainTablDel (tablptr, (GainLink *) velxptr); /* Remove element from table */ + velxptr->gainlink.next = VMESHSEPAGGSTATEPART1; /* Move element to part 1 */ + ncmpload2 += velxptr->ncmpgain2; /* Update partition parameters */ + ncmploaddlt += velxptr->ncmpgaindlt; + + sepaptr = NULL; /* No frontier elements to relink yet */ + for (eelmnum = meshptr->m.verttax[velmnum]; /* For all neighbor node vertices */ + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnodnum; /* Number of current node neighbor */ + + vnodnum = meshptr->m.edgetax[eelmnum]; /* Get number of neighbor node */ + +#ifdef SCOTCH_DEBUG_VMESH2 + if (vnoxtax[vnodnum].partval == 1) { + errorPrint ("vmeshSeparateGg: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (vnoxtax[vnodnum].partval == 0) { /* If yet untouched neighbor node */ + Gnum enodnum; /* Current egde of current neighbor node */ + Gnum vnloval; + + vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; + vnoxtax[vnodnum].partval = 2; /* Node now belongs to separator */ + vnoxtax[vnodnum].commsize0 = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum] - 1; + vnoxtax[vnodnum].velmisum0 = - velmnum; + + for (enodnum = meshptr->m.verttax[vnodnum]; /* For all its elements */ + enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { + Gnum velmend; + + velmend = meshptr->m.edgetax[enodnum]; /* Get neighbor element */ + + vnoxtax[vnodnum].velmisum0 += velmend; /* Sum-up element indices for neighbor node */ +#ifdef SCOTCH_DEBUG_VMESH2 + if ((velxtax[velmend].gainlink.next == VMESHSEPAGGSTATEPART1) && + (velmend != velmnum)) { + errorPrint ("vmeshSeparateGg: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (velxtax[velmend].gainlink.next == VMESHSEPAGGSTATEPART0) { /* If untouched element */ + Gnum ncmpgain1; /* Gain (2->1) */ + Gnum ncmpgain2; /* Gain (0->2) */ +#ifdef SCOTCH_DEBUG_VMESH2 + Gnum eelmend; +#endif /* SCOTCH_DEBUG_VMESH2 */ + + velxtax[velmend].gainlink.next = VMESHSEPAGGSTATEPART2; /* Move element to frontier */ + velxtax[velmend].gainlink.prev = (GainLink *) sepaptr; /* Chain vertex */ + sepaptr = &velxtax[velmend]; + + ncmpgain2 = (meshptr->m.vnlotax == NULL) /* Set gains */ + ? meshptr->m.vendtax[velmend] - meshptr->m.verttax[velmend] - 1 + : velstax[velmend] - vnloval; + ncmpgain1 = velitax[velmend]; + +#ifdef SCOTCH_DEBUG_VMESH2 + for (eelmend = meshptr->m.verttax[velmend]; /* For all its neighboring nodes */ + eelmend < meshptr->m.vendtax[velmend]; eelmend ++) { + Gnum vnodend; + + vnodend = meshptr->m.edgetax[eelmend]; + + if ((vnoxtax[vnodend].partval == 1) || + ((vnoxtax[vnodend].partval == 2) && (vnodend != vnodnum))) { + errorPrint ("vmeshSeparateGg: internal error (3)"); + return (1); + } + if (meshptr->m.vendtax[vnodend] - meshptr->m.verttax[vnodend] == 1) { + if (vnoxtax[vnodend].partval != 0) { + errorPrint ("vmeshSeparateGg: internal error (4)"); + return (1); + } + } + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + velxtax[velmend].ncmpgain2 = ncmpgain1 + ncmpgain2; + velxtax[velmend].ncmpgaindlt = ncmpgain1 - ncmpgain2; + } + else { /* Neighbor element belongs to frontier */ + velxtax[velmend].ncmpgain2 -= vnloval; /* One less node to add to separator for element */ + velxtax[velmend].ncmpgaindlt += vnloval; /* One less node to remove from part 0 */ + + if (velxtax[velmend].gainlink.next >= VMESHSEPAGGSTATELINK) { + gainTablDel (tablptr, (GainLink *) &velxtax[velmend]); /* Unlink vertex */ + velxtax[velmend].gainlink.next = VMESHSEPAGGSTATEPART2; /* Chain vertex */ + velxtax[velmend].gainlink.prev = (GainLink *) sepaptr; + sepaptr = &velxtax[velmend]; + } + } + } + } + else { /* Neighbor node already in separator */ + vnoxtax[vnodnum].commsize0 --; /* One less neighbor element in part 0 */ + vnoxtax[vnodnum].velmisum0 -= velmnum; /* Subtract index of removed element */ + } + + if (vnoxtax[vnodnum].commsize0 == 0) /* If node no longer has neighbors in part 0 */ + vnoxtax[vnodnum].partval = 1; /* Node moves from separator to part 1 */ + else if (vnoxtax[vnodnum].commsize0 == 1) { /* If only one neighbor element in part 0 */ + Gnum velmend; /* Index of remaining element in part 0 */ + Gnum vnloval; + + velmend = vnoxtax[vnodnum].velmisum0; /* Get neighbor element from remaining index */ + +#ifdef SCOTCH_DEBUG_VMESH2 + if (velxtax[velmend].gainlink.next < VMESHSEPAGGSTATEPART2) { /* Element should have been declared in part 0 at this stage */ + errorPrint ("vmeshSeparateGg: internal error (5)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; + velxtax[velmend].ncmpgain2 -= vnloval; + velxtax[velmend].ncmpgaindlt -= vnloval; + + if (velxtax[velmend].gainlink.next >= VMESHSEPAGGSTATELINK) { + gainTablDel (tablptr, (GainLink *) &velxtax[velmend]); /* Unlink vertex */ + velxtax[velmend].gainlink.next = VMESHSEPAGGSTATEPART2; /* Chain vertex */ + velxtax[velmend].gainlink.prev = (GainLink *) sepaptr; + sepaptr = &velxtax[velmend]; + } + } + } + + while (sepaptr != NULL) { /* For all vertices in chain list */ + velxptr = sepaptr; /* Unlink vertex from list */ + sepaptr = (VmeshSeparateGgElem *) velxptr->gainlink.prev; + gainTablAdd (tablptr, (GainLink *) velxptr, velxptr->ncmpgain2); /* Relink it */ + } + +#ifdef SCOTCH_DEBUG_VMESH3 + if (vmeshSeparateGgCheck (meshptr, ncmpload2, ncmploaddlt, velxtax, vnoxtax) != 0) { + errorPrint ("vmeshSeparateGg: internal error (6)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH3 */ + } while ((velxptr = (VmeshSeparateGgElem *) gainTablFrst (tablptr)) != NULL); + + if (permptr == NULL) { /* If element permutation not yet built */ + if (permtab == NULL) { /* If permutation array not yet allocated */ + if ((permtab = (Gnum *) memAlloc (meshptr->m.velmnbr * sizeof (Gnum))) == NULL) { + errorPrint ("vmeshSeparateGg: out of memory (2)"); + memFree (vexxtab); + gainTablExit (tablptr); + return (1); + } + intAscn (permtab, meshptr->m.velmnbr, meshptr->m.baseval); /* Initialize permutation array */ + } + intPerm (permtab, meshptr->m.velmnbr); /* Build random permutation */ + permptr = permtab; /* Start at beginning of permutation */ + } + for ( ; permptr < permtab + meshptr->m.velmnbr; permptr ++) { /* Find next root vertex */ +#ifdef SCOTCH_DEBUG_VMESH2 + if (velxtax[*permptr].gainlink.next >= VMESHSEPAGGSTATEPART2) { + errorPrint ("vmeshSeparateGg: internal error (7)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (velxtax[*permptr].gainlink.next == VMESHSEPAGGSTATEPART0) { + velxptr = velxtax + (*permptr ++); + break; + } + } + } while (velxptr != NULL); + + if ((passnum == 0) || /* If it is the first try */ + ( (meshptr->ncmpload[2] > ncmpload2) || /* Or if better solution reached */ + ((meshptr->ncmpload[2] == ncmpload2) && + (abs (meshptr->ncmploaddlt) > abs (ncmploaddlt))))) { + Gnum vertnum; + + meshptr->ecmpsize[0] = ecmpsize0; /* Set graph parameters */ + meshptr->ncmpload[2] = ncmpload2; + meshptr->ncmploaddlt = ncmploaddlt; + + for (vertnum = meshptr->m.velmbas; vertnum < meshptr->m.velmnnd; vertnum ++) /* Copy element bipartition state */ + meshptr->parttax[vertnum] = (velxtax[vertnum].gainlink.next == VMESHSEPAGGSTATEPART1) ? 1 : 0; + for (vertnum = meshptr->m.vnodbas; vertnum < meshptr->m.vnodnnd; vertnum ++) /* Copy node bipartition state */ + meshptr->parttax[vertnum] = vnoxtax[vertnum].partval; + } + } + + meshptr->ecmpsize[1] = meshptr->m.velmnbr - meshptr->ecmpsize[0]; + meshptr->ncmpload[1] = ((meshptr->m.vnlosum - meshptr->ncmpload[2]) - meshptr->ncmploaddlt) >> 1; + meshptr->ncmpload[0] = (meshptr->m.vnlosum - meshptr->ncmpload[2]) - meshptr->ncmpload[1]; + + for (vnodnum = meshptr->m.vnodbas, fronnum = 0, ncmpsize1 = ncmpsize2 = 0; + vnodnum < meshptr->m.vnodnnd; vnodnum ++) { + Gnum partval; + + partval = meshptr->parttax[vnodnum]; + ncmpsize1 += (partval & 1); /* Superscalar update */ + ncmpsize2 += (partval >> 1); + if (partval == 2) + meshptr->frontab[fronnum ++] = vnodnum; /* Vertex belongs to frontier */ + } + meshptr->ncmpsize[0] = meshptr->m.vnodnbr - (ncmpsize1 + ncmpsize2); + meshptr->ncmpsize[1] = ncmpsize1; + meshptr->fronnbr = ncmpsize2; + +#ifdef SCOTCH_DEBUG_VMESH2 + if (vmeshCheck (meshptr) != 0) { + errorPrint ("vmeshSeparateGg: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + if (permtab != NULL) + memFree (permtab); + memFree (vexxtab); /* Free group leader */ + gainTablExit (tablptr); + +/* printf ("GG Sepa\tsize=%ld\tload=%ld\tbal=%ld\n", (long) meshptr->fronnbr, (long) meshptr->ncmpload[2], (long) meshptr->ncmploaddlt); */ + + return (0); +} + +/* This routine checks the consistency +** of the current bipartition. +** It returns: +** - 0 : if the bipartition is consistent. +** - !0 : on error. +*/ + +#ifdef SCOTCH_DEBUG_VMESH3 +static +int +vmeshSeparateGgCheck ( +Vmesh * restrict const meshptr, +const Gnum ncmpload2, +const Gnum ncmploaddlt, +const VmeshSeparateGgElem * restrict const velxtax, +const VmeshSeparateGgNode * restrict const vnoxtax) +{ + Gnum vnodnum; + Gnum vnloval; + Gnum ncmpsize0c; + Gnum ncmpsize1c; + Gnum ncmpsize2c; + Gnum ncmpload0c; + Gnum ncmpload1c; + Gnum ncmpload2c; + + ncmpsize1c = + ncmpsize2c = + ncmpload1c = + ncmpload2c = 0; + vnloval = 1; + for (vnodnum = meshptr->m.vnodbas; vnodnum < meshptr->m.vnodnnd; vnodnum ++) { + int partval; + Gnum partval1; + Gnum partval2; + + partval = vnoxtax[vnodnum].partval; + partval1 = partval & 1; + partval2 = partval >> 1; + if (meshptr->m.vnlotax != NULL) + vnloval = meshptr->m.vnlotax[vnodnum]; + if (partval > 2) { + errorPrint ("vmeshSeparateGgCheck: invalid node part value"); + return (1); + } + ncmpsize1c += partval1; + ncmpsize2c += partval2; + ncmpload1c += partval1 * vnloval; + ncmpload2c += partval2 * vnloval; + } + ncmpsize0c = meshptr->m.vnodnbr - ncmpsize1c - ncmpsize2c; + ncmpload0c = meshptr->m.vnlosum - ncmpload1c - ncmpload2c; + + if (ncmpload2c != ncmpload2) { + errorPrint ("vmeshSeparateGgCheck: invalid separator size"); + return (1); + } + if (ncmploaddlt != (ncmpload0c - ncmpload1c)) { + errorPrint ("vmeshSeparateGgCheck: invalid separator balance"); + return (1); + } + + return (0); +} +#endif /* SCOTCH_DEBUG_VMESH3 */ diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_gg.h b/scotch_6.0.3/src/libscotch/vmesh_separate_gg.h new file mode 100644 index 00000000..9fb3cbf3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_gg.h @@ -0,0 +1,104 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_gg.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the the greedy mesh growing node **/ +/** separation method. **/ +/** **/ +/** DATES : # Version 4.0 : from : 16 sep 2002 **/ +/** to 07 apr 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ System-defined constants. +*/ + +#define VMESHSEPAGGSUBBITS 4 + +#define VMESHSEPAGGSTATEPART0 ((GainLink *) 0) /*+ Element vertex in part 0 (initial state) +*/ +#define VMESHSEPAGGSTATEPART1 ((GainLink *) 1) /*+ Element vertex in part 1 +*/ +#define VMESHSEPAGGSTATEPART2 ((GainLink *) 2) /*+ Element vertex in part 2, chained +*/ +#define VMESHSEPAGGSTATELINK ((GainLink *) 3) /*+ Currently in gain table if higher +*/ + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct VmeshSeparateGgParam_ { + INT passnbr; /*+ Number of passes to perform +*/ +} VmeshSeparateGgParam; + +/*+ The complementary element vertex structure. + For trick reasons, the gain table data structure + must be the first field of the structure. +*/ + +typedef struct VmeshSeparateGgElem_ { + GainLink gainlink; /*+ Gain link: FIRST +*/ + Gnum ncmpgain2; /*+ Computation gain in separator: (0->2) - (2->1) +*/ + Gnum ncmpgaindlt; /*+ Overall computation delta: - (0->2) - (2->1) +*/ +} VmeshSeparateGgElem; + +/*+ The complementary vertex structure. Only + partval is always valid. Other fields are + valid only when vertex belongs to separator. +*/ + +typedef struct VmeshSeparateGgNode_ { + int partval; /*+ Part to which node vertex belongs +*/ + Gnum commsize0; /*+ Number of neighbors in part 0 +*/ + Gnum velmisum0; /*+ Sum of all element indices in part 0; the last one is the right one +*/ +} VmeshSeparateGgNode; + +/* +** The function prototypes. +*/ + +#ifndef VMESH_SEPARATE_GG +#define static +#endif + +int vmeshSeparateGg (Vmesh * restrict const, const VmeshSeparateGgParam * restrict const); + +#ifdef SCOTCH_DEBUG_VMESH3 +static int vmeshSeparateGgCheck (Vmesh * restrict const, const Gnum, const Gnum, const VmeshSeparateGgElem * restrict const, const VmeshSeparateGgNode * restrict const vnoxtax); +#endif /* SCOTCH_DEBUG_VMESH3 */ + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_gr.c b/scotch_6.0.3/src/libscotch/vmesh_separate_gr.c new file mode 100644 index 00000000..4b7ef6c4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_gr.c @@ -0,0 +1,156 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_gr.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module separates a node separation **/ +/** mesh by turning the mesh into a graph **/ +/** and using a graph separation strategy. **/ +/** **/ +/** DATES : # Version 4.0 : from : 13 oct 2003 **/ +/** to 13 oct 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH_SEPARATE_GR + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_st.h" +#include "mesh.h" +#include "vmesh.h" +#include "vmesh_separate_gr.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vmeshSeparateGr ( +Vmesh * restrict const meshptr, /*+ Node separation mesh +*/ +const VmeshSeparateGrParam * restrict const paraptr) /*+ Method parameters +*/ +{ + Vgraph grafdat; + Gnum fronnum; + Gnum velmnum; + Gnum ecmpsize1; + + graphInit (&grafdat.s); + if (meshGraph (&meshptr->m, &grafdat.s) != 0) { + errorPrint ("vmeshSeparateGr: cannot build graph"); + return (1); + } + grafdat.parttax = meshptr->parttax + (meshptr->m.vnodbas - grafdat.s.baseval); /* Get node area of part array */ + grafdat.compload[0] = meshptr->ncmpload[0]; + grafdat.compload[1] = meshptr->ncmpload[1]; + grafdat.compload[2] = meshptr->ncmpload[2]; + grafdat.comploaddlt = meshptr->ncmploaddlt; + grafdat.compsize[0] = meshptr->ncmpsize[0]; + grafdat.compsize[1] = meshptr->ncmpsize[1]; + grafdat.fronnbr = meshptr->fronnbr; + grafdat.frontab = meshptr->frontab; /* Re-use frontier array */ + grafdat.levlnum = meshptr->levlnum; + + for (fronnum = 0; fronnum < grafdat.fronnbr; fronnum ++) + grafdat.frontab[fronnum] -= (meshptr->m.vnodbas - grafdat.s.baseval); + +#ifdef SCOTCH_DEBUG_VMESH2 + if (vgraphCheck (&grafdat) != 0) { + errorPrint ("vmeshSeparateGr: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + if (vgraphSeparateSt (&grafdat, paraptr->stratptr) != 0) { + errorPrint ("vmeshSeparateGr: cannot separate graph"); + return (1); + } + + for (fronnum = 0; fronnum < grafdat.fronnbr; fronnum ++) /* Restore mesh-based frontier array */ + grafdat.frontab[fronnum] += (meshptr->m.vnodbas - grafdat.s.baseval); + meshptr->ncmpload[0] = grafdat.compload[0]; + meshptr->ncmpload[1] = grafdat.compload[1]; + meshptr->ncmpload[2] = grafdat.compload[2]; + meshptr->ncmploaddlt = grafdat.comploaddlt; + meshptr->ncmpsize[0] = grafdat.compsize[0]; + meshptr->ncmpsize[1] = grafdat.compsize[1]; + meshptr->fronnbr = grafdat.fronnbr; + + for (velmnum = meshptr->m.velmbas, ecmpsize1 = 0; + velmnum < meshptr->m.velmnnd; velmnum ++) { /* Compute part of all elements */ + Gnum eelmnum; + GraphPart partval; + + partval = 0; /* Empty elements move to part 0 */ + for (eelmnum = meshptr->m.verttax[velmnum]; + eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { + Gnum vnodnum; + + vnodnum = meshptr->m.edgetax[eelmnum]; + partval = meshptr->parttax[vnodnum]; + if (partval != 2) + break; + } + partval &= 1; /* In case all nodes in separator */ + ecmpsize1 += (Gnum) partval; /* Count elements in part 1 */ + meshptr->parttax[velmnum] = partval; /* Set part of element */ + } + meshptr->ecmpsize[0] = meshptr->m.velmnbr - ecmpsize1; + meshptr->ecmpsize[1] = ecmpsize1; + +#ifdef SCOTCH_DEBUG_VMESH2 + if (vmeshCheck (meshptr) != 0) { + errorPrint ("vmeshSeparateGr: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_gr.h b/scotch_6.0.3/src/libscotch/vmesh_separate_gr.h new file mode 100644 index 00000000..0b45e138 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_gr.h @@ -0,0 +1,71 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_gr.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the the graph separation-based node **/ +/** separation method. **/ +/** **/ +/** DATES : # Version 4.0 : from : 11 oct 2003 **/ +/** to 11 oct 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct VmeshSeparateGrParam_ { + Strat * stratptr; /*+ Graph separation strategy +*/ +} VmeshSeparateGrParam; + +/* +** The function prototypes. +*/ + +#ifndef VMESH_SEPARATE_GR +#define static +#endif + +int vmeshSeparateGr (Vmesh * restrict const, const VmeshSeparateGrParam * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_ml.c b/scotch_6.0.3/src/libscotch/vmesh_separate_ml.c new file mode 100644 index 00000000..8f274ff0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_ml.c @@ -0,0 +1,263 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_ml.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module separates an active **/ +/** mesh using a multi-level scheme. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 feb 2003 **/ +/** to 31 aug 2005 **/ +/** # Version 5.0 : from : 30 jan 2008 **/ +/** to 30 jan 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH_SEPARATE_ML + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "mesh.h" +#include "mesh_coarsen.h" +#include "vmesh.h" +#include "vmesh_separate_ml.h" +#include "vmesh_separate_st.h" + +/*********************************************/ +/* */ +/* The coarsening and uncoarsening routines. */ +/* */ +/*********************************************/ + +/* This routine builds a coarser mesh from the +** mesh that is given on input. The coarser +** meshes differ at this stage from classical +** active meshes as their internal gains are not +** yet computed. +** It returns: +** - 0 : if the coarse mesh has been built. +** - 1 : if threshold achieved. +** - 2 : on error. +*/ + +static +int +vmeshSeparateMlCoarsen ( +const Vmesh * restrict const finemeshptr, /*+ Finer mesh +*/ +Vmesh * restrict const coarmeshptr, /*+ Coarser mesh to build +*/ +Gnum * restrict * const finecoarptr, /*+ Pointer to multinode table to build +*/ +const VmeshSeparateMlParam * const paraptr) /*+ Method parameters +*/ +{ + int o; + + if (finemeshptr->m.vnodnbr <= (Gnum) paraptr->vnodnbr) + return (1); + + if ((o = meshCoarsen (&finemeshptr->m, &coarmeshptr->m, finecoarptr, (Gnum) paraptr->vnodnbr, paraptr->coarrat, paraptr->coartype)) != 0) + return (o); /* Return if coarsening failed */ + + coarmeshptr->parttax = NULL; /* Do not allocate partition data yet */ + coarmeshptr->frontab = finemeshptr->frontab; /* Re-use frontier array for coarser mesh */ + coarmeshptr->levlnum = finemeshptr->levlnum + 1; /* Mesh level is coarsening level */ + + return (0); +} + +/* This routine propagates the separation of the +** coarser mesh back to the finer mesh, according +** to the multinode table of collapsed elements. +** After the separation is propagated, it finishes +** to compute the parameters of the finer mesh that +** were not computed at the coarsening stage. +** It returns: +** - 0 : if coarse mesh data has been propagated to fine mesh. +** - !0 : on error. +*/ + +static +int +vmeshSeparateMlUncoarsen ( +Vmesh * restrict const finemeshptr, /*+ Finer mesh +*/ +const Vmesh * restrict const coarmeshptr, /*+ Coarser mesh +*/ +const Gnum * restrict const finecoartax) /*+ Multinode array +*/ +{ + if (finemeshptr->parttax == NULL) { /* If partition array not yet allocated */ + if ((finemeshptr->parttax = (GraphPart *) memAlloc ((finemeshptr->m.velmnbr + finemeshptr->m.vnodnbr) * sizeof (GraphPart))) == NULL) { + errorPrint ("vmeshSeparateMlUncoarsen: out of memory"); + return (1); /* Allocated data will be freed along with mesh structure */ + } + finemeshptr->parttax -= finemeshptr->m.baseval; + } + + if (coarmeshptr != NULL) { /* If coarser mesh provided */ + Gnum finevelmnum; + Gnum fineecmpsize1; /* Number of fine elements */ + Gnum fineecmpsize2; + Gnum finevnodnum; + Gnum finencmpsize1; /* Number of fine nodes */ + Gnum finefronnbr; /* Number of frontier vertices in fine mesh */ + + for (finevelmnum = finemeshptr->m.velmbas, fineecmpsize1 = fineecmpsize2 = 0; + finevelmnum < finemeshptr->m.velmnnd; finevelmnum ++) { + Gnum partval; + +#ifdef SCOTCH_DEBUG_VMESH2 + if ((finecoartax[finevelmnum] < coarmeshptr->m.baseval) || + (finecoartax[finevelmnum] >= (coarmeshptr->m.velmnbr + coarmeshptr->m.vnodnbr + coarmeshptr->m.baseval))) { + errorPrint ("vmeshSeparateMlUncoarsen: internal error (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + partval = (Gnum) coarmeshptr->parttax[finecoartax[finevelmnum]]; + finemeshptr->parttax[finevelmnum] = partval; + + fineecmpsize1 += (partval & 1); /* Superscalar update of counters */ + fineecmpsize2 += (partval & 2); + } + finemeshptr->ecmpsize[0] = finemeshptr->m.velmnbr - fineecmpsize1 - (fineecmpsize2 >> 1); + finemeshptr->ecmpsize[1] = fineecmpsize1; + + for (finevnodnum = finemeshptr->m.vnodbas, finencmpsize1 = finefronnbr = 0; + finevnodnum < finemeshptr->m.vnodnnd; finevnodnum ++) { + Gnum partval; + +#ifdef SCOTCH_DEBUG_VMESH2 + if ((finecoartax[finevnodnum] < coarmeshptr->m.vnodbas) || /* Sons of nodes are always nodes */ + (finecoartax[finevnodnum] >= coarmeshptr->m.vnodnnd)) { + errorPrint ("vmeshSeparateMlUncoarsen: internal error (2)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + partval = coarmeshptr->parttax[finecoartax[finevnodnum]]; + finemeshptr->parttax[finevnodnum] = partval; + + if ((partval & 2) != 0) /* If node is in separator */ + finemeshptr->frontab[finefronnbr ++] = finevnodnum; /* Add to frontier */ + + finencmpsize1 += (partval & 1); + } + + finemeshptr->ncmpload[0] = coarmeshptr->ncmpload[0]; + finemeshptr->ncmpload[1] = coarmeshptr->ncmpload[1]; + finemeshptr->ncmpload[2] = coarmeshptr->ncmpload[2]; + finemeshptr->ncmploaddlt = coarmeshptr->ncmploaddlt; + finemeshptr->ncmpsize[0] = finemeshptr->m.vnodnbr - finencmpsize1 - finefronnbr; + finemeshptr->ncmpsize[1] = finencmpsize1; + finemeshptr->fronnbr = finefronnbr; + } + else /* No coarse mesh provided */ + vmeshZero (finemeshptr); /* Assign all vertices to part 0 */ + +#ifdef SCOTCH_DEBUG_VMESH2 + if (vmeshCheck (finemeshptr) != 0) { + errorPrint ("vmeshSeparateMlUncoarsen: internal error (3)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + + return (0); +} + +/* This routine recursively performs the +** coarsening recursion. +** It returns: +** - 0 : if recursion proceeded well. +** - !0 : on error. +*/ + +static +int +vmeshSeparateMl2 ( +Vmesh * restrict const finemeshptr, /* Vertex-separation mesh */ +const VmeshSeparateMlParam * restrict const paraptr) /* Method parameters */ +{ + Vmesh coarmeshdat; + Gnum * restrict finecoartax; + int o; + + o = 1; /* Assume an error if "switch...case" returns a strange value in debug mode */ + switch (vmeshSeparateMlCoarsen (finemeshptr, &coarmeshdat, &finecoartax, paraptr)) { + case 0 : + if (((o = vmeshSeparateMl2 (&coarmeshdat, paraptr)) == 0) && + ((o = vmeshSeparateMlUncoarsen (finemeshptr, &coarmeshdat, finecoartax)) == 0) && + ((o = vmeshSeparateSt (finemeshptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ + errorPrint ("vmeshSeparateMl2: cannot apply ascending strategy"); + coarmeshdat.frontab = NULL; /* Prevent frontab of fine mesh from being freed */ + vmeshExit (&coarmeshdat); + memFree (finecoartax + finemeshptr->m.baseval); /* Free finecoartab as not part of coarse mesh vertex group (unlike for graphCoarsen) */ + break; +#ifdef SCOTCH_DEBUG_VMESH2 + case 1 : + case 2 : /* Cannot coarsen due to lack of memory */ + finecoartax = NULL; /* Prevent Valgrind from yelling */ +#else /* SCOTCH_DEBUG_VMESH2 */ + default : +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (((o = vmeshSeparateMlUncoarsen (finemeshptr, NULL, finecoartax)) == 0) && /* Finalize mesh */ + ((o = vmeshSeparateSt (finemeshptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ + errorPrint ("vmeshSeparateMl2: cannot apply low strategy"); + break; + } + + return (o); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +int +vmeshSeparateMl ( +Vmesh * restrict const meshptr, /*+ Node-separation mesh +*/ +const VmeshSeparateMlParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum levlnum; /* Save value for mesh level */ + int o; + + levlnum = meshptr->levlnum; /* Save mesh level */ + meshptr->levlnum = 0; /* Initialize coarsening level */ + o = vmeshSeparateMl2 (meshptr, paraptr); /* Perform multi-level separation */ + meshptr->levlnum = levlnum; /* Restore mesh level */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_ml.h b/scotch_6.0.3/src/libscotch/vmesh_separate_ml.h new file mode 100644 index 00000000..1c635ab9 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_ml.h @@ -0,0 +1,75 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_ml.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the multi-level node separation **/ +/** routines. **/ +/** **/ +/** DATES : # Version 4.0 : from : 20 feb 2003 **/ +/** to 31 aug 2005 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct VmeshSeparateMlParam_ { + INT vnodnbr; /*+ Minimum number of node vertices +*/ + double coarrat; /*+ Coarsening ratio +*/ + MeshCoarsenType coartype; /*+ Element matching function type +*/ + Strat * stratlow; /*+ Strategy at lowest level +*/ + Strat * stratasc; /*+ Strategy at ascending levels +*/ +} VmeshSeparateMlParam; + +/* +** The function prototypes. +*/ + +#ifndef VMESH_SEPARATE_ML +#define static +#endif + +static int vmeshSeparateMlCoarsen (const Vmesh * restrict const, Vmesh * restrict const, Gnum * restrict * const, const VmeshSeparateMlParam * const); +static int vmeshSeparateMlUncoarsen (Vmesh * const, const Vmesh * const, const Gnum * restrict const); + +int vmeshSeparateMl (Vmesh * const, const VmeshSeparateMlParam * const); +static int vmeshSeparateMl2 (Vmesh * const, const VmeshSeparateMlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_st.c b/scotch_6.0.3/src/libscotch/vmesh_separate_st.c new file mode 100644 index 00000000..365e4e9e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_st.c @@ -0,0 +1,288 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_st.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the global mesh **/ +/** separation strategy and method tables. **/ +/** **/ +/** DATES : # Version 4.0 : from : 20 sep 2002 **/ +/** to 08 feb 2003 **/ +/** # Version 5.0 : from : 04 aug 2007 **/ +/** to 04 aug 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH_SEPARATE_ST + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "parser.h" +#include "graph.h" +#include "vgraph.h" +#include "vgraph_separate_st.h" +#include "mesh.h" +#include "mesh_coarsen.h" +#include "vmesh.h" +#include "vmesh_separate_fm.h" +#include "vmesh_separate_gg.h" +#include "vmesh_separate_gr.h" +#include "vmesh_separate_ml.h" +#include "vmesh_separate_zr.h" +#include "vmesh_separate_st.h" + +/* +** The static and global variables. +*/ + +static Vmesh vmeshdummy; /* Dummy separator mesh for offset computations */ + +static union { + VmeshSeparateFmParam param; + StratNodeMethodData padding; +} vmeshseparatedefaultfm = { { 200, 1000, 0.1L } }; + +static union { + VmeshSeparateGgParam param; + StratNodeMethodData padding; +} vmeshseparatedefaultgg = { { 5 } }; + +static union { + VmeshSeparateGrParam param; + StratNodeMethodData padding; +} vmeshseparatedefaultgr = { { &stratdummy } }; + +static union { + VmeshSeparateMlParam param; + StratNodeMethodData padding; +} vmeshseparatedefaultml = { { 1000, 0.8L, MESHCOARSENNGB, &stratdummy, &stratdummy } }; + +static StratMethodTab vmeshseparatestmethtab[] = { /* Mesh separation methods array */ + { VMESHSEPASTMETHFM, "f", vmeshSeparateFm, &vmeshseparatedefaultfm }, + { VMESHSEPASTMETHGG, "h", vmeshSeparateGg, &vmeshseparatedefaultgg }, +#ifdef SCOTCH_DEBUG_VMESH2 + { VMESHSEPASTMETHGR, "v", vmeshSeparateGr, &vmeshseparatedefaultgr }, +#endif /* SCOTCH_DEBUG_VMESH2 */ + { VMESHSEPASTMETHML, "m", vmeshSeparateMl, &vmeshseparatedefaultml }, + { VMESHSEPASTMETHZR, "z", vmeshSeparateZr, NULL }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab vmeshseparatestparatab[] = { /* Mesh separation method parameter list */ + { VMESHSEPASTMETHFM, STRATPARAMINT, "move", + (byte *) &vmeshseparatedefaultfm.param, + (byte *) &vmeshseparatedefaultfm.param.movenbr, + NULL }, + { VMESHSEPASTMETHFM, STRATPARAMINT, "pass", + (byte *) &vmeshseparatedefaultfm.param, + (byte *) &vmeshseparatedefaultfm.param.passnbr, + NULL }, + { VMESHSEPASTMETHFM, STRATPARAMDOUBLE, "bal", + (byte *) &vmeshseparatedefaultfm.param, + (byte *) &vmeshseparatedefaultfm.param.deltrat, + NULL }, + { VMESHSEPASTMETHGG, STRATPARAMINT, "pass", + (byte *) &vmeshseparatedefaultgg.param, + (byte *) &vmeshseparatedefaultgg.param.passnbr, + NULL }, +#ifdef SCOTCH_DEBUG_VMESH2 + { VMESHSEPASTMETHGR, STRATPARAMSTRAT, "strat", + (byte *) &vmeshseparatedefaultgr.param, + (byte *) &vmeshseparatedefaultgr.param.stratptr, + (void *) &vgraphseparateststratab }, +#endif /* SCOTCH_DEBUG_VMESH2 */ + { VMESHSEPASTMETHML, STRATPARAMSTRAT, "asc", + (byte *) &vmeshseparatedefaultml.param, + (byte *) &vmeshseparatedefaultml.param.stratasc, + (void *) &vmeshseparateststratab }, + { VMESHSEPASTMETHML, STRATPARAMSTRAT, "low", + (byte *) &vmeshseparatedefaultml.param, + (byte *) &vmeshseparatedefaultml.param.stratlow, + (void *) &vmeshseparateststratab }, + { VMESHSEPASTMETHML, STRATPARAMCASE, "type", + (byte *) &vmeshseparatedefaultml.param, + (byte *) &vmeshseparatedefaultml.param.coartype, + (void *) "hsn" }, + { VMESHSEPASTMETHML, STRATPARAMINT, "vnod", + (byte *) &vmeshseparatedefaultml.param, + (byte *) &vmeshseparatedefaultml.param.vnodnbr, + NULL }, + { VMESHSEPASTMETHML, STRATPARAMDOUBLE, "rat", + (byte *) &vmeshseparatedefaultml.param, + (byte *) &vmeshseparatedefaultml.param.coarrat, + NULL }, + { VMESHSEPASTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab vmeshseparatestcondtab[] = { /* Mesh condition parameter table */ + { STRATNODECOND, STRATPARAMINT, "edge", + (byte *) &vmeshdummy, + (byte *) &vmeshdummy.m.edgenbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "levl", + (byte *) &vmeshdummy, + (byte *) &vmeshdummy.levlnum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "load", + (byte *) &vmeshdummy, + (byte *) &vmeshdummy.m.vnlosum, + NULL }, + { STRATNODECOND, STRATPARAMINT, "velm", + (byte *) &vmeshdummy, + (byte *) &vmeshdummy.m.velmnbr, + NULL }, + { STRATNODECOND, STRATPARAMINT, "vnod", + (byte *) &vmeshdummy, + (byte *) &vmeshdummy.m.vnodnbr, + NULL }, + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab vmeshseparateststratab = { /* Strategy tables for mesh separation methods */ + vmeshseparatestmethtab, + vmeshseparatestparatab, + vmeshseparatestcondtab }; + +/*******************************************/ +/* */ +/* This is the generic separation routine. */ +/* */ +/*******************************************/ + +/* This routine computes the separation of +** the given graph according to the given +** strategy. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +vmeshSeparateSt ( +Vmesh * restrict const meshptr, /*+ Separation mesh +*/ +const Strat * restrict const strat) /*+ Separation strategy +*/ +{ + StratTest val; + VmeshStore save[2]; /* Results of the two strategies */ + int o; + +#ifdef SCOTCH_DEBUG_VMESH2 + if (sizeof (Gnum) != sizeof (INT)) { + errorPrint ("vmeshSeparateSt: invalid type specification for parser variables"); + return (1); + } + if ((sizeof (VmeshSeparateFmParam) > sizeof (StratNodeMethodData)) || + (sizeof (VmeshSeparateGgParam) > sizeof (StratNodeMethodData)) || + (sizeof (VmeshSeparateGrParam) > sizeof (StratNodeMethodData)) || + (sizeof (VmeshSeparateMlParam) > sizeof (StratNodeMethodData))) { + errorPrint ("vmeshSeparateSt: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH2 */ +#ifdef SCOTCH_DEBUG_VMESH1 + if (strat->tabl != &vmeshseparateststratab) { + errorPrint ("vmeshSeparateSt: invalid parameter (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_VMESH1 */ + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + o = vmeshSeparateSt (meshptr, strat->data.concat.strat[0]); /* Apply first strategy */ + if (o == 0) /* If it worked all right */ + o |= vmeshSeparateSt (meshptr, strat->data.concat.strat[1]); /* Then apply second strategy */ + break; + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) meshptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_VMESH2 + if ((val.typetest != STRATTESTVAL) && + (val.typenode != STRATPARAMLOG)) { + errorPrint ("vmeshSeparateSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_VMESH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = vmeshSeparateSt (meshptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = vmeshSeparateSt (meshptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + break; + case STRATNODESELECT : + if (((vmeshStoreInit (meshptr, &save[0])) != 0) || /* Allocate save areas */ + ((vmeshStoreInit (meshptr, &save[1])) != 0)) { + errorPrint ("vmeshSeparateSt: out of memory"); + vmeshStoreExit (&save[0]); + return (1); + } + + vmeshStoreSave (meshptr, &save[1]); /* Save initial bipartition */ + vmeshSeparateSt (meshptr, strat->data.select.strat[0]); /* Apply first strategy */ + vmeshStoreSave (meshptr, &save[0]); /* Save its result */ + vmeshStoreUpdt (meshptr, &save[1]); /* Restore initial bipartition */ + vmeshSeparateSt (meshptr, strat->data.select.strat[1]); /* Apply second strategy */ + + if ( (save[0].fronnbr < meshptr->fronnbr) || /* If first strategy is better */ + ((save[0].fronnbr == meshptr->fronnbr) && + (abs (save[0].ncmploaddlt) < abs (meshptr->ncmploaddlt)))) + vmeshStoreUpdt (meshptr, &save[0]); /* Restore its result */ + + vmeshStoreExit (&save[0]); /* Free both save areas */ + vmeshStoreExit (&save[1]); + break; +#ifdef SCOTCH_DEBUG_VMESH1 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_VMESH1 */ + default : +#endif /* SCOTCH_DEBUG_VMESH1 */ + return (strat->tabl->methtab[strat->data.method.meth].func (meshptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_VMESH1 + default : + errorPrint ("vmeshSeparateSt: invalid parameter (2)"); + return (1); +#endif /* SCOTCH_DEBUG_VMESH1 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_st.h b/scotch_6.0.3/src/libscotch/vmesh_separate_st.h new file mode 100644 index 00000000..27d5dff3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_st.h @@ -0,0 +1,80 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_st.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the global mesh separation **/ +/** strategy and method tables. **/ +/** **/ +/** DATES : # Version 4.0 : from : 20 sep 2002 **/ +/** to 31 oct 2003 **/ +/** **/ +/************************************************************/ + +/* +** The type definitions. +*/ + +/*+ Method types. +*/ + +typedef enum VmeshSeparateStMethodType_ { + VMESHSEPASTMETHFM = 0, /*+ Fiduccia-Mattheyses +*/ + VMESHSEPASTMETHGG, /*+ Greedy Mesh Growing +*/ +#ifdef SCOTCH_DEBUG_VMESH2 + VMESHSEPASTMETHGR, /*+ Graph partitioning +*/ +#endif /* SCOTCH_DEBUG_VMESH2 */ + VMESHSEPASTMETHML, /*+ Multi-level separation +*/ + VMESHSEPASTMETHZR, /*+ Zero method +*/ + VMESHSEPASTMETHNBR /*+ Number of methods +*/ +} VmeshSeparateStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab vmeshseparateststratab; + +/* +** The function prototypes. +*/ + +#ifndef VMESH_SEPARATE_ST +#define static +#endif + +int vmeshSeparateSt (Vmesh * restrict const, const Strat * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_zr.c b/scotch_6.0.3/src/libscotch/vmesh_separate_zr.c new file mode 100644 index 00000000..359bf421 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_zr.c @@ -0,0 +1,81 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vgraph_separate_zr.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module moves all of the vertices **/ +/** to the first subdomain. **/ +/** **/ +/** DATES : # Version 4.0 : from : 10 sep 2002 **/ +/** to 29 may 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH_SEPARATE_ZR + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "vmesh.h" +#include "vmesh_separate_zr.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine moves all of the mesh nodes +** and elements to the first part of the +** partition. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +vmeshSeparateZr ( +Vmesh * restrict const meshptr) +{ + if (meshptr->ncmpload[0] != meshptr->m.vnlosum) /* If not all vertices already in part zero */ + vmeshZero (meshptr); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/vmesh_separate_zr.h b/scotch_6.0.3/src/libscotch/vmesh_separate_zr.h new file mode 100644 index 00000000..ae061a67 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_separate_zr.h @@ -0,0 +1,57 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_separate_zr.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the move-all-to-first-subdomain **/ +/** mesh node separation method. **/ +/** **/ +/** DATES : # Version 4.0 : from : 10 sep 2002 **/ +/** to 10 sep 2002 **/ +/** **/ +/************************************************************/ + +/* +** The function prototypes. +*/ + +#ifndef VMESH_SEPARATE_ZR +#define static +#endif + +int vmeshSeparateZr (Vmesh * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/vmesh_store.c b/scotch_6.0.3/src/libscotch/vmesh_store.c new file mode 100644 index 00000000..f16f77c6 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/vmesh_store.c @@ -0,0 +1,166 @@ +/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : vmesh_store.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the save data **/ +/** structure handling routines for node **/ +/** separation meshes. **/ +/** **/ +/** DATES : # Version 4.0 : from : 10 sep 2002 **/ +/** to : 10 sep 2002 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define VMESH_STORE + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "mesh.h" +#include "vmesh.h" + +/*********************************/ +/* */ +/* Store mesh handling routines. */ +/* */ +/*********************************/ + +/* This routine builds a save structure +** for the given node separation mesh. +** It returns: +** - 0 : if allocation succeeded. +** - !0 : on error. +*/ + +int +vmeshStoreInit ( +const Vmesh * const meshptr, +VmeshStore * const storptr) +{ + Gnum savsize; + + savsize = (meshptr->m.velmnbr + meshptr->m.vnodnbr) * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ + + if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ + errorPrint ("vmeshStoreInit: out of memory"); + return (1); + } + + return (0); +} + +/* This routine frees a mesh node +** separation save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +vmeshStoreExit ( +VmeshStore * const storptr) +{ + memFree (storptr->datatab); +#ifdef SCOTCH_DEBUG_VMESH2 + storptr->datatab = NULL; +#endif /* SCOTCH_DEBUG_VMESH2 */ +} + +/* This routine saves partition data from the +** given node separation mesh to the given +** save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +vmeshStoreSave ( +const Vmesh * const meshptr, +VmeshStore * const storptr) +{ + byte * parttab; /* Pointer to part data save area */ + byte * frontab; /* Pointer to frontier data save area */ + + storptr->ecmpsize[0] = meshptr->ecmpsize[0]; /* Save partition parameters */ + storptr->ecmpsize[1] = meshptr->ecmpsize[1]; + storptr->ncmpload[0] = meshptr->ncmpload[0]; + storptr->ncmpload[1] = meshptr->ncmpload[1]; + storptr->ncmpload[2] = meshptr->ncmpload[2]; + storptr->ncmploaddlt = meshptr->ncmploaddlt; + storptr->ncmpsize[0] = meshptr->ncmpsize[0]; + storptr->ncmpsize[1] = meshptr->ncmpsize[1]; + storptr->fronnbr = meshptr->fronnbr; + + frontab = storptr->datatab; /* Compute data offsets within save structure */ + parttab = frontab + meshptr->fronnbr * sizeof (Gnum); + + memCpy (frontab, meshptr->frontab, meshptr->fronnbr * sizeof (Gnum)); + memCpy (parttab, meshptr->parttax + meshptr->m.baseval, (meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (GraphPart)); +} + +/* This routine updates partition data of the +** given active graph, using the given save graph. +** It returns: +** - VOID : in all cases. +*/ + +void +vmeshStoreUpdt ( +Vmesh * const meshptr, +const VmeshStore * const storptr) +{ + byte * frontab; /* Pointer to frontier data save area */ + byte * parttab; /* Pointer to part data save area */ + + meshptr->ecmpsize[0] = storptr->ecmpsize[0]; /* Load partition parameters */ + meshptr->ecmpsize[1] = storptr->ecmpsize[1]; + meshptr->ncmpload[0] = storptr->ncmpload[0]; + meshptr->ncmpload[1] = storptr->ncmpload[1]; + meshptr->ncmpload[2] = storptr->ncmpload[2]; + meshptr->ncmploaddlt = storptr->ncmploaddlt; + meshptr->ncmpsize[0] = storptr->ncmpsize[0]; + meshptr->ncmpsize[1] = storptr->ncmpsize[1]; + meshptr->fronnbr = storptr->fronnbr; + + frontab = storptr->datatab; /* Compute data offsets within save structure */ + parttab = frontab + storptr->fronnbr * sizeof (Gnum); + + memCpy (meshptr->frontab, frontab, storptr->fronnbr * sizeof (Gnum)); + memCpy (meshptr->parttax + meshptr->m.baseval, parttab, (meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (GraphPart)); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph.c b/scotch_6.0.3/src/libscotch/wgraph.c new file mode 100644 index 00000000..27468bb4 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph.c @@ -0,0 +1,155 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** Charles-Edmond BICHOT (5.1b) **/ +/** **/ +/** FUNCTION : This module contains the data structure **/ +/** handling routines for the vertex overl- **/ +/** apped graph partitioning **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 28 may 2010 **/ +/** to : 29 may 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "wgraph.h" + +/***********************************/ +/* */ +/* Active graph handling routines. */ +/* */ +/***********************************/ + +/* This routine initialize the active graph +** corresponding to the source graph +** It returns: +** - VOID : in all cases. +*/ + +void +wgraphInit ( +Wgraph * restrict const actgrafptr, /* Active graph */ +const Graph * restrict const srcgrafptr, /* Source graph */ +const Anum partnbr) +{ + actgrafptr->s = *srcgrafptr; /* Clone source graph */ + actgrafptr->s.flagval &= ~GRAPHFREETABS; /* Do not free its contents */ + actgrafptr->compload = NULL; /* No group leader yet */ + actgrafptr->partnbr = partnbr; + actgrafptr->parttax = NULL; /* No part array yet */ +} + +/* This routine frees the contents +** of the given active graph +** It returns: +** - VOID : in all cases. +*/ + +void +wgraphExit ( +Wgraph * const grafptr) /* Active graph */ +{ + if (grafptr->compload != NULL) + memFree (grafptr->compload); /* Free group leader */ + + graphExit (&grafptr->s); /* Free source graph */ + +#ifdef SCOTCH_DEBUG_WGRAPH2 + memSet (grafptr, ~0, sizeof (Wgraph)); +#endif /* SCOTCH_DEBUG_WGRAPH2 */ +} + +/* This routine builds the active graph +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +wgraphAlloc ( +Wgraph * const grafptr) /* Active graph */ +{ + Gnum partsiz; + Gnum * restrict parttab; + + partsiz = (grafptr->parttax == NULL) ? grafptr->s.vertnbr : 0; /* Allocate part array only if not already */ + + if (memAllocGroup ((void **) (void *) + &grafptr->compload, (size_t) (grafptr->partnbr * sizeof (Gnum)), + &grafptr->compsize, (size_t) (grafptr->partnbr * sizeof (Gnum)), + &parttab, (size_t) (partsiz * sizeof (Anum)), + &grafptr->frontab, (size_t) (grafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("wgraphAlloc: out of memory (1)"); + return (1); + } + if (grafptr->parttax == NULL) /* Part array does not need flag as will be group freed */ + grafptr->parttax = parttab - grafptr->s.baseval; + + return (0); +} + +/* This routine moves all of the graph +** vertices to the first part. +** It returns: +** - VOID : in all cases. +*/ + +void +wgraphZero ( +Wgraph * const grafptr) +{ + memSet (grafptr->compload, 0, grafptr->partnbr * sizeof (Gnum)); + memSet (grafptr->compsize, 0, grafptr->partnbr * sizeof (Gnum)); + + grafptr->compload[0] = grafptr->s.velosum; + grafptr->compsize[0] = grafptr->s.vertnbr; + grafptr->fronload = 0; + grafptr->fronnbr = 0; + + memSet (grafptr->parttax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (Anum)); /* Set all vertices to part 0 */ +} diff --git a/scotch_6.0.3/src/libscotch/wgraph.h b/scotch_6.0.3/src/libscotch/wgraph.h new file mode 100644 index 00000000..77927a38 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph.h @@ -0,0 +1,110 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** Charles-Edmond BICHOT (5.1b) **/ +/** **/ +/** FUNCTION : This module contains the data declarat- **/ +/** ions for the vertex overlapped graph **/ +/** partitioning. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +#define WGRAPH_H + +/* +** The type and structure definitions. +*/ + +/*+ The graph structure. +*/ + +#ifndef ARCH_H +typedef INT Anum; /*+ Generic integer +*/ +#endif /* ARCH_H */ + +typedef struct Wgraph_ { + Graph s; /*+ Source graph +*/ + Anum partnbr; /*+ Current number of parts +*/ + Gnum fronnbr; /*+ Number of frontier vertices +*/ + Gnum fronload; /*+ load for frontier +*/ + Gnum * frontab; /*+ Array of frontier vertex numbers +*/ + Gnum * compload; /*+ Array of part loads +*/ + Gnum * compsize; /*+ Array of part number of vertives +*/ + Anum * parttax; /*+ Part array; can be allocated separately +*/ + Gnum levlnum; +} Wgraph; + +/*+ The save graph structure. +*/ + +typedef struct WgraphStore_ { + Anum partnbr; /*+ Number of parts +*/ + Gnum fronnbr; /*+ Number of frontier vertices +*/ + Gnum fronload; /*+ Frontier load +*/ + byte * datatab; /*+ Variable-sized data array +*/ +} WgraphStore; + +/*+ This structure stores part lists. +*/ + +typedef struct WgraphPartList_ { + Gnum vertnum; /*+ Number of vertex of which part is neighbor +*/ + Anum nextidx; /*+ Pointer to index of next recorded neighbor +*/ +} WgraphPartList; + +/* +** The function prototypes. +*/ + +#ifndef WGRAPH +#define static +#endif + +void wgraphInit (Wgraph * const, const Graph * restrict const, const Anum); +void wgraphExit (Wgraph * const); +int wgraphAlloc (Wgraph * const); +void wgraphZero (Wgraph * const); +int wgraphCheck (const Wgraph * const); + +int wgraphStoreInit (const Wgraph * const, WgraphStore * const); +void wgraphStoreExit (WgraphStore * const); +void wgraphStoreSave (const Wgraph * const, WgraphStore * const); +void wgraphStoreUpdt (Wgraph * const, const WgraphStore * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/wgraph_check.c b/scotch_6.0.3/src/libscotch/wgraph_check.c new file mode 100644 index 00000000..24a2c376 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_check.c @@ -0,0 +1,189 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_check.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : This module check the graph consistency **/ +/** for the vertex overlapped graph partit- **/ +/** ioning. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 10 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH_CHECK + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "wgraph.h" + +/* +** The static variables. +*/ + +static const Gnum wgraphcheckloadone = 1; + +/*************************/ +/* */ +/* These routines handle */ +/* separator graphs. */ +/* */ +/*************************/ + +/* This routine checks the consistency +** of the given separator graph. +** It returns: +** - 0 : if graph data are consistent. +** - !0 : on error. +*/ + +int +wgraphCheck ( +const Wgraph * const grafptr) +{ + Gnum vertnbr; /* number of vertex */ + Gnum vertnum; /* Number of current vertex */ + const Gnum * restrict velobax; /* Data for handling of optional arrays */ + Gnum velomsk; + Gnum edgenum; + Gnum partnum; + Gnum fronnum; /* Current number of frontier vertex */ + Gnum fronload; + Gnum * restrict compload; + Gnum * restrict compsize; + Gnum * restrict flagtab; + + vertnbr = grafptr->s.vertnbr; + + if (memAllocGroup ((void **) (void *) + &flagtab, (size_t) (grafptr->partnbr * sizeof (Gnum)), + &compload, (size_t) (grafptr->partnbr * sizeof (Gnum)), + &compsize, (size_t) (grafptr->partnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("wgraphCheck: out of memory (1)"); + return (1); + } + + if (grafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ + velobax = &wgraphcheckloadone; /* In case vertices not weighted (least often) */ + velomsk = 0; + } + else { + velobax = grafptr->s.velotax; + velomsk = ~((Gnum) 0); + } + + fronnum = + fronload = 0; + memSet (compload, 0, grafptr->partnbr * sizeof (Gnum)); /* Reset loads */ + memSet (compsize, 0, grafptr->partnbr * sizeof (Gnum)); + memSet (flagtab, ~0, grafptr->partnbr * sizeof (Gnum)); /* Reset flag array */ + + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + if ((grafptr->parttax[vertnum] >= grafptr->partnbr) || + (grafptr->parttax[vertnum] < -1)) { + errorPrint ("wgraphCheck: invalid part array"); + memFree (flagtab); /* Free group leader */ + return (1); + } + + if (grafptr->parttax[vertnum] == -1) { + fronnum ++; + fronload += velobax[vertnum & velomsk]; + + for (edgenum = grafptr->s.verttax[vertnum]; + edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { + Gnum vertend; + + vertend = grafptr->s.edgetax[edgenum]; + if ((grafptr->parttax[vertend] != -1) && + (flagtab[grafptr->parttax[vertend]] != vertnum)) { + compload[grafptr->parttax[vertend]] += velobax[vertnum & velomsk]; + compsize[grafptr->parttax[vertend]] ++; + flagtab[grafptr->parttax[vertend]] = vertnum; + } + } + } + else { + compload[grafptr->parttax[vertnum]] += velobax[vertnum & velomsk]; + compsize[grafptr->parttax[vertnum]] ++; + } + } + + for (partnum = 0; partnum < grafptr->partnbr; partnum ++) { + if (grafptr->compsize[partnum] != compsize[partnum]) { + errorPrint ("wgraphCheck: invalid part size %d %d %d", grafptr->compsize[partnum], compsize[partnum], partnum); + memFree (flagtab); + return (1); + } + if (grafptr->compload[partnum] != compload[partnum]) { + errorPrintW ("wgraphCheck: invalid part load %d %d %d", grafptr->compload[partnum], compload[partnum], partnum); + memFree (flagtab); + return (1); + } + } + + if (grafptr->fronload != fronload) { + errorPrint ("wgraphCheck: invalid frontier load %d %d", grafptr->fronload, fronload); + memFree (flagtab); + return (1); + } + if (grafptr->fronnbr != fronnum) { + errorPrint ("wgraphCheck: invalid frontier size %d %d", grafptr->fronnbr, fronnum); + memFree (flagtab); + return (1); + } + + for(fronnum = 0; fronnum < grafptr->fronnbr; fronnum++) { + vertnum = grafptr->frontab[fronnum]; + if (grafptr->parttax[vertnum] != -1) { + errorPrint ("wgraphCheck: invalid frontab"); + memFree (flagtab); + return (1); + } + } + + memFree (flagtab); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_fm.c b/scotch_6.0.3/src/libscotch/wgraph_part_fm.c new file mode 100644 index 00000000..44469ae5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_fm.c @@ -0,0 +1,915 @@ +/* Copyright 2007-2013 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_fm.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module is the improved Fiduccia- **/ +/** Mattheyses refinement routine for the **/ +/** vertex overlapped graph partitioning. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to 24 dec 2013 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH_PART_FM + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "graph.h" +#include "wgraph.h" +#include "wgraph_part_gg.h" +#include "wgraph_part_fm.h" + +/* +** The static variables. +*/ + +static const Gnum wgraphpartfmloadone = 1; + + +/*********************************/ +/* */ +/* Gain table handling routines. */ +/* */ +/*********************************/ + +/* This routine returns the vertex of best gain +** whose swap will keep the balance correct. +** It returns: +** - !NULL : pointer to the vertex gainlink. +** - NULL : if no more vertices available. +*/ + +static +WgraphPartFmLink * +wgraphPartFmTablGet ( +Wgraph * restrict const grafptr, /*+ Active graph +*/ +WgraphPartFmVertex * hashtab, +GainTabl * const tablptr, /*+ Gain table +*/ +Gnum * restrict diffload) +{ + Gnum gainbest; /* Separator gain of best link */ + Gnum bestdiffload; + const GainEntr * tablbest; /* Gain table entry of best link */ + WgraphPartFmLink * linkptr; /* Pointer to current gain link */ + WgraphPartFmLink * linkbest; /* Pointer to best link found */ + + linkbest = NULL; /* Assume no candidate vertex found yet */ + tablbest = tablptr->tend; + gainbest = GAINMAX; + + for (linkptr = (WgraphPartFmLink *) gainTablFrst (tablptr); /* Select candidate vertices */ + (linkptr != NULL) && (linkptr->gainlink.tabl <= tablbest); + linkptr = (WgraphPartFmLink *) gainTablNext (tablptr, (GainLink *) linkptr)) { + Gnum vertpart; /* Part of current vertex */ + Gnum gaincur; /* Separator gain of current link */ + + vertpart = linkptr->partval; + gaincur = linkptr->gain; /* Get separator gain and vertex balance */ + + if (linkptr->minloadpartval == -1) { + return (linkptr); /* Return best link found */ + } + + if ((gaincur < gainbest) || /* And if it gives better gain than gain max */ + ((gaincur == gainbest) && /* Or is in preferred part */ + ((grafptr->compload[vertpart] - grafptr->compload[linkptr->minloadpartval]) <= bestdiffload))) { + linkbest = linkptr; /* Select it */ + gainbest = gaincur; + tablbest = linkptr->gainlink.tabl; + bestdiffload = grafptr->compload[vertpart] - grafptr->compload[linkptr->minloadpartval]; + } + } + + *diffload += bestdiffload; + return (linkbest); /* Return best link found */ +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +int +wgraphPartFm ( +Wgraph * restrict const grafptr, /*+ Active graph +*/ +const WgraphPartFmParam * const paraptr) /*+ Method parameters +*/ +{ + int passnbr; /* Maximum number of passes to go */ + int moveflag; /* Flag set if useful moves made */ + Gnum fronnum; /* Current index of frontier vertex */ + Gnum partval; + Gnum partnbr; + Gnum vertnum; + Gnum hashnum; + Gnum velosum; + Gnum minload; + Gnum maxload; + Gnum frlobst; + Gnum linknbr; + Gnum savenum; + Gnum hashmax; /* Maximum number of elements in table */ + Gnum hashsiz; /* Size of hash and save tables */ + Gnum hashmsk; /* Mask for access to hash table */ + Gnum hashnbr; /* Number of elements in hash table */ + Gnum velomsk; + Gnum * restrict movetab; + GainTabl * restrict tablptr; /* Pointer to gain tables */ + const Gnum * restrict velobax; /* Data for handling of optional arrays */ + WgraphPartFmVertex * hashtab; /* Hash vertex table */ + WgraphPartFmVertex * vexxptr; + WgraphPartFmVertex * vertlist; + WgraphPartFmVertex * locklist; + WgraphPartFmSave * restrict savetab; + WgraphPartFmLink * restrict linktab; + WgraphPartFmPartList * restrict partlist; + WgraphPartFmPartList * restrict partlistptr; + WgraphPartFmPartList * restrict partlistloadptr; + + partnbr = grafptr->partnbr; + for (partval = 0, velosum = 0; partval < partnbr; partval ++) + velosum += grafptr->compload[partval]; + + if (grafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ + velobax = &wgraphpartfmloadone; /* In case vertices not weighted (least often) */ + velomsk = 0; + } + else { + velobax = grafptr->s.velotax; + velomsk = ~((Gnum) 0); + } + + minload = velosum * (1. - paraptr->deltrat) / (float) (partnbr); + maxload = velosum * (1. + paraptr->deltrat) / (float) (partnbr); + + if (grafptr->fronnbr == 0) { /* If no frontier defined */ + for (partval = 0; partval < partnbr; partval ++) { + if (grafptr->compload[partval] < minload /* If balance is not achieved */ + || grafptr->compload[partval] > maxload) { /* Imbalance must be fought */ + WgraphPartGgParam paradat; + + paradat.passnbr = 5; /* Use a standard algorithm */ + + wgraphPartGg (grafptr, ¶dat); + + if (grafptr->fronnbr == 0) /* If new partition has no frontier */ + return (0); /* This algorithm is still useless */ + + } + return (0); /* This algorithm is still useless */ + } + } + + hashnbr = 16 * (grafptr->fronnbr + paraptr->movenbr + grafptr->s.degrmax) + 1; + + if (hashnbr > grafptr->s.vertnbr) + hashnbr = 4 * grafptr->s.vertnbr; + + hashnbr *= 2; + + for (hashsiz = 512; hashsiz < hashnbr; hashsiz <<= 1) ; /* Get upper power of two */ + hashmsk = hashsiz - 1; + hashmax = hashsiz >> 2; /* Use hash table at 1/4 of its capacity */ + hashnbr = 0; + + if (((tablptr = gainTablInit (GAINMAX, WGRAPHSEPAFMGAINBITS)) == NULL) || /* Use logarithmic array only */ + (memAllocGroup ((void **) (void *) + &hashtab, (size_t) (hashsiz * sizeof (WgraphPartFmVertex)), + &linktab, (size_t) (hashsiz * sizeof (WgraphPartFmLink)), + &partlist,(size_t) (partnbr * sizeof (WgraphPartFmPartList)), + &savetab, (size_t) (hashsiz * sizeof (WgraphPartFmSave)), + &movetab, (size_t) (hashsiz * sizeof (Gnum)), NULL) == NULL)) { + errorPrint ("wgraphPartFm: out of memory (1)"); + + if (tablptr != NULL) + gainTablExit (tablptr); + + return (1); + } + memSet (hashtab, ~0, hashsiz * sizeof (WgraphPartFmVertex)); + memSet (linktab, ~0, hashsiz * sizeof (WgraphPartFmLink)); + + linknbr = 0; + locklist = NULL; + passnbr = paraptr->passnbr; + frlobst = grafptr->fronload; + for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { /* Set initial gains */ + Gnum edgenum; + Gnum compgain; + Gnum minloadpartval; + Gnum minloadpartload; + Gnum secondloadpartval; + WgraphPartFmLink * restrict linklist; + WgraphPartFmLink * restrict linkptr; + + minloadpartval = + secondloadpartval = -1; + partlistptr = NULL; + vertnum = grafptr->frontab[fronnum]; + + compgain = - velobax[vertnum & velomsk]; /* Gain initialised as negative value for the frontier */ + memSet (partlist, 0, partnbr * sizeof (WgraphPartFmPartList)); + for (edgenum = grafptr->s.verttax[vertnum]; + edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { + Gnum vertnum2; + WgraphPartFmVertex * vexxptr; + + vertnum2 = grafptr->s.edgetax[edgenum]; + for (hashnum = (vertnum2 * WGRAPHSEPAFMHASHPRIME) & hashmsk; + (hashtab[hashnum].vertnum != vertnum2) && (hashtab[hashnum].vertnum != ~0); + hashnum = (hashnum + 1) & hashmsk); + + vexxptr = hashtab + hashnum; + if (vexxptr->vertnum == ~0) { /* If vertex not found add it in the hash table */ + vexxptr->vertnum = vertnum2; + vexxptr->partval = grafptr->parttax[vertnum2]; + vexxptr->linklist = NULL; + hashnbr ++; + if (hashnbr >= hashmax) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + } + if (vexxptr->partval != -1) { /* If its part is not the separator */ + if (partlist[vexxptr->partval].gain == 0) { /* and not yet linked */ + partlist[vexxptr->partval].prev = partlistptr; /* link it */ + partlistptr = partlist + vexxptr->partval; + + if (minloadpartval == -1 || + minloadpartload > grafptr->compload[vexxptr->partval]) { + secondloadpartval = minloadpartval; + minloadpartval = vexxptr->partval; + minloadpartload = grafptr->compload[minloadpartval]; + } + else if (secondloadpartval != vexxptr->partval) { + secondloadpartval = vexxptr->partval; + } + } + partlist[vexxptr->partval].gain -= velobax[vertnum2 & velomsk]; /* Store the gain of this vertex move for this part */ + compgain += velobax[vertnum2 & velomsk]; /* Store the global gain of this vertex move */ + } + } + + for (hashnum = (vertnum * WGRAPHSEPAFMHASHPRIME) & hashmsk; + hashtab[hashnum].vertnum != vertnum && hashtab[hashnum].vertnum != ~0; + hashnum = (hashnum + 1) & hashmsk); + if (hashtab[hashnum].vertnum == ~0) { /* If vertex not found */ + hashtab[hashnum].vertnum = vertnum; /* Add it in the hash table */ + hashtab[hashnum].partval = -1; + hashtab[hashnum].linklist = NULL; + hashnbr ++; + + if (hashnbr >= hashmax) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + } + + hashtab[hashnum].linklist = (partlistptr != NULL) /* If selected vertex is not isolated */ + ? linktab + linknbr /* Then first link will next element in linktab */ + : NULL; /* Else, no link */ + linklist = + linkptr = NULL; /* Assume list is empty */ + while (partlistptr != NULL) { /* For each linked part */ + partval = partlistptr - partlist; + partlistptr = partlistptr->prev; + linkptr = linktab + linknbr; /* Create link at the end of linktab */ + linkptr->partval = partval; + linkptr->hashnum = hashnum; + linkptr->gain = compgain + partlist[partval].gain; + + if (partval != minloadpartval) + linkptr->minloadpartval = minloadpartval; + else + linkptr->minloadpartval = secondloadpartval; + linkptr->minloadpartload = minloadpartload; + + if (linklist != NULL) /* Add link to the list */ + linklist->next = linkptr; + linklist = linkptr; + + gainTablAdd (tablptr, (GainLink *) (linktab + linknbr), linkptr->gain); /* add the link in the gain table */ + linknbr ++; + + partlist[partval].prev = NULL; + partlist[partval].gain = 0; + } + if (linkptr != NULL) + linkptr->next = NULL; /* close the end of the list */ + } + + movetab[0] = -1; + + do { /* As long as there is improvement */ + Gnum partval2; + Gnum movenbr; /* Number of uneffective moves done */ + Gnum savenbr; /* Position of current move */ + Gnum diffload; + WgraphPartFmLink * restrict linkptr; + + movenbr = 0; /* No uneffective moves yet */ + savenbr = 0; /* No recorded moves yet */ + moveflag = 0; /* No moves to date */ + diffload = 0; + + while ((movenbr < paraptr->movenbr) && /* As long as we can find effective vertices */ + ((linkptr = wgraphPartFmTablGet (grafptr, hashtab, tablptr, &diffload)) != NULL)) { + Gnum edgenum; + WgraphPartFmVertex * vexxptr2; /* Pointer to current vertex */ + WgraphPartFmVertex * vertlist2; + + movenbr ++; + minload = velosum * (1. - paraptr->deltrat) / (float) (partnbr); + maxload = velosum * (1. + paraptr->deltrat) / (float) (partnbr); + partval = linkptr->partval; /* Get data from the selected link */ + hashnum = linkptr->hashnum; + vexxptr2 = hashtab + hashnum; + vertnum = vexxptr2->vertnum; + + vertlist = NULL; /* and a list of vertex */ + partlistptr = NULL; /* initialise an empty list of part */ + partlistloadptr = NULL; + + vexxptr2->linked = 1; /* link the vertex */ + vexxptr2->partval2 = partval; /* the vertex will move to the part partval */ + vexxptr2->prev = vertlist; + vertlist = hashtab + hashnum; + + for (edgenum = grafptr->s.verttax[vertnum]; /* for neighbours vertices */ + edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { + WgraphPartFmVertex * vexxptr3; /* Pointer to current vertex */ + Gnum vertnum2; + Gnum edgenum2; + + vertnum2 = grafptr->s.edgetax[edgenum]; + + for (hashnum = (vertnum2 * WGRAPHSEPAFMHASHPRIME) & hashmsk; /* search the vertex in the hash table */ + hashtab[hashnum].vertnum != vertnum2 && hashtab[hashnum].vertnum != ~0; + hashnum = (hashnum + 1) & hashmsk); + vexxptr3 = hashtab + hashnum; + + if (vexxptr3->vertnum == ~0) { /* if vertex not found */ + vexxptr3->vertnum = vertnum2; /* add it in the hash table */ + vexxptr3->partval = grafptr->parttax[vertnum2]; + vexxptr3->linklist = NULL; + hashnbr ++; + if (hashnbr >= hashmax) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + } + + if (vexxptr3->partval == -1) { /* if vertex is in the separator */ + if (vexxptr3->linked == ~0) { /* link the vertex */ + vexxptr3->linked = 1; + vexxptr3->prev = vertlist; + vertlist = hashtab + hashnum; + vexxptr3->partval2 = -1; /* the vertex will stay in the separator */ + } + } + else if ((vexxptr3->partval != partval)) { /* or if it's not in the part of the selected vertex */ + if (vexxptr3->linked == ~0) { /* link the vertex */ + vexxptr3->linked = 1; + vexxptr3->prev = vertlist; + vertlist = hashtab + hashnum; + vexxptr3->partval2 = -1; /* the vertex will move to the separator */ + } + + for (edgenum2 = grafptr->s.verttax[vertnum2]; /* for neighbours vertices */ + edgenum2 < grafptr->s.vendtax[vertnum2]; edgenum2 ++) { + WgraphPartFmVertex * vexxptr4; /* Pointer to current vertex */ + Gnum vertnum3; + + vertnum3 = grafptr->s.edgetax[edgenum2]; + + for (hashnum = (vertnum3 * WGRAPHSEPAFMHASHPRIME) & hashmsk; /* search the vertex in the hash table */ + hashtab[hashnum].vertnum != vertnum3 && hashtab[hashnum].vertnum != ~0; + hashnum = (hashnum + 1) & hashmsk); + vexxptr4 = hashtab + hashnum; + + if (vexxptr4->vertnum == ~0) { /* if vertex not found */ + vexxptr4->vertnum = vertnum3; /* add it in the hash table */ + vexxptr4->partval = grafptr->parttax[vertnum3]; + vexxptr4->linklist = NULL; + hashnbr ++; + if (hashnbr >= hashmax) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + } + + if (vexxptr4->partval == -1) { /* if vertex in separator */ + if (vexxptr4->linked == ~0) { /* link the vertex */ + vexxptr4->linked = 1; + vexxptr4->prev = vertlist; + vexxptr4->partval2 = -1; + vertlist = hashtab + hashnum; + } + } + } + } + } + vertlist2 = vertlist; + grafptr->fronload -= velobax[vertnum & velomsk]; /* Decrease the frontier load (due to the selected vertex) */ + grafptr->fronnbr --; /* Decrease the frontier size (due to the selected vertex) */ + + while (vertlist != NULL) { /* For each vertex in the list of linked vertices */ + Gnum newpart; /* Move vertex from part parval to part partval2 */ + Gnum oldpart; + Gnum vertnum2; + + vertnum2 = vertlist->vertnum; + oldpart = vertlist->partval; + newpart = vertlist->partval2; + if (oldpart != newpart) + moveflag = 1; + + if ((newpart == -1) && (oldpart != -1)) { /* If the vertex will move into separator */ + grafptr->fronload += velobax[vertnum2 & velomsk]; /* Increase the frontier load */ + grafptr->fronnbr ++; /* Increase the frontier size */ + } + + if (oldpart != -1) { + grafptr->compload[oldpart] -= velobax[vertnum2 & velomsk]; /* Decrease the load of the selected part */ + grafptr->compsize[oldpart] --; /* Decrease the size of the selected part */ + + partlist[oldpart].loadgain -= velobax[vertnum2 & velomsk]; + partlist[oldpart].sizegain --; + if (partlist[oldpart].isinloadlist != 1) { + partlist[oldpart].loadprev = partlistloadptr; + partlistloadptr = partlist + oldpart; + partlist[oldpart].isinloadlist = 1; + } + } + if (newpart != -1) { + grafptr->compload[newpart] += velobax[vertnum2 & velomsk]; /* increase the load of the selected part */ + grafptr->compsize[newpart] ++; /* increase the size of the selected part */ + partlist[newpart].loadgain += velobax[vertnum2 & velomsk]; + partlist[newpart].sizegain ++; + if (partlist[newpart].isinloadlist != 1) { + partlist[newpart].loadprev = partlistloadptr; + partlistloadptr = partlist + newpart; + partlist[newpart].isinloadlist = 1; + } + } + + vertlist->partval2 = oldpart; /* exchange the old and the new parts */ + vertlist->partval = newpart; + if (savenbr >= hashsiz) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + + savetab[savenbr].type = WGRAPHSEPAFMSAVEMOVE; /* save the move */ + savetab[savenbr].u.movedata.hashnum = vertlist - hashtab; + savetab[savenbr].u.movedata.partval = vertlist->partval2; + movetab[movenbr] = savenbr; + savenbr ++; + + vertlist = vertlist->prev; + } + + while (vertlist2 != NULL) { /* for each vertex in the same list of linked vertices */ + Gnum vertnum2; + + vertnum2 = vertlist2->vertnum; + + if (vertlist2->partval2 == -1) { /* If vertex was in separator */ + WgraphPartFmLink * restrict linkptr2; + + for (linkptr2 = vertlist2->linklist; /* For each link of the vertex */ + linkptr2 != NULL; linkptr2 = linkptr2->next) { + if (linkptr2->gainlink.next != NULL) { + grafptr->compload[linkptr2->partval] -= velobax[vertnum2 & velomsk]; /* decrease the load of this part */ + grafptr->compsize[linkptr2->partval]--; /* decrease the size of this part */ + partlist[linkptr2->partval].loadgain -= velobax[vertnum2 & velomsk]; + partlist[linkptr2->partval].sizegain --; + + if (partlist[linkptr2->partval].isinloadlist != 1) { + partlist[linkptr2->partval].loadprev = partlistloadptr; + partlistloadptr = partlist + linkptr2->partval; + partlist[linkptr2->partval].isinloadlist = 1; + } + } + + if (linkptr2->gainlink.next != NULL) { + if (linkptr2->gainlink.next != (GainLink *) 1) /* If link is in gain table */ + gainTablDel (tablptr, (GainLink *) linkptr2); /* Remove link from table */ + + if (savenbr >= hashsiz) { + if (wgraphPartFmResize () != 0) { /* TODO: Check if table resizing changes linkptr2 ? */ + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + + savetab[savenbr].type = WGRAPHSEPAFMSAVELINKDEL; /* Save link removal from table */ + savetab[savenbr].u.linkdata.linknum = linkptr2 - linktab; + savetab[savenbr].u.linkdata.gain = linkptr2->gain; + movetab[movenbr] = savenbr; + savenbr ++; + } + + linkptr2->gainlink.next = NULL; + } + } + + if (vertlist2->partval == -1) { /* if vertex move (or stay) in the separator */ + Gnum gain; + Gnum minloadpartval; + Gnum minloadpartload; + Gnum secondloadpartval; + WgraphPartFmLink * restrict linklist; + WgraphPartFmLink * restrict linkptr2; + + vertnum2 = vertlist2->vertnum; + partlistptr = NULL; + gain = -1; + minloadpartval = -1; + secondloadpartval = -1; + + for (hashnum = (vertnum2 * WGRAPHSEPAFMHASHPRIME) & hashmsk; /* search the vertex in the hash table */ + hashtab[hashnum].vertnum != vertnum2; + hashnum = (hashnum + 1) & hashmsk); + + vexxptr = hashtab + hashnum; + + for (edgenum = grafptr->s.verttax[vertnum2]; /* recompute the gain */ + edgenum < grafptr->s.vendtax[vertnum2]; edgenum ++) { + WgraphPartFmVertex * vexxptr4; /* Pointer to current vertex */ + Gnum vertnum3; + + vertnum3 = grafptr->s.edgetax[edgenum]; + + for (hashnum = (vertnum3 * WGRAPHSEPAFMHASHPRIME) & hashmsk; /* search the vertex in the hash table */ + hashtab[hashnum].vertnum != vertnum3 && hashtab[hashnum].vertnum != ~0; + hashnum = (hashnum + 1) & hashmsk); + vexxptr4 = hashtab + hashnum; + + if (vexxptr4->vertnum == ~0) { /* if vertex not found */ + vexxptr4->vertnum = vertnum3; /* add it in the hash table */ + vexxptr4->partval = grafptr->parttax[vertnum3]; + vexxptr4->linklist = NULL; + hashnbr ++; + if (hashnbr >= hashmax) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + } + if (vexxptr4->partval != -1) { /* if part is not the separator */ + if (partlist[vexxptr4->partval].gain == 0) { /* and not yet linked */ + partlist[vexxptr4->partval].prev = partlistptr; /* link it */ + partlistptr = partlist + vexxptr4->partval; + + if (minloadpartval == -1 || + minloadpartload > grafptr->compload[vexxptr4->partval]) { + secondloadpartval = minloadpartval; + minloadpartval = vexxptr4->partval; + minloadpartload = grafptr->compload[minloadpartval]; + } else if (secondloadpartval != vexxptr4->partval) { + secondloadpartval = vexxptr4->partval; + } + } + + partlist[vexxptr4->partval].gain --; + gain ++; + } + } + + for (linkptr2 = vexxptr->linklist, linklist = NULL; /* For each vertex link in list */ + linkptr2 != NULL; linkptr2 = linkptr2->next) { + linklist = linkptr2; + partval2 = linkptr2->partval; + + if (partlist[partval2].gain != 0) { /* If part is linked */ + hashtab[linkptr2->hashnum].vertnum = vertnum2; + linkptr2->partval = partval2; + linkptr2->gain = gain + partlist[partval2].gain; + + if (partval2 != minloadpartval) + linkptr2->minloadpartval = minloadpartval; + else + linkptr2->minloadpartval = secondloadpartval; + linkptr2->minloadpartload = minloadpartload; + + if (hashtab[linkptr2->hashnum].lockprev == (WgraphPartFmVertex *) ~0) { /* If vertex is not locked */ + if (savenbr >= hashsiz) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + savetab[savenbr].type = WGRAPHSEPAFMSAVELINKADD; + savetab[savenbr].u.linkdata.linknum = linkptr2 - linktab; + savetab[savenbr].u.linkdata.gain = linkptr2->gain; + movetab[movenbr] = savenbr; + savenbr ++; + + gainTablAdd(tablptr, (GainLink *) linkptr2, linkptr2->gain); /* add the link in the gain table of the part */ + } + else { + if (savenbr >= hashsiz) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + + savetab[savenbr].type = WGRAPHSEPAFMSAVELINKADD; + savetab[savenbr].u.linkdata.linknum = linkptr2 - linktab; + savetab[savenbr].u.linkdata.gain = linkptr2->gain; + movetab[movenbr] = savenbr; + savenbr ++; + + linkptr2->gainlink.next = (GainLink *) 1; + } + + partlist[partval2].gain = 0; + grafptr->compload[linkptr2->partval] += velobax[hashtab[linkptr2->hashnum].vertnum & velomsk]; /* increase the load of this part */ + grafptr->compsize[linkptr2->partval] ++; /* increase the size of this part */ + partlist[linkptr2->partval].loadgain += velobax[hashtab[linkptr2->hashnum].vertnum & velomsk]; + partlist[linkptr2->partval].sizegain ++; + + if (partlist[linkptr2->partval].isinloadlist != 1) { + partlist[linkptr2->partval].isinloadlist = 1; + partlist[linkptr2->partval].loadprev = partlistloadptr; + partlistloadptr = partlist + linkptr2->partval; + } + } + } + + while (partlistptr != NULL) { /* for each part in the linked list */ + partval2 = partlistptr - partlist; + if (partlist[partval2].gain != 0) { + WgraphPartFmLink * restrict linkptr3; + + linkptr3 = linktab + linknbr; + if (linklist != NULL) /* If vertex has a list of link */ + linklist->next = linkptr3; /* Add link to the list */ + else + vexxptr->linklist = linkptr3; /* Else create the list */ + + linknbr ++; + + linkptr3->hashnum = vexxptr - hashtab; + hashtab[linkptr3->hashnum].vertnum = vertnum2; + linkptr3->partval = partval2; + linkptr3->gain = gain + partlist[partval2].gain; + + if (partval2 != minloadpartval) + linkptr3->minloadpartval = minloadpartval; + else + linkptr3->minloadpartval = secondloadpartval; + linkptr3->minloadpartload = minloadpartload; + + if (vexxptr->lockprev == (WgraphPartFmVertex *) ~0/* || linkptr3->gain == -1 */) + gainTablAdd(tablptr, (GainLink *) linkptr3, linkptr3->gain); /* add the link in the gain table of the part */ + else + linkptr3->gainlink.next = (GainLink *) 1; + + if (savenbr >= hashsiz) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + savetab[savenbr].type = WGRAPHSEPAFMSAVELINKADD; + savetab[savenbr].u.linkdata.linknum = linkptr3 - linktab; + savetab[savenbr].u.linkdata.gain = linkptr3->gain; + movetab[movenbr] = savenbr; + savenbr ++; + + linklist = linkptr3; + + grafptr->compload[partval2] += velobax[vertnum2 & velomsk]; + partlist[partval2].loadgain += velobax[vertnum2 & velomsk]; + grafptr->compsize[partval2] ++; + partlist[partval2].sizegain ++; + + if (partlist[partval2].isinloadlist != 1) { /* link the part in the load list */ + partlist[partval2].isinloadlist = 1; + partlist[partval2].loadprev = partlistloadptr; + partlistloadptr = partlist + partval2; + } + + partlist[partval2].gain = 0; + } + + partlistptr = partlistptr->prev; + partlist[partval2].prev = NULL; + } + if (linklist != NULL) + linklist->next = NULL; + } + vertlist2->linked = ~0; + vertlist2 = vertlist2->prev; + } + + while (partlistloadptr != NULL) { /* For each part in the load list */ + if (partlistloadptr->loadgain != 0) { + if (savenbr >= hashsiz) { + if (wgraphPartFmResize () != 0) { + errorPrint ("wgraphPartFm: out of memory (2)"); + return (1); + } + } + savetab[savenbr].type = WGRAPHSEPAFMSAVELOAD; /* Save load variation */ + savetab[savenbr].u.loaddata.partval = partlistloadptr - partlist; + savetab[savenbr].u.loaddata.loaddiff = partlistloadptr->loadgain; + savetab[savenbr].u.loaddata.sizediff = partlistloadptr->sizegain; + movetab[movenbr] = savenbr; + savenbr ++; + velosum += partlistloadptr->loadgain; + } + partlistloadptr->loadgain = + partlistloadptr->sizegain = + partlistloadptr->isinloadlist = 0; + partlistloadptr = partlistloadptr->loadprev; + } + + vexxptr2->lockprev = locklist; /* Lock the selected vertex */ + locklist = vexxptr2; + if (grafptr->fronload < frlobst) { + movenbr = + savenbr = + diffload = 0; + moveflag = 1; + frlobst = grafptr->fronload; + } + else if ((grafptr->fronload == frlobst) && (diffload < -1)) { + movenbr = + savenbr = + diffload = 0; + moveflag = 1; + } + else if (linkptr->minloadpartval == -1) { + movenbr = + savenbr = + diffload = 0; + } + else if ((grafptr->compload[linkptr->partval] < minload) || + (grafptr->compload[linkptr->partval] < grafptr->compload[linkptr->minloadpartval])) { + movenbr = + savenbr = + diffload = 0; + } + } + + while (locklist != NULL) { /* For each locked vertex */ + WgraphPartFmLink * restrict linkptr2; + + vexxptr = locklist; + locklist = locklist->lockprev; /* Unlock it */ + vexxptr->lockprev = (WgraphPartFmVertex *) ~0; + + for (linkptr2 = vexxptr->linklist; linkptr2 != NULL; linkptr2 = linkptr2->next) { + if (linkptr2->gainlink.next == (GainLink *) 1) + gainTablAdd(tablptr, (GainLink *) linkptr2, linkptr2->gain); /* Add link to part gain table */ + } + } + locklist = NULL; + + for ( ; movenbr > 0; movenbr --) { /* For each move to undo */ + for (savenum = movetab[movenbr]; savenum > movetab[movenbr - 1]; savenum --) { + WgraphPartFmLink * restrict linkptr2; + + switch (savetab[savenum].type) { + case WGRAPHSEPAFMSAVEMOVE : + if (savetab[savenum].u.movedata.partval == -1) + grafptr->fronload += velobax[hashtab[savetab[savenum].u.movedata.hashnum].vertnum & velomsk]; + if (hashtab[savetab[savenum].u.movedata.hashnum].partval == -1) + grafptr->fronload -= velobax[hashtab[savetab[savenum].u.movedata.hashnum].vertnum & velomsk]; + + hashtab[savetab[savenum].u.movedata.hashnum].partval = savetab[savenum].u.movedata.partval; + break; + + case WGRAPHSEPAFMSAVELINKDEL : + linkptr2 = linktab + savetab[savenum].u.linkdata.linknum; + linkptr2->gain = savetab[savenum].u.linkdata.gain; + gainTablAdd (tablptr, (GainLink *) linkptr2, linkptr2->gain); /* Add link into part gain table */ + break; + + case WGRAPHSEPAFMSAVELINKADD : + linkptr2 = linktab + savetab[savenum].u.linkdata.linknum; + if (linkptr2->gainlink.next != (GainLink *) 1) { + gainTablDel (tablptr, (GainLink *) linkptr2); /* Remove link from table */ + linkptr2->gainlink.next = NULL; + } + break; + + case WGRAPHSEPAFMSAVELOAD: + grafptr->compload[savetab[savenum].u.loaddata.partval] -= savetab[savenum].u.loaddata.loaddiff; + grafptr->compsize[savetab[savenum].u.loaddata.partval] -= savetab[savenum].u.loaddata.sizediff; + break; + } + } + } + } while ((moveflag != 0) && /* As long as vertices are moved */ + (-- passnbr > 0)); /* and we are allowed to loop */ + + grafptr->fronload = 0; + + for (vexxptr = hashtab, fronnum = 0; /* Build new frontier */ + vexxptr < hashtab + (hashmax << 2); vexxptr ++) { /* from all vertices in table */ + Gnum vertnum; + + vertnum = vexxptr->vertnum; + if (vertnum != ~0) { /* If vertex slot is used */ + Gnum partval; /* New part of current vertex */ + Gnum partold; /* Old part of current vertex */ + + partval = vexxptr->partval; + partold = grafptr->parttax[vertnum]; /* Get old part value from array */ + if (partval != partold) /* If vertex part changed */ + grafptr->parttax[vertnum] = partval; /* Set new part value */ + + if (partval == -1) + { + grafptr->fronload += velobax[vertnum & velomsk]; + grafptr->frontab[fronnum ++] = vexxptr->vertnum; + } + } + } + + grafptr->fronnbr = fronnum; + memFree (hashtab); /* Free group leader */ + gainTablExit (tablptr); + + return (0); +} + + + + +/* This routine doubles the size all of the arrays +** involved in handling the hash table and hash +** vertex arrays. +** It returns: +** - 0 : if resizing succeeded. +** - !0 : if out of memory. +*/ + +static +int +wgraphPartFmResize () + +{ + errorPrint ("wgraphPartFmResize: not implemented"); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_fm.h b/scotch_6.0.3/src/libscotch/wgraph_part_fm.h new file mode 100644 index 00000000..fcc43148 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_fm.h @@ -0,0 +1,157 @@ +/* Copyright 2007-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_fm.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the improved Fiduccia-Mattheyses **/ +/** refinement routine for the vertex over- **/ +/** lapped graph partitioning. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 30 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Gain table subbits. +*/ + +#define WGRAPHSEPAFMGAINBITS 4 + +/*+ Prime number for hashing vertex numbers. +*/ + +#define WGRAPHSEPAFMHASHPRIME 17 /*+ Prime number for hashing +*/ + +/*+ +*/ + +#define WGRAPHSEPAFMMAXPARTLOAD ((Gnum) (((Gunum) ~0) >> 1)) + +/*+ Gain table vertex status. +*/ + +#define WGRAPHSEPAFMSTATEFREE ((GainLink *) 0) /*+ Vertex is free or separator-chained +*/ +#define WGRAPHSEPAFMSTATESUCH ((GainLink *) 1) /*+ Separator vertex is used and chained +*/ +#define WGRAPHSEPAFMSTATEUSED ((GainLink *) 2) /*+ Vertex already swapped once +*/ +#define WGRAPHSEPAFMSTATELINK ((GainLink *) 3) /*+ Currently in gain table if higher +*/ + +/*+ Save type identifier +*/ + +#define WGRAPHSEPAFMSAVEMOVE 0 +#define WGRAPHSEPAFMSAVELINKDEL 1 +#define WGRAPHSEPAFMSAVELINKADD 2 +#define WGRAPHSEPAFMSAVELOAD 3 + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct WgraphPartFmParam_ { + INT movenbr; /*+ Maximum number of uneffective moves that can be done +*/ + INT passnbr; /*+ Number of passes to be performed (-1 : infinite) +*/ + double deltrat; /*+ Maximum weight imbalance ratio +*/ +} WgraphPartFmParam; + + +typedef struct WgraphPartFmPartList_ { + struct WgraphPartFmPartList_ * prev; + Gnum gain; + struct WgraphPartFmPartList_ * loadprev; + Gnum loadgain; + Gnum sizegain; + Gnum isinloadlist; +} WgraphPartFmPartList; + +typedef struct WgraphPartFmVertex_ { + Gnum partval; /*+ Vertex part TRICK: same type as vertload +*/ + Gnum partval2; /*+ Vertex part into which the current vertex moves +*/ + Gnum vertnum; /*+ Number of vertex in hash table +*/ + struct WgraphPartFmVertex_ * prev; + struct WgraphPartFmLink_ * linklist; + Gnum linked; + struct WgraphPartFmVertex_ * lockprev; +} WgraphPartFmVertex; + +/*+ The move recording structure. +*/ + +typedef struct WgraphPartFmLink_ { + GainLink gainlink; /*+ Gain link: FIRST +*/ + Gnum partval; + Gnum hashnum; + Gnum gain; + struct WgraphPartFmLink_ * next; + Gnum minloadpartval; + Gnum minloadpartload; +} WgraphPartFmLink; + +typedef struct WgraphPartFmSave_ { + Gnum type; + union { + struct { + Gnum hashnum; /*+ Number of hash slot for saved vertex +*/ + Gnum partval; /*+ Saved vertex part value +*/ + } movedata; + struct { + Gnum linknum; + Gnum gain; + } linkdata; + struct { + Gnum loaddiff; + Gnum sizediff; + Gnum partval; + } loaddata; + } u; +} WgraphPartFmSave; + +/* +** The function prototypes. +*/ + +#ifndef WGRAPH_PART_FM +#define static +#endif + +int wgraphPartFm (Wgraph * const, const WgraphPartFmParam * const); + +static int wgraphPartFmResize (); +static int wgraphPartFmCheck (const Wgraph * restrict const, const WgraphPartFmVertex * restrict const, Gnum, const Gnum, const Gnum); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_gg.c b/scotch_6.0.3/src/libscotch/wgraph_part_gg.c new file mode 100644 index 00000000..2bf6179d --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_gg.c @@ -0,0 +1,330 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_gg.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : This module is the vertex overlapped **/ +/** graph partitioning rountine based on **/ +/** a vertex-oriented version of the Greedy **/ +/** Graph Growing algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 14 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH_PART_GG + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "graph.h" +#include "wgraph.h" +#include "wgraph_part_gg.h" + +/* +** The static variables. +*/ + +static const Gnum wgraphpartggloadone = 1; + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +wgraphPartGg ( +Wgraph * restrict const wgrafptr, /*+ Separation graph +*/ +const WgraphPartGgParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum i; + Gnum gain; + Gnum fronnbr; /* Number of frontier vertices */ + Gnum fronload; /* Load of frontier vertices */ + Gnum frlobst; /* Best frontier load found */ + Gnum fronnum; + Gnum partval; + Gnum vertnum; + Gnum vertnum2; + Gnum vertnum3; + Gnum edgenum; + Gnum edgenum2; + Gnum palooth; /* Load of vertices in the remained unassigned part */ + Gnum paloexc; /* Load of vertices in the current part excepting the frontier */ + Gnum frloprt; /* Load of vertices in the frontier of the current part */ + Gnum passnum; + Gnum velomsk; + const Gnum * restrict velobax; /* Data for handling of optional arrays */ + Gnum * restrict permtab; /* permutation table */ + Gnum * restrict parttax; + Gnum * restrict compload; /* Array of part load */ + Gnum * restrict compsize; /* Array of part vertices number */ + GainTabl * restrict tabl; /* Pointer to gain table */ + WgraphPartGgVertex * vexxtax; /* Complementary vertex array */ + GainLink * restrict gainlinkptr; + WgraphPartGgVertex * restrict vertlist; /* List of vertices */ + + printf("GG (%d)\n", wgrafptr->s.vertnbr); + + if (((tabl = gainTablInit (GAIN_LINMAX, WGRAPHSEPAGGSUBBITS)) == NULL) || /* Use logarithmic array only */ + memAllocGroup((void **) (void *) + &vexxtax, (size_t) (wgrafptr->s.vertnbr * sizeof (WgraphPartGgVertex)), + &compload, (size_t) (wgrafptr->partnbr * sizeof (Gnum)), + &compsize, (size_t) (wgrafptr->partnbr * sizeof (Gnum)), + &parttax, (size_t) (wgrafptr->s.vertnbr * sizeof (Gnum)), + &permtab, (size_t) (wgrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("wgraphPartGg: out of memory (1)"); + gainTablExit (tabl); + return (1); + } + + vexxtax -= wgrafptr->s.baseval; /* Base access to vexxtax */ + parttax -= wgrafptr->s.baseval; /* Base access to parttax */ + + + for (vertnum = 0; vertnum < wgrafptr->s.vertnbr; vertnum ++) { /* Initialization of the permutation table */ + i = intRandVal (vertnum + 1); + permtab[vertnum] = permtab[i]; + permtab[i] = vertnum; + } + + if (wgrafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ + velobax = &wgraphpartggloadone; /* In case vertices not weighted (least often) */ + velomsk = 0; + } + else { + velobax = wgrafptr->s.velotax; + velomsk = ~((Gnum) 0); + } + + frlobst = wgrafptr->s.velosum + 1; + for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { + + fronload = + fronnbr = 0; + vertnum = -1; + palooth = wgrafptr->s.velosum; + + memSet (compload, 0, wgrafptr->partnbr * sizeof (Gnum)); + memSet (compsize, 0, wgrafptr->partnbr * sizeof (Gnum)); + memSet (parttax + wgrafptr->s.baseval, 0, wgrafptr->s.vertnbr * sizeof (Gnum)); + memSet (vexxtax + wgrafptr->s.baseval, 0, wgrafptr->s.vertnbr * sizeof (WgraphPartGgVertex)); + + gainTablFree (tabl); + + for (partval = 0; partval < wgrafptr->partnbr; partval ++) { + + paloexc = + frloprt = 0; + + gainlinkptr = gainTablFrst (tabl); /* Try to take a vertex from the frontier of the last part */ + gainTablFree (tabl); + if (gainlinkptr != NULL) { /* If the table was not empty */ + vertnum = (WgraphPartGgVertex *) gainlinkptr - vexxtax; + + for (edgenum = wgrafptr->s.verttax[vertnum]; /* search a neighbor vertex that is in the part 0 */ + edgenum < wgrafptr->s.vendtax[vertnum]; edgenum ++) { + vertnum2 = wgrafptr->s.edgetax[edgenum]; + if (parttax[vertnum2] == 0) { + gainTablAdd(tabl, &(vexxtax[vertnum2].gainlink), 0); /* Add it in the table in order to be selected */ + /* (the table will contain only this vertex) */ + + fronnbr ++; + parttax[vertnum2] = -1; /* Move it in the seperator */ + fronload += velobax[vertnum2 & velomsk]; + compload[partval] += velobax[vertnum2 & velomsk]; + compsize[partval] ++; + break; + } + } + } + + do { /* While the part is not big enought */ + + gainlinkptr = gainTablFrst(tabl); + if (gainlinkptr != NULL) { + vertnum = (WgraphPartGgVertex *) gainlinkptr - vexxtax; + gainTablDel(tabl, gainlinkptr); + } + else { /* If the table was empty */ + if ((2 * (paloexc + frloprt / 2)) * (wgrafptr->partnbr - partval + 1) <= palooth) { /* If the part load is not big enought */ + for (i = 0; i < wgrafptr->s.vertnbr; i ++) { /* select a random vertex in the part 0 */ + Gnum pos = i + intRandVal (wgrafptr->s.vertnbr - i); + + vertnum = permtab[pos]; + permtab[pos] = permtab[i]; + permtab[i] = vertnum; + vertnum += wgrafptr->s.baseval; + if (parttax[vertnum] == 0) { + for (edgenum = wgrafptr->s.verttax[vertnum]; edgenum < wgrafptr->s.vendtax[vertnum]; edgenum ++) { + vertnum2 = wgrafptr->s.edgetax[edgenum]; + if (parttax[vertnum2] > 0) { + break; + } + } + break; + } + } + fronload += velobax[vertnum & velomsk]; + frloprt += velobax[vertnum & velomsk]; + compload[partval] += velobax[vertnum & velomsk]; + parttax[vertnum] = -1; + compsize[partval] ++; + fronnbr ++; + } + else + break; + } + + fronnbr --; + frloprt -= velobax[vertnum & velomsk]; + fronload -= velobax[vertnum & velomsk]; + paloexc += velobax[vertnum & velomsk]; + parttax[vertnum] = partval; + vertlist = NULL; + + for (edgenum = wgrafptr->s.verttax[vertnum]; edgenum < wgrafptr->s.vendtax[vertnum]; edgenum ++) { + vertnum2 = wgrafptr->s.edgetax[edgenum]; + if ((parttax[vertnum2] != -1) && (parttax[vertnum2] != partval)) { /* If the vertex is in a different part */ + fronnbr ++; + parttax[vertnum2] = -1; /* Move the vertex in the separator */ + fronload += velobax[vertnum2 & velomsk]; + frloprt += velobax[vertnum2 & velomsk]; + compload[partval] += velobax[vertnum2 & velomsk]; + compsize[partval] ++; + + vexxtax[vertnum2].partlvl = partval; /* Label the vertex for this part */ + vexxtax[vertnum2].prev = vertlist; /* Add the vertex in the list */ + vertlist = vexxtax + vertnum2; + + } else if (parttax[vertnum2] == -1) { + if (vexxtax[vertnum2].partlvl == partval) { /* If the vertex is labeled for the current part */ + if (vexxtax[vertnum2].gainlink.next != (GainLink * )~0) { /* If the vertex is in the table */ + gainTablDel(tabl, &(vexxtax[vertnum2].gainlink)); /* Remove it from table */ + + vexxtax[vertnum2].prev = vertlist; /* Add the vertex in the list */ + vertlist = vexxtax + vertnum2; + } + } + else { + frloprt += velobax[vertnum2 & velomsk]; + compload[partval] += velobax[vertnum2 & velomsk]; + compsize[partval] ++; + vexxtax[vertnum2].partlvl = partval; /* Label it for the part */ + vexxtax[vertnum2].gainlink.next = (GainLink * )~0; + } + } + } + + while (vertlist != NULL) { /* For eack linked vertices */ + + vertnum2 = vertlist - vexxtax; + gain = - velobax[vertnum2 & velomsk]; /* Compute gain */ + for (edgenum2 = wgrafptr->s.verttax[vertnum2]; + edgenum2 < wgrafptr->s.vendtax[vertnum2]; edgenum2 ++) { + vertnum3 = wgrafptr->s.edgetax[edgenum2]; + if ((parttax[vertnum3] != -1) && (parttax[vertnum3] != partval)) { + gain += velobax[vertnum3 & velomsk]; + } + } + + gainTablAdd(tabl, &(vertlist->gainlink), gain); /* Add the vertex in the table */ + vertlist = vertlist->prev; + } + } while ((paloexc + frloprt / 2) * (wgrafptr->partnbr - partval + 1) <= palooth); /* While the part is not big enought */ + + palooth -= (paloexc + frloprt / 2); + } + + compload[0] = + compsize[0] = 0; + for (vertnum = wgrafptr->s.baseval; vertnum < wgrafptr->s.vertnnd; vertnum++) { /* Recompute load and size of part 0 */ + if (parttax[vertnum] == 0) { + compload[0] += velobax[vertnum & velomsk]; + compsize[0] ++; + } + else if (parttax[vertnum] == -1) { + for (edgenum = wgrafptr->s.verttax[vertnum]; + edgenum < wgrafptr->s.vendtax[vertnum]; edgenum ++) { + vertnum2 = wgrafptr->s.edgetax[edgenum]; + if (parttax[vertnum2] == 0) { + compload[0] += velobax[vertnum & velomsk]; + compsize[0] ++; + break; + } + } + } + } + + if (frlobst > fronload) { /* If the pass frontier load is better than the better one */ + + wgrafptr->fronnbr = fronnbr; + wgrafptr->fronload = fronload; + memCpy (wgrafptr->compload, compload, sizeof (Gnum) * wgrafptr->partnbr); + memCpy (wgrafptr->compsize, compsize, sizeof (Gnum) * wgrafptr->partnbr); + memCpy (wgrafptr->parttax + wgrafptr->s.baseval, parttax + wgrafptr->s.baseval, sizeof (Gnum) * wgrafptr->s.vertnbr); + + + for (vertnum = wgrafptr->s.baseval, fronnum = 0; vertnum < wgrafptr->s.vertnnd; vertnum ++) { /* Recompute frontab */ + if (parttax[vertnum] == -1) + wgrafptr->frontab[fronnum ++] = vertnum; + } + + frlobst = fronload; /* This frontier load will the best found */ + } + } + + for (partval = 0; partval < wgrafptr->partnbr; partval ++) + printf("\033[0;33mcompload[%d] %d %d\033[0m\n", partval, wgrafptr->compload[partval], wgrafptr->compsize[partval]); + memFree(vexxtax + wgrafptr->s.baseval); /* Free work arrays */ + gainTablExit (tabl); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_gg.h b/scotch_6.0.3/src/libscotch/wgraph_part_gg.h new file mode 100644 index 00000000..a81ba824 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_gg.h @@ -0,0 +1,92 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_gg.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the graph partitioning rountine **/ +/** based on a vertex-oriented version of **/ +/** the Greedy Graph Growing algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ System-defined constants. +*/ + +#define WGRAPHSEPAGGSUBBITS 4 + +#define WGRAPHGGCHOOSELASTPART + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct WgraphPartGgParam_ { + INT passnbr; /*+ Number of passes to do +*/ +} WgraphPartGgParam; + +/*+ The complementary vertex structure. For + trick reasons, the gain table data structure + must be the first field of the structure. +*/ + +typedef struct WgraphPartGgVertex_ { + GainLink gainlink; /*+ Gain link: FIRST +*/ + Gnum partlvl; + struct WgraphPartGgVertex_ * prev; + struct WgraphPartGgVertex_ * next; +} WgraphPartGgVertex; + +/* +** The function prototypes. +*/ + +#ifndef WGRAPH_PART_GG +#define static +#endif + +int wgraphPartGg (Wgraph * restrict const, const WgraphPartGgParam * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_gp.c b/scotch_6.0.3/src/libscotch/wgraph_part_gp.c new file mode 100644 index 00000000..cf1eb43e --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_gp.c @@ -0,0 +1,306 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_gp.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : This module is the vertex overlapped **/ +/** graph partitioning rountine based on **/ +/** a vertex-oriented version of the Gibbs- **/ +/** Poole-Stockmeyer algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 14 mar 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH_PART_GP + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "wgraph.h" +#include "wgraph_part_gp.h" + +/* +** The static variables. +*/ + +static const Gnum wgraphpartgploadone = 1; + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the bipartitioning. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +wgraphPartGp ( +Wgraph * restrict const wgrafptr, /*+ Separation graph +*/ +const WgraphPartGpParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum i; + Gnum head; + Gnum tail; + Gnum fronnum; + Gnum fronnbr; /* number of frontier vertices */ + Gnum fronload; /* load of frontier vertices */ + Gnum frlobst; /* best frontier load found */ + Gnum partval; + Gnum vertnum; + Gnum vertnum2; + Gnum edgenum; + Gnum palooth; /* load of vertices in the remained unassigned part */ + Gnum paloexc; /* load of vertices in the current part excepting the frontier */ + Gnum frloprt; /* load of vertices in the frontier of the current part */ + Gnum passnum; + Gnum velomsk; + const Gnum * restrict velobax; /* Data for handling of optional arrays */ + Gnum * restrict compload; /* array of part load */ + Gnum * restrict compsize; /* array of part vertices number */ + Gnum * restrict permtab; /* permutation table */ + Gnum * restrict stack; /* Pointer to stack */ + Gnum * restrict parttax; + WgraphPartGpVertex * vexxtax; /* Complementary vertex array */ + WgraphPartGpVertex * restrict vertlist; /* list of vertices */ + + if (memAllocGroup((void **) (void *) + &vexxtax, (size_t) (wgrafptr->s.vertnbr * sizeof (WgraphPartGpVertex)), + &compload, (size_t) (wgrafptr->partnbr * sizeof (Gnum)), + &compsize, (size_t) (wgrafptr->partnbr * sizeof (Gnum)), + &stack , (size_t) (wgrafptr->s.vertnbr * sizeof (Gnum)), + &parttax, (size_t) (wgrafptr->s.vertnbr * sizeof (Gnum)), + &permtab, (size_t) (wgrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { + errorPrint ("wgraphPartGp: out of memory (1)"); + return (1); + } + + vexxtax -= wgrafptr->s.baseval; /* Base access to vexxtax */ + parttax -= wgrafptr->s.baseval; /* Base access to parttax */ + + for (vertnum = 0; vertnum < wgrafptr->s.vertnbr; vertnum ++) { /* Initialization of the permutation table */ + i = intRandVal (vertnum + 1); + permtab[vertnum] = permtab[i]; + permtab[i] = vertnum; + } + + if (wgrafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ + velobax = &wgraphpartgploadone; /* In case vertices not weighted (least often) */ + velomsk = 0; + } + else { + velobax = wgrafptr->s.velotax; + velomsk = ~((Gnum) 0); + } + + frlobst = wgrafptr->s.velosum + 1; /* The first solution that will be found will be better than frlobst */ + + for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { + fronnbr = /* Begin with empty separators */ + fronload = 0; + vertnum = -1; + palooth = wgrafptr->s.velosum; + + memSet (compload, 0, wgrafptr->partnbr * sizeof (Gnum)); + memSet (compsize, 0, wgrafptr->partnbr * sizeof (Gnum)); + memSet (parttax + wgrafptr->s.baseval, 0, wgrafptr->s.vertnbr * sizeof (Gnum)); + memSet (vexxtax + wgrafptr->s.baseval, 0, wgrafptr->s.vertnbr * sizeof (WgraphPartGpVertex)); + + head = + tail = 0; + for (partval = 0; partval < wgrafptr->partnbr; partval ++) { + frloprt = + paloexc = 0; + if (tail > head) /* try to take a vertex from the frontier of the last part */ + vertnum = stack[tail % wgrafptr->s.vertnbr]; + else + vertnum = -1; + + head = + tail = 0; + if (vertnum != -1) { /* if the stack was not empty */ + for (edgenum = wgrafptr->s.verttax[vertnum]; /* search a neighbor vertex that is in the part 0 */ + edgenum < wgrafptr->s.vendtax[vertnum]; edgenum ++) { + vertnum2 = wgrafptr->s.edgetax[edgenum]; + if (parttax[vertnum2] == 0) { + fronnbr ++; + compsize[partval] ++; + parttax[vertnum2] = -1; /* move it in the seperator */ + fronload += velobax[vertnum2 & velomsk]; /* update load and size of parts */ + compload[partval] += velobax[vertnum2 & velomsk]; + vexxtax[vertnum2].isinstack = 0; + stack[(head ++) % (wgrafptr->s.vertnbr)] = vertnum2; + break; + } + } + } + + do { /* while the part is not big enought */ + if (head > tail) /* select a vertex */ + vertnum = stack[tail % wgrafptr->s.vertnbr]; + else + vertnum = -1; + + if (vertnum != -1) { + tail ++; + } + else /* if the stack was empty */ + { + if ((2 * (paloexc + frloprt / 2)) * (wgrafptr->partnbr - partval + 1) <= palooth) { /* if the part load is not big enought */ + for (i = 0; i < wgrafptr->s.vertnbr; i ++) { /* select a random vertex in the part 0 */ + Gnum pos = i + intRandVal (wgrafptr->s.vertnbr - i); + + vertnum = permtab[pos]; + permtab[pos] = permtab[i]; + permtab[i] = vertnum; + vertnum += wgrafptr->s.baseval; + if (parttax[vertnum] == 0) { + for (edgenum = wgrafptr->s.verttax[vertnum]; edgenum < wgrafptr->s.vendtax[vertnum]; edgenum ++) { + vertnum2 = wgrafptr->s.edgetax[edgenum]; + if (parttax[vertnum2] > 0) { + break; + } + } + break; + } + } + fronnbr ++; + parttax[vertnum] = -1; + frloprt += velobax[vertnum & velomsk]; + fronload += velobax[vertnum & velomsk]; + compload[partval] += velobax[vertnum & velomsk]; + compsize[partval] ++; + } + else + break; + } + fronnbr --; + vertlist = NULL; + parttax[vertnum] = partval; /* Move selected vertex in the current part */ + paloexc += velobax[vertnum & velomsk]; + frloprt -= velobax[vertnum & velomsk]; + fronload -= velobax[vertnum & velomsk]; + + for (edgenum = wgrafptr->s.verttax[vertnum]; edgenum < wgrafptr->s.vendtax[vertnum]; edgenum ++) { + vertnum2 = wgrafptr->s.edgetax[edgenum]; /* for each neighbor vertex */ + + if (parttax[vertnum2] != -1 && parttax[vertnum2] != partval) { + parttax[vertnum2] = -1; /* Move the part in the separator */ + fronnbr ++; + fronload += velobax[vertnum2 & velomsk]; + frloprt += velobax[vertnum2 & velomsk]; + compload[partval] += velobax[vertnum2 & velomsk]; + compsize[partval] ++; + vexxtax[vertnum2].partlvl = partval; /* Label the vertex for this part */ + vexxtax[vertnum2].prev = vertlist; /* Add the vertex in the list */ + vertlist = vexxtax + vertnum2; + + } else if (parttax[vertnum2] == -1) { /* If the vertex is in the separator */ + if (vexxtax[vertnum2].partlvl == partval) { + if (vexxtax[vertnum2].isinstack != 1) { /* If the vertex is in the stack */ + } + } + else { /* If the vertex is not labeled for the current part */ + frloprt += velobax[vertnum2 & velomsk]; + compload[partval] += velobax[vertnum2 & velomsk]; + compsize[partval] ++; + vexxtax[vertnum2].partlvl = partval; /* Label it for the part */ + vexxtax[vertnum2].isinstack = 1; + } + } + } + + while (vertlist != NULL) { /* For eack linked vertices */ + vertnum2 = vertlist - vexxtax; + stack[head ++ % wgrafptr->s.vertnbr] = vertnum2; + vexxtax[vertnum2].isinstack = 0; + vertlist = vertlist->prev; + } + + } while ((paloexc + frloprt / 2) * (wgrafptr->partnbr - partval + 1) <= palooth); /* While the part is not big enought */ + palooth -= (paloexc + frloprt / 2); + } + + compload[0] = + compsize[0] = 0; + for (vertnum = wgrafptr->s.baseval; vertnum < wgrafptr->s.vertnnd; vertnum ++) { /* Recompute load and size of part 0 */ + if (parttax[vertnum] == 0) { + compload[0] += velobax[vertnum & velomsk]; + compsize[0] ++; + } else if (parttax[vertnum] == -1) { + for (edgenum = wgrafptr->s.verttax[vertnum]; + edgenum < wgrafptr->s.vendtax[vertnum]; edgenum ++) { + vertnum2 = wgrafptr->s.edgetax[edgenum]; + if (parttax[vertnum2] == 0) { + compload[0] += velobax[vertnum & velomsk]; + compsize[0] ++; + break; + } + } + } + } + + if (frlobst > fronload) { /* If the pass frontier load is better than the better one */ + wgrafptr->fronnbr = fronnbr; + wgrafptr->fronload = fronload; + memCpy (wgrafptr->compload, compload, sizeof (Gnum) * wgrafptr->partnbr); + memCpy (wgrafptr->compsize, compsize, sizeof (Gnum) * wgrafptr->partnbr); + memCpy (wgrafptr->parttax + wgrafptr->s.baseval, parttax + wgrafptr->s.baseval, sizeof (Gnum) * wgrafptr->s.vertnbr); + for (vertnum = wgrafptr->s.baseval, fronnum = 0; vertnum < wgrafptr->s.vertnnd; vertnum ++) { /* Recompute frontab */ + if (parttax[vertnum] == -1) + wgrafptr->frontab[fronnum ++] = vertnum; + } + frlobst = fronload; + } + } + for (partval = 0; partval < wgrafptr->partnbr; partval ++) /* for each part */ + printf("\033[0;33mcompload[%d] %d %d\033[0m\n", partval, wgrafptr->compload[partval], wgrafptr->compsize[partval]); + printf("\033[0;33mfronload %d %d\033[0m\n", wgrafptr->fronload, wgrafptr->fronnbr); + memFree(vexxtax + wgrafptr->s.baseval); /* Free work arrays */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_gp.h b/scotch_6.0.3/src/libscotch/wgraph_part_gp.h new file mode 100644 index 00000000..51fe6414 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_gp.h @@ -0,0 +1,90 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_gp.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** for the graph partitioning rountine **/ +/** based on a vertex-oriented version of **/ +/** the Gibbs-Poole-Stockmeyer algorithm. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 04 nov 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ System-defined constants. +*/ + +#define WGRAPHSEPAGPSUBBITS 4 + +#define WGRAPHGPCHOOSELASTPART + +/* +** The type and structure definitions. +*/ + +/*+ Method parameters. +*/ + +typedef struct WgraphPartGpParam_ { + INT passnbr; /*+ Number of passes to do +*/ +} WgraphPartGpParam; + +/*+ The complementary vertex structure. +*/ + +typedef struct WgraphPartGpVertex_ { + Gnum partlvl; + struct WgraphPartGpVertex_ * prev; + struct WgraphPartGpVertex_ * next; + Gnum isinstack; +} WgraphPartGpVertex; + +/* +** The function prototypes. +*/ + +#ifndef WGRAPH_PART_GP +#define static +#endif + +int wgraphPartGp (Wgraph * restrict const, const WgraphPartGpParam * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_ml.c b/scotch_6.0.3/src/libscotch/wgraph_part_ml.c new file mode 100644 index 00000000..270776f3 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_ml.c @@ -0,0 +1,317 @@ +/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_ml.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module conducts multilevel framew- **/ +/** ork for the vertex overlapped graph pa- **/ +/** rtitioning. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to 16 apr 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH_PART_ML + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "graph_coarsen.h" +#include "wgraph.h" +#include "wgraph_part_ml.h" +#include "wgraph_part_st.h" + +/* +** The static variables. +*/ + +static const Gnum wgraphpartmlloadone = 1; + +/*********************************************/ +/* */ +/* The coarsening and uncoarsening routines. */ +/* */ +/*********************************************/ + +/* This routine builds a coarser graph from the +** graph that is given on input. The coarser +** graphs differ at this stage from classical +** active graphs as their internal gains are not +** yet computed. +** It returns: +** - 0 : if the coarse graph has been built. +** - 1 : if threshold achieved or on error. +*/ + +static +int +wgraphPartMlCoarsen ( +const Wgraph * restrict const finegrafptr, /*+ Finer graph +*/ +Wgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ +GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ +const WgraphPartMlParam * const paraptr) /*+ Method parameters +*/ +{ + if (graphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, + (paraptr->coarnbr * finegrafptr->partnbr), + paraptr->coarval, NULL, NULL, 0, NULL) != 0) + return (1); /* Return if coarsening failed */ + + coargrafptr->parttax = NULL; /* Do not allocate partition data yet */ + coargrafptr->compload = NULL; + coargrafptr->partnbr = finegrafptr->partnbr; + coargrafptr->levlnum = finegrafptr->levlnum + 1; /* Graph level is coarsening level */ + + return (0); +} + +/* This routine propagates the separation of the +** coarser graph back to the finer graph, according +** to the multinode table of collapsed vertices. +** After the separation is propagated, it finishes +** to compute the parameters of the finer graph that +** were not computed at the coarsening stage. +** It returns: +** - 0 : if coarse graph data has been propagated to fine graph. +** - !0 : on error. +*/ + +static +int +wgraphPartMlUncoarsen ( +Wgraph * restrict const finegrafptr, /*+ Finer graph +*/ +const Wgraph * restrict const coargrafptr, /*+ Coarser graph +*/ +const GraphCoarsenMulti * restrict const coarmulttax) /*+ Multinode array +*/ +{ + Gnum coarvertnum; /* Number of current coarse vertex */ + const Anum * restrict coarparttax; + Anum * restrict fineparttax; + Gnum * restrict finefrontab; + Gnum finefronnbr; /* Number of frontier vertices in fine graph */ + Gnum finevertnum; + WgraphPartList * restrict finelisttab; + Gnum finevelomsk; + const Gnum * restrict finevelobax; /* Data for handling of optional arrays */ + Gnum * restrict finecompload; + Gnum * restrict finecompsize; + + const Gnum * restrict const fineverttax = finegrafptr->s.verttax; + const Gnum * restrict const finevendtax = finegrafptr->s.vendtax; + const Gnum * restrict const fineedgetax = finegrafptr->s.edgetax; + + if ((finegrafptr->levlnum > 0) && /* If partition data not yet allocated */ + (wgraphAlloc (finegrafptr) != 0)) { /* Allocate tables before processing */ + errorPrint ("wgraphPartMlUncoarsen: out of memory (1)"); + return (1); + } + + if (coargrafptr == NULL) { /* If no coarse graph provided */ + wgraphZero (finegrafptr); + return (0); + } + + finecompload = finegrafptr->compload; + finecompsize = finegrafptr->compsize; + + if ((finelisttab = (WgraphPartList *) memAlloc ((finegrafptr->partnbr + 1) * sizeof (WgraphPartList))) == NULL) { /* TRICK: "+1" to create slot for a "-1" index */ + errorPrint ("wgraphPartMlUncoarsen: out of memory (2)"); + return (1); + } + finelisttab ++; /* TRICK: Trim array so that finelisttab[-1] is valid */ + memSet (finelisttab, ~0, finegrafptr->partnbr * sizeof (WgraphPartList)); /* Set vertex indices to ~0 */ + + memSet (finecompload, 0, finegrafptr->partnbr * sizeof (Gnum)); /* Reset load arrays to 0 */ + memSet (finecompsize, 0, finegrafptr->partnbr * sizeof (Gnum)); + + if (finegrafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ + finevelobax = &wgraphpartmlloadone; /* In case vertices not weighted */ + finevelomsk = 0; + } + else { + finevelobax = finegrafptr->s.velotax; + finevelomsk = ~((Gnum) 0); + } + + finefronnbr = 0; + finefrontab = finegrafptr->frontab; + fineparttax = finegrafptr->parttax; + coarparttax = coargrafptr->parttax; + for (coarvertnum = coargrafptr->s.baseval; coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { + Anum coarpartval; /* Value of current multinode part */ + Gnum finevertnum0; + Gnum finevertnum1; + + coarpartval = coarparttax[coarvertnum]; + finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; + finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; + fineparttax[finevertnum0] = coarpartval; + + if (coarpartval >= 0) { /* If vertex is not in separator */ + if (finevertnum0 != finevertnum1) + fineparttax[finevertnum1] = coarpartval; + } + else { /* Vertex is in separator */ + finefrontab[finefronnbr ++] = finevertnum0; + if (finevertnum0 != finevertnum1) { + fineparttax[finevertnum1] = coarpartval; + finefrontab[finefronnbr ++] = finevertnum1; /* One extra vertex in separator */ + } + } + } + finegrafptr->fronnbr = finefronnbr; + finegrafptr->fronload = coargrafptr->fronload; + + for (finevertnum = finegrafptr->s.baseval; finevertnum < finegrafptr->s.vertnnd; finevertnum ++) { + Anum finepartval; + + finepartval = fineparttax[finevertnum]; + if (finepartval >= 0) { + finecompload[finepartval] += finevelobax[finevertnum & finevelomsk]; + finecompsize[finepartval] ++; + } + else { /* Fine vertex is in separator */ + Gnum finelistidx; /* Index of first neighbor part */ + Gnum fineedgenum; + Gnum fineveloval; + + finelistidx = -1; /* No neighboring parts recorded yet */ + finelisttab[-1].vertnum = finevertnum; /* Separator neighbors will not be considered */ + for (fineedgenum = fineverttax[finevertnum]; + fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { /* Compute gain */ + Gnum finevertend; + Anum finepartend; + + finevertend = fineedgetax[fineedgenum]; + finepartend = fineparttax[finevertend]; + if (finelisttab[finepartend].vertnum != finevertnum) { /* If part not yet considered */ + finelisttab[finepartend].vertnum = finevertnum; /* Link it in list of neighbors */ + finelisttab[finepartend].nextidx = finelistidx; + finelistidx = finepartend; + } + } + + fineveloval = finevelobax[finevertnum & finevelomsk]; + + while (finelistidx != -1) { /* For all neighboring parts found */ + finecompload[finelistidx] += fineveloval; /* Add load of separator vertex to part */ + finecompsize[finelistidx] ++; + finelistidx = finelisttab[finelistidx].nextidx; + } + } + } + + memFree (finelisttab - 1); /* TRICK: free array using its real beginning */ + +#ifdef SCOTCH_DEBUG_WGRAPH2 + if (wgraphCheck (finegrafptr) != 0) { + errorPrint ("wgraphPartMlUncoarsen: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_WGRAPH2 */ + + return (0); +} + +/* This routine recursively performs the partitioning. +** It returns: +** - 0 : if separator could be computed. +** - !0 : on error. +*/ + +static +int +wgraphPartMl2 ( +Wgraph * restrict const grafptr, +const WgraphPartMlParam * const paraptr) +{ + Wgraph coargrafdat; + GraphCoarsenMulti * restrict coarmulttax; + int o; + + if (wgraphPartMlCoarsen (grafptr, &coargrafdat, &coarmulttax, paraptr) == 0) { + if (((o = wgraphPartMl2 (&coargrafdat, paraptr)) == 0) && + ((o = wgraphPartMlUncoarsen (grafptr, &coargrafdat, coarmulttax)) == 0) && + ((o = wgraphPartSt (grafptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ + errorPrint ("wgraphPartMl2: cannot apply ascending strategy"); + wgraphExit (&coargrafdat); + } + else { /* Cannot coarsen due to lack of memory or error */ + if (((o = wgraphPartMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ + ((o = wgraphPartSt (grafptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ + errorPrint ("wgraphPartMl2: cannot apply low strategy"); + } + + return (o); +} + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine performs the muti-level separation. +** It returns: +** - 0 : if separator could be computed. +** - 1 : on error. +*/ + +int +wgraphPartMl ( +Wgraph * const wgrafptr, /*+ Vertex-separation graph +*/ +const WgraphPartMlParam * const paraptr) /*+ Method parameters +*/ +{ + Gnum levlnum; /* Save value for graph level */ + int o; + + levlnum = wgrafptr->levlnum; /* Save graph level */ + wgrafptr->levlnum = 0; /* Initialize coarsening level */ + o = wgraphPartMl2 (wgrafptr, paraptr); /* Perform multi-level separation */ + wgrafptr->levlnum = levlnum; /* Restore graph level */ + + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_ml.h b/scotch_6.0.3/src/libscotch/wgraph_part_ml.h new file mode 100644 index 00000000..386066f0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_ml.h @@ -0,0 +1,77 @@ +/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_ml.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : These lines are the data declarations **/ +/** multilevel framework for the vertex **/ +/** overlapped graph partitioning. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 16 apr 2011 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct WgraphPartMlParam_ { + INT coarnbr; /*+ Minimum number of vertices per part +*/ + double coarval; /*+ Coarsening ratio +*/ + Strat * stratlow; /*+ Strategy at lowest level +*/ + Strat * stratasc; /*+ Strategy at ascending levels +*/ +} WgraphPartMlParam; + +/* +** The function prototypes. +*/ + +#ifndef WGRAPH_PART_ML +#define static +#endif + +static int wgraphPartMlCoarsen (const Wgraph * const, Wgraph * const, GraphCoarsenMulti * restrict * const, const WgraphPartMlParam * const); +static int wgraphPartMlUncoarsen (Wgraph * const, const Wgraph * const, const GraphCoarsenMulti * restrict const); + +int wgraphPartMl (Wgraph * const, const WgraphPartMlParam * const); +static int wgraphPartMl2 (Wgraph * const, const WgraphPartMlParam * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_rb.c b/scotch_6.0.3/src/libscotch/wgraph_part_rb.c new file mode 100644 index 00000000..3e1d0b05 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_rb.c @@ -0,0 +1,378 @@ +/* Copyright 2010,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_rb.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module performs the vertex overla- **/ +/** pped graph partitioning based on recur- **/ +/** sive bipartitioning approach. **/ +/** **/ +/** DATES : # Version 6.0 : from : 16 mar 2010 **/ +/** to 12 aug 2014 **/ +/** **/ +/** NOTES : # This code derives from the code of **/ +/** kgraph_map_rb_part.c for the vertex **/ +/** overlapped graph partitioning. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH_PART_RB + +#include "module.h" +#include "common.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "arch_cmplt.h" +#include "mapping.h" +#include "vgraph.h" +#include "vgraph_separate_st.h" +#include "vgraph_separate_zr.h" +#include "wgraph.h" +#include "wgraph_part_rb.h" +#include "scotch.h" + +/* +** The static variables. +*/ + +static const Gnum wgraphpartrbloadone = 1; + +/********************************************/ +/* */ +/* This is the entry point for the vertex */ +/* overlapped graph partitioning based on */ +/* recursive bipartitioning approach. */ +/* */ +/********************************************/ + +/* This routine runs recursive +** bipartitioning approach. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +static +int +wgraphPartRb3 ( +const Graph * restrict const orggrafptr, /* Graph to induce and bipartition */ +const GraphPart * restrict const orgparttax, /* Part array of original graph */ +const GraphPart indpartval, /* Part of graph to consider */ +const int domnnum, /* Index of domain onto which map the part */ +Mapping * restrict const mappptr) /* Final mapping */ +{ + Gnum vertnum; + + if (orgparttax == NULL) { /* If graph is full graph */ +#ifdef SCOTCH_DEBUG_WGRAPH2 + if ((orggrafptr->vnumtax != NULL) || (domnnum != 0)) { + errorPrint ("wgraphPartRb3: internal error"); + return (1); + } +#endif /* SCOTCH_DEBUG_WGRAPH2 */ + memSet (mappptr->parttax + mappptr->grafptr->baseval, 0, orggrafptr->vertnbr * sizeof (ArchDomNum)); + } + else { /* Graph to consider is a subgraph of the original graph */ + if (orggrafptr->vnumtax == NULL) { /* If original graph is not itself a subgraph */ + for (vertnum = orggrafptr->baseval; vertnum < orggrafptr->vertnnd; vertnum ++) { /* For all graph vertices */ + if (orgparttax[vertnum] == indpartval) /* If vertex belongs to the right part */ + mappptr->parttax[vertnum] = domnnum; + } + } + else { + for (vertnum = orggrafptr->baseval; vertnum < orggrafptr->vertnnd; vertnum ++) { /* For all graph vertices */ + if (orgparttax[vertnum] == indpartval) /* If vertex belongs to the right part */ + mappptr->parttax[orggrafptr->vnumtax[vertnum]] = domnnum; + } + } + } + + return (0); +} + +static +int +wgraphPartRb2 ( +WgraphPartRbData * restrict const dataptr, /* Top-level graph and partition data */ +Graph * restrict const orggrafptr, /* Graph to induce and bipartition */ +const GraphPart * restrict const orgparttax, /* Part array of original graph to consider */ +const GraphPart indpartval, /* Part of graph to consider */ +const int indvertnbr, /* Number of vertices in part or in graph */ +const int domnnum) /* Index of domain onto which map the part */ +{ + Graph indgrafdat; + Graph * indgrafptr; + Vgraph actgrafdat; + Anum domnsubidx; + Anum domnsubdlt; + ArchDom domnsubtab[2]; /* Target subdomains */ + Anum domnsubnum[2]; /* Index of subdomains in mapping */ + Gnum grafsubsiz[2]; + Gnum vertnum; + Mapping * restrict mappptr; + int i; + int o; + + mappptr = &dataptr->mappdat; + o = archDomBipart (mappptr->archptr, &mappptr->domntab[domnnum], &domnsubtab[0], &domnsubtab[1]); + + switch (o) { + case 1 : /* If target domain is terminal */ + return (wgraphPartRb3 (orggrafptr, orgparttax, indpartval, domnnum, mappptr)); /* Update mapping and return */ + case 2 : /* On error */ + errorPrint ("wgraphPartRb2: cannot bipartition domain"); + return (1); + } + + indgrafptr = orggrafptr; /* Assume we will work on the original graph */ + if (orgparttax != NULL) { /* If not the case, build induced subgraph */ + indgrafptr = &indgrafdat; + if (graphInducePart (orggrafptr, orgparttax, indvertnbr, indpartval, &indgrafdat) != 0) { + errorPrint ("wgraphPartRb2: cannot induce graph"); + return (1); + } + } + + actgrafdat.s = *indgrafptr; + actgrafdat.s.vlbltax = NULL; + if ((actgrafdat.frontab = (Gnum *) memAlloc (actgrafdat.s.vertnbr * sizeof (Gnum))) == NULL) { + errorPrint ("wgraphPartRb2: out of memory (1)"); + return (1); + } + if ((actgrafdat.parttax = (GraphPart *) memAlloc (actgrafdat.s.vertnbr * sizeof (GraphPart))) == NULL) { + errorPrint ("wgraphPartRb2: out of memory (2)"); + memFree (actgrafdat.frontab); + return (1); + } + actgrafdat.parttax -= actgrafdat.s.baseval; + vgraphZero (&actgrafdat); /* Create active graph */ + if (vgraphSeparateSt (&actgrafdat, dataptr->stratptr) != 0) { /* Perform bipartitioning */ + errorPrint ("wgraphPartRb2: cannot bipartition graph"); + vgraphExit (&actgrafdat); + return (1); + } + + if (actgrafdat.s.vnumtax == NULL) { /* If the active graph is not itself a subgraph */ + for (vertnum = actgrafdat.s.baseval; vertnum < actgrafdat.s.vertnnd; vertnum ++) { /* For all graph vertices */ + if (actgrafdat.parttax[vertnum] == 2) { /* If vertex belongs to frontier */ + mappptr->parttax[vertnum] = -1; + actgrafdat.parttax[vertnum] = 3; + } + } + } + else { + for (vertnum = actgrafdat.s.baseval; vertnum < actgrafdat.s.vertnnd; vertnum ++) { /* For all graph vertices */ + if (actgrafdat.parttax[vertnum] == 2) { /* If vertex belongs to frontier */ + mappptr->parttax[actgrafdat.s.vnumtax[vertnum]]= -1; + actgrafdat.parttax[vertnum] = 3; + } + } + } + + + domnsubdlt = mappptr->domnnbr - domnnum; /* Increment in domain number */ + domnsubidx = domnnum - domnsubdlt; /* Place where to insert subdomain */ + mappptr->domnnbr --; /* One less subdomain as for now */ + grafsubsiz[0] = actgrafdat.compsize[0]; + grafsubsiz[1] = actgrafdat.compsize[1]; + + o = 0; + for (i = 1; i >= 0; i --) { /* For all subparts */ + if (grafsubsiz[i] <= 0) /* If subpart is empty, skip it */ + continue; + mappptr->domnnbr ++; /* One more subdomain to account for */ + domnsubidx += domnsubdlt; /* Compute location of subdomain */ + domnsubnum[i] = domnsubidx; /* Record it before recursion */ + mappptr->domntab[domnsubidx] = domnsubtab[i]; /* Write it at this place */ + } + + if (o == 0) { + for (i = 1; i >= 0; i --) { /* For all subparts */ + if (grafsubsiz[i] <= 0) /* If subpart is empty, skip it */ + continue; + + if ((o = wgraphPartRb2 (dataptr, indgrafptr, actgrafdat.parttax, (GraphPart) i, grafsubsiz[i], domnsubnum[i])) != 0) + return (1); /* If problem in recursion, stop */ + } + } + + memFree (actgrafdat.frontab); /* Frontier array of bipartitioning graph is no longer necessary */ + memFree (actgrafdat.parttax + actgrafdat.s.baseval); /* Frontier array of bipartitioning graph is no longer necessary */ + if (indgrafptr == &indgrafdat) /* If an induced subgraph had been created */ + graphExit (indgrafptr); /* Free it */ + + return (o); +} + +int +wgraphPartRb ( +Wgraph * restrict const grafptr, +const WgraphPartRbParam * restrict const paraptr) +{ + const Anum * restrict parttax; + Anum partval; + Gnum vertnum; + Gnum velomsk; + const Gnum * restrict velobax; /* Data for handling of optional arrays */ + Gnum * restrict frontab; + Gnum fronnbr; + Gnum fronload; + Gnum * restrict compload; + Gnum * restrict compsize; + WgraphPartRbData datadat; + Arch archdat; + WgraphPartList * restrict listtab; + + const Gnum * restrict const verttax = grafptr->s.verttax; + const Gnum * restrict const vendtax = grafptr->s.vendtax; + const Gnum * restrict const edgetax = grafptr->s.edgetax; + + if ((listtab = (WgraphPartList *) memAlloc ((grafptr->partnbr + 1) * sizeof (WgraphPartList))) == NULL) { /* TRICK: "+1" to create slot for a "-1" index */ + errorPrint ("wgraphPartRb: out of memory (1)"); + return (1); + } + listtab ++; /* TRICK: Trim array so that listtab[-1] is valid */ + memSet (listtab, ~0, grafptr->partnbr * sizeof (WgraphPartList)); /* Set vertex indices to ~0 */ + + datadat.grafptr = &grafptr->s; + datadat.frontab = grafptr->frontab; /* Re-use frontier array */ + datadat.fronnbr = 0; + datadat.stratptr = paraptr->stratptr; + datadat.mappdat.grafptr = &grafptr->s; + datadat.mappdat.parttax = grafptr->parttax; /* Re-use part array */ + datadat.mappdat.domnmax = grafptr->partnbr + 1; + datadat.mappdat.domnnbr = 1; + + SCOTCH_archCmplt ((SCOTCH_Arch *) &archdat, grafptr->partnbr); /* Create a complete graph architecture */ + datadat.mappdat.archptr = &archdat; + + archDomFrst (datadat.mappdat.archptr, &datadat.mappdat.domnorg); /* Get first domain of architecture */ + if ((datadat.mappdat.domntab = (ArchDom *) memAlloc ((grafptr->partnbr + 2) * sizeof (ArchDom))) == NULL) { + errorPrint ("wgraphPartRb: out of memory (2)"); + memFree (listtab - 1); /* TRICK: free array using its real beginning */ + return (1); + } + datadat.mappdat.domntab[0] = datadat.mappdat.domnorg; /* Set first domain */ + + if (wgraphPartRb2 (&datadat, &grafptr->s, NULL, 0, grafptr->s.vertnbr, 0) != 0) { + errorPrint ("wgraphPartRb: internal error (1)"); + return (1); + } + + if (grafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ + velobax = &wgraphpartrbloadone; /* In case vertices not weighted (least often) */ + velomsk = 0; + } + else { + velobax = grafptr->s.velotax; + velomsk = ~((Gnum) 0); + } + + compload = grafptr->compload; + compsize = grafptr->compsize; + memSet (compload, 0, grafptr->partnbr * sizeof (Gnum)); + memSet (compsize, 0, grafptr->partnbr * sizeof (Gnum)); + + parttax = grafptr->parttax; + frontab = grafptr->frontab; + fronnbr = + fronload = 0; + for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { + Gnum partval; + + partval = parttax[vertnum]; + if (partval >= 0) { + compload[partval] += velobax[vertnum & velomsk]; + compsize[partval] ++; + } + else { /* Vertex is in separator */ + Gnum listidx; /* Index of first neighbor part */ + Gnum edgenum; + Gnum veloval; + + frontab[fronnbr ++] = vertnum; /* Add vertex to frontier */ + fronload += velobax[vertnum & velomsk]; + + listidx = -1; /* No neighboring parts recorded yet */ + listtab[-1].vertnum = vertnum; /* Separator neighbors will not be considered */ + for (edgenum = verttax[vertnum]; + edgenum < vendtax[vertnum]; edgenum ++) { /* Compute gain */ + Gnum vertend; + Gnum partend; + + vertend = edgetax[edgenum]; + partend = parttax[vertend]; + if (listtab[partend].vertnum != vertnum) { /* If part not yet considered */ + listtab[partend].vertnum = vertnum; /* Link it in list of neighbors */ + listtab[partend].nextidx = listidx; + listidx = partend; + } + } + + veloval = velobax[vertnum & velomsk]; + + while (listidx != -1) { /* For all neighboring parts found */ + compload[listidx] += veloval; /* Add load of separator vertex to part */ + compsize[listidx] ++; + listidx = listtab[listidx].nextidx; + } + } + } + grafptr->fronnbr = fronnbr; + grafptr->fronload = fronload; + +#if 0 /* TODO REMOVE */ + for (partval = 0; partval < grafptr->partnbr; partval ++) + printf("\033[0;33mcompload[%d] %d %d\033[0m\n", partval, grafptr->compload[partval], grafptr->compsize[partval]); +#endif + + memFree (datadat.mappdat.domntab); /* Free only newly allocated array of mapping */ + memFree (listtab - 1); /* TRICK: free array using its real beginning */ + +#ifdef SCOTCH_DEBUG_WGRAPH2 + if (wgraphCheck (grafptr) != 0) { + errorPrint ("wgraphPartRb: inconsistent graph data"); + return (1); + } +#endif /* SCOTCH_DEBUG_WGRAPH2 */ + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_rb.h b/scotch_6.0.3/src/libscotch/wgraph_part_rb.h new file mode 100644 index 00000000..419eac90 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_rb.h @@ -0,0 +1,82 @@ +/* Copyright 2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_rb.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** **/ +/** FUNCTION : These lines are the data declaration **/ +/** for the vertex overlapped graph partit- **/ +/** ioning based on recursive bipartitioni- **/ +/** ng approach. **/ +/** **/ +/** DATES : # Version 6.0 : from : 16 mar 2010 **/ +/** to 04 nov 2010 **/ +/** **/ +/** NOTES : # This code derives from the code of **/ +/** kgraph_map_rb_part.h for the vertex **/ +/** overlapped graph partitioning. **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions. +*/ + +/*+ This structure holds the method parameters. +*/ + +typedef struct WgraphPartRbParam_ { + Strat * stratptr; /*+ Bipartitioning strategy used +*/ +} WgraphPartRbParam; + +/*+ This structure holds global data. +*/ + +typedef struct WgraphPartRbData_ { + const Graph * grafptr; /*+ Pointer to top-level graph +*/ + Gnum * frontab; /*+ Pointer to top-level frontier array +*/ + Gnum fronnbr; /*+ Current number of frontier vertices +*/ + Mapping mappdat; /*+ Current state of mapping +*/ + Strat * stratptr; /*+ Bipartitioning strategy used +*/ +} WgraphPartRbData; + +/* +** The function prototypes. +*/ + +#ifndef WGRAPH_PART_RB +#define static +#endif + +int wgraphPartRb (Wgraph * restrict const, const WgraphPartRbParam * restrict const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_st.c b/scotch_6.0.3/src/libscotch/wgraph_part_st.c new file mode 100644 index 00000000..eeca1761 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_st.c @@ -0,0 +1,278 @@ +/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_st.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : This module contains the global **/ +/** vertex overlapped graph partitioning **/ +/** strategy and method tables. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to 16 apr 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH_PART_ST + +#include "module.h" +#include "common.h" +#include "gain.h" +#include "parser.h" +#include "graph.h" +#include "arch.h" +#include "mapping.h" +#include "graph_coarsen.h" +#include "vgraph.h" +#include "vgraph_separate_st.h" +#include "wgraph.h" +#include "wgraph_part_fm.h" +#include "wgraph_part_gg.h" +#include "wgraph_part_gp.h" +#include "wgraph_part_ml.h" +#include "wgraph_part_rb.h" +#include "wgraph_part_st.h" +#include "wgraph_part_zr.h" + +/* +** The static and global variables. +*/ + +static Wgraph wgraphdummy; /* Dummy overlap graph for offset computations */ + +static union { + WgraphPartFmParam param; + StratNodeMethodData padding; +} wgraphpartdefaultfm = { { 10, 40, 0.1L } }; + +static union { + WgraphPartGgParam param; + StratNodeMethodData padding; +} wgraphpartdefaultgg = { { 10 } }; + +static union { + WgraphPartGpParam param; + StratNodeMethodData padding; +} wgraphpartdefaultgp = { { 5 } }; + +static union { + WgraphPartMlParam param; + StratNodeMethodData padding; +} wgraphpartdefaultml = { { 20, 0.8L, &stratdummy, &stratdummy } }; + +static union { + WgraphPartRbParam param; + StratNodeMethodData padding; +} wgraphpartdefaultrb = { { &stratdummy } }; + +static StratMethodTab wgraphpartstmethtab[] = { /* Graph overlap partitioning methods array */ + { WGRAPHSEPASTMETHGG, "h", wgraphPartGg, &wgraphpartdefaultgg }, + { WGRAPHSEPASTMETHGP, "g", wgraphPartGp, &wgraphpartdefaultgp }, + { WGRAPHSEPASTMETHFM, "f", wgraphPartFm, &wgraphpartdefaultfm }, + { WGRAPHSEPASTMETHML, "m", wgraphPartMl, &wgraphpartdefaultml }, + { WGRAPHSEPASTMETHRB, "r", wgraphPartRb, &wgraphpartdefaultrb }, + { WGRAPHSEPASTMETHZR, "z", wgraphPartZr, NULL }, + { -1, NULL, NULL, NULL } }; + +static StratParamTab wgraphpartstparatab[] = { /* Method parameter list */ + { WGRAPHSEPASTMETHFM, STRATPARAMINT, "pass", + (byte *) &wgraphpartdefaultfm.param, + (byte *) &wgraphpartdefaultfm.param.passnbr, + NULL }, + { WGRAPHSEPASTMETHFM, STRATPARAMINT, "move", + (byte *) &wgraphpartdefaultfm.param, + (byte *) &wgraphpartdefaultfm.param.movenbr, + NULL }, + { WGRAPHSEPASTMETHFM, STRATPARAMDOUBLE, "bal", + (byte *) &wgraphpartdefaultfm.param, + (byte *) &wgraphpartdefaultfm.param.deltrat, + NULL }, + { WGRAPHSEPASTMETHGG, STRATPARAMINT, "pass", + (byte *) &wgraphpartdefaultgg.param, + (byte *) &wgraphpartdefaultgg.param.passnbr, + NULL }, + { WGRAPHSEPASTMETHGP, STRATPARAMINT, "pass", + (byte *) &wgraphpartdefaultgp.param, + (byte *) &wgraphpartdefaultgp.param.passnbr, + NULL }, + { WGRAPHSEPASTMETHML, STRATPARAMSTRAT, "asc", + (byte *) &wgraphpartdefaultml.param, + (byte *) &wgraphpartdefaultml.param.stratasc, + (void *) &wgraphpartststratab }, + { WGRAPHSEPASTMETHML, STRATPARAMSTRAT, "low", + (byte *) &wgraphpartdefaultml.param, + (byte *) &wgraphpartdefaultml.param.stratlow, + (void *) &wgraphpartststratab }, + { WGRAPHSEPASTMETHML, STRATPARAMINT, "vert", + (byte *) &wgraphpartdefaultml.param, + (byte *) &wgraphpartdefaultml.param.coarnbr, + NULL }, + { WGRAPHSEPASTMETHML, STRATPARAMDOUBLE, "rat", + (byte *) &wgraphpartdefaultml.param, + (byte *) &wgraphpartdefaultml.param.coarval, + NULL }, + { WGRAPHSEPASTMETHRB, STRATPARAMSTRAT, "sep", + (byte *) &wgraphpartdefaultrb.param, + (byte *) &wgraphpartdefaultrb.param.stratptr, + (void *) &vgraphseparateststratab }, + { WGRAPHSEPASTMETHNBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +static StratParamTab wgraphpartstcondtab[] = { /* Overlap graph condition parameter table*/ + { STRATNODENBR, STRATPARAMINT, NULL, + NULL, NULL, NULL } }; + +StratTab wgraphpartststratab = { /* Strategy tables for overlap partitioning methods */ + wgraphpartstmethtab, + wgraphpartstparatab, + wgraphpartstcondtab }; + +/*********************************************/ +/* */ +/* This is the generic partitioning routine. */ +/* */ +/*********************************************/ + +/* This routine computes the separation of +** the given graph according to the given +** strategy. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +wgraphPartSt ( +Wgraph * restrict const grafptr, /*+ Overlap partitioning graph +*/ +const Strat * restrict const strat) /*+ Overlap partitioning strategy +*/ +{ + StratTest val; /* Result of condition evaluation */ + WgraphStore savetab[2]; /* Results of the two strategies */ + int o; + int o2; + +#ifdef SCOTCH_DEBUG_WGRAPH2 + if (sizeof (Gnum) != sizeof (INT)) { + errorPrint ("wgraphPartSt: invalid type specification for parser variables"); + return (1); + } + if ((sizeof (WgraphPartFmParam) > sizeof (StratNodeMethodData)) || + (sizeof (WgraphPartGgParam) > sizeof (StratNodeMethodData)) || + (sizeof (WgraphPartGpParam) > sizeof (StratNodeMethodData)) || + (sizeof (WgraphPartMlParam) > sizeof (StratNodeMethodData)) || + (sizeof (WgraphPartRbParam) > sizeof (StratNodeMethodData))) { + errorPrint ("wgraphPartSt: invalid type specification"); + return (1); + } +#endif /* SCOTCH_DEBUG_WGRAPH2 */ +#ifdef SCOTCH_DEBUG_WGRAPH1 + if ((strat->tabl != &wgraphpartststratab) && + (strat != &stratdummy)) { + errorPrint ("wgraphPartSt: invalid parameter (1)"); + return (1); + } +#endif /* SCOTCH_DEBUG_WGRAPH1 */ + + o = 0; + switch (strat->type) { + case STRATNODECONCAT : + o = wgraphPartSt (grafptr, strat->data.concat.strat[0]); /* Apply the first strategy */ + if (o == 0) /* If it worked all right */ + o |= wgraphPartSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ + break; + case STRATNODECOND : + o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ + if (o == 0) { /* If evaluation was correct */ +#ifdef SCOTCH_DEBUG_WGRAPH2 + if ((val.typetest != STRATTESTVAL) || + (val.typenode != STRATPARAMLOG)) { + errorPrint ("wgraphPartSt: invalid test result"); + o = 1; + break; + } +#endif /* SCOTCH_DEBUG_WGRAPH2 */ + if (val.data.val.vallog == 1) /* If expression is true */ + o = wgraphPartSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ + else { /* Else if expression is false */ + if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ + o = wgraphPartSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ + } + } + break; + case STRATNODEEMPTY : + break; + case STRATNODESELECT : + if (((wgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ + ((wgraphStoreInit (grafptr, &savetab[1])) != 0)) { + errorPrint ("wgraphPartSt: out of memory"); + wgraphStoreExit (&savetab[0]); + return (1); + } + + wgraphStoreSave (grafptr, &savetab[1]); /* Save initial partition */ + o = wgraphPartSt (grafptr, strat->data.select.strat[0]); /* Apply first strategy */ + wgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ + wgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial partition */ + o2 = wgraphPartSt (grafptr, strat->data.select.strat[1]); /* Apply second strategy */ + + if ((o == 0) || (o2 == 0)) { /* If at least one method make a k-partition */ + if (savetab[0].fronload < grafptr->fronload) /* If first strategy is better */ + wgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ + } + + wgraphStoreExit (&savetab[0]); /* Free both save areas */ + wgraphStoreExit (&savetab[1]); + break; +#ifdef SCOTCH_DEBUG_WGRAPH2 + case STRATNODEMETHOD : +#else /* SCOTCH_DEBUG_WGRAPH2 */ + default : +#endif /* SCOTCH_DEBUG_WGRAPH2 */ + return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); +#ifdef SCOTCH_DEBUG_WGRAPH2 + default : + errorPrint ("wgraphPartSt: invalid parameter (2)"); + return (1); +#endif /* SCOTCH_DEBUG_WGRAPH2 */ + } + return (o); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_st.h b/scotch_6.0.3/src/libscotch/wgraph_part_st.h new file mode 100644 index 00000000..95f659bb --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_st.h @@ -0,0 +1,84 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_part_st.h **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for vertex overlapped graph par- **/ +/** titioning strategy and method tables. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2009 **/ +/** to : 14 mar 2010 **/ +/** **/ +/************************************************************/ +/* +** The type definitions. +*/ + +/** Method types. **/ + +typedef enum WgraphPartStMethodType_ { + WGRAPHSEPASTMETHGG = 0, /*+ Greedy Graph Growing +*/ + WGRAPHSEPASTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ + WGRAPHSEPASTMETHFM, /*+ Fiduccia-Mattheyses +*/ + WGRAPHSEPASTMETHML, /*+ Multi-level separation +*/ + WGRAPHSEPASTMETHRB, /*+ Recursive bisection +*/ + WGRAPHSEPASTMETHZR, /*+ Zero method +*/ + WGRAPHSEPASTMETHES, /*+ Edge separation strategy +*/ + WGRAPHSEPASTMETHVW, /*+ Partition viewer +*/ + WGRAPHSEPASTMETHNBR /*+ Number of methods +*/ +} WgraphPartStMethodType; + +/* +** The external declarations. +*/ + +extern StratTab wgraphpartststratab; + +/* +** The function prototypes. +*/ + +#ifndef WGRAPH_PART_ST +#define static +#endif + +int wgraphPartSt (Wgraph * restrict const, const Strat * restrict const); + +#undef static + diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_zr.c b/scotch_6.0.3/src/libscotch/wgraph_part_zr.c new file mode 100644 index 00000000..734596a5 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_zr.c @@ -0,0 +1,35 @@ +/* +** The defines and includes. +*/ + +#define WGRAPH_PART_ZR + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "wgraph.h" +#include "wgraph_part_zr.h" + +/*****************************/ +/* */ +/* This is the main routine. */ +/* */ +/*****************************/ + +/* This routine moves all of the graph vertices +** to the first part of the partition. +** It returns: +** - 0 : if the bipartitioning could be computed. +** - !0 : on error. +*/ + +int +wgraphPartZr ( +Wgraph * const grafptr) /*+ Active graph +*/ +{ + + if (grafptr->compload[0] != grafptr->s.velosum) /* If not all vertices already in part zero */ + wgraphZero (grafptr); + + return (0); +} diff --git a/scotch_6.0.3/src/libscotch/wgraph_part_zr.h b/scotch_6.0.3/src/libscotch/wgraph_part_zr.h new file mode 100644 index 00000000..8a1457e0 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_part_zr.h @@ -0,0 +1,11 @@ +/* +** The function prototypes. +*/ + +#ifndef WGRAPH_PART_ZR +#define static +#endif + +int wgraphPartZr (Wgraph * const); + +#undef static diff --git a/scotch_6.0.3/src/libscotch/wgraph_store.c b/scotch_6.0.3/src/libscotch/wgraph_store.c new file mode 100644 index 00000000..f23b8998 --- /dev/null +++ b/scotch_6.0.3/src/libscotch/wgraph_store.c @@ -0,0 +1,173 @@ +/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : wgraph_store.c **/ +/** **/ +/** AUTHOR : Jun-Ho HER (v6.0) **/ +/** Charles-Edmond BICHOT (v5.1b) **/ +/** **/ +/** FUNCTION : This module contains the data store re- **/ +/** lated rountines for the vertex overlap- **/ +/** ped graph partitioning. **/ +/** **/ +/** DATES : # Version 5.1 : from : 01 dec 2007 **/ +/** to : 01 jul 2008 **/ +/** # Version 6.0 : from : 05 nov 2010 **/ +/** to : 30 may 2010 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define WGRAPH_STORE + +#include "module.h" +#include "common.h" +#include "graph.h" +#include "arch.h" +#include "wgraph.h" + +/**********************************/ +/* */ +/* Store graph handling routines. */ +/* */ +/**********************************/ + +/* This routine builds a save structure +** for the given active graph. +** It returns: +** - 0 : if allocation succeeded. +** - !0 : on error. +*/ + +int +wgraphStoreInit ( +const Wgraph * const grafptr, +WgraphStore * const storptr) +{ + Gnum savsize; + + savsize = 2 * grafptr->partnbr * sizeof (Gnum) + /* Compute size for frontier, part arrays, communication load and size */ + grafptr->s.vertnbr * (sizeof (Gnum) + sizeof (Anum)); + + if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ + errorPrint ("wgraphStoreInit: out of memory"); + return (1); + } + + return (0); +} + +/* This routine frees a save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +wgraphStoreExit ( +WgraphStore * const storptr) +{ + memFree (storptr->datatab); +#ifdef SCOTCH_DEBUG_WGRAPH2 + storptr->datatab = NULL; +#endif /* SCOTCH_DEBUG_WGRAPH2 */ +} + +/* This routine saves partition data from the +** given active graph to the given save structure. +** It returns: +** - VOID : in all cases. +*/ + +void +wgraphStoreSave ( +const Wgraph * const grafptr, +WgraphStore * const storptr) +{ + byte * compload; /* Pointer to part load data save area */ + byte * compsize; /* Pointer to part size data save area */ + byte * frontab; /* Pointer to frontier data save area */ + byte * parttab; /* Pointer to partition data save area */ + + storptr->partnbr = grafptr->partnbr; /* Save partition parameters */ + storptr->fronnbr = grafptr->fronnbr; + storptr->fronload = grafptr->fronload; + + compload = storptr->datatab; /* Compute data offsets within save structure */ + compsize = compload + grafptr->partnbr * sizeof (Gnum); + frontab = compsize + grafptr->partnbr * sizeof (Gnum); + parttab = frontab + grafptr->fronnbr * sizeof (Gnum); + + memCpy (compload, grafptr->compload, grafptr->partnbr * sizeof (Gnum)); + memCpy (compsize, grafptr->compsize, grafptr->partnbr * sizeof (Gnum)); + memCpy (frontab, grafptr->frontab, grafptr->fronnbr * sizeof (Gnum)); + memCpy (parttab, grafptr->parttax + grafptr->s.baseval, grafptr->s.vertnbr * sizeof (Anum)); +} + +/* This routine updates partition data of the +** given active graph, using the given save graph. +** It returns: +** - VOID : in all cases. +*/ + +void +wgraphStoreUpdt ( +Wgraph * const grafptr, +const WgraphStore * const storptr) +{ + byte * compload; /* Pointer to part load data save area */ + byte * compsize; /* Pointer to part size data save area */ + byte * frontab; /* Pointer to frontier data save area */ + byte * parttab; /* Pointer to partition data save area */ + + grafptr->partnbr = storptr->partnbr; /* Load partition parameters */ + grafptr->fronnbr = storptr->fronnbr; + grafptr->fronload = storptr->fronload; + + compload = storptr->datatab; /* Compute data offsets within save structure */ + compsize = compload + grafptr->partnbr * sizeof (Gnum); + frontab = compsize + grafptr->partnbr * sizeof (Gnum); + parttab = frontab + grafptr->fronnbr * sizeof (Gnum); + + memCpy (grafptr->compload, compload, grafptr->partnbr * sizeof (Gnum)); + memCpy (grafptr->compsize, compsize, grafptr->partnbr * sizeof (Gnum)); + memCpy (grafptr->frontab, frontab, grafptr->fronnbr * sizeof (Gnum)); + memCpy (grafptr->parttax + grafptr->s.baseval, parttab, grafptr->s.vertnbr * sizeof (Anum)); + +#ifdef SCOTCH_DEBUG_WGRAPH2 + if (wgraphCheck (grafptr) != 0) + errorPrint ("wgraphStoreUpdt: inconsistent graph data"); +#endif /* SCOTCH_DEBUG_WGRAPH2 */ +} diff --git a/scotch_6.0.3/src/libscotchmetis/Makefile b/scotch_6.0.3/src/libscotchmetis/Makefile new file mode 100644 index 00000000..d81d02c0 --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/Makefile @@ -0,0 +1,140 @@ +## Copyright 2007-2010 ENSEIRB, INRIA & CNRS +## +## This file is part of the Scotch software package for static mapping, +## graph partitioning and sparse matrix ordering. +## +## This software is governed by the CeCILL-C license under French law +## and abiding by the rules of distribution of free software. You can +## use, modify and/or redistribute the software under the terms of the +## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +## URL: "http://www.cecill.info". +## +## As a counterpart to the access to the source code and rights to copy, +## modify and redistribute granted by the license, users are provided +## only with a limited warranty and the software's author, the holder of +## the economic rights, and the successive licensors have only limited +## liability. +## +## In this respect, the user's attention is drawn to the risks associated +## with loading, using, modifying and/or developing or reproducing the +## software by the user in light of its specific status of free software, +## that may mean that it is complicated to manipulate, and that also +## therefore means that it is reserved for developers and experienced +## professionals having in-depth computer knowledge. Users are therefore +## encouraged to load and test the software's suitability as regards +## their requirements in conditions enabling the security of their +## systems and/or data to be ensured and, more generally, to use and +## operate it in the same conditions as regards security. +## +## The fact that you are presently reading this means that you have had +## knowledge of the CeCILL-C license and that you accept its terms. +## + +bindir = ../../bin +includedir = ../../include +libdir = ../../lib + +## +## General inference rules. +## + +include ../Makefile.inc + +%$(OBJ) : %.c + $(CC) $(CFLAGS) $(CLIBFLAGS) -I$(includedir) -I../libscotch -c $(<) -o $(@) + +%$(EXE) : %.c + $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -o $(@) -L$(libdir) $(LDFLAGS) + +## +## Project rules. +## + +.PHONY : ptscotch scotch ptinstall install clean realclean + +scotch : + $(MAKE) CC="$(CCS)" SCOTCHLIB=ptscotch \ + libscotchmetis$(LIB) + +ptscotch : + $(MAKE) CFLAGS="$(CFLAGS) -DSCOTCH_PTSCOTCH" CC="$(CCP)" SCOTCHLIB=ptscotch \ + libptscotchparmetis$(LIB) + +install : scotch + -$(CP) metis.h $(includedir) + -$(CP) libscotchmetis$(LIB) $(libdir) + +ptinstall : ptscotch + -$(CP) parmetis.h $(includedir) + -$(CP) libptscotchparmetis$(LIB) $(libdir) + +clean : + -$(RM) *~ *$(OBJ) lib*$(LIB) + +realclean : clean + +## +## Todo list. +## + +metis_graph_order$(OBJ) : metis_graph_order.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + metis.h + +metis_graph_order_f$(OBJ) : metis_graph_order_f.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + metis.h + +metis_graph_part$(OBJ) : metis_graph_part.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + metis.h + +metis_graph_part_f$(OBJ) : metis_graph_part_f.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + metis.h + +parmetis_dgraph_order$(OBJ) : parmetis_dgraph_order.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + parmetis.h + +parmetis_dgraph_order_f$(OBJ) : parmetis_dgraph_order_f.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + parmetis.h + +parmetis_dgraph_part$(OBJ) : parmetis_dgraph_part.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + parmetis.h + +parmetis_dgraph_part_f$(OBJ) : parmetis_dgraph_part_f.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + parmetis.h + +libptscotchparmetis$(LIB) : parmetis_dgraph_order$(OBJ) \ + parmetis_dgraph_order_f$(OBJ) \ + parmetis_dgraph_part$(OBJ) \ + parmetis_dgraph_part_f$(OBJ) + $(AR) $(ARFLAGS) $(@) $(^) + -$(RANLIB) $(@) + +libscotchmetis$(LIB) : metis_graph_order$(OBJ) \ + metis_graph_order_f$(OBJ) \ + metis_graph_part$(OBJ) \ + metis_graph_part_f$(OBJ) + $(AR) $(ARFLAGS) $(@) $(^) + -$(RANLIB) $(@) diff --git a/scotch_6.0.3/src/libscotchmetis/metis.h b/scotch_6.0.3/src/libscotchmetis/metis.h new file mode 100644 index 00000000..da99b944 --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/metis.h @@ -0,0 +1,97 @@ +/********************************************************* +** ** +** WARNING: THIS IS NOT THE ORIGINAL INCLUDE FILE OF ** +** THE MeTiS SOFTWARE PACKAGE. ** +** This file is a compatibility include file provided ** +** as part of the Scotch software distribution. ** +** Preferably use the original MeTiS include file to ** +** keep definitions of routines not overloaded by ** +** the libScotchMeTiS library. ** +** ** +*********************************************************/ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : metis.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Compatibility declaration file for the **/ +/** MeTiS interface routines provided by **/ +/** the Scotch project. **/ +/** **/ +/** DATES : # Version 5.0 : from : 08 sep 2006 **/ +/** to 07 jun 2007 **/ +/** # Version 5.1 : from : 30 jun 2010 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +#ifdef SCOTCH_METIS_PREFIX +#define SCOTCH_METIS_PREFIXL scotch_ +#define SCOTCH_METIS_PREFIXU SCOTCH_ +#endif /* SCOTCH_METIS_PREFIX */ + +#ifndef SCOTCH_METIS_PREFIXL +#define SCOTCH_METIS_PREFIXL +#endif /* SCOTCH_METIS_PREFIXL */ + +#ifndef SCOTCH_METIS_PREFIXU +#define SCOTCH_METIS_PREFIXU +#endif /* SCOTCH_METIS_PREFIXU */ + +#ifndef METISNAMEL +#define METISNAMEL(s) METISNAME2(METISNAME3(SCOTCH_METIS_PREFIXL),s) +#define METISNAMEU(s) METISNAME2(METISNAME3(SCOTCH_METIS_PREFIXU),s) +#define METISNAME2(p,s) METISNAME4(p,s) +#define METISNAME3(s) s +#define METISNAME4(p,s) p##s +#endif /* METISNAMEL */ + +/* +** The function prototypes. +*/ + +void METISNAMEU(METIS_EdgeND) (const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void METISNAMEU(METIS_NodeND) (const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void METISNAMEU(METIS_NodeWND) (const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); + +void METISNAMEU(METIS_PartGraphKway) (const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void METISNAMEU(METIS_PartGraphRecursive) (const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); +void METISNAMEU(METIS_PartGraphVKway) (const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); diff --git a/scotch_6.0.3/src/libscotchmetis/metis_graph_order.c b/scotch_6.0.3/src/libscotchmetis/metis_graph_order.c new file mode 100644 index 00000000..b69c165c --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/metis_graph_order.c @@ -0,0 +1,141 @@ +/* Copyright 2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : metis_graph_order.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the compatibility **/ +/** library for the MeTiS ordering **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 08 sep 2006 **/ +/** to 07 jun 2007 **/ +/** # Version 5.1 : from : 30 jun 2010 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "metis.h" /* Our "metis.h" file */ + +/************************************/ +/* */ +/* These routines are the C API for */ +/* MeTiS graph ordering routines. */ +/* */ +/************************************/ + +/* +** +*/ + +void +METISNAMEU(METIS_EdgeND) ( +const SCOTCH_Num * const n, +const SCOTCH_Num * const xadj, +const SCOTCH_Num * const adjncy, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const options, +SCOTCH_Num * const perm, +SCOTCH_Num * const iperm) +{ + METISNAMEU(METIS_NodeWND) (n, xadj, adjncy, NULL, numflag, options, perm, iperm); +} + +/* +** +*/ + +void +METISNAMEU(METIS_NodeND) ( +const SCOTCH_Num * const n, +const SCOTCH_Num * const xadj, +const SCOTCH_Num * const adjncy, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const options, +SCOTCH_Num * const perm, +SCOTCH_Num * const iperm) +{ + METISNAMEU(METIS_NodeWND) (n, xadj, adjncy, NULL, numflag, options, perm, iperm); +} + +/* +** +*/ + +void +METISNAMEU(METIS_NodeWND) ( +const SCOTCH_Num * const n, +const SCOTCH_Num * const xadj, +const SCOTCH_Num * const adjncy, +const SCOTCH_Num * const vwgt, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const options, +SCOTCH_Num * const perm, +SCOTCH_Num * const iperm) +{ + SCOTCH_Graph grafdat; /* Scotch graph object to interface with libScotch */ + SCOTCH_Ordering ordedat; /* Scotch ordering object to interface with libScotch */ + SCOTCH_Strat stradat; + + SCOTCH_graphInit (&grafdat); + + if (SCOTCH_graphBuild (&grafdat, + *numflag, *n, xadj, xadj + 1, vwgt, NULL, + xadj[*n] - *numflag, adjncy, NULL) == 0) { + SCOTCH_stratInit (&stradat); +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_graphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ +#endif /* SCOTCH_DEBUG_ALL */ + { + if (SCOTCH_graphOrderInit (&grafdat, &ordedat, iperm, perm, /* MeTiS and Scotch have opposite definitions for (inverse) permutations */ + NULL, NULL, NULL) == 0) { + SCOTCH_graphOrderCompute (&grafdat, &ordedat, &stradat); + SCOTCH_graphOrderExit (&grafdat, &ordedat); + } + } + SCOTCH_stratExit (&stradat); + } + SCOTCH_graphExit (&grafdat); +} diff --git a/scotch_6.0.3/src/libscotchmetis/metis_graph_order_f.c b/scotch_6.0.3/src/libscotchmetis/metis_graph_order_f.c new file mode 100644 index 00000000..44f23be4 --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/metis_graph_order_f.c @@ -0,0 +1,125 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : metis_graph_order_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API of **/ +/** the compatibility library for the **/ +/** MeTiS ordering routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 10 sep 2006 **/ +/** to 10 sep 2006 **/ +/** # Version 5.1 : from : 30 jun 2010 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "common.h" +#include "scotch.h" +#include "metis.h" /* Our "metis.h" file */ + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph ordering routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +METISNAMEU(METIS_EDGEND), METISNAMEL(metis_edgend), ( \ +const SCOTCH_Num * const n, \ +const SCOTCH_Num * const xadj, \ +const SCOTCH_Num * const adjncy, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const perm, \ +SCOTCH_Num * const iperm), \ +(n, xadj, adjncy, numflag, options, perm, iperm)) +{ + METISNAMEU(METIS_EdgeND) (n, xadj, adjncy, numflag, options, perm, iperm); +} + +/* +** +*/ + +FORTRAN ( \ +METISNAMEU(METIS_NODEND), METISNAMEL(metis_nodend), ( \ +const SCOTCH_Num * const n, \ +const SCOTCH_Num * const xadj, \ +const SCOTCH_Num * const adjncy, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const perm, \ +SCOTCH_Num * const iperm), \ +(n, xadj, adjncy, numflag, options, perm, iperm)) +{ + METISNAMEU(METIS_NodeND) (n, xadj, adjncy, numflag, options, perm, iperm); +} + +/* When an input stream is built from the given +** file handle, it is set as unbuffered, so as to +** allow for multiple stream reads from the same +** file handle. If it were buffered, too many +** input characters would be read on the first +** block read. +*/ + +FORTRAN ( \ +METISNAMEU(METIS_NODEWND), METISNAMEL(metis_nodewnd), ( \ +const SCOTCH_Num * const n, \ +const SCOTCH_Num * const xadj, \ +const SCOTCH_Num * const adjncy, \ +const SCOTCH_Num * const vwgt, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const perm, \ +SCOTCH_Num * const iperm), \ +(n, xadj, adjncy, vwgt, numflag, options, perm, iperm)) +{ + METISNAMEU(METIS_NodeWND) (n, xadj, adjncy, vwgt, numflag, options, perm, iperm); +} diff --git a/scotch_6.0.3/src/libscotchmetis/metis_graph_part.c b/scotch_6.0.3/src/libscotchmetis/metis_graph_part.c new file mode 100644 index 00000000..cc199ce0 --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/metis_graph_part.c @@ -0,0 +1,357 @@ +/* Copyright 2007-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : metis_graph_part.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the compatibility **/ +/** library for the MeTiS partitioning **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 08 sep 2006 **/ +/** to 07 jun 2007 **/ +/** # Version 5.1 : from : 06 jun 2009 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 23 dec 2011 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "metis.h" /* Our "metis.h" file */ + +/************************************/ +/* */ +/* These routines are the C API for */ +/* MeTiS graph ordering routines. */ +/* */ +/************************************/ + +/* This routine is the interface between MeTiS +** and Scotch. It computes the partition of a +** weighted or unweighted graph. +** It returns: +** - 0 : if the partition could be computed. +** - !0 : on error. +*/ + +static +int +_SCOTCH_METIS_PartGraph2 ( +const SCOTCH_Num * const n, +const SCOTCH_Num * const xadj, +const SCOTCH_Num * const adjncy, +const SCOTCH_Num * const vwgt, +const SCOTCH_Num * const adjwgt, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const nparts, +SCOTCH_Num * const part, +SCOTCH_Num flagval, +double kbalval) +{ + SCOTCH_Graph grafdat; /* Scotch graph object to interface with libScotch */ + SCOTCH_Strat stradat; + SCOTCH_Num baseval; + SCOTCH_Num vertnbr; + int o; + + SCOTCH_graphInit (&grafdat); + + baseval = *numflag; + vertnbr = *n; + + o = 1; /* Assume something will go wrong */ + if (SCOTCH_graphBuild (&grafdat, baseval, vertnbr, xadj, xadj + 1, vwgt, NULL, + xadj[vertnbr] - baseval, adjncy, adjwgt) == 0) { + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphMapBuild (&stradat, flagval, *nparts, kbalval); +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_graphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ +#endif /* SCOTCH_DEBUG_ALL */ + o = SCOTCH_graphPart (&grafdat, *nparts, &stradat, part); + SCOTCH_stratExit (&stradat); + } + SCOTCH_graphExit (&grafdat); + + if (o != 0) + return (1); + + if (baseval != 0) { /* MeTiS part array is based, Scotch is not */ + SCOTCH_Num vertnum; + + for (vertnum = 0; vertnum < vertnbr; vertnum ++) + part[vertnum] += baseval; + } + + return (0); +} + +/* +** +*/ + +static +void +_SCOTCH_METIS_PartGraph ( +const SCOTCH_Num * const n, +const SCOTCH_Num * const xadj, +const SCOTCH_Num * const adjncy, +const SCOTCH_Num * const vwgt, +const SCOTCH_Num * const adjwgt, +const SCOTCH_Num * const wgtflag, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const nparts, +const SCOTCH_Num * const options, +SCOTCH_Num * const edgecut, +SCOTCH_Num * const part, +SCOTCH_Num flagval, +double kbalval) +{ + const SCOTCH_Num * vwgt2; + const SCOTCH_Num * adjwgt2; + const SCOTCH_Num * restrict parttax; + const SCOTCH_Num * restrict verttax; + const SCOTCH_Num * restrict edgetax; + SCOTCH_Num vertnnd; + SCOTCH_Num vertnum; + SCOTCH_Num edgenum; + SCOTCH_Num commcut; + + vwgt2 = (((*wgtflag & 2) != 0) ? vwgt : NULL); + adjwgt2 = (((*wgtflag & 1) != 0) ? adjwgt : NULL); + + if (_SCOTCH_METIS_PartGraph2 (n, xadj, adjncy, vwgt2, adjwgt2, numflag, nparts, part, flagval, kbalval) != 0) { + *edgecut = -1; /* Indicate error */ + return; + } + + parttax = part - *numflag; + verttax = xadj - *numflag; + edgetax = adjncy - *numflag; + edgenum = *numflag; + vertnum = *numflag; + vertnnd = *n + vertnum; + commcut = 0; + + if (adjwgt2 == NULL) { /* If graph does not have edge weights */ + for ( ; vertnum < vertnnd; vertnum ++) { + SCOTCH_Num edgennd; + SCOTCH_Num partval; + + partval = parttax[vertnum]; + for (edgennd = verttax[vertnum + 1]; edgenum < edgennd; edgenum ++) { + if (parttax[edgetax[edgenum]] != partval) + commcut ++; + } + } + } + else { /* Graph has edge weights */ + const SCOTCH_Num * restrict edlotax; + + edlotax = adjwgt2 - *numflag; + for ( ; vertnum < vertnnd; vertnum ++) { + SCOTCH_Num edgennd; + SCOTCH_Num partval; + + partval = parttax[vertnum]; + for (edgennd = verttax[vertnum + 1]; edgenum < edgennd; edgenum ++) { + SCOTCH_Num vertend; + + vertend = edgetax[edgenum]; + if (parttax[vertend] != partval) + commcut += edlotax[edgenum]; + } + } + } + *edgecut = commcut / 2; +} + +/* +** +*/ + +void +METISNAMEU (METIS_PartGraphKway) ( +const SCOTCH_Num * const n, +const SCOTCH_Num * const xadj, +const SCOTCH_Num * const adjncy, +const SCOTCH_Num * const vwgt, +const SCOTCH_Num * const adjwgt, +const SCOTCH_Num * const wgtflag, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const nparts, +const SCOTCH_Num * const options, +SCOTCH_Num * const edgecut, +SCOTCH_Num * const part) +{ + _SCOTCH_METIS_PartGraph (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part, + SCOTCH_STRATDEFAULT, 0.01); +} + +void +METISNAMEU (METIS_PartGraphRecursive) ( +const SCOTCH_Num * const n, +const SCOTCH_Num * const xadj, +const SCOTCH_Num * const adjncy, +const SCOTCH_Num * const vwgt, +const SCOTCH_Num * const adjwgt, +const SCOTCH_Num * const wgtflag, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const nparts, +const SCOTCH_Num * const options, +SCOTCH_Num * const edgecut, +SCOTCH_Num * const part) +{ + _SCOTCH_METIS_PartGraph (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part, + SCOTCH_STRATRECURSIVE, 0.01); +} + +/* Scotch does not directly consider communication volume. +** Instead, wertex communication loads are added to the edge +** loads so as to emulate this behavior: heavily weighted +** edges, connected to heavily communicating vertices, will +** be less likely to be cut. +*/ + +void +METISNAMEU (METIS_PartGraphVKway) ( +const SCOTCH_Num * const n, +const SCOTCH_Num * const xadj, +const SCOTCH_Num * const adjncy, +const SCOTCH_Num * const vwgt, +const SCOTCH_Num * const vsize, +const SCOTCH_Num * const wgtflag, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const nparts, +const SCOTCH_Num * const options, +SCOTCH_Num * const volume, +SCOTCH_Num * const part) +{ + SCOTCH_Num baseval; + const SCOTCH_Num * vwgt2; + const SCOTCH_Num * vsize2; + SCOTCH_Num vsizval; /* Communication volume of current vertex */ + SCOTCH_Num vertnbr; + SCOTCH_Num vertnum; + SCOTCH_Num edgenum; + const SCOTCH_Num * restrict edgetax; + const SCOTCH_Num * restrict parttax; + SCOTCH_Num * restrict nghbtab; + SCOTCH_Num commvol; + + vsize2 = ((*wgtflag & 1) != 0) ? vsize : NULL; + vwgt2 = ((*wgtflag & 2) != 0) ? vwgt : NULL; + baseval = *numflag; + vertnbr = *n; + edgetax = adjncy - baseval; + + if (vsize2 == NULL) { /* If no communication load data provided */ + if (_SCOTCH_METIS_PartGraph2 (n, xadj, adjncy, vwgt2, NULL, numflag, nparts, part, SCOTCH_STRATDEFAULT, 0.01) != 0) + return; + } + else { /* Will have to turn communication volumes into edge loads */ + const SCOTCH_Num * restrict vsiztax; + SCOTCH_Num edgenbr; + SCOTCH_Num * restrict edlotax; + int o; + + edgenbr = xadj[vertnbr] - baseval; + if ((edlotax = memAlloc (edgenbr * sizeof (SCOTCH_Num))) == NULL) + return; + edlotax -= baseval; /* Base access to edlotax */ + vsiztax = vsize2 - baseval; + + for (vertnum = 0, edgenum = baseval; /* Un-based scan of vertex array xadj */ + vertnum < vertnbr; vertnum ++) { + SCOTCH_Num vsizval; /* Communication size of current vertex */ + SCOTCH_Num edgennd; + + vsizval = vsize2[vertnum]; + for (edgennd = xadj[vertnum + 1]; edgenum < edgennd; edgenum ++) { /* Based traversal of edge array adjncy */ + SCOTCH_Num vertend; /* Based end vertex number */ + + vertend = edgetax[edgenum]; + edlotax[edgenum] = vsizval + vsiztax[vertend]; + } + } + + o = _SCOTCH_METIS_PartGraph2 (n, xadj, adjncy, vwgt2, edlotax + baseval, numflag, nparts, part, + SCOTCH_STRATDEFAULT, 0.01); + + memFree (edlotax + baseval); + + if (o != 0) + return; + } + + if ((nghbtab = memAlloc (*nparts * sizeof (SCOTCH_Num))) == NULL) + return; + memSet (nghbtab, ~0, *nparts * sizeof (SCOTCH_Num)); + + parttax = part - baseval; + vsizval = 1; /* Assume no vertex communication sizes */ + for (vertnum = 0, edgenum = baseval, commvol = 0; /* Un-based scan of vertex array xadj */ + vertnum < vertnbr; vertnum ++) { + SCOTCH_Num partval; + SCOTCH_Num edgennd; + + partval = part[vertnum]; + nghbtab[partval] = vertnum; /* Do not count local neighbors in communication volume */ + if (vsize2 != NULL) + vsizval = vsize2[vertnum]; + + for (edgennd = xadj[vertnum + 1]; edgenum < edgennd; edgenum ++) { /* Based traversal of edge array adjncy */ + SCOTCH_Num vertend; /* Based end vertex number */ + SCOTCH_Num partend; + + vertend = edgetax[edgenum]; + partend = parttax[vertend]; + if (nghbtab[partend] != vertnum) { /* If first neighbor in this part */ + nghbtab[partend] = vertnum; /* Set part as accounted for */ + commvol += vsizval; + } + } + } + *volume = commvol; + + memFree (nghbtab); +} diff --git a/scotch_6.0.3/src/libscotchmetis/metis_graph_part_f.c b/scotch_6.0.3/src/libscotchmetis/metis_graph_part_f.c new file mode 100644 index 00000000..07f32a0a --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/metis_graph_part_f.c @@ -0,0 +1,132 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : metis_graph_part_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API of **/ +/** the compatibility library for the **/ +/** MeTiS partitioning routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 10 sep 2006 **/ +/** to 07 jun 2007 **/ +/** # Version 5.1 : from : 30 jun 2010 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "common.h" +#include "scotch.h" +#include "metis.h" /* Our "metis.h" file */ + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the graph ordering routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +METISNAMEU(METIS_PARTGRAPHKWAY), METISNAMEL(metis_partgraphkway), ( \ +const SCOTCH_Num * const n, \ +const SCOTCH_Num * const xadj, \ +const SCOTCH_Num * const adjncy, \ +const SCOTCH_Num * const vwgt, \ +const SCOTCH_Num * const adjwgt, \ +const SCOTCH_Num * const wgtflag, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const nparts, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const edgecut, \ +SCOTCH_Num * const part), \ +(n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part)) +{ + METISNAMEU(METIS_PartGraphKway) (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part); +} + +/* +** +*/ + +FORTRAN ( \ +METISNAMEU(METIS_PARTGRAPHRECURSIVE), METISNAMEL(metis_partgraphrecursive), ( \ +const SCOTCH_Num * const n, \ +const SCOTCH_Num * const xadj, \ +const SCOTCH_Num * const adjncy, \ +const SCOTCH_Num * const vwgt, \ +const SCOTCH_Num * const adjwgt, \ +const SCOTCH_Num * const wgtflag, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const nparts, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const edgecut, \ +SCOTCH_Num * const part), \ +(n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part)) +{ + METISNAMEU(METIS_PartGraphRecursive) (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part); +} + +/* +** +*/ + +FORTRAN ( \ +METISNAMEU(METIS_PARTGRAPHVKWAY), METISNAMEL(metis_partgraphvkway), ( \ +const SCOTCH_Num * const n, \ +const SCOTCH_Num * const xadj, \ +const SCOTCH_Num * const adjncy, \ +const SCOTCH_Num * const vwgt, \ +const SCOTCH_Num * const vsize, \ +const SCOTCH_Num * const wgtflag, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const nparts, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const volume, \ +SCOTCH_Num * const part), \ +(n, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, options, volume, part)) +{ + METISNAMEU(METIS_PartGraphVKway) (n, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, options, volume, part); +} diff --git a/scotch_6.0.3/src/libscotchmetis/parmetis.h b/scotch_6.0.3/src/libscotchmetis/parmetis.h new file mode 100644 index 00000000..ffc8bf2b --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/parmetis.h @@ -0,0 +1,100 @@ +/********************************************************* +** ** +** WARNING: THIS IS NOT THE ORIGINAL INCLUDE FILE OF ** +** THE ParMeTiS SOFTWARE PACKAGE. ** +** This file is a compatibility include file provided ** +** as part of the Scotch software distribution. ** +** Preferably use the original ParMeTiS include file ** +** to keep definitions of routines not overloaded by ** +** the libPTScotchMeTiS library. ** +** ** +*********************************************************/ +/* Copyright 2007,2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parmetis.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Compatibility declaration file for the **/ +/** MeTiS interface routines provided by **/ +/** the Scotch project. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 oct 2007 **/ +/** to 18 oct 2007 **/ +/** # Version 5.1 : from : 19 jun 2008 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#ifndef __parmetis_h__ +#define __parmetis_h__ + +#include /* Since ParMeTiS does it, do it too */ + +#endif /* __parmetis_h__ */ + +#ifdef SCOTCH_METIS_PREFIX +#define SCOTCH_METIS_PREFIXL scotch_ +#define SCOTCH_METIS_PREFIXU SCOTCH_ +#endif /* SCOTCH_METIS_PREFIX */ + +#ifndef SCOTCH_METIS_PREFIXL +#define SCOTCH_METIS_PREFIXL +#endif /* SCOTCH_METIS_PREFIXL */ + +#ifndef SCOTCH_METIS_PREFIXU +#define SCOTCH_METIS_PREFIXU +#endif /* SCOTCH_METIS_PREFIXU */ + +#ifndef METISNAMEL +#define METISNAMEL(s) METISNAME2(METISNAME3(SCOTCH_METIS_PREFIXL),s) +#define METISNAMEU(s) METISNAME2(METISNAME3(SCOTCH_METIS_PREFIXU),s) +#define METISNAME2(p,s) METISNAME4(p,s) +#define METISNAME3(s) s +#define METISNAME4(p,s) p##s +#endif /* METISNAMEL */ + +/* +** The function prototypes. +*/ + +void METISNAMEU(ParMETIS_V3_NodeND) (const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, MPI_Comm * const); +void METISNAMEU(ParMETIS_V3_PartGeomKway) (const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const float * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const float * const, const float * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, MPI_Comm * const); +void METISNAMEU(ParMETIS_V3_PartKway) (const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const float * const, const float * const, const SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, MPI_Comm * const); diff --git a/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_order.c b/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_order.c new file mode 100644 index 00000000..fd5fdc87 --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_order.c @@ -0,0 +1,220 @@ +/* Copyright 2007-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parmetis_dgraph_order.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the compatibility **/ +/** library for the ParMeTiS ordering **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 oct 2007 **/ +/** to 07 dec 2007 **/ +/** # Version 5.1 : from : 18 mar 2009 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" +#include "parmetis.h" /* Our "parmetis.h" file */ + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the ParMeTiS graph ordering */ +/* routine. */ +/* */ +/************************************/ + +static +void +_SCOTCH_ParMETIS_V3_NodeNDTree ( +SCOTCH_Num * const sizeglbtnd, +SCOTCH_Num * const sizeglbtab, +SCOTCH_Num * const sepaglbtab, +const SCOTCH_Num levlmax, +const SCOTCH_Num levlnum, +const SCOTCH_Num cblknum, +SCOTCH_Num cblkidx) +{ + SCOTCH_Num sizeval; + + sizeval = sizeglbtab[cblknum]; /* Assume node is terminal or has no nested dissection sons */ + if (levlnum < levlmax) { + if ((sepaglbtab[3 * cblknum] >= 0) && /* If node has at least two sons, assume is is a nested dissection node */ + (sepaglbtab[3 * cblknum + 1] >= 0)) { + _SCOTCH_ParMETIS_V3_NodeNDTree (sizeglbtnd, sizeglbtab, sepaglbtab, levlmax, levlnum + 1, sepaglbtab[3 * cblknum], (cblkidx << 1) + 1); + _SCOTCH_ParMETIS_V3_NodeNDTree (sizeglbtnd, sizeglbtab, sepaglbtab, levlmax, levlnum + 1, sepaglbtab[3 * cblknum + 1], (cblkidx << 1)); + sizeval = (sepaglbtab[3 * cblknum + 2] < 0) ? 0 : sizeglbtab[sepaglbtab[3 * cblknum + 2]]; /* Get size of separator, if any */ + } + } + + sizeglbtnd[- cblkidx] = sizeval; /* Set size of current column block */ +} + +/* +** +*/ + +void +METISNAMEU(ParMETIS_V3_NodeND) ( +const SCOTCH_Num * const vtxdist, +SCOTCH_Num * const xadj, +SCOTCH_Num * const adjncy, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const options, /* Not used */ +SCOTCH_Num * const order, +SCOTCH_Num * const sizes, /* Of size twice the number of processors ; not used */ +MPI_Comm * comm) +{ + MPI_Comm proccomm; + int procglbnbr; + int proclocnum; + SCOTCH_Num baseval; + SCOTCH_Dgraph grafdat; /* Scotch distributed graph object to interface with libScotch */ + SCOTCH_Dordering ordedat; /* Scotch distributed ordering object to interface with libScotch */ + SCOTCH_Strat stradat; + SCOTCH_Num vertlocnbr; + SCOTCH_Num edgelocnbr; + + proccomm = *comm; + if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) + return; + + MPI_Comm_size (proccomm, &procglbnbr); + MPI_Comm_rank (proccomm, &proclocnum); + baseval = *numflag; + vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; + edgelocnbr = xadj[vertlocnbr] - baseval; + + if (sizes != NULL) + memSet (sizes, ~0, (2 * procglbnbr - 1) * sizeof (SCOTCH_Num)); /* Array not used if procglbnbr is not a power of 2 or if error */ + + if (SCOTCH_dgraphBuild (&grafdat, baseval, + vertlocnbr, vertlocnbr, xadj, xadj + 1, NULL, NULL, + edgelocnbr, edgelocnbr, adjncy, NULL, NULL) == 0) { + SCOTCH_stratInit (&stradat); +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_dgraphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ +#endif /* SCOTCH_DEBUG_ALL */ + { + if (SCOTCH_dgraphOrderInit (&grafdat, &ordedat) == 0) { + SCOTCH_Num levlmax; + SCOTCH_Num bitsnbr; + SCOTCH_Num proctmp; + + SCOTCH_dgraphOrderCompute (&grafdat, &ordedat, &stradat); + SCOTCH_dgraphOrderPerm (&grafdat, &ordedat, order); + + for (levlmax = -1, bitsnbr = 0, proctmp = procglbnbr; /* Count number of bits set to 1 in procglbnbr */ + proctmp != 0; levlmax ++, proctmp >>= 1) + bitsnbr += proctmp & 1; + + if (bitsnbr == 1) { + SCOTCH_Num cblkglbnbr; + + if ((cblkglbnbr = SCOTCH_dgraphOrderCblkDist (&grafdat, &ordedat)) >= 0) { + SCOTCH_Num * treeglbtab; + SCOTCH_Num * sizeglbtab; + SCOTCH_Num * sepaglbtab; + + if (memAllocGroup ((void **) (void *) + &treeglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num)), + &sizeglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num)), + &sepaglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num) * 3), NULL) != NULL) { + if (SCOTCH_dgraphOrderTreeDist (&grafdat, &ordedat, treeglbtab, sizeglbtab) == 0) { + SCOTCH_Num rootnum; + SCOTCH_Num cblknum; + + memSet (sepaglbtab, ~0, cblkglbnbr * sizeof (SCOTCH_Num) * 3); + + for (rootnum = -1, cblknum = 0; cblknum < cblkglbnbr; cblknum ++) { + SCOTCH_Num fathnum; + + fathnum = treeglbtab[cblknum] - baseval; /* Use un-based indices */ + if (fathnum < 0) { /* If father index indicates root */ + if (rootnum != -1) { /* If another root already found */ + rootnum = -1; /* Indicate an error */ + break; + } + rootnum = cblknum; /* Record index of root node */ + } + else { + SCOTCH_Num i; + + for (i = 0; i < 3; i ++) { + SCOTCH_Num j; + + j = 3 * fathnum + i; /* Slot number of prospective son */ + if (sepaglbtab[j] < 0) { /* If potentially empty slot found */ + if (sepaglbtab[j] == -1) /* If we don't have too many sons */ + sepaglbtab[j] = cblknum; /* Add link to son in slot */ + break; + } + } + if (i == 3) { /* If no empty slot found */ + sepaglbtab[3 * fathnum] = -2; /* Indicate there are too many sons */ + break; + } + } + } + + if ((rootnum >= 0) && (sizes != NULL)) { /* If no error above, go on processing separator tree */ + memSet (sizes, 0, (2 * procglbnbr - 1) * sizeof (SCOTCH_Num)); /* Set array of sizes to 0 by default */ + _SCOTCH_ParMETIS_V3_NodeNDTree (sizes + (2 * procglbnbr - 1), sizeglbtab, sepaglbtab, levlmax, 0, rootnum, 1); + } + } + + memFree (treeglbtab); /* Free group leader */ + } + } + } + + SCOTCH_dgraphOrderExit (&grafdat, &ordedat); + } + } + SCOTCH_stratExit (&stradat); + } + SCOTCH_dgraphExit (&grafdat); +} diff --git a/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_order_f.c b/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_order_f.c new file mode 100644 index 00000000..4b3446c5 --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_order_f.c @@ -0,0 +1,86 @@ +/* Copyright 2007,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parmetis_dgraph_order_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API of **/ +/** the compatibility library for the **/ +/** ParMeTiS ordering routine. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 oct 2007 **/ +/** to 17 oct 2007 **/ +/** # Version 5.1 : from : 30 jun 2010 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "common.h" +#include "ptscotch.h" +#include "parmetis.h" /* Our "parmetis.h" file */ + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph ordering */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +METISNAMEU(PARMETIS_V3_NODEND), METISNAMEL(parmetis_v3_nodend), ( \ +const SCOTCH_Num * const vtxdist, \ +SCOTCH_Num * const xadj, \ +SCOTCH_Num * const adjncy, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const order, \ +SCOTCH_Num * const sizes, \ +MPI_Comm * const commptr), \ +(vtxdist, xadj, adjncy, numflag, options, order, sizes, commptr)) +{ + METISNAMEU(ParMETIS_V3_NodeND) (vtxdist, xadj, adjncy, numflag, options, order, sizes, commptr); +} diff --git a/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_part.c b/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_part.c new file mode 100644 index 00000000..1aad0d19 --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_part.c @@ -0,0 +1,196 @@ +/* Copyright 2008-2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parmetis_dgraph_part.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module is the compatibility **/ +/** library for the ParMeTiS ordering **/ +/** routines. **/ +/** **/ +/** DATES : # Version 5.1 : from : 19 jun 2008 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "module.h" +#include "common.h" +#include "ptscotch.h" +#include "parmetis.h" /* Our "parmetis.h" file */ + +/************************************/ +/* */ +/* These routines are the C API for */ +/* the ParMeTiS graph ordering */ +/* routine. */ +/* */ +/************************************/ + +void +METISNAMEU(ParMETIS_V3_PartKway) ( +const SCOTCH_Num * const vtxdist, +SCOTCH_Num * const xadj, +SCOTCH_Num * const adjncy, +SCOTCH_Num * const vwgt, +SCOTCH_Num * const adjwgt, +const SCOTCH_Num * const wgtflag, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const ncon, /* Not used */ +const SCOTCH_Num * const nparts, +const float * const tpwgts, +const float * const ubvec, /* Not used */ +const SCOTCH_Num * const options, /* Not used */ +SCOTCH_Num * const edgecut, +SCOTCH_Num * const part, +MPI_Comm * comm) +{ + MPI_Comm proccomm; + int procglbnbr; + int proclocnum; + SCOTCH_Num baseval; + SCOTCH_Arch archdat; + SCOTCH_Dgraph grafdat; /* Scotch distributed graph object to interface with libScotch */ + SCOTCH_Dmapping mappdat; /* Scotch distributed mapping object to interface with libScotch */ + SCOTCH_Strat stradat; + SCOTCH_Num vertlocnbr; + SCOTCH_Num * veloloctab; + SCOTCH_Num edgelocnbr; + SCOTCH_Num * edloloctab; + SCOTCH_Num * velotab; + double * vwgttab; + SCOTCH_Num i; + + if ((vwgttab = malloc (*nparts * sizeof (double))) == NULL) + return; + if ((velotab = malloc (*nparts * sizeof (SCOTCH_Num))) == NULL) { + free (vwgttab); + return; + } + for (i = 0; i < *nparts; i ++) + vwgttab[i] = (double) tpwgts[i] * (double) (*nparts); + for (i = 0; i < *nparts; i ++) { + double deltval; + deltval = fabs (vwgttab[i] - floor (vwgttab[i] + 0.5)); + if (deltval > 0.01) { + SCOTCH_Num j; + + deltval = 1.0 / deltval; + for (j = 0; j < *nparts; j ++) + vwgttab[j] *= deltval; + } + } + for (i = 0; i < *nparts; i ++) + velotab[i] = (SCOTCH_Num) (vwgttab[i] + 0.5); + + proccomm = *comm; + if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) + return; + + MPI_Comm_size (proccomm, &procglbnbr); + MPI_Comm_rank (proccomm, &proclocnum); + baseval = *numflag; + vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; + edgelocnbr = xadj[vertlocnbr] - baseval; + veloloctab = ((vwgt != NULL) && ((*wgtflag & 2) != 0)) ? vwgt : NULL; + edloloctab = ((adjwgt != NULL) && ((*wgtflag & 1) != 0)) ? adjwgt : NULL; + + if (SCOTCH_dgraphBuild (&grafdat, baseval, + vertlocnbr, vertlocnbr, xadj, xadj + 1, veloloctab, NULL, + edgelocnbr, edgelocnbr, adjncy, NULL, edloloctab) == 0) { + SCOTCH_stratInit (&stradat); +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_dgraphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ +#endif /* SCOTCH_DEBUG_ALL */ + { + SCOTCH_archInit (&archdat); + + if ((SCOTCH_archCmpltw (&archdat, *nparts, velotab) == 0) && + (SCOTCH_dgraphMapInit (&grafdat, &mappdat, &archdat, part) == 0)) { + SCOTCH_dgraphMapCompute (&grafdat, &mappdat, &stradat); + + SCOTCH_dgraphMapExit (&grafdat, &mappdat); + } + SCOTCH_archExit (&archdat); + } + SCOTCH_stratExit (&stradat); + } + SCOTCH_dgraphExit (&grafdat); + + *edgecut = 0; /* TODO : compute real edge cut for people who might want it */ + + free (vwgttab); + free (velotab); + + if (baseval != 0) { /* MeTiS part array is based, Scotch is not */ + SCOTCH_Num vertlocnum; + + for (vertlocnum = 0; vertlocnum < vertlocnbr; vertlocnum ++) + part[vertlocnum] += baseval; + } +} + +/* +** +*/ + +void +METISNAMEU(ParMETIS_V3_PartGeomKway) ( +const SCOTCH_Num * const vtxdist, +SCOTCH_Num * const xadj, +SCOTCH_Num * const adjncy, +SCOTCH_Num * const vwgt, +SCOTCH_Num * const adjwgt, +const SCOTCH_Num * const wgtflag, +const SCOTCH_Num * const numflag, +const SCOTCH_Num * const ndims, /* Not used */ +const float * const xyz, /* Not used */ +const SCOTCH_Num * const ncon, /* Not used */ +const SCOTCH_Num * const nparts, +const float * const tpwgts, +const float * const ubvec, +const SCOTCH_Num * const options, /* Not used */ +SCOTCH_Num * const edgecut, +SCOTCH_Num * const part, +MPI_Comm * commptr) +{ + METISNAMEU(ParMETIS_V3_PartKway) (vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr); +} diff --git a/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_part_f.c b/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_part_f.c new file mode 100644 index 00000000..e46f7974 --- /dev/null +++ b/scotch_6.0.3/src/libscotchmetis/parmetis_dgraph_part_f.c @@ -0,0 +1,119 @@ +/* Copyright 2008,2010,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : parmetis_dgraph_part_f.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the Fortran API of **/ +/** the compatibility library for the **/ +/** ParMeTiS partitioning routine. **/ +/** **/ +/** DATES : # Version 5.1 : from : 19 jun 2008 **/ +/** to 30 jun 2010 **/ +/** # Version 6.0 : from : 13 sep 2012 **/ +/** to 13 sep 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define LIBRARY + +#include "common.h" +#include "ptscotch.h" +#include "parmetis.h" /* Our "parmetis.h" file */ + +/**************************************/ +/* */ +/* These routines are the Fortran API */ +/* for the distributed graph ordering */ +/* routines. */ +/* */ +/**************************************/ + +/* +** +*/ + +FORTRAN ( \ +METISNAMEU(PARMETIS_V3_PARTKWAY), METISNAMEL(parmetis_v3_partkway), ( \ +const SCOTCH_Num * const vtxdist, \ +SCOTCH_Num * const xadj, \ +SCOTCH_Num * const adjncy, \ +SCOTCH_Num * const vwgt, \ +SCOTCH_Num * const adjwgt, \ +const SCOTCH_Num * const wgtflag, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const ncon, \ +const SCOTCH_Num * const nparts, \ +const float * const tpwgts, \ +const float * const ubvec, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const edgecut, \ +SCOTCH_Num * const part, \ +MPI_Comm * const commptr), \ +(vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr)) +{ + METISNAMEU(ParMETIS_V3_PartKway) (vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr); +} + +/* +** +*/ + +FORTRAN ( \ +METISNAMEU(PARMETIS_V3_PARTGEOMKWAY), METISNAMEL(parmetis_v3_partgeomkway), ( \ +const SCOTCH_Num * const vtxdist, \ +SCOTCH_Num * const xadj, \ +SCOTCH_Num * const adjncy, \ +SCOTCH_Num * const vwgt, \ +SCOTCH_Num * const adjwgt, \ +const SCOTCH_Num * const wgtflag, \ +const SCOTCH_Num * const numflag, \ +const SCOTCH_Num * const ndims, \ +const float * const xyz, \ +const SCOTCH_Num * const ncon, \ +const SCOTCH_Num * const nparts, \ +const float * const tpwgts, \ +const float * const ubvec, \ +const SCOTCH_Num * const options, \ +SCOTCH_Num * const edgecut, \ +SCOTCH_Num * const part, \ +MPI_Comm * const commptr), \ +(vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ndims, xyz, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr)) +{ + METISNAMEU(ParMETIS_V3_PartGeomKway) (vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ndims, xyz, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr); +} diff --git a/scotch_6.0.3/src/misc/pthread.h b/scotch_6.0.3/src/misc/pthread.h new file mode 100644 index 00000000..7fe9eba8 --- /dev/null +++ b/scotch_6.0.3/src/misc/pthread.h @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2004-2012 Samuel Thibault + * All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY Samuel Thibault ``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 REGENTS 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. + */ + +/* This is a minimal pthread implementation based on windows functions. + * It is *not* intended to be complete - just complete enough to get + * simple applications running. + */ + +#ifndef _WIN_PTHREAD_PTHREAD_H +#define _WIN_PTHREAD_PTHREAD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include +#include + +#ifdef __CYGWIN32__ +#include +#define unixErrno() cygwin_internal(CW_GET_ERRNO_FROM_WINERROR, (GetLastError()) +#else +#define unixErrno() win_toErrno(GetLastError()) +#endif + +#define setSystemErrno() errno = unixErrno() +#define winPthreadAssertWindows(expr) do { if (!(expr)) { setSystemErrno(); return errno; } } while (0) +#define winPthreadAssertPthread(expr) do { int ret = (expr); if (ret) return ret; } while (0) +#define winPthreadAssert(expr) do { if (!(expr)) return EIO; } while (0) + +/*********** + * threads * + ***********/ + +typedef DWORD pthread_attr_t; +typedef HANDLE pthread_t; + +static inline pthread_t pthread_self(void) { + return GetCurrentThread(); +} + +static inline int pthread_equal(pthread_t t1, pthread_t t2) { + return t1 == t2; +} + +static inline int pthread_attr_init (pthread_attr_t *attr) { + *attr = 0; + return 0; +} + +#define PTHREAD_CREATE_DETACHED 1 +static inline int pthread_attr_setdetachstate (pthread_attr_t *attr, int yes) { + (void)attr; + (void)yes; + /* not supported, ignore */ + return 0; +} + +static inline int pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize) { + (void)attr; + (void)stacksize; + /* not supported, ignore */ + return 0; +} + +static inline int pthread_attr_destroy (pthread_attr_t *attr) { + (void)attr; + return 0; +} + +/* "real" cleanup handling not yet implemented */ +typedef struct { + void (*routine) (void *); + void *arg; +} __pthread_cleanup_handler; + +void pthread_cleanup_push (void (*routine) (void *), void *arg); +#define pthread_cleanup_push(routine, arg) do { \ + __pthread_cleanup_handler __cleanup_handler = {routine, arg}; + +void pthread_cleanup_pop (int execute); +#define pthread_cleanup_pop(execute) \ + if (execute) __cleanup_handler.routine(__cleanup_handler.arg); \ +} while (0); + +static inline int pthread_create ( + pthread_t *thread, const pthread_attr_t *attr, + void * (*fun) (void *), void *arg +) { + if (attr && *attr) + return EINVAL; + winPthreadAssertWindows(*thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) fun, arg, 0, NULL)); + return 0; +} + +static inline int pthread_setcancelstate (int state, int *oldstate) { + (void)state; + (void)oldstate; + /* not yet implemented :( */ + return 0; +} + +static inline int pthread_cancel (pthread_t thread) { + /* This is quite harsh :( */ + winPthreadAssertWindows(TerminateThread(thread, 0)); + return 0; +} + +static inline void pthread_exit (void *res) { + ExitThread((DWORD) (DWORD_PTR) res); +} + +static inline int pthread_join (pthread_t thread, void **res) { +again: + switch (WaitForSingleObject(thread, INFINITE)) { + default: + case WAIT_FAILED: + return unixErrno(); + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + break; + case WAIT_TIMEOUT: + goto again; + } + if (res) { + DWORD _res; + if (GetExitCodeThread(thread, &_res)) + *res = (void *)(DWORD_PTR)_res; + } + return 0; +} + +/*********** + * mutexes * + ***********/ + +#define PTHREAD_MUTEX_INITIALIZER NULL +typedef HANDLE pthread_mutex_t; +#define PTHREAD_MUTEX_RECURSIVE 1 +#define PTHREAD_MUTEX_ERRORCHECK 2 +typedef int pthread_mutexattr_t; + +static inline int pthread_mutexattr_init(pthread_mutexattr_t *attr) { + *attr = PTHREAD_MUTEX_RECURSIVE; + return 0; +} + +static inline int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { + if (type != PTHREAD_MUTEX_RECURSIVE && type != PTHREAD_MUTEX_ERRORCHECK) + return EINVAL; + *attr = type; + return 0; +} + +static inline int pthread_mutex_init (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) { + if (attr && *attr!=PTHREAD_MUTEX_RECURSIVE) + return EINVAL; + winPthreadAssertWindows(*mutex = CreateMutex(NULL, FALSE, NULL)); + return 0; +} + +static inline int pthread_mutex_unlock (pthread_mutex_t *mutex) { + winPthreadAssertWindows(ReleaseMutex(*mutex)); + return 0; +} + +static inline int pthread_mutex_lock (pthread_mutex_t *mutex); +static inline int __pthread_mutex_alloc_concurrently (pthread_mutex_t *mutex) { + HANDLE mutex_init_mutex; + /* Get access to one global named mutex to serialize mutex initialization */ + winPthreadAssertWindows((mutex_init_mutex = CreateMutex(NULL, FALSE, "StarPU mutex init"))); + winPthreadAssertPthread(pthread_mutex_lock(&mutex_init_mutex)); + /* Now we are the one that can initialize it */ + if (!*mutex) + winPthreadAssertPthread(pthread_mutex_init(mutex,NULL)); + winPthreadAssertPthread(pthread_mutex_unlock(&mutex_init_mutex)); + winPthreadAssertWindows(CloseHandle(mutex_init_mutex)); + return 0; +} + +static inline int pthread_mutex_lock (pthread_mutex_t *mutex) { + if (!*mutex) + __pthread_mutex_alloc_concurrently (mutex); +again: + switch (WaitForSingleObject(*mutex, INFINITE)) { + default: + case WAIT_FAILED: + return unixErrno();; + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + return 0; + case WAIT_TIMEOUT: + goto again; + } +} + +static inline int pthread_mutex_trylock (pthread_mutex_t *mutex) { + if (!*mutex) + __pthread_mutex_alloc_concurrently (mutex); + switch (WaitForSingleObject(*mutex, 0)) { + default: + case WAIT_FAILED: + return unixErrno(); + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + return 0; + case WAIT_TIMEOUT: + return EBUSY; + } +} + +static inline int pthread_mutex_destroy (pthread_mutex_t *mutex) { + winPthreadAssertWindows(CloseHandle(*mutex)); + *mutex = INVALID_HANDLE_VALUE; + return 0; +} + +/******************************************** + * rwlock * + * VERY LAZY, don't even look at it please! * + * Should be fine unoptimized for now. * + * TODO: FIXME, using conds for instance? * + ********************************************/ + +#define PTHREAD_RWLOCK_INITIALIZER NULL +typedef pthread_mutex_t pthread_rwlock_t; +#define pthread_rwlock_init(lock, attr) pthread_mutex_init(lock, NULL) +#define pthread_rwlock_wrlock(lock) pthread_mutex_lock(lock) +#define pthread_rwlock_rdlock(lock) pthread_mutex_lock(lock) +#define pthread_rwlock_unlock(lock) pthread_mutex_unlock(lock) +#define pthread_rwlock_destroy(lock) pthread_mutex_destroy(lock) + +/************** + * conditions * + **************/ + +typedef struct { + HANDLE sem; + volatile unsigned nbwait; +} pthread_cond_t; +#define PTHREAD_COND_INITIALIZER { NULL, 0} + +#ifndef _TIMESPEC_DEFINED +struct timespec { + time_t tv_sec; /* Seconds */ + long tv_nsec; /* Nanoseconds */ +}; +#endif + +typedef unsigned pthread_condattr_t; + +static inline int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr) { + if (attr) + return EINVAL; + winPthreadAssertWindows(cond->sem = CreateSemaphore(NULL, 0, MAXLONG, NULL)); + cond->nbwait = 0; + return 0; +} + +static inline int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *time) { + if (!cond->sem) + winPthreadAssertPthread(pthread_cond_init(cond,NULL)); + cond->nbwait++; + winPthreadAssertPthread(pthread_mutex_unlock(mutex)); +again: + switch (WaitForSingleObject(cond->sem, time->tv_sec*1000+time->tv_nsec/1000)) { + default: + case WAIT_FAILED: + { + int error = unixErrno(); + winPthreadAssertPthread(pthread_mutex_lock(mutex)); + return error; + } + case WAIT_TIMEOUT: + goto again; + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + break; + } + winPthreadAssertPthread(pthread_mutex_lock(mutex)); + cond->nbwait--; + return 0; +} + +static inline int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) { + if (!cond->sem) + winPthreadAssertPthread(pthread_cond_init(cond,NULL)); + cond->nbwait++; + winPthreadAssertPthread(pthread_mutex_unlock(mutex)); +again: + switch (WaitForSingleObject(cond->sem, INFINITE)) { + case WAIT_FAILED: + { + int error; + error = unixErrno(); + winPthreadAssertPthread(pthread_mutex_lock(mutex)); + return error; + } + case WAIT_TIMEOUT: + goto again; + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + break; + } + winPthreadAssertPthread(pthread_mutex_lock(mutex)); + cond->nbwait--; + return 0; +} + +static inline int pthread_cond_signal (pthread_cond_t *cond) { + if (!cond->sem) + winPthreadAssertPthread(pthread_cond_init(cond,NULL)); + if (cond->nbwait) + ReleaseSemaphore(cond->sem, 1, NULL); + return 0; +} + +static inline int pthread_cond_broadcast (pthread_cond_t *cond) { + if (!cond->sem) + winPthreadAssertPthread(pthread_cond_init(cond,NULL)); + ReleaseSemaphore(cond->sem, cond->nbwait, NULL); + return 0; +} + +static inline int pthread_cond_destroy (pthread_cond_t *cond) { + if (cond->sem) { + winPthreadAssertWindows(CloseHandle(cond->sem)); + cond->sem = NULL; + } + return 0; +} + +/******* + * TLS * + *******/ + +typedef DWORD pthread_key_t; +#define PTHREAD_ONCE_INIT {PTHREAD_MUTEX_INITIALIZER, 0} +typedef struct { + pthread_mutex_t mutex; + unsigned done; +} pthread_once_t; + +static inline int pthread_once (pthread_once_t *once, void (*oncefun)(void)) { + winPthreadAssertPthread(pthread_mutex_lock(&once->mutex)); + if (!once->done) { + oncefun(); + once->done = 1; + } + winPthreadAssertPthread(pthread_mutex_unlock(&once->mutex)); + return 0; +} + +static inline int pthread_key_create (pthread_key_t *key, void (*freefun)(void *)) { + (void)freefun; + DWORD res; + winPthreadAssertWindows((res = TlsAlloc()) != 0xFFFFFFFF); + *key = res; + return 0; +} + +static inline int pthread_key_delete (pthread_key_t key) { + winPthreadAssertWindows(TlsFree(key)); + return 0; +} + +static inline void *pthread_getspecific (pthread_key_t key) { + return TlsGetValue(key); +} + +static inline int pthread_setspecific (pthread_key_t key, const void *data) { + winPthreadAssertWindows(TlsSetValue(key, (LPVOID) data)); + return 0; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _WIN_PTHREAD_PTHREAD_H */ diff --git a/scotch_6.0.3/src/misc/scotch_5.1.12_openmpi.spec b/scotch_6.0.3/src/misc/scotch_5.1.12_openmpi.spec new file mode 100644 index 00000000..b59e5835 --- /dev/null +++ b/scotch_6.0.3/src/misc/scotch_5.1.12_openmpi.spec @@ -0,0 +1,220 @@ +# RPM spec file for Scotch, tested on RHEL 5 & 6. +# Licence: CeCILL-C + +# Build PT-Scotch stuff with openmpi. Probably there should be an mpich +# version too, but we don't use mpich. +# The mpiwrappers-openmpi-devel required on RHEL5 is in the EPEL repo. +%bcond_with openmpi + +# fixme: Is there a better way? +%define rhel5 %(fgrep -q ' 5.' /etc/redhat-release 2>/dev/null && echo 1) + +Name: scotch +# The original tar file was called 5.1.12b, but unpacks into 5.1.12, so it +# was re-named. +Version: 5.1.12 +Release: 1%{?dist} +Summary: programs and libraries for graph, mesh and hypergraph partitioning +Group: Applications/Engineering +License: CeCILL-C +URL: https://gforge.inria.fr/projects/scotch +Source0: https://gforge.inria.fr/frs/download.php/28925/scotch_%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +BuildRequires: gcc, make, binutils, bison, flex +%if %{with openmpi} +%if 0%rhel5 +BuildRequires: mpiwrappers-openmpi-devel +%else +BuildRequires: openmpi-devel +%endif +%endif + +# Cribbed from the Debian package +%description +Scotch is a software package for graph and mesh/hypergraph partitioning, +graph clustering, and sparse matrix ordering. + +Its purpose is to apply graph theory, with a divide and conquer +approach, to scientific computing problems such as graph and mesh +partitioning, static mapping, and sparse matrix ordering, in +application domains ranging from structural mechanics to operating +systems or bio-chemistry. + +The SCOTCH distribution is a set of programs and libraries which +implement the static mapping and sparse matrix reordering algorithms +developed within the SCOTCH project. + +SCOTCH has many interesting features: + +o Its capabilities can be used through a set of stand-alone programs +as well as through the libSCOTCH library, which offers both C and +Fortran interfaces. + +o It provides algorithms to partition graph structures, as well as +mesh structures defined as node-element bipartite graphs and which +can also represent hypergraphs. + +o It can map any weighted source graph onto any weighted target +graph. The source and target graphs may have any topology, and their +vertices and edges may be weighted. Moreover, both source and target +graphs may be disconnected. This feature allows for the mapping of +programs onto disconnected subparts of a parallel architecture made +up of heterogeneous processors and communication links. + +o It computes amalgamated block orderings of sparse matrices, for +efficient solving using BLAS routines. + +o Its running time is linear in the number of edges of the source +graph, and logarithmic in the number of vertices of the target graph +for mapping computations. + +o It can handle indifferently graph and mesh data structures created +within C or Fortran programs, with array indices starting from 0 or +1. + +o It offers extended support for adaptive graphs and meshes through +the handling of disjoint edge arrays. + +o It is dynamically parametrizable thanks to strategy strings that +are interpreted at run-time. + +o It uses system memory efficiently, to process large graphs and +meshes without incurring out-of-memory faults; + +o It can be easily interfaced to other programs. The programs +comprising the SCOTCH project have been designed to run in +command-line mode without any interactive prompting, so that they can +be called easily from other programs by means of system() or popen() +calls, or piped together on a single command line. Moreover, vertex +labeling capabilities allow for easy renumbering of vertices. + +o It provides many tools to build, check, and display graphs, meshes +and matrix patterns. + +%package libs +Summary: Shared library files for scotch. +Group: Applications/Engineering + +%description libs +Scotch is a software package for graph and mesh/hypergraph partitioning, +graph clustering, and sparse matrix ordering. +This package contains its library files. + +%package devel +Summary: Development files for the scotch library. +Group: Applications/Engineering +Requires: %{name}-libs = %{version}-%{release} + +%description devel +Scotch is a software package for graph and mesh/hypergraph partitioning, +graph clustering, and sparse matrix ordering. +This package contains development files. + +%if %{with openmpi} +%package pt +Summary: PT-Scotch (parallel programs). +Group: Applications/Engineering + +%description pt +Scotch is a software package for graph and mesh/hypergraph partitioning, +graph clustering, and sparse matrix ordering. +This package contains the MPI-based programs. + +%package ptlibs +Summary: Shared library files for ptscotch. +Group: Applications/Engineering + +%description ptlibs +Scotch is a software package for graph and mesh/hypergraph partitioning, +graph clustering, and sparse matrix ordering. +This package contains the MPI-based libraries. +%endif + +%prep +%setup -q -n %{name}_%{version} +cat >src/Makefile.inc < - 5.1.12b-1 +- Initial packaging diff --git a/scotch_6.0.3/src/misc/semaphore.h b/scotch_6.0.3/src/misc/semaphore.h new file mode 100644 index 00000000..511163ef --- /dev/null +++ b/scotch_6.0.3/src/misc/semaphore.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2004-2012 Samuel Thibault + * All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY Samuel Thibault ``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 REGENTS 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. + */ + +/* This is a minimal pthread implementation based on windows functions. + * It is *not* intended to be complete - just complete enough to get + * simple applications running. + */ + +#ifndef _WIN_PTHREAD_SEMAPHORE_H +#define _WIN_PTHREAD_SEMAPHORE_H + +#include "pthread.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************** + * semaphores * + **************/ + +typedef HANDLE sem_t; + +static inline int sem_init(sem_t *sem, int pshared, unsigned int value) { + (void)pshared; + winPthreadAssertWindows(*sem = CreateSemaphore(NULL, value, MAXLONG, NULL)); + return 0; +} + +static inline int do_sem_wait(sem_t *sem, DWORD timeout) { + switch (WaitForSingleObject(*sem, timeout)) { + default: + case WAIT_FAILED: + setSystemErrno(); + return -1; + case WAIT_TIMEOUT: + errno = EAGAIN; + return -1; + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + return 0; + } +} + +#define sem_wait(sem) do_sem_wait(sem, INFINITE) +#define sem_trywait(sem) do_sem_wait(sem, 0) + +static inline int sem_post(sem_t *sem) { + winPthreadAssertWindows(ReleaseSemaphore(*sem, 1, NULL)); + return 0; +} + +static inline int sem_destroy(sem_t *sem) { + winPthreadAssertWindows(CloseHandle(*sem)); + return 0; +} + +#endif /* _WIN_PTHREAD_SEMAPHORE_H */ diff --git a/scotch_6.0.3/src/scotch/Makefile b/scotch_6.0.3/src/scotch/Makefile new file mode 100644 index 00000000..e1862420 --- /dev/null +++ b/scotch_6.0.3/src/scotch/Makefile @@ -0,0 +1,383 @@ +## Copyright 2004,2007-2012 IPB, Universite de Bordeaux, INRIA & CNRS +## +## This file is part of the Scotch software package for static mapping, +## graph partitioning and sparse matrix ordering. +## +## This software is governed by the CeCILL-C license under French law +## and abiding by the rules of distribution of free software. You can +## use, modify and/or redistribute the software under the terms of the +## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +## URL: "http://www.cecill.info". +## +## As a counterpart to the access to the source code and rights to copy, +## modify and redistribute granted by the license, users are provided +## only with a limited warranty and the software's author, the holder of +## the economic rights, and the successive licensors have only limited +## liability. +## +## In this respect, the user's attention is drawn to the risks associated +## with loading, using, modifying and/or developing or reproducing the +## software by the user in light of its specific status of free software, +## that may mean that it is complicated to manipulate, and that also +## therefore means that it is reserved for developers and experienced +## professionals having in-depth computer knowledge. Users are therefore +## encouraged to load and test the software's suitability as regards +## their requirements in conditions enabling the security of their +## systems and/or data to be ensured and, more generally, to use and +## operate it in the same conditions as regards security. +## +## The fact that you are presently reading this means that you have had +## knowledge of the CeCILL-C license and that you accept its terms. +## + +bindir = ../../bin +includedir = ../../include +libdir = ../../lib + +## +## General inference rules. +## + +include ../Makefile.inc + +%$(EXE) : %$(OBJ) + $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -o $(@) -L$(libdir) -l$(SCOTCHLIB) -lscotch -l$(SCOTCHLIB)errexit $(LDFLAGS) + +%$(OBJ) : %.c + $(CC) $(CFLAGS) -I$(includedir) -I../libscotch -c $(<) -o $(@) + +%$(EXE) : %.c + $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -o $(@) -L$(libdir) -l$(SCOTCHLIB) -lscotch -l$(SCOTCHLIB)errexit $(LDFLAGS) + +## +## Project rules. +## + +.PHONY : ptscotch scotch ptinstall install clean realclean + +scotch : + $(MAKE) CC="$(CCS)" SCOTCHLIB=scotch \ + acpl$(EXE) \ + amk_ccc$(EXE) \ + amk_fft2$(EXE) \ + amk_grf$(EXE) \ + amk_hy$(EXE) \ + amk_m2$(EXE) \ + amk_p2$(EXE) \ + atst$(EXE) \ + gbase$(EXE) \ + gcv$(EXE) \ + gmap$(EXE) \ + gmk_hy$(EXE) \ + gmk_m2$(EXE) \ + gmk_m3$(EXE) \ + gmk_msh$(EXE) \ + gmk_ub2$(EXE) \ + gmtst$(EXE) \ + gord$(EXE) \ + gotst$(EXE) \ + gout$(EXE) \ + gpart$(EXE) \ + gscat$(EXE) \ + gtst$(EXE) \ + mcv$(EXE) \ + mmk_m2$(EXE) \ + mmk_m3$(EXE) \ + mord$(EXE) \ + mtst$(EXE) + +ptscotch : + $(MAKE) CC="$(CCP)" SCOTCHLIB=ptscotch \ + dggath$(EXE) \ + dgmap$(EXE) \ + dgord$(EXE) \ + dgpart$(EXE) \ + dgscat$(EXE) \ + dgtst$(EXE) + +install : scotch + -$(CP) acpl$(EXE) amk_ccc$(EXE) amk_fft2$(EXE) amk_grf$(EXE) amk_hy$(EXE) amk_m2$(EXE) amk_p2$(EXE) atst$(EXE) gbase$(EXE) gcv$(EXE) gmap$(EXE) gmk_hy$(EXE) gmk_m2$(EXE) gmk_m3$(EXE) gmk_msh$(EXE) gmk_ub2$(EXE) gmtst$(EXE) gord$(EXE) gotst$(EXE) gout$(EXE) gpart$(EXE) *gtst$(EXE) gscat$(EXE) mcv$(EXE) mmk_m2$(EXE) mmk_m3$(EXE) mord$(EXE) mtst$(EXE) $(bindir) + +ptinstall : ptscotch + -$(CP) dggath$(EXE) dgmap$(EXE) dgord$(EXE) dgpart$(EXE) dgscat$(EXE) dgtst$(EXE) $(bindir) + +clean : + -$(RM) *~ *$(OBJ) acpl$(EXE) amk_ccc$(EXE) amk_fft2$(EXE) amk_grf$(EXE) amk_hy$(EXE) amk_m2$(EXE) amk_p2$(EXE) atst$(EXE) gbase$(EXE) gcv$(EXE) *ggath$(EXE) *gmap$(EXE) gmk_hy$(EXE) gmk_m2$(EXE) gmk_m3$(EXE) gmk_msh$(EXE) gmk_ub2$(EXE) gmtst$(EXE) *gord$(EXE) gotst$(EXE) gout$(EXE) *gpart$(EXE) *gscat$(EXE) *gtst$(EXE) mcv$(EXE) mmk_m2$(EXE) mmk_m3$(EXE) mord$(EXE) mtst$(EXE) + +realclean : clean + +## +## Todo list. +## + +acpl$(EXE) : acpl.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + acpl.h + +amk_ccc$(EXE) : amk_ccc.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + amk_ccc.h + +amk_fft2$(EXE) : amk_fft2.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + amk_fft2.h + +amk_grf$(EXE) : amk_grf.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + amk_grf.h + +amk_hy$(EXE) : amk_hy.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + amk_hy.h + +amk_m2$(EXE) : amk_m2.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + amk_m2.h + +amk_p2$(EXE) : amk_p2.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + amk_p2.h + +atst$(EXE) : atst.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + atst.h + +dggath$(EXE) : dggath.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + $(libdir)/libptscotch$(LIB) \ + $(libdir)/libptscotcherrexit$(LIB) \ + dggath.h + +dgmap$(EXE) : dgmap.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + $(libdir)/libptscotch$(LIB) \ + $(libdir)/libptscotcherrexit$(LIB) \ + dgmap.h + +dgord$(EXE) : dgord.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + $(libdir)/libptscotch$(LIB) \ + $(libdir)/libptscotcherrexit$(LIB) \ + dgord.h + +dgpart$(EXE) : dgmap.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + $(libdir)/libptscotch$(LIB) \ + $(libdir)/libptscotcherrexit$(LIB) \ + dgmap.h + $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -DSCOTCH_COMPILE_PART -o $(@) -L$(libdir) -lptscotch -lscotch -lptscotcherrexit $(LDFLAGS) + +dgscat$(EXE) : dgscat.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + $(libdir)/libptscotch$(LIB) \ + $(libdir)/libptscotcherrexit$(LIB) \ + dgscat.h + +dgtst$(EXE) : dgtst.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/ptscotch.h \ + $(libdir)/libptscotch$(LIB) \ + $(libdir)/libptscotcherrexit$(LIB) \ + dgtst.h + +gbase$(EXE) : gbase.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gbase.h + +gcv$(EXE) : gcv.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gcv.h + +gmap$(EXE) : gmap.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gmap.h + +gmk_hy$(EXE) : gmk_hy.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gmk_hy.h + +gmk_m2$(EXE) : gmk_m2.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gmk_m2.h + +gmk_m3$(EXE) : gmk_m3.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gmk_m3.h + +gmk_msh$(EXE) : gmk_msh.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gmk_msh.h + +gmk_ub2$(EXE) : gmk_ub2.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gmk_ub2.h + +gmtst$(EXE) : gmtst.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gmtst.h + +gord$(EXE) : gord.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gord.h + +gotst$(EXE) : gotst.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gotst.h + +gout$(EXE) : gout_c.c \ + gout_o.c \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) + $(CC) $(CFLAGS) -I../libscotch -I$(includedir) gout_c.c gout_o.c -o $(@) -L$(libdir) -lscotch -lscotcherrexit $(LDFLAGS) + +gpart$(EXE) : gmap.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gmap.h + $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -DSCOTCH_COMPILE_PART -o $(@) -L$(libdir) -lscotch -lscotcherrexit $(LDFLAGS) + +gscat$(EXE) : gscat.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gscat.h + +gtst$(EXE) : gtst.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + gtst.h + +mcv$(EXE) : mcv.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + mcv.h + +mmk_m2$(EXE) : mmk_m2.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + mmk_m2.h + +mmk_m3$(EXE) : mmk_m3.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + mmk_m3.h + +mord$(EXE) : mord.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + mord.h + +mtst$(EXE) : mtst.c \ + ../libscotch/module.h \ + ../libscotch/common.h \ + $(includedir)/scotch.h \ + $(libdir)/libscotch$(LIB) \ + $(libdir)/libscotcherrexit$(LIB) \ + mtst.h diff --git a/scotch_6.0.3/src/scotch/acpl.c b/scotch_6.0.3/src/scotch/acpl.c new file mode 100644 index 00000000..64f9b9b0 --- /dev/null +++ b/scotch_6.0.3/src/scotch/acpl.c @@ -0,0 +1,157 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : acpl.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module compiles target architec- **/ +/** ture decomposition files for fast **/ +/** loading. **/ +/** **/ +/** DATES : # Version 2.0 : from : 12 nov 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 3.0 : from : 06 jul 1995 **/ +/** to : 19 sep 1995 **/ +/** # Version 3.2 : from : 24 sep 1996 **/ +/** to : 12 may 1998 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 4.0 : from : 09 feb 2004 **/ +/** to : 09 feb 2004 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ACPL + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "acpl.h" + +/* +** The static variables. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "acpl [ []] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Arch arch; /* Architecture read and written */ + int i; + + errorProg ("acpl"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "acpl, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_archInit (&arch); /* Initialize architecture structure */ + SCOTCH_archLoad (&arch, C_filepntrtgtinp); /* Load architecture */ + if (strcmp (SCOTCH_archName (&arch), "deco") != 0) { /* If not a decomposition */ + errorPrint ("main: architecture is not decomposition-defined"); + return (1); + } + SCOTCH_archSave (&arch, C_filepntrtgtout); /* Save the compiled architecture */ + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_archExit (&arch); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/acpl.h b/scotch_6.0.3/src/scotch/acpl.h new file mode 100644 index 00000000..8676183a --- /dev/null +++ b/scotch_6.0.3/src/scotch/acpl.h @@ -0,0 +1,66 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : acpl.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the target archi- **/ +/** tecture compilation function defini- **/ +/** tions. **/ +/** **/ +/** DATES : # Version 2.0 : from : 12 nov 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 3.0 : from : 06 jul 1995 **/ +/** to : 06 jul 1995 **/ +/** # Version 3.2 : from : 24 sep 1996 **/ +/** to : 01 jun 1997 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenametgtinp C_fileTab[0].name /* Target architecture input file name */ +#define C_filenametgtout C_fileTab[1].name /* Target architecture output file name */ + +#define C_filepntrtgtinp C_fileTab[0].pntr /* Target architecture input file */ +#define C_filepntrtgtout C_fileTab[1].pntr /* Target architecture output file */ diff --git a/scotch_6.0.3/src/scotch/amk_ccc.c b/scotch_6.0.3/src/scotch/amk_ccc.c new file mode 100644 index 00000000..020abd13 --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_ccc.c @@ -0,0 +1,240 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_ccc.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the distance map for CCC **/ +/** graphs, to be used to build the archi- **/ +/** tecture description files for these **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 1.3 : from : 24 apr 1994 **/ +/** to : 24 apr 1994 **/ +/** # Version 2.0 : from : 13 jul 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 3.0 : from : 18 sep 1995 **/ +/** to : 19 sep 1995 **/ +/** # Version 3.2 : from : 07 may 1997 **/ +/** to : 07 may 1997 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define AMK_CCC + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "amk_ccc.h" + +/* +** The static and global definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" } }; + +static C_VertDist * C_distaTab; /* Pointer to distance map table */ +static C_Queue C_distaQueue; /* Distance queue */ + +static const char * C_usageList[] = { /* Usage list */ + "amk_ccc [] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/*************************************************/ +/* */ +/* The main routine, which computes the distance */ +/* triangular table. */ +/* */ +/*************************************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num ccdim; /* Dimension of the graph */ + SCOTCH_Num ccnbr; /* Number of vertices */ + SCOTCH_Num ccbit; /* Mask variable */ + SCOTCH_Num ccmax; /* Maximum terminal */ + C_Vertex v, w, x; /* Vertex variables */ + SCOTCH_Num d; /* Vertex distance to root */ + SCOTCH_Num t; /* Vertex terminal value */ + SCOTCH_Num i, j, k; + + errorProg ("amk_ccc"); + + ccdim = 2; + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 1) { /* If number of parameters not reached */ + if ((ccdim = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + C_paraNum ++; + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILENBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "amk_ccc, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + ccnbr = ccdim * (1 << ccdim); /* Compute number of vertices */ + ccbit = (1 << ccdim) - 1; /* Get maximum position number */ + for (ccmax = ((1 << (ccdim + 1)) - 1), i = ccdim - 1; /* Compute biggest terminal value */ + i != 0; + i >>= 1) + ccmax = (ccmax << 1) | (i & 1); + + fprintf (C_filepntrarcout, "deco\n0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Print the file header */ + (SCOTCH_Num) ccnbr, /* Print number of terminal domains */ + (SCOTCH_Num) ccmax); /* Print biggest terminal value */ + + for (v.lvl = 0; v.lvl < ccdim; v.lvl ++) { /* For all levels */ + for (v.pos = 0; v.pos <= ccbit; v.pos ++) { /* For all positions in these levels */ + t = (1 << ccdim) | v.pos; /* Perform the hypercube cuts */ + for (i = v.lvl, j = ccdim; j != 1; ) { /* Perform the cycle cuts */ + t <<= 1; + k = (j + 1) >> 1; + if (i >= k) { /* If upper (smallest) half */ + t |= 1; + i -= k; + j -= k; + } + else /* If lower (biggest) half */ + j = k; + } + fprintf (C_filepntrarcout, SCOTCH_NUMSTRING "\t1\t" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) C_vertLabl (&v), /* Print terminal label */ + (SCOTCH_Num) t); /* Print terminal number */ + } + } + + if ((C_queueInit (&C_distaQueue, ccmax) != 0) || /* Allocate the distance array */ + ((C_distaTab = (C_VertDist *) memAlloc (ccmax * sizeof (C_VertDist))) == NULL)) { + errorPrint ("main: out of memory"); + return (1); + } + + for (v.lvl = 0; v.lvl < ccdim; v.lvl ++) { /* For all levels */ + for (v.pos = 0; v.pos <= ccbit; v.pos ++) { /* For all positions in these levels */ + for (i = 0; i < ccnbr; i ++) /* Initialize vertex table */ + C_distaTab[i].queued = 0; /* Vertex not queued yet */ + + C_distaRoot (&v); /* Set the queue with root v */ + + while (C_distaGet (&w, &d)) { /* As long as the queue is not empty */ + C_distaTab[C_vertLabl (&w)].dist = d; /* Keep the distance information */ + + d ++; /* Search for neighbors at next level */ + x.lvl = w.lvl; /* Add neighbors to queue */ + x.pos = w.pos ^ (1 << x.lvl); + C_distaPut (&x, d); + x.lvl = (w.lvl == 0) ? (ccdim - 1) : (w.lvl - 1); + x.pos = w.pos; + C_distaPut (&x, d); + x.lvl = (w.lvl == (ccdim - 1)) ? 0 : (w.lvl + 1); + C_distaPut (&x, d); + } + + if (v.lvl + v.pos > 0) { /* Print distance triangular map line */ + fprintf (C_filepntrarcout, SCOTCH_NUMSTRING, + (SCOTCH_Num) C_distaTab[0].dist); + for (i = 1; i < C_vertLabl (&v); i ++) + fprintf (C_filepntrarcout, " " SCOTCH_NUMSTRING, + (SCOTCH_Num) C_distaTab[i].dist); + fprintf (C_filepntrarcout, "\n"); + } + } + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + C_queueExit (&C_distaQueue); + memFree (C_distaTab); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/amk_ccc.h b/scotch_6.0.3/src/scotch/amk_ccc.h new file mode 100644 index 00000000..00d66b3e --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_ccc.h @@ -0,0 +1,125 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_ccc.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the distance map for CCC **/ +/** graphs, to be used to build the **/ +/** architecture description files for **/ +/** these graphs. **/ +/** **/ +/** DATES : # Version 1.3 : from : 24 apr 1994 **/ +/** to : 24 apr 1994 **/ +/** # Version 2.0 : from : 13 jul 1994 **/ +/** to : 18 jul 1994 **/ +/** # Version 3.0 : from : 18 sep 1995 **/ +/** to : 18 sep 1995 **/ +/** # Version 3.2 : from : 07 may 1997 **/ +/** to : 07 may 1997 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 1 /* Number of files in list */ + +#define C_filenamearcout C_fileTab[0].name /* Architecture output file name */ + +#define C_filepntrarcout C_fileTab[0].pntr /* Architecture output file */ + +/* +** The type and structure definitions. +*/ + +/*+ This structure defines a CCC vertex. +*/ + +typedef struct C_Vertex_ { + SCOTCH_Num lvl; /*+ Vertex level +*/ + SCOTCH_Num pos; /*+ Vertex position +*/ +} C_Vertex; + +/*+ This structure defines a vertex distance information. +*/ + +typedef struct C_VertDist_ { + int queued; /*+ Flag set if vertex queued +*/ + SCOTCH_Num dist; /*+ Distance to initial vertex +*/ +} C_VertDist; + +/*+ This is a neighbor queue element. +*/ + +typedef struct C_QueueElem_ { + C_Vertex vert; /*+ Vertex number +*/ + SCOTCH_Num dist; /*+ Distance reached +*/ +} C_QueueElem; + +/*+ This is the distance queue. +*/ + +typedef struct C_Queue_ { + C_QueueElem * tab; /*+ Pointer to queue data +*/ + SCOTCH_Num min; /*+ Pointer to first element +*/ + SCOTCH_Num max; /*+ Pointer to last element +*/ +} C_Queue; + +/* +** The macro definitions. +*/ + +#define C_vertLabl(v) (((v)->lvl << ccdim) | (v)->pos) + +#define C_queueInit(q,n) ((((q)->tab = (C_QueueElem *) memAlloc ((n) * sizeof (C_QueueElem))) == NULL) ? 1 : 0) +#define C_queueExit(q) memFree ((q)->tab) +#define C_queueFlush(q) (q)->min = \ + (q)->max = 0 +#define C_queuePut(q,v,d) ((q)->tab[(q)->max].vert = *(v), \ + (q)->tab[(q)->max ++].dist = (d)) +#define C_queueGet(q,v,d) (((q)->min < (q)->max) ? (*(v) = (q)->tab[(q)->min].vert, \ + *(d) = (q)->tab[(q)->min ++].dist, \ + 1) \ + : 0) + +#define C_distaRoot(v) (C_queueFlush (&C_distaQueue), \ + C_queuePut (&C_distaQueue, (v), 0), \ + C_distaTab[C_vertLabl (v)].queued = 1) +#define C_distaGet(v,d) (C_queueGet (&C_distaQueue, (v), (d))) +#define C_distaPut(v,d) ((C_distaTab[C_vertLabl (v)].queued == 0) \ + ? C_queuePut (&C_distaQueue, (v), d), \ + C_distaTab[C_vertLabl (v)].queued = 1 \ + : 0) diff --git a/scotch_6.0.3/src/scotch/amk_fft2.c b/scotch_6.0.3/src/scotch/amk_fft2.c new file mode 100644 index 00000000..90880954 --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_fft2.c @@ -0,0 +1,243 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_fft2.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the distance map for FFT **/ +/** graphs, to be used to build the archi- **/ +/** tecture description files for these **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 1.3 : from : 19 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to : 19 sep 1995 **/ +/** # Version 3.2 : from : 07 may 1997 **/ +/** to : 07 may 1997 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define AMK_FFT2 + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "amk_fft2.h" + +/* +** The static and global definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" } }; + +static C_VertDist * C_distaTab; /* Pointer to distance map table */ +static C_Queue C_distaQueue; /* Distance queue */ + +static const char * C_usageList[] = { /* Usage list */ + "amk_fft2 [ []] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/*************************************************/ +/* */ +/* The main routine, which computes the distance */ +/* triangular table. */ +/* */ +/*************************************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num fdim; /* FFT dimension */ + SCOTCH_Num fnbr; /* Number of FFT vertices */ + SCOTCH_Num fmax; /* Maximum terminal number */ + SCOTCH_Num fmsk; /* Position bit mask */ + C_Vertex v, w, x; /* A FFT vertex (lvl, pos) */ + SCOTCH_Num b, d; /* Mask and bit variables */ + SCOTCH_Num i; /* Loop counter */ + SCOTCH_Num t; /* Vertex terminal value */ + + errorProg ("amk_fft2"); + + fdim = 2; + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 1) { /* If number of parameters not reached */ + if ((fdim = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + C_paraNum ++; + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILENBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "amk_fft2, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + fnbr = (fdim + 1) * (1 << fdim); /* Compute number of vertices */ + fmax = (1 << (fdim * 2 - 1)) - 1; /* Compute maximum terminal number */ + fmsk = (1 << fdim) - 1; /* Get maximum position number */ + + fprintf (C_filepntrarcout, "deco\n0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Print file header */ + (SCOTCH_Num) fnbr, /* Print number of terminal domains */ + (SCOTCH_Num) fmax); /* Print the biggest terminal value */ + + for (v.lvl = 0; v.lvl <= fdim; v.lvl ++) { /* For all vertices */ + for (v.pos = 0; v.pos <= fmsk; v.pos ++) { + for (i = v.lvl, b = 1 << (fdim - 1), t = 1; /* Recurse through the vertical + horizontal cuts */ + i <= fdim; + i ++, b >>= 1) { + t <<= 1; /* Vertical cut: tell if vertex is in left or... */ + t |= (v.pos & b) ? 1 : 0; /* right part from the position heaviest bits */ + t <<= 1; /* Vertex is still in upper part of horizontal cut */ + } + if (v.lvl == 0) /* If vertex is in the first level... */ + t >>= 2; /* We have gone one step too far */ + else { /* Else */ + t |= 1; /* This time vertex is in the lower part */ + t <<= (v.lvl - 1); /* Make space for the chain bipartition */ + t |= v.pos & ((1 << (v.lvl - 1)) - 1); /* Bipartition the chain following the lowest bits */ + } + + printf (((v.lvl == fdim) && (v.pos == fmsk)) /* Print terminal domain number */ + ? "%u\n\n" : "%u ", t); + } + } + + if ((C_queueInit (&C_distaQueue, fnbr) != 0) || /* Allocate distance array */ + ((C_distaTab = (C_VertDist *) memAlloc (fnbr * sizeof (C_VertDist))) == NULL)) { + errorPrint ("main: out of memory"); + return (1); + } + + for (v.lvl = 0; v.lvl <= fdim; v.lvl ++) { /* For all vertices */ + for (v.pos = 0; v.pos <= fmsk; v.pos ++) { + for (i = 0; i < fnbr; i ++) /* Initialize the vertex table */ + C_distaTab[i].queued = 0; /* Vertex not queued yet */ + + C_distaRoot (&v); /* Set the queue with root v */ + + while (C_distaGet (&w, &d)) { /* As long as the queue is not empty */ + C_distaTab[C_vertLabl (&w)].dist = d; /* Keep the distance information */ + + d ++; /* Search for neighbors at next level */ + if (w.lvl > 0) { /* Add new neighbors to the queue */ + x.lvl = w.lvl - 1; + x.pos = w.pos; + C_distaPut (&x, d); + x.pos = w.pos ^ (1 << (w.lvl - 1)); + C_distaPut (&x, d); + } + if (w.lvl < fdim) { + x.lvl = w.lvl + 1; + x.pos = w.pos; + C_distaPut (&x, d); + x.pos = w.pos ^ (1 << w.lvl); + C_distaPut (&x, d); + } + } + + if (v.lvl + v.pos > 0) { /* Print the distance triangular map line */ + fprintf (C_filepntrarcout, SCOTCH_NUMSTRING, + (SCOTCH_Num) C_distaTab[0].dist); + for (i = 1; i < (v.lvl << fdim) + v.pos; i ++) + fprintf (C_filepntrarcout, " " SCOTCH_NUMSTRING, + (SCOTCH_Num) C_distaTab[i].dist); + fprintf (C_filepntrarcout, "\n"); + } + } + } + + C_queueExit (&C_distaQueue); + memFree (C_distaTab); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/amk_fft2.h b/scotch_6.0.3/src/scotch/amk_fft2.h new file mode 100644 index 00000000..fe8d1173 --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_fft2.h @@ -0,0 +1,121 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_fft2.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the distance map for FFT **/ +/** graphs, to be used to build the archi- **/ +/** tecture description files for these **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 1.3 : from : 19 apr 1994 **/ +/** to : 20 apr 1994 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to : 04 jul 1995 **/ +/** # Version 3.2 : from : 07 may 1997 **/ +/** to : 07 may 1997 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 5.0 : from : 01 jan 2008 **/ +/** to : 01 jan 2008 **/ +/** **/ +/************************************************************/ + +/* +** The type and structure definitions +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 1 /* Number of files in list */ + +#define C_filenamearcout C_fileTab[0].name /* Architecture output file name */ + +#define C_filepntrarcout C_fileTab[0].pntr /* Architecture output file */ + +/*+ This structure defines an FFT vertex. +*/ + +typedef struct C_Vertex_ { + SCOTCH_Num lvl; /*+ Vertex level +*/ + SCOTCH_Num pos; /*+ Vertex position +*/ +} C_Vertex; + +/*+ This structure defines a vertex distance information. +*/ + +typedef struct C_VertDist_ { + int queued; /*+ Flag set if vertex queued +*/ + SCOTCH_Num dist; /*+ Distance to initial vertex +*/ +} C_VertDist; + +/*+ This is a neighbor queue element. +*/ + +typedef struct C_QueueElem_ { + C_Vertex vert; /*+ Vertex number +*/ + SCOTCH_Num dist; /*+ Distance reached +*/ +} C_QueueElem; + +/*+ This is the distance queue. +*/ + +typedef struct C_Queue_ { + C_QueueElem * tab; /*+ Pointer to queue data +*/ + SCOTCH_Num min; /*+ Pointer to first element +*/ + SCOTCH_Num max; /*+ Pointer to last element +*/ +} C_Queue; + +/* +** The macro definitions. +*/ + +#define C_vertLabl(v) (((v)->lvl << fdim) | (v)->pos) + +#define C_queueInit(q,n) ((((q)->tab = (C_QueueElem *) memAlloc ((n) * sizeof (C_QueueElem))) == NULL) ? 1 : 0) +#define C_queueExit(q) memFree ((q)->tab) +#define C_queueFlush(q) (q)->min = \ + (q)->max = 0 +#define C_queuePut(q,v,d) ((q)->tab[(q)->max].vert = *(v), \ + (q)->tab[(q)->max ++].dist = (d)) +#define C_queueGet(q,v,d) (((q)->min < (q)->max) ? (*(v) = (q)->tab[(q)->min].vert, \ + *(d) = (q)->tab[(q)->min ++].dist, \ + 1) \ + : 0) + +#define C_distaRoot(v) (C_queueFlush (&C_distaQueue), \ + C_queuePut (&C_distaQueue, (v), 0), \ + C_distaTab[C_vertLabl (v)].queued = 1) +#define C_distaGet(v,d) (C_queueGet (&C_distaQueue, (v), (d))) +#define C_distaPut(v,d) ((C_distaTab[C_vertLabl (v)].queued == 0) \ + ? C_queuePut (&C_distaQueue, (v), d), \ + C_distaTab[C_vertLabl (v)].queued = 1 \ + : 0) diff --git a/scotch_6.0.3/src/scotch/amk_grf.c b/scotch_6.0.3/src/scotch/amk_grf.c new file mode 100644 index 00000000..a9ff22dd --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_grf.c @@ -0,0 +1,253 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_grf.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the architecture description **/ +/** file for any source graph. **/ +/** **/ +/** DATES : # Version 3.0 : from : 06 jul 1995 **/ +/** to : 02 oct 1995 **/ +/** # Version 3.1 : from : 26 mar 1996 **/ +/** to : 26 mar 1996 **/ +/** # Version 3.2 : from : 23 apr 1997 **/ +/** to : 03 jun 1998 **/ +/** # Version 3.3 : from : 15 may 1999 **/ +/** to : 15 may 1999 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to : 17 mar 2005 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 11 dec 2008 **/ +/** to : 17 jul 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define AMK_GRF + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "amk_grf.h" + +/* +** The static variables. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" }, + { "-", NULL, "r" } }; + +static const char * C_usageList[] = { /* Usage */ + "amk_grf [ []] ", + " -b : Apply bipartitioning strategy ", + " -h : Display this help", + " -l : Load vertex list from ", + " -V : Print program version and copyright", + "", + "Default option set is : '-Bhf{move=1000}/((load0=load)|(load0=0))?x;'", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Strat bipastrat; /* Bipartitioning strategy */ + SCOTCH_Arch archdat; /* Target (terminal) architecture */ + SCOTCH_Graph grafdat; /* Source graph to turn into architecture */ + SCOTCH_Num vertnbr; /* Number of vertices in graph */ + SCOTCH_Num * vlbltab; /* Pointer to vertex label array, if present */ + SCOTCH_Num listnbr; /* Size of list array */ + SCOTCH_Num * listtab; /* Pointer to list array */ + C_VertSort * sorttab; /* Vertex label sort area */ + SCOTCH_Num baseval; + int flagval; /* Process flags */ + int i; + + errorProg ("amk_grf"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + flagval = C_FLAGNONE; + SCOTCH_stratInit (&bipastrat); + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'B' : /* Bipartitioning strategy */ + case 'b' : + SCOTCH_stratExit (&bipastrat); + SCOTCH_stratInit (&bipastrat); + if ((SCOTCH_stratGraphBipart (&bipastrat, &argv[i][2])) != 0) { + errorPrint ("main: invalid bipartitioning strategy"); + return (1); + } + break; + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'L' : /* Input vertex list */ + case 'l' : + flagval |= C_FLAGVRTINP; + if (argv[i][2] != '\0') + C_filenamevrtinp = &argv[i][2]; + break; + case 'V' : + fprintf (stderr, "amk_grf, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_graphInit (&grafdat); /* Create graph structure */ + SCOTCH_graphLoad (&grafdat, C_filepntrgrfinp, -1, 0); /* Load source graph */ + SCOTCH_graphData (&grafdat, &baseval, &vertnbr, NULL, NULL, NULL, /* Get graph data */ + &vlbltab, NULL, NULL, NULL); + + listnbr = 0; /* Initialize vertex list */ + listtab = NULL; + if (flagval & C_FLAGVRTINP) { /* If list of vertices provided */ + SCOTCH_Num listnum; + + if ((intLoad (C_filepntrvrtinp, &listnbr) != 1) || /* Read list size */ + (listnbr < 0) || + (listnbr > vertnbr)) { + errorPrint ("main: bad list input (1)"); + return (1); + } + if ((listtab = (SCOTCH_Num *) memAlloc (listnbr * sizeof (SCOTCH_Num) + 1)) == NULL) { + errorPrint ("main: out of memory (1)"); + return (1); + } + for (listnum = 0; listnum < listnbr; listnum ++) { /* Read list data */ + if (intLoad (C_filepntrvrtinp, &listtab[listnum]) != 1) { + errorPrint ("main: bad list input (2)"); + return (1); + } + } + intSort1asc1 (listtab, listnbr); + for (listnum = 0; listnum < listnbr - 1; listnum ++) { /* Search for duplicates */ + if (listtab[listnum] == listtab[listnum + 1]) { + errorPrint ("main: duplicate list labels"); + memFree (listtab); + return (1); + } + } + + if (vlbltab != NULL) { /* If graph has vertex labels */ + SCOTCH_Num vertnum; + + if ((sorttab = (C_VertSort *) memAlloc (vertnbr * sizeof (C_VertSort))) == NULL) { + errorPrint ("main: out of memory (2)"); + memFree (listtab); + return (1); + } + for (vertnum = 0; vertnum < vertnbr; vertnum ++) { /* Initialize sort area */ + sorttab[vertnum].vlblnum = vlbltab[vertnum]; + sorttab[vertnum].vertnum = vertnum; + } + intSort2asc1 (sorttab, vertnbr); /* Sort by ascending labels */ + + for (listnum = 0, vertnum = 0; listnum < listnbr; listnum ++) { /* For all labels in list */ + while ((vertnum < vertnbr) && (sorttab[vertnum].vlblnum < listtab[listnum])) + vertnum ++; /* Search vertex graph with corresponding label */ + if ((vertnum >= vertnbr) || /* If label not found */ + (sorttab[vertnum].vlblnum > listtab[listnum])) { + errorPrint ("main: list label '" SCOTCH_NUMSTRING "' not in graph", (SCOTCH_Num) listtab[listnum]); + memFree (sorttab); + memFree (listtab); + return (1); + } + listtab[listnum] = sorttab[vertnum ++].vertnum; /* Replace label by number */ + } + memFree (sorttab); /* Free sort area */ + } + } + + SCOTCH_archInit (&archdat); /* Initialize target architecture */ + SCOTCH_archBuild (&archdat, &grafdat, listnbr, listtab, &bipastrat); /* Compute architecture */ + SCOTCH_archSave (&archdat, C_filepntrtgtout); /* Write target architecture */ + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end potential (un)compression tasks */ + + SCOTCH_graphExit (&grafdat); /* Free target graph */ + SCOTCH_archExit (&archdat); /* Free target architecture */ + SCOTCH_stratExit (&bipastrat); /* Free strategy string */ + if (listtab != NULL) /* If vertex list provided */ + memFree (listtab); /* Free it */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/amk_grf.h b/scotch_6.0.3/src/scotch/amk_grf.h new file mode 100644 index 00000000..86840d9b --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_grf.h @@ -0,0 +1,87 @@ +/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_grf.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Decomposition architecture builder. **/ +/** These lines are the data declarations **/ +/** for the program routines. **/ +/** **/ +/** DATES : # Version 3.0 : from : 06 jul 1995 **/ +/** to : 02 oct 1995 **/ +/** # Version 3.1 : from : 26 mar 1996 **/ +/** to : 26 mar 1996 **/ +/** # Version 3.2 : from : 23 apr 1997 **/ +/** to : 02 jun 1997 **/ +/** # Version 3.3 : from : 15 may 1999 **/ +/** to : 15 may 1999 **/ +/** # Version 5.1 : from : 17 jul 2011 **/ +/** to : 17 jul 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 3 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamegrfinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenametgtout C_fileTab[1].name /* Architecture output file name */ +#define C_filenamevrtinp C_fileTab[2].name /* Vertex list input file name */ + +#define C_filepntrgrfinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrtgtout C_fileTab[1].pntr /* Architecture output file */ +#define C_filepntrvrtinp C_fileTab[2].pntr /* Vertex list input file */ + +/*+ Process flags. +*/ + +#define C_FLAGVRTINP 0x0001 /* Input vertex list */ + +#define C_FLAGNONE 0x0000 /* Default flags */ + +/* +** The type and structure definitions. +*/ + +/*+ The sort structure, used to sort graph vertices by label. +*/ + +typedef struct C_VertSort_ { + SCOTCH_Num vlblnum; /*+ Vertex label +*/ + SCOTCH_Num vertnum; /*+ Vertex number +*/ +} C_VertSort; diff --git a/scotch_6.0.3/src/scotch/amk_hy.c b/scotch_6.0.3/src/scotch/amk_hy.c new file mode 100644 index 00000000..56c96a63 --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_hy.c @@ -0,0 +1,182 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_hy.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the distance map for hypercube **/ +/** graphs, to be used to build the archi- **/ +/** tecture description files for these **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 2.0 : from : 14 nov 1994 **/ +/** to : 14 nov 1994 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to : 19 sep 1995 **/ +/** # Version 3.2 : from : 31 may 1997 **/ +/** to : 02 jun 1997 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define AMK_HY + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "amk_hy.h" + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "amk_hy [] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/*************************************************/ +/* */ +/* The main routine, which computes the distance */ +/* triangular table. */ +/* */ +/*************************************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num hdim; /* Hypercube dimension */ + SCOTCH_Num hnbr; /* Number of hypercube vertices */ + SCOTCH_Num hmax; /* Number of domains */ + SCOTCH_Num hv0, hv1; + SCOTCH_Num i, j; + + errorProg ("amk_hy"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + hdim = 1; /* Preset hypercube dimension */ + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 1) { /* If number of parameters not reached */ + if ((hdim = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + C_paraNum ++; + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "amk_hy, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + hnbr = 1 << hdim; /* Compute number of terminals */ + hmax = (1 << (hdim + 1)) - 1; /* Maximum terminal value */ + + fprintf (C_filepntrtgtout, "deco\n0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Print the file header */ + (SCOTCH_Num) hnbr, /* Print number of terminal domains */ + (SCOTCH_Num) hmax); /* Print the biggest terminal value */ + + for (i = 0; i < hnbr; i ++) /* For all vertices */ + fprintf (C_filepntrtgtout, SCOTCH_NUMSTRING "\t1\t" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) i, /* Print terminal label */ + (SCOTCH_Num) (hnbr + i)); /* Print terminal number */ + + for (hv0 = 1; hv0 < hnbr; hv0 ++) { /* For all vertices */ + for (hv1 = 0; hv1 < hv0; hv1 ++) { + for (i = hv0 ^ hv1, j = 0; i > 0; i >>=1) + j += (i & 1); + fprintf (C_filepntrtgtout, + (hv1 == 0) ? SCOTCH_NUMSTRING : " " SCOTCH_NUMSTRING, (SCOTCH_Num) j); + } + fprintf (C_filepntrtgtout, "\n"); + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/amk_hy.h b/scotch_6.0.3/src/scotch/amk_hy.h new file mode 100644 index 00000000..b5c41bb4 --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_hy.h @@ -0,0 +1,75 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_hy.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the target architecture file **/ +/** for hypercube graphs. **/ +/** Here are the data declaration for the **/ +/** target machine architecture functions. **/ +/** **/ +/** DATES : # Version 2.0 : from : 14 nov 1994 **/ +/** to : 14 nov 1994 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to : 07 jul 1995 **/ +/** # Version 3.1 : from : 30 may 1996 **/ +/** to : 30 may 1996 **/ +/** # Version 3.2 : from : 31 may 1997 **/ +/** to : 31 may 1997 **/ +/** # Version 3.3 : from : 02 oct 1998 **/ +/** to : 02 oct 1998 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** File name aliases. **/ + +#define C_FILENBR 1 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenametgtout C_fileTab[0].name /* Architecture output file name */ + +#define C_filepntrtgtout C_fileTab[0].pntr /* Architecture output file */ + +/* +** The macro definitions. +*/ + +#ifndef abs +#define abs(a) (((a) >= 0) ? (a) : -(a)) +#endif /* abs */ diff --git a/scotch_6.0.3/src/scotch/amk_m2.c b/scotch_6.0.3/src/scotch/amk_m2.c new file mode 100644 index 00000000..ba675f3f --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_m2.c @@ -0,0 +1,307 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_m2.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the distance map for **/ +/** bidimensional mesh graphs, to be used **/ +/** to build the architecture description **/ +/** files for these graphs. **/ +/** **/ +/** DATES : # Version 1.3 : from : 21 apr 1994 **/ +/** to : 21 apr 1994 **/ +/** # Version 2.0 : from : 12 jul 1994 **/ +/** to : 12 nov 1994 **/ +/** # Version 3.0 : from : 17 jul 1995 **/ +/** to : 19 sep 1995 **/ +/** # Version 3.2 : from : 31 may 1997 **/ +/** to : 02 jun 1997 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 4.0 : from : 09 feb 2004 **/ +/** to : 09 feb 2004 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 21 apr 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/** NOTES : # The vertices of the (dX,dY) mesh are **/ +/** numbered as terminals so that **/ +/** t (0,0)=0, t (1,0) = 1, **/ +/** t (dX - 1, 0) = dX - 1, **/ +/** t (0,1) = dX, and **/ +/** t(x,y) = (y * dX) + x. **/ +/** **/ +/** # The nested dissection method should **/ +/** behave like the architecture built in **/ +/** the mapper. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define AMK_M2 + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "arch.h" +#include "arch_mesh.h" +#include "amk_m2.h" + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "amk_m2 [ []] ", + " -h : Display this help", + " -m : Decomposition method", + " n : Nested dissection (cut biggest dimension)", + " o : One-way dissection (y, then x)", + " -V : Print program version and copyright", + "", + "Default option set is : '-Mn'", + NULL }; + +/*************************************************/ +/* */ +/* The main routine, which computes the distance */ +/* triangular table. */ +/* */ +/*************************************************/ + +int +main ( +int argc, +char * argv[]) +{ + ArchMesh2 arch; /* Mesh dimensions */ + ArchMesh2Dom dom; /* Initial domain */ + C_MethType methtype; /* Bipartitioning method */ + unsigned int termnbr; /* Number of terminal domains */ + unsigned int termmax; /* Maximum terminal number */ + unsigned int * termtab; /* Terminal numbers table */ + unsigned int x0, y0, x1, y1; + int i; + + errorProg ("amk_m2"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + methtype = C_METHNESTED; + arch.c[0] = /* Preset mesh dimensions */ + arch.c[1] = 1; + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 2) { /* If number of parameters not reached */ + if ((arch.c[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'M' : /* Use a built-in method */ + case 'm' : + switch (argv[i][2]) { + case 'N' : /* Nested dissection */ + case 'n' : + methtype = C_METHNESTED; + break; + case 'O' : /* One-way dissection */ + case 'o' : + methtype = C_METHONEWAY; + break; + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + break; + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "amk_m2, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + dom.c[0][0] = 0; /* Set the initial domain */ + dom.c[0][1] = arch.c[0] - 1; + dom.c[1][0] = 0; + dom.c[1][1] = arch.c[1] - 1; + + termnbr = arch.c[0] * arch.c[1]; /* Compute number of terminals */ + termmax = 0; /* Maximum terminal value not known yet */ + if ((termtab = (unsigned int *) memAlloc (termnbr * sizeof (unsigned int))) == NULL) { /* Allocate terminal array */ + errorPrint ("main: out of memory"); + return (1); + } + memset (termtab, -1, termnbr * sizeof (unsigned int)); /* Initilize mapping table */ + + C_termBipart (&arch, &dom, 1, termtab, &termmax, /* Compute terminal numbers */ + (methtype == C_METHNESTED) ? archMesh2DomBipart : C_methBipartOne); + + fprintf (C_filepntrarcout, "deco\n0\n%u\t%u\n", /* Print file header */ + termnbr, /* Print number of terminal domains */ + termmax); /* Print biggest terminal value */ + for (i = 0; i < termnbr; i ++) /* For all terminals */ + fprintf (C_filepntrarcout, "%u\t1\t%u\n", /* Print terminal data */ + i, termtab[i]); + + for (y0 = 0; y0 < arch.c[1]; y0 ++) { /* For all vertices */ + for (x0 = 0; x0 < arch.c[0]; x0 ++) { + for (y1 = 0; y1 <= y0; y1 ++) { /* Compute distance to smaller vertices */ + for (x1 = 0; (x1 < arch.c[0]) && ((y1 < y0) || (x1 < x0)); x1 ++) + fprintf (C_filepntrarcout, + ((x1 == 0) && (y1 == 0)) ? "%u" : " %u", + C_termDist (x0, y0, x1, y1)); + } + fprintf (C_filepntrarcout, "\n"); + } + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + memFree (termtab); /* Free terminal number array */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} + +/* This routine recursively determines the values +** of all the terminal vertices of the mesh domain, +** and puts them in table. +*/ + +void +C_termBipart ( +ArchMesh2 * archptr, +ArchMesh2Dom * domptr, +unsigned int num, +unsigned int * termtab, +unsigned int * termmax, +int (* methfunc) ()) +{ + ArchMesh2Dom dom0; + ArchMesh2Dom dom1; + + if (methfunc (archptr, domptr, &dom0, &dom1) == 0) { /* If we can bipartition */ + C_termBipart (archptr, &dom0, num + num, termtab, termmax, methfunc); /* Bipartition recursively */ + C_termBipart (archptr, &dom1, num + num + 1, termtab, termmax, methfunc); + } + else { /* If we have reached the end */ + termtab[domptr->c[1][0] * archptr->c[0] + /* Set the terminal number */ + domptr->c[0][0]] = num; + if (*termmax < num) /* If we have reached a new maximum */ + *termmax = num; /* Record it */ + } +} + +/* This function tries to split a rectangular domain into +** two subdomains using a one-way dissection method, by +** cutting first in the Y dimension, then in the X one. +** It returns: +** - 1 : if the domain has been bipartitioned. +** - 0 : else. +*/ + +int +C_methBipartOne ( +const ArchMesh2 * const archptr, +const ArchMesh2Dom * const domptr, +ArchMesh2Dom * restrict const dom0ptr, +ArchMesh2Dom * restrict const dom1ptr) +{ + if ((domptr->c[0][0] == domptr->c[0][1]) && /* Return if cannot split more */ + (domptr->c[1][0] == domptr->c[1][1])) + return (0); + + if (domptr->c[1][1] == domptr->c[1][0]) { /* If the Y dimension cannot be cut */ + dom0ptr->c[0][0] = domptr->c[0][0]; /* Cut in the X dimension */ + dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; + dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; + dom1ptr->c[0][1] = domptr->c[0][1]; + + dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; + } + else { /* If the Y dimension can be cut, cut it */ + dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; + dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; + + dom0ptr->c[1][0] = domptr->c[1][0]; + dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; + dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; + dom1ptr->c[1][1] = domptr->c[1][1]; + } + + return (1); +} diff --git a/scotch_6.0.3/src/scotch/amk_m2.h b/scotch_6.0.3/src/scotch/amk_m2.h new file mode 100644 index 00000000..b148a70a --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_m2.h @@ -0,0 +1,98 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_m2.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the target architecture file **/ +/** for bidimensional mesh graphs. **/ +/** Here are the data declaration for the **/ +/** target machine architecture functions. **/ +/** **/ +/** DATES : # Version 1.3 : from : 21 apr 1994 **/ +/** to : 22 apr 1994 **/ +/** # Version 2.0 : from : 12 jul 1994 **/ +/** to : 13 nov 1994 **/ +/** # Version 2.0 : from : 18 sep 1995 **/ +/** to : 19 sep 1995 **/ +/** # Version 3.1 : from : 30 may 1996 **/ +/** to : 30 may 1996 **/ +/** # Version 3.2 : from : 31 may 1997 **/ +/** to : 02 jun 1997 **/ +/** # Version 4.0 : from : 09 feb 2004 **/ +/** to : 09 feb 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** File name aliases. **/ + +#define C_FILENBR 1 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenamearcout C_fileTab[0].name /* Architecture output file name */ + +#define C_filepntrarcout C_fileTab[0].pntr /* Architecture output file */ + +/* +** The type and structure definitions. +*/ + +/** The method type. **/ + +typedef enum C_MethType_ { + C_METHNESTED, /*+ Nested decomposition +*/ + C_METHONEWAY /*+ One-way decomposition +*/ +} C_MethType; + +/* +** The function prototypes. +*/ + +void C_termBipart (ArchMesh2 *, ArchMesh2Dom *, unsigned int, unsigned int *, unsigned int *, int (*) ()); +int C_methBipartOne (const ArchMesh2 * const, const ArchMesh2Dom * const, ArchMesh2Dom * restrict const, ArchMesh2Dom * restrict const); + +/* +** The macro definitions. +*/ + +#ifndef abs +#define abs(a) (((a) >= 0) ? (a) : -(a)) +#endif /* abs */ + +#define C_termDist(x0,y0,x1,y1) ((unsigned int) (abs ((int) (x0) - (int) (x1)) + \ + abs ((int) (y0) - (int) (y1)))) diff --git a/scotch_6.0.3/src/scotch/amk_p2.c b/scotch_6.0.3/src/scotch/amk_p2.c new file mode 100644 index 00000000..076032c4 --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_p2.c @@ -0,0 +1,152 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_p2.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the target architecture file **/ +/** for a weighted path with two vertices **/ +/** used to bipartition graphs in parts of **/ +/** different sizes. **/ +/** **/ +/** DATES : # Version 3.0 : from : 17 jul 1995 **/ +/** to : 17 jul 1995 **/ +/** # Version 3.2 : from : 02 jun 1997 **/ +/** to : 02 jun 1997 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 5.1 : from : 16 dec 2007 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define AMK_P2 + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "amk_p2.h" + +/* +** The static variables. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "amk_p2 [ []] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/************************************/ +/* */ +/* The main routine, which computes */ +/* the decomposition. */ +/* */ +/************************************/ + +int +main ( +int argc, +char * argv[]) +{ + int wght[2] = {1, 1}; /* Vertex weights */ + int i; + + errorProg ("amk_p2"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 2) { /* If number of parameters not reached */ + if ((wght[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get vertex weights */ + errorPrint ("main: invalid weight '%s'", argv[i]); + return (1); + } + continue; /* Process remaining parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "amk_p2, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + fprintf (C_filepntrtgtout, "cmpltw\t2\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Print target description */ + (SCOTCH_Num) wght[0], + (SCOTCH_Num) wght[1]); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/amk_p2.h b/scotch_6.0.3/src/scotch/amk_p2.h new file mode 100644 index 00000000..8be8ecc5 --- /dev/null +++ b/scotch_6.0.3/src/scotch/amk_p2.h @@ -0,0 +1,63 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : amk_p2.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the target architecture file **/ +/** for a weighted path with two vertices **/ +/** used to bipartition graphs in parts of **/ +/** different sizes. **/ +/** Here are the data declaration for the **/ +/** target machine architecture functions. **/ +/** **/ +/** DATES : # Version 3.0 : from : 17 jul 1995 **/ +/** to : 17 jul 1995 **/ +/** # Version 3.2 : from : 02 jun 1997 **/ +/** to : 02 jun 1997 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** File name aliases. **/ + +#define C_FILENBR 1 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenametgtout C_fileTab[0].name /* Architecture output file name */ + +#define C_filepntrtgtout C_fileTab[0].pntr /* Architecture output file */ diff --git a/scotch_6.0.3/src/scotch/atst.c b/scotch_6.0.3/src/scotch/atst.c new file mode 100644 index 00000000..e508e335 --- /dev/null +++ b/scotch_6.0.3/src/scotch/atst.c @@ -0,0 +1,205 @@ +/* Copyright 2004,2007,2008,2010-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : atst.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Target architecture graph analyzer. **/ +/** **/ +/** DATES : # Version 1.3 : from : 17 may 1994 **/ +/** to : 17 may 1994 **/ +/** # Version 2.0 : from : 11 nov 1994 **/ +/** to : 11 nov 1994 **/ +/** # Version 3.0 : from : 05 jul 1995 **/ +/** to : 19 aug 1995 **/ +/** # Version 3.2 : from : 24 sep 1996 **/ +/** to : 12 may 1998 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 4.0 : from : 09 feb 2004 **/ +/** to : 23 nov 2005 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jul 2014 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define ATST + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "arch.h" +#include "arch_deco.h" +#include "arch_mesh.h" +#include "atst.h" + +/* +** The static variables. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "atst [ []] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main (argc, argv) +int argc; +char * argv[]; +{ + Arch archdat; /* The architecture read */ + ArchDeco * deco; /* Its decomposition */ + ArchDecoDom dom0; + ArchDecoDom dom1; + Anum dstval; + Anum dstmin; + Anum dstmax; + Anum dstsum; + double dstavg; + double dstdlt; + int i; + + errorProg ("atst"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "atst, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + archInit (&archdat); /* Initialize architecture structure */ + archLoad (&archdat, C_filepntrtgtinp); /* Load architecture */ + if (strcmp (archName (&archdat), "deco") != 0) { /* If it is not a decomposition */ + errorPrint ("main: architecture is not decomposition-defined"); + return (1); + } + deco = (ArchDeco *) (void *) &archdat.data; /* Point to the decomposition */ + + dstmin = (Anum) (((unsigned long) ((Anum) -1)) >> 1); /* Set to maximum number in Anum */ + dstmax = 0; + dstsum = 0; + + for (dom0.num = 1; dom0.num <= deco->domvertnbr; dom0.num ++) { /* For all pairs of vertices */ + if (archDecoDomSize (deco, &dom0) == 1) { /* If vertex is a terminal */ + for (dom1.num = dom0.num + 1; dom1.num <= deco->domvertnbr; dom1.num ++) { + if (archDecoDomSize (deco, &dom1) == 1) { /* If vertex is a terminal */ + dstval = archDecoDomDist (deco, &dom0, &dom1); /* Compute distance between pairs */ + if (dstmin > dstval) + dstmin = dstval; + if (dstmax < dstval) + dstmax = dstval; + dstsum += dstval; /* Compute distance between pairs */ + } + } + } + } + dstavg = (deco->domtermnbr > 1) + ? (double) dstsum / (double) (deco->domtermnbr * (deco->domtermnbr - 1) / 2) + : 0.0L; + dstdlt = 0.0L; + for (dom0.num = 1; dom0.num <= deco->domvertnbr; dom0.num ++) { /* For all pairs of vertices */ + if (archDecoDomSize (deco, &dom0) == 1) { /* If vertex is a terminal */ + for (dom1.num = dom0.num + 1; dom1.num <= deco->domvertnbr; dom1.num ++) { + if (archDecoDomSize (deco, &dom1) == 1) /* If vertex is a terminal */ + dstdlt += fabs (archDecoDomDist (deco, &dom0, &dom1) - dstavg); + } + } + } + if (deco->domtermnbr > 1) + dstdlt /= (double) (deco->domtermnbr * (deco->domtermnbr - 1) / 2); + + fprintf (C_filepntrlogout, "A\tTerminals\tnbr=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) deco->domtermnbr); + fprintf (C_filepntrlogout, "A\tDistance\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) dstmin, (SCOTCH_Num) dstmax, dstavg, dstdlt); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + archExit (&archdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/atst.h b/scotch_6.0.3/src/scotch/atst.h new file mode 100644 index 00000000..2644d060 --- /dev/null +++ b/scotch_6.0.3/src/scotch/atst.h @@ -0,0 +1,65 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : atst.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Target architecture graph analyzer. **/ +/** **/ +/** DATES : # Version 1.3 : from : 17 may 1994 **/ +/** to : 17 may 1994 **/ +/** # Version 2.0 : from : 11 nov 1994 **/ +/** to : 11 nov 1994 **/ +/** # Version 3.0 : from : 05 jul 1995 **/ +/** to : 05 jul 1995 **/ +/** # Version 3.2 : from : 01 jun 1997 **/ +/** to : 01 jun 1997 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** File name aliases. **/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + + +#define C_filenametgtinp C_fileTab[0].name /* Target graph input file name */ +#define C_filenamelogout C_fileTab[1].name /* Statistics output file name */ + +#define C_filepntrtgtinp C_fileTab[0].pntr /* Target graph input file */ +#define C_filepntrlogout C_fileTab[1].pntr /* Statistics output file */ diff --git a/scotch_6.0.3/src/scotch/dggath.c b/scotch_6.0.3/src/scotch/dggath.c new file mode 100644 index 00000000..d6601450 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dggath.c @@ -0,0 +1,230 @@ +/* Copyright 2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dggath.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program gathers the fragments of a **/ +/** distributed graph and saves it as a **/ +/** centralized source graph. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 5.1 : from : 26 oct 2008 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGGATH +#define SCOTCH_PTSCOTCH + +#include "module.h" +#include "common.h" +#include "ptscotch.h" +#include "dggath.h" + +/* +** The static and global definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "dggath [ []] ", + " -c : Check the input graph after loading", + " -h : Display this help", + " -r : Set root process for centralized files (default is 0)", + " -V : Print program version and copyright", + NULL }; + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Graph * cgrfptr; + SCOTCH_Graph cgrfdat; + SCOTCH_Dgraph dgrfdat; + int procglbnbr; + int proclocnum; + int protglbnum; /* Root process */ + int flagval; + int i; + int reduloctab[2]; + int reduglbtab[2]; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + errorProg ("dggath"); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); + protglbnum = 0; /* Assume root process is process 0 */ + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + flagval = C_FLAGNONE; + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else + errorPrint ("main: too many file names given"); + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'C' : + case 'c' : + flagval |= C_FLAGCHECK; + break; +#ifdef SCOTCH_DEBUG_ALL + case 'D' : + case 'd' : + flagval |= C_FLAGDEBUG; + break; +#endif /* SCOTCH_DEBUG_ALL */ + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'R' : /* Root process (if necessary) */ + case 'r' : + protglbnum = atoi (&argv[i][2]); + if ((protglbnum < 0) || + (protglbnum >= procglbnbr) || + ((protglbnum == 0) && (argv[i][2] != '0'))) { + errorPrint ("main: invalid root process number"); + } + break; + case 'V' : + case 'v' : + fprintf (stderr, "dggath, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + } + } + } + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) { + fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); + if (proclocnum == protglbnum) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } + MPI_Barrier (MPI_COMM_WORLD); + } +#endif /* SCOTCH_DEBUG_ALL */ + + fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ + + if (C_filepntrsrcout == NULL) { + cgrfptr = NULL; + reduloctab[0] = + reduloctab[1] = 0; + } + else { + cgrfptr = &cgrfdat; + reduloctab[0] = 1; + reduloctab[1] = proclocnum; + } + if (MPI_Allreduce (reduloctab, reduglbtab, 2, MPI_INT, MPI_SUM, MPI_COMM_WORLD) != MPI_SUCCESS) + errorPrint ("main: communication error"); + + if (reduglbtab[0] != 1) + errorPrint ("main: should have only one root"); + if (reduglbtab[1] != protglbnum) + errorPrint ("main: root process mismatch"); + + SCOTCH_dgraphInit (&dgrfdat, MPI_COMM_WORLD); + SCOTCH_dgraphLoad (&dgrfdat, C_filepntrsrcinp, -1, 0); + + if ((flagval & C_FLAGCHECK) != 0) + SCOTCH_dgraphCheck (&dgrfdat); + + SCOTCH_graphInit (&cgrfdat); + SCOTCH_dgraphGather (&dgrfdat, cgrfptr); + if (cgrfptr != NULL) + SCOTCH_graphSave (cgrfptr, C_filepntrsrcout); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_graphExit (&cgrfdat); + SCOTCH_dgraphExit (&dgrfdat); + + MPI_Finalize (); +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/dggath.h b/scotch_6.0.3/src/scotch/dggath.h new file mode 100644 index 00000000..e0bb5614 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dggath.h @@ -0,0 +1,66 @@ +/* Copyright 2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dggath.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This module contains the data declara- **/ +/** tions for the distributed graph file **/ +/** gathering program. **/ +/** **/ +/** DATES : # Version 5.1 : from : 26 oct 2008 **/ +/** to : 26 oct 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenamesrcout C_fileTab[1].name /* Source graph output file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrsrcout C_fileTab[1].pntr /* Source graph output file */ + +/*+ Process flags. +*/ + +#define C_FLAGNONE 0x0000 /* No flags */ +#define C_FLAGCHECK 0x0001 /* Check distributed source graph */ +#define C_FLAGDEBUG 0x0002 /* Enable easy debugger attachment */ diff --git a/scotch_6.0.3/src/scotch/dgmap.c b/scotch_6.0.3/src/scotch/dgmap.c new file mode 100644 index 00000000..191bee37 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dgmap.c @@ -0,0 +1,497 @@ +/* Copyright 2008-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgmap.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel static mapping **/ +/** software. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 5.0 : from : 12 jun 2008 **/ +/** to : 28 aug 2008 **/ +/** # Version 5.1 : from : 26 oct 2008 **/ +/** to : 31 aug 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGMAP +#define SCOTCH_PTSCOTCH + +#include + +#include "module.h" +#include "common.h" +#include "ptscotch.h" +#include "dgmap.h" + +/* +** The static variables. +*/ + +static int C_partNbr = 1; /* Default number of parts / cluster load */ +static int C_paraNum = 0; /* Number of parameters */ +static int C_paraNbr = 0; /* No parameters for mapping */ +static int C_fileNum = 0; /* Number of file in arg list */ +static int C_fileNbr = 4; /* Number of files for mapping */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "r" }, + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { /* Usage */ + "dgmap [ [ [ []]]] ", + "dgpart [] [ [ []]] ", + " -b : Load imbalance tolerance (default: 0.05)", + " -c : Choose default mapping strategy according to one or several of :", + " b : enforce load balance as much as possible", + " q : privilege quality over speed (default)", + " s : privilege speed over quality", + " t : enforce safety", + " x : enforce scalability", + " -h : Display this help", + " -m : Set parallel mapping strategy (see user's manual)", + " -q : Do graph clustering instead of graph partitioning (for dgpart)", + " -q : Do graph clustering instead of static mapping (for dgmap)", + " -r : Set root process for centralized files (default is 0)", + " -s : Force unity weights on :", + " e : edges", + " v : vertices", + " -V : Print program version and copyright", + " -v : Set verbose mode to :", + " a : memory allocation information", + " m : mapping information", + " s : strategy information", + " t : timing information", + "", + "See default strategy with option '-vs'", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Dgraph grafdat; /* Source graph */ + SCOTCH_Num grafflag; /* Source graph properties */ + SCOTCH_Arch archdat; /* Target architecture */ + SCOTCH_Dmapping mappdat; /* Mapping data */ + SCOTCH_Strat stradat; /* Mapping strategy */ + SCOTCH_Num straval; + char * straptr; + int flagval; + double kbalval; /* Imbalance tolerance value */ + int procglbnbr; + int proclocnum; + int protglbnum; /* Root process */ + Clock runtime[2]; /* Timing variables */ + double reduloctab[12]; /* 3 * (min, max, sum) */ + double reduglbtab[12]; + MPI_Datatype redutype; + MPI_Op reduop; + int i, j; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + flagval = C_FLAGNONE; /* Default behavior */ + kbalval = 0.05; /* Default imbalance */ + straval = 0; /* No strategy flags */ + straptr = NULL; + +#ifdef SCOTCH_COMPILE_PART + flagval |= C_FLAGPART; + C_paraNbr = 1; /* One more parameter */ + C_fileNbr = 3; /* One less file to provide */ + errorProg ("dgpart"); +#else + errorProg ("dgmap"); +#endif /* SCOTCH_COMPILE_PART */ + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); + protglbnum = 0; /* Assume root process is process 0 */ + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + grafflag = 0; /* Use vertex and edge weights */ + SCOTCH_stratInit (&stradat); + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < C_paraNbr) { /* If number of parameters not reached */ + if ((C_partNbr = atoi (argv[i])) < 1) /* Get the number of parts */ + errorPrint ("main: invalid number of parts '%s'", argv[i]); + C_paraNum ++; + continue; /* Process the other parameters */ + } + if (C_fileNum < C_fileNbr) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else + errorPrint ("main: too many file names given"); + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'B' : + case 'b' : + flagval |= C_FLAGKBALVAL; + kbalval = atof (&argv[i][2]); + if ((kbalval < 0.0) || + (kbalval > 1.0) || + ((kbalval == 0.0) && + ((argv[i][2] != '0') && (argv[i][2] != '.')))) { + errorPrint ("main: invalid load imbalance ratio"); + } + break; + case 'C' : + case 'c' : /* Strategy selection parameters */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'B' : + case 'b' : + straval |= SCOTCH_STRATBALANCE; + break; + case 'Q' : + case 'q' : + straval |= SCOTCH_STRATQUALITY; + break; + case 'S' : + case 's' : + straval |= SCOTCH_STRATSPEED; + break; + case 'T' : + case 't' : + straval |= SCOTCH_STRATSAFETY; + break; + case 'X' : + case 'x' : + straval |= SCOTCH_STRATSCALABILITY; + break; + default : + errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); + } + } + break; +#ifdef SCOTCH_DEBUG_ALL + case 'D' : + case 'd' : + flagval |= C_FLAGDEBUG; + break; +#endif /* SCOTCH_DEBUG_ALL */ + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'M' : + case 'm' : + straptr = &argv[i][2]; + SCOTCH_stratExit (&stradat); + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphMap (&stradat, straptr); + break; + case 'Q' : + case 'q' : + flagval |= C_FLAGCLUSTER; + if ((flagval & C_FLAGPART) != 0) { /* If partitioning program */ + if (argv[i][2] != '\0') + errorPrint ("main: invalid parameter '%s' after '-q' for dgpart", argv[i] + 2); + } + else { + if (argv[i][1] == '\0') + errorPrint ("main: missing parameter after '-q' for dgmap"); + if ((C_partNbr = atoi (argv[i] + 2)) < 1) /* Get maximum cluster load */ + errorPrint ("main: invalid cluster load '%s'", argv[i] + 2); + } + break; + case 'R' : /* Root process (if necessary) */ + case 'r' : + protglbnum = atoi (&argv[i][2]); + if ((protglbnum < 0) || + (protglbnum >= procglbnbr) || + ((protglbnum == 0) && (argv[i][2] != '0'))) + errorPrint ("main: invalid root process number"); + break; + case 'S' : + case 's' : /* Source graph parameters */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'E' : + case 'e' : + grafflag |= 2; /* Do not load edge weights */ + break; + case 'V' : + case 'v' : + grafflag |= 1; /* Do not load vertex weights */ + break; + default : + errorPrint ("main: invalid source graph option '%c'", argv[i][j]); + } + } + break; + case 'V' : + fprintf (stderr, "dgmap/dgpart, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2008-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + case 'v' : /* Output control info */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'A' : + case 'a' : +#ifdef COMMON_MEMORY_TRACE + flagval |= C_FLAGVERBMEM; +#else /* COMMON_MEMORY_TRACE */ + errorPrint ("main: not compiled with COMMON_MEMORY_TRACE"); +#endif /* COMMON_MEMORY_TRACE */ + break; + case 'M' : + case 'm' : + flagval |= C_FLAGVERBMAP; + break; + case 'S' : + case 's' : + flagval |= C_FLAGVERBSTR; + break; + case 'T' : + case 't' : + flagval |= C_FLAGVERBTIM; + break; + default : + errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); + } + } + break; + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + } + } + } + if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ + C_fileTab[3].name = C_fileTab[2].name; /* Put provided file names at their right place */ + C_fileTab[2].name = C_fileTab[1].name; + C_fileTab[1].name = "-"; + } + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) { + fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); + if (proclocnum == protglbnum) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } + MPI_Barrier (MPI_COMM_WORLD); + } +#endif /* SCOTCH_DEBUG_ALL */ + + fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ + + clockInit (&runtime[0]); + clockStart (&runtime[0]); + + SCOTCH_dgraphInit (&grafdat, MPI_COMM_WORLD); /* Initialize distributed source graph */ + SCOTCH_dgraphLoad (&grafdat, C_filepntrsrcinp, -1, 0); + + SCOTCH_archInit (&archdat); /* Create architecture structure */ + if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ + if ((flagval & C_FLAGCLUSTER) != 0) /* If program run as graph clustering */ + SCOTCH_archVcmplt (&archdat); /* Create a variable-sized complete graph */ + else /* Program is run as plain graph partitioner */ + SCOTCH_archCmplt (&archdat, C_partNbr); /* Create a complete graph of proper size */ + } + else { + if (C_filepntrtgtinp == NULL) + errorPrint ("main: target architecture file not provided"); + SCOTCH_archLoad (&archdat, C_filepntrtgtinp); /* Read target architecture */ + if ((flagval & C_FLAGCLUSTER) == 0) /* If part size not to be preserved */ + C_partNbr = SCOTCH_archSize (&archdat); + else { + if (SCOTCH_archVar (&archdat) == 0) + errorPrint ("main: non variable-sized architecture provided while '-q' flag set"); + } + } + + if (((straval != 0) || ((flagval & C_FLAGKBALVAL) != 0)) && (straptr != NULL)) + errorPrint ("main: options '-b' / '-c' and '-m' are exclusive"); + + if ((flagval & C_FLAGCLUSTER) != 0) /* If clustering wanted */ + SCOTCH_stratDgraphClusterBuild (&stradat, straval, (SCOTCH_Num) procglbnbr, (SCOTCH_Num) C_partNbr, 1.0, kbalval); + else + SCOTCH_stratDgraphMapBuild (&stradat, straval, (SCOTCH_Num) procglbnbr, (SCOTCH_Num) C_partNbr, kbalval); + + clockStop (&runtime[0]); /* Get input time */ + clockInit (&runtime[1]); + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) + MPI_Barrier (MPI_COMM_WORLD); +#endif /* SCOTCH_DEBUG_ALL */ + + clockStart (&runtime[1]); + + SCOTCH_dgraphGhst (&grafdat); /* Compute it once for good */ + + SCOTCH_dgraphMapInit (&grafdat, &mappdat, &archdat, NULL); + SCOTCH_dgraphMapCompute (&grafdat, &mappdat, &stradat); /* Perform mapping */ + + clockStop (&runtime[1]); /* Get computation time */ + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) + MPI_Barrier (MPI_COMM_WORLD); +#endif /* SCOTCH_DEBUG_ALL */ + + clockStart (&runtime[0]); + + SCOTCH_dgraphMapSave (&grafdat, &mappdat, (proclocnum == protglbnum) ? C_filepntrmapout : NULL); /* Write mapping */ + + clockStop (&runtime[0]); /* Get output time */ + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) + MPI_Barrier (MPI_COMM_WORLD); +#endif /* SCOTCH_DEBUG_ALL */ + + MPI_Type_contiguous (3, MPI_DOUBLE, &redutype); + MPI_Type_commit (&redutype); + MPI_Op_create ((MPI_User_function *) dgmapStatReduceOp, 1, &reduop); + + if ((flagval & C_FLAGVERBTIM) != 0) { + reduloctab[0] = + reduloctab[1] = + reduloctab[2] = (double) clockVal (&runtime[1]); + reduloctab[3] = + reduloctab[4] = + reduloctab[5] = (double) clockVal (&runtime[0]); + reduloctab[6] = + reduloctab[7] = + reduloctab[8] = reduloctab[0] + reduloctab[3]; + MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 3, redutype, reduop, MPI_COMM_WORLD); + } +#ifdef COMMON_MEMORY_TRACE + if ((flagval & C_FLAGVERBMEM) != 0) { + reduloctab[9] = + reduloctab[10] = + reduloctab[11] = (double) memMax (); + MPI_Allreduce (&reduloctab[9], &reduglbtab[9], 1, redutype, reduop, MPI_COMM_WORLD); + } +#endif /* COMMON_MEMORY_TRACE */ + + MPI_Op_free (&reduop); + MPI_Type_free (&redutype); + + if (C_filepntrlogout != NULL) { + if ((flagval & C_FLAGVERBSTR) != 0) { + fprintf (C_filepntrlogout, "S\tStrat="); + SCOTCH_stratSave (&stradat, C_filepntrlogout); + putc ('\n', C_filepntrlogout); + } + if ((flagval & C_FLAGVERBTIM) != 0) { + fprintf (C_filepntrlogout, "T\tMapping\tmin=%g\tmax=%g\tavg=%g\nT\tI/O\tmin=%g\tmax=%g\tavg=%g\nT\tTotal\tmin=%g\tmax=%g\tavg=%g\n", + reduglbtab[0], reduglbtab[1], reduglbtab[2] / (double) procglbnbr, + reduglbtab[3], reduglbtab[4], reduglbtab[5] / (double) procglbnbr, + reduglbtab[6], reduglbtab[7], reduglbtab[8] / (double) procglbnbr); + } +#ifdef COMMON_MEMORY_TRACE + if ((flagval & C_FLAGVERBMEM) != 0) + fprintf (C_filepntrlogout, "A\tMemory\tmin=%g\tmax=%g\tavg=%g\n", + reduglbtab[9], reduglbtab[10], reduglbtab[11] / (double) procglbnbr); +#endif /* COMMON_MEMORY_TRACE */ + } + if (flagval & C_FLAGVERBMAP) + SCOTCH_dgraphMapView (&grafdat, &mappdat, C_filepntrlogout); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_dgraphMapExit (&grafdat, &mappdat); + SCOTCH_dgraphExit (&grafdat); + SCOTCH_stratExit (&stradat); + SCOTCH_archExit (&archdat); + + MPI_Finalize (); +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} + +/* Reduction routine for statistics output. +*/ + +void +dgmapStatReduceOp ( +double * in, +double * inout, +int * len, +MPI_Datatype * datatype) +{ + int i; + + for (i = 0; i < *len; i ++) { + inout[3 * i] = MIN (in[3 * i], inout[3 * i]); + inout[3 * i + 1] = MAX (in[3 * i + 1], inout[3 * i + 1]); + inout[3 * i + 2] = in[3 * i + 2] + inout[3 * i + 2]; + } +} diff --git a/scotch_6.0.3/src/scotch/dgmap.h b/scotch_6.0.3/src/scotch/dgmap.h new file mode 100644 index 00000000..cce370c9 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dgmap.h @@ -0,0 +1,81 @@ +/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgmap.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel static mapper. **/ +/** These lines are the data declaration **/ +/** for the main routine. **/ +/** **/ +/** DATES : # Version 5.1 : from : 12 jun 2008 **/ +/** to : 18 jul 2011 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 4 /* Number of files in list */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenametgtinp C_fileTab[1].name /* Target architecture input file name */ +#define C_filenamemapout C_fileTab[2].name /* Mapping result output file name */ +#define C_filenamelogout C_fileTab[3].name /* Log file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrtgtinp C_fileTab[1].pntr /* Target architecture input file */ +#define C_filepntrmapout C_fileTab[2].pntr /* Mapping result output file */ +#define C_filepntrlogout C_fileTab[3].pntr /* Log file */ + +/*+ Process flags. +*/ + +#define C_FLAGNONE 0x0000 /* No flags */ +#define C_FLAGPART 0x0001 /* Partitioning */ +#define C_FLAGVERBSTR 0x0002 /* Verbose flags */ +#define C_FLAGVERBTIM 0x0004 +#define C_FLAGVERBMAP 0x0008 +#define C_FLAGVERBMEM 0x0010 +#define C_FLAGDEBUG 0x0020 /* Debugging */ +#define C_FLAGKBALVAL 0x0040 /* Imbalance tolerance */ +#define C_FLAGCLUSTER 0x0080 /* Clustering */ + +/* +** The function prototypes. +*/ + +void dgmapStatReduceOp (double *, double *, int *, MPI_Datatype *); diff --git a/scotch_6.0.3/src/scotch/dgord.c b/scotch_6.0.3/src/scotch/dgord.c new file mode 100644 index 00000000..86090b11 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dgord.c @@ -0,0 +1,432 @@ +/* Copyright 2007-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgord.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER (v5.0) **/ +/** **/ +/** FUNCTION : Part of a parallel sparse matrix **/ +/** ordering software. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 5.0 : from : 30 apr 2006 **/ +/** to : 16 jun 2008 **/ +/** # Version 5.1 : from : 26 oct 2008 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGORD +#define SCOTCH_PTSCOTCH + +#include + +#include "module.h" +#include "common.h" +#include "ptscotch.h" +#include "dgord.h" + +/* +** The static and global definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" }, + { "-", NULL, "w" }, + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "dgord [ [ []]] ", + " -b : Output block ordering data instead of plain ordering data", + " -c : Choose default ordering strategy according to one or several of :", + " b : enforce load balance as much as possible", + " q : privilege quality over speed (default)", + " s : privilege speed over quality", + " t : enforce safety", + " x : enforce scalability", + " -h : Display this help", + " -m : Save column block mapping data to ", + " -o : Set parallel ordering strategy (see user's manual)", + " -r : Set root process for centralized files (default is 0)", + " -t : Save partitioning tree data to ", + " -V : Print program version and copyright", + " -v : Set verbose mode to :", + " a : memory allocation information", + " s : strategy information", + " t : timing information", + "", + "See default strategy with option '-vs'", + NULL }; + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Dgraph grafdat; + SCOTCH_Dordering ordedat; + SCOTCH_Strat stradat; + SCOTCH_Num straval; + char * straptr; + int flagval; + int procglbnbr; + int proclocnum; + int protglbnum; /* Root process */ + Clock runtime[2]; /* Timing variables */ + double reduloctab[12]; /* 3 * (min, max, sum) */ + double reduglbtab[12]; + MPI_Datatype redutype; + MPI_Op reduop; + int i, j; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + errorProg ("dgord"); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); + protglbnum = 0; /* Assume root process is process 0 */ + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + flagval = C_FLAGNONE; /* Default behavior */ + straval = 0; /* No strategy flags */ + straptr = NULL; + SCOTCH_stratInit (&stradat); + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else + errorPrint ("main: too many file names given"); + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'B' : + case 'b' : + flagval |= C_FLAGBLOCK; + break; + case 'C' : + case 'c' : /* Strategy selection parameters */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'B' : + case 'b' : + straval |= SCOTCH_STRATBALANCE; + break; + case 'Q' : + case 'q' : + straval |= SCOTCH_STRATQUALITY; + break; + case 'S' : + case 's' : + straval |= SCOTCH_STRATSPEED; + break; + case 'T' : + case 't' : + straval |= SCOTCH_STRATSAFETY; + break; + case 'X' : + case 'x' : + straval |= SCOTCH_STRATSCALABILITY; + break; + default : + errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); + } + } + break; +#ifdef SCOTCH_DEBUG_ALL + case 'D' : + case 'd' : + flagval |= C_FLAGDEBUG; + break; +#endif /* SCOTCH_DEBUG_ALL */ + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'M' : /* Output separator mapping */ + case 'm' : + flagval |= C_FLAGMAPOUT; + if (argv[i][2] != '\0') + C_filenamemapout = &argv[i][2]; + break; + case 'O' : /* Ordering strategy */ + case 'o' : + straptr = &argv[i][2]; + SCOTCH_stratExit (&stradat); + SCOTCH_stratInit (&stradat); + SCOTCH_stratDgraphOrder (&stradat, straptr); + break; + case 'R' : /* Root process (if necessary) */ + case 'r' : + protglbnum = atoi (&argv[i][2]); + if ((protglbnum < 0) || + (protglbnum >= procglbnbr) || + ((protglbnum == 0) && (argv[i][2] != '0'))) + errorPrint ("main: invalid root process number"); + break; + case 'T' : /* Output separator tree */ + case 't' : + flagval |= C_FLAGTREOUT; + if (argv[i][2] != '\0') + C_filenametreout = &argv[i][2]; + break; + case 'V' : + fprintf (stderr, "dgord, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2007-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + case 'v' : /* Output control info */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'A' : + case 'a' : +#ifdef COMMON_MEMORY_TRACE + flagval |= C_FLAGVERBMEM; +#else /* COMMON_MEMORY_TRACE */ + errorPrint ("main: not compiled with COMMON_MEMORY_TRACE"); +#endif /* COMMON_MEMORY_TRACE */ + break; + case 'S' : + case 's' : + flagval |= C_FLAGVERBSTR; + break; + case 'T' : + case 't' : + flagval |= C_FLAGVERBTIM; + break; + default : + errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); + } + } + break; + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + } + } + } + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) { + fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); + if (proclocnum == protglbnum) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } + MPI_Barrier (MPI_COMM_WORLD); + } +#endif /* SCOTCH_DEBUG_ALL */ + + fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ + + clockInit (&runtime[0]); + clockStart (&runtime[0]); + + SCOTCH_dgraphInit (&grafdat, MPI_COMM_WORLD); + SCOTCH_dgraphLoad (&grafdat, C_filepntrsrcinp, -1, 0); + + if (straval != 0) { + if (straptr != NULL) + errorPrint ("main: options '-c' and '-o' are exclusive"); + + SCOTCH_stratDgraphOrderBuild (&stradat, straval, (SCOTCH_Num) procglbnbr, 0, 0.2); + } + + clockStop (&runtime[0]); /* Get input time */ + clockInit (&runtime[1]); + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) + MPI_Barrier (MPI_COMM_WORLD); +#endif /* SCOTCH_DEBUG_ALL */ + + clockStart (&runtime[1]); + + SCOTCH_dgraphGhst (&grafdat); /* Compute it once for good */ + + SCOTCH_dgraphOrderInit (&grafdat, &ordedat); + SCOTCH_dgraphOrderCompute (&grafdat, &ordedat, &stradat); + + clockStop (&runtime[1]); /* Get ordering time */ + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) + MPI_Barrier (MPI_COMM_WORLD); +#endif /* SCOTCH_DEBUG_ALL */ + + clockStart (&runtime[0]); + + if (proclocnum == protglbnum) { + if ((flagval & C_FLAGBLOCK) == 0) + SCOTCH_dgraphOrderSave (&grafdat, &ordedat, C_filepntrordout); + else + SCOTCH_dgraphOrderSaveBlock (&grafdat, &ordedat, C_filepntrordout); + if ((flagval & C_FLAGMAPOUT) != 0) /* If mapping wanted */ + SCOTCH_dgraphOrderSaveMap (&grafdat, &ordedat, C_filepntrmapout); /* Write mapping */ + if ((flagval & C_FLAGTREOUT) != 0) /* If separator tree wanted */ + SCOTCH_dgraphOrderSaveTree (&grafdat, &ordedat, C_filepntrtreout); /* Write tree */ + } + else { + if ((flagval & C_FLAGBLOCK) == 0) + SCOTCH_dgraphOrderSave (&grafdat, &ordedat, NULL); + else + SCOTCH_dgraphOrderSaveBlock (&grafdat, &ordedat, NULL); + if ((flagval & C_FLAGMAPOUT) != 0) + SCOTCH_dgraphOrderSaveMap (&grafdat, &ordedat, NULL); + if ((flagval & C_FLAGTREOUT) != 0) + SCOTCH_dgraphOrderSaveTree (&grafdat, &ordedat, NULL); + } + + clockStop (&runtime[0]); + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) + MPI_Barrier (MPI_COMM_WORLD); +#endif /* SCOTCH_DEBUG_ALL */ + + MPI_Type_contiguous (3, MPI_DOUBLE, &redutype); + MPI_Type_commit (&redutype); + MPI_Op_create ((MPI_User_function *) dgordStatReduceOp, 1, &reduop); + + if ((flagval & C_FLAGVERBTIM) != 0) { + reduloctab[0] = + reduloctab[1] = + reduloctab[2] = (double) clockVal (&runtime[1]); + reduloctab[3] = + reduloctab[4] = + reduloctab[5] = (double) clockVal (&runtime[0]); + reduloctab[6] = + reduloctab[7] = + reduloctab[8] = reduloctab[0] + reduloctab[3]; + MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 3, redutype, reduop, MPI_COMM_WORLD); + } +#ifdef COMMON_MEMORY_TRACE + if ((flagval & C_FLAGVERBMEM) != 0) { + reduloctab[9] = + reduloctab[10] = + reduloctab[11] = (double) memMax (); + MPI_Allreduce (&reduloctab[9], &reduglbtab[9], 1, redutype, reduop, MPI_COMM_WORLD); + } +#endif /* COMMON_MEMORY_TRACE */ + + MPI_Op_free (&reduop); + MPI_Type_free (&redutype); + + if (C_filepntrlogout != NULL) { + if ((flagval & C_FLAGVERBSTR) != 0) { + fprintf (C_filepntrlogout, "S\tStrat="); + SCOTCH_stratSave (&stradat, C_filepntrlogout); + putc ('\n', C_filepntrlogout); + } + if ((flagval & C_FLAGVERBTIM) != 0) { + fprintf (C_filepntrlogout, "T\tOrder\tmin=%g\tmax=%g\tavg=%g\nT\tI/O\tmin=%g\tmax=%g\tavg=%g\nT\tTotal\tmin=%g\tmax=%g\tavg=%g\n", + reduglbtab[0], reduglbtab[1], reduglbtab[2] / (double) procglbnbr, + reduglbtab[3], reduglbtab[4], reduglbtab[5] / (double) procglbnbr, + reduglbtab[6], reduglbtab[7], reduglbtab[8] / (double) procglbnbr); + } +#ifdef COMMON_MEMORY_TRACE + if ((flagval & C_FLAGVERBMEM) != 0) + fprintf (C_filepntrlogout, "A\tMemory\tmin=%g\tmax=%g\tavg=%g\n", + reduglbtab[9], reduglbtab[10], reduglbtab[11] / (double) procglbnbr); +#endif /* COMMON_MEMORY_TRACE */ + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_dgraphOrderExit (&grafdat, &ordedat); + SCOTCH_dgraphExit (&grafdat); + SCOTCH_stratExit (&stradat); + + MPI_Finalize (); +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} + +/* Reduction routine for statistics output. +*/ + +void +dgordStatReduceOp ( +double * in, +double * inout, +int * len, +MPI_Datatype * datatype) +{ + int i; + + for (i = 0; i < *len; i ++) { + inout[3 * i] = MIN (in[3 * i], inout[3 * i]); + inout[3 * i + 1] = MAX (in[3 * i + 1], inout[3 * i + 1]); + inout[3 * i + 2] = in[3 * i + 2] + inout[3 * i + 2]; + } +} diff --git a/scotch_6.0.3/src/scotch/dgord.h b/scotch_6.0.3/src/scotch/dgord.h new file mode 100644 index 00000000..6ef69bda --- /dev/null +++ b/scotch_6.0.3/src/scotch/dgord.h @@ -0,0 +1,87 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgord.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Cedric CHEVALIER **/ +/** **/ +/** FUNCTION : Part of a parallel sparse matrix **/ +/** ordering software. **/ +/** This module contains the data declara- **/ +/** tions for the main routine. **/ +/** **/ +/** DATES : # Version 5.0 : from : 30 apr 2006 **/ +/** to : 27 may 2008 **/ +/** # Version 5.1 : from : 22 nov 2008 **/ +/** to : 22 nov 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 5 /* Number of files in list */ +#define C_FILEARGNBR 3 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenameordout C_fileTab[1].name /* Ordering output file name */ +#define C_filenamelogout C_fileTab[2].name /* Log file name */ +#define C_filenamemapout C_fileTab[3].name /* Separator mapping file name */ +#define C_filenametreout C_fileTab[4].name /* Separator tree file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrordout C_fileTab[1].pntr /* Ordering output file */ +#define C_filepntrlogout C_fileTab[2].pntr /* Log file */ +#define C_filepntrmapout C_fileTab[3].pntr /* Separator mapping file */ +#define C_filepntrtreout C_fileTab[4].pntr /* Separator tre file */ + +/*+ Process flags. +*/ + +#define C_FLAGNONE 0x0000 /* No flags */ +#define C_FLAGMAPOUT 0x0001 /* Output mapping data */ +#define C_FLAGTREOUT 0x0002 /* Output separator tree data */ +#define C_FLAGVERBSTR 0x0004 /* Output strategy string */ +#define C_FLAGVERBTIM 0x0008 /* Output timing information */ +#define C_FLAGVERBMEM 0x0010 /* Output memory information */ +#define C_FLAGBLOCK 0x0020 /* Output block ordering */ +#define C_FLAGDEBUG 0x0040 /* Debugging */ + +/* +** The function prototypes. +*/ + +void dgordStatReduceOp (double *, double *, int *, MPI_Datatype *); diff --git a/scotch_6.0.3/src/scotch/dgscat.c b/scotch_6.0.3/src/scotch/dgscat.c new file mode 100644 index 00000000..bcae6aa0 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dgscat.c @@ -0,0 +1,205 @@ +/* Copyright 2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgscat.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program distributes a source graph **/ +/** across processors and saves it as a **/ +/** distributed source graph. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 5.0 : from : 17 may 2007 **/ +/** to : 16 jun 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGSCAT +#define SCOTCH_PTSCOTCH + +#include "module.h" +#include "common.h" +#include "ptscotch.h" +#include "dgscat.h" + +/* +** The static and global definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "dgscat [ []] ", + " -c : Check the input graph after loading", + " -h : Display this help", + " -r : Set root process for centralized files (default is 0)", + " -V : Print program version and copyright", + NULL }; + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Dgraph grafdat; + int procglbnbr; + int proclocnum; + int protglbnum; /* Root process */ + int flagval; + int i; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + errorProg ("dgscat"); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); + protglbnum = 0; /* Assume root process is process 0 */ + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + flagval = C_FLAGNONE; + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else + errorPrint ("main: too many file names given"); + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'C' : + case 'c' : + flagval |= C_FLAGCHECK; + break; +#ifdef SCOTCH_DEBUG_ALL + case 'D' : + case 'd' : + flagval |= C_FLAGDEBUG; + break; +#endif /* SCOTCH_DEBUG_ALL */ + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'R' : /* Root process (if necessary) */ + case 'r' : + protglbnum = atoi (&argv[i][2]); + if ((protglbnum < 0) || + (protglbnum >= procglbnbr) || + ((protglbnum == 0) && (argv[i][2] != '0'))) + errorPrint ("main: invalid root process number"); + break; + case 'V' : + case 'v' : + fprintf (stderr, "dgscat, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + } + } + } + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) { + fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); + if (proclocnum == protglbnum) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } + MPI_Barrier (MPI_COMM_WORLD); + } +#endif /* SCOTCH_DEBUG_ALL */ + + fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ + + SCOTCH_dgraphInit (&grafdat, MPI_COMM_WORLD); + SCOTCH_dgraphLoad (&grafdat, C_filepntrsrcinp, -1, 0); + + if ((flagval & C_FLAGCHECK) != 0) + SCOTCH_dgraphCheck (&grafdat); + + SCOTCH_dgraphSave (&grafdat, C_filepntrsrcout); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_dgraphExit (&grafdat); + + MPI_Finalize (); +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/dgscat.h b/scotch_6.0.3/src/scotch/dgscat.h new file mode 100644 index 00000000..48e77f48 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dgscat.h @@ -0,0 +1,68 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgscat.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel sparse matrix **/ +/** ordering software. **/ +/** This module contains the data declara- **/ +/** tions for the graph file scattering **/ +/** program. **/ +/** **/ +/** DATES : # Version 5.0 : from : 21 may 2007 **/ +/** to : 21 may 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenamesrcout C_fileTab[1].name /* Source graph output file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrsrcout C_fileTab[1].pntr /* Source graph output file */ + +/*+ Process flags. +*/ + +#define C_FLAGNONE 0x0000 /* No flags */ +#define C_FLAGCHECK 0x0001 /* Check distributed source graph */ +#define C_FLAGDEBUG 0x0002 /* Enable easy debugger attachment */ diff --git a/scotch_6.0.3/src/scotch/dgtst.c b/scotch_6.0.3/src/scotch/dgtst.c new file mode 100644 index 00000000..1147ebd6 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dgtst.c @@ -0,0 +1,229 @@ +/* Copyright 2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgtst.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program gives statistics on **/ +/** distributed source graphs. **/ +/** **/ +/** DATES : # Version 5.0 : from : 23 jun 2007 **/ +/** to : 16 jun 2008 **/ +/** # Version 5.1 : from : 26 oct 2008 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define DGTST +#define SCOTCH_PTSCOTCH + +#include "module.h" +#include "common.h" +#include "ptscotch.h" +#include "dgtst.h" + +/* +** The static and global definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "dgtst [ []] ", + " -h : Display this help", + " -r : Set root process for centralized files (default is 0)", + " -V : Print program version and copyright", + NULL }; + +/*********************/ +/* */ +/* The main routine. */ +/* */ +/*********************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Dgraph grafdat; + int procglbnbr; + int proclocnum; + int protglbnum; /* Root process */ + SCOTCH_Num vertnbr; + SCOTCH_Num velomin; + SCOTCH_Num velomax; + SCOTCH_Num velosum; + double veloavg; + double velodlt; + SCOTCH_Num degrmin; + SCOTCH_Num degrmax; + double degravg; + double degrdlt; + SCOTCH_Num edgenbr; + SCOTCH_Num edlomin; + SCOTCH_Num edlomax; + SCOTCH_Num edlosum; + double edloavg; + double edlodlt; + int flagval; + int i; +#ifdef SCOTCH_PTHREAD + int thrdlvlreqval; + int thrdlvlproval; +#endif /* SCOTCH_PTHREAD */ + + errorProg ("dgtst"); + +#ifdef SCOTCH_PTHREAD + thrdlvlreqval = MPI_THREAD_MULTIPLE; + if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (1)"); + if (thrdlvlreqval > thrdlvlproval) + errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); +#else /* SCOTCH_PTHREAD */ + if (MPI_Init (&argc, &argv) != MPI_SUCCESS) + errorPrint ("main: Cannot initialize (2)"); +#endif /* SCOTCH_PTHREAD */ + + MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ + MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); + protglbnum = 0; /* Assume root process is process 0 */ + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + flagval = C_FLAGNONE; + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '+') && /* If found a file name */ + ((argv[i][0] != '-') || (argv[i][1] == '\0'))) { + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else + errorPrint ("main: too many file names given"); + } + else { /* If found an option name */ + switch (argv[i][1]) { +#ifdef SCOTCH_DEBUG_ALL + case 'D' : + case 'd' : + flagval |= C_FLAGDEBUG; + break; +#endif /* SCOTCH_DEBUG_ALL */ + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'R' : /* Root process (if necessary) */ + case 'r' : + protglbnum = atoi (&argv[i][2]); + if ((protglbnum < 0) || + (protglbnum >= procglbnbr) || + ((protglbnum == 0) && (argv[i][2] != '0'))) + errorPrint ("main: invalid root process number"); + break; + case 'V' : + case 'v' : + fprintf (stderr, "dgtst, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + } + } + } + +#ifdef SCOTCH_DEBUG_ALL + if ((flagval & C_FLAGDEBUG) != 0) { + fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); + if (proclocnum == protglbnum) { /* Synchronize on keybord input */ + char c; + + printf ("Waiting for key press...\n"); + scanf ("%c", &c); + } + MPI_Barrier (MPI_COMM_WORLD); + } +#endif /* SCOTCH_DEBUG_ALL */ + + fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ + + SCOTCH_dgraphInit (&grafdat, MPI_COMM_WORLD); + SCOTCH_dgraphLoad (&grafdat, C_filepntrsrcinp, -1, 0); + SCOTCH_dgraphCheck (&grafdat); + + SCOTCH_dgraphSize (&grafdat, &vertnbr, NULL, &edgenbr, NULL); + SCOTCH_dgraphStat (&grafdat, &velomin, &velomax, &velosum, &veloavg, &velodlt, + °rmin, °rmax, °ravg, °rdlt, + &edlomin, &edlomax, &edlosum, &edloavg, &edlodlt); + + if (C_filepntrdatout != NULL) { + fprintf (C_filepntrdatout, "S\tVertex\tnbr=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) vertnbr); + fprintf (C_filepntrdatout, "S\tVertex load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) velomin, (SCOTCH_Num) velomax, (SCOTCH_Num) velosum, veloavg, velodlt); + fprintf (C_filepntrdatout, "S\tVertex degree\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) degrmin, (SCOTCH_Num) degrmax, (SCOTCH_Num) edgenbr, degravg, degrdlt); + fprintf (C_filepntrdatout, "S\tEdge\tnbr=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) (edgenbr / 2)); + fprintf (C_filepntrdatout, "S\tEdge load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) edlomin, (SCOTCH_Num) edlomax, (SCOTCH_Num) edlosum, edloavg, edlodlt); + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_dgraphExit (&grafdat); + + MPI_Finalize (); +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/dgtst.h b/scotch_6.0.3/src/scotch/dgtst.h new file mode 100644 index 00000000..3f43e2b1 --- /dev/null +++ b/scotch_6.0.3/src/scotch/dgtst.h @@ -0,0 +1,67 @@ +/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : dgtst.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a parallel sparse matrix **/ +/** ordering software. **/ +/** This module contains the data declara- **/ +/** tions for the distributed source graph **/ +/** analyzer. **/ +/** **/ +/** DATES : # Version 5.0 : from : 23 jun 2007 **/ +/** to : 24 jun 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenamedatout C_fileTab[1].name /* Statistics output file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrdatout C_fileTab[1].pntr /* Statistics output file */ + +/*+ Process flags. +*/ + +#define C_FLAGNONE 0x0000 /* No flags */ +#define C_FLAGDEBUG 0x0001 /* Enable easy debugger attachment */ diff --git a/scotch_6.0.3/src/scotch/gbase.c b/scotch_6.0.3/src/scotch/gbase.c new file mode 100644 index 00000000..3a7b8a2e --- /dev/null +++ b/scotch_6.0.3/src/scotch/gbase.c @@ -0,0 +1,153 @@ +/* Copyright 2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gbase.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program changes the base of source **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 4.0 : from : 12 may 2006 **/ +/** to : 12 may 2006 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GBASE + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gbase.h" + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gbase [ []] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Graph grafdat; /* Source graph */ + int baseval; + int i; + + errorProg ("gbase"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + exit (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 1) { /* If number of parameters not reached */ + C_paraNum ++; /* One more parameter */ + baseval = atoi (argv[i]); /* Get the base value */ + if ((baseval < 0) || (baseval > 1)) { + errorPrint ("main: invalid base value '%s'", argv[i]); + return (1); + } + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + exit (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + exit (0); + case 'V' : + fprintf (stderr, "gbase, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + exit (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_graphInit (&grafdat); + SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, (SCOTCH_Num) baseval, 0); + SCOTCH_graphSave (&grafdat, C_filepntrsrcout); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_graphExit (&grafdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gbase.h b/scotch_6.0.3/src/scotch/gbase.h new file mode 100644 index 00000000..05b3e569 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gbase.h @@ -0,0 +1,59 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gbase.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the declarations **/ +/** for the source graph base changer. **/ +/** **/ +/** DATES : # Version 4.0 : from : 12 may 2006 **/ +/** to : 12 may 2006 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** File name aliases. **/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenamesrcout C_fileTab[1].name /* Source graph output file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrsrcout C_fileTab[1].pntr /* Source graph output file */ diff --git a/scotch_6.0.3/src/scotch/gcv.c b/scotch_6.0.3/src/scotch/gcv.c new file mode 100644 index 00000000..ec75e559 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gcv.c @@ -0,0 +1,230 @@ +/* Copyright 2004,2007,2008,2010-2012 Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gcv.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Bruno MARCUSSEAU (v3.1) **/ +/** **/ +/** FUNCTION : Part of a graph file converter. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 0.0 : from : 02 apr 1993 **/ +/** to 02 apr 1993 **/ +/** # Version 2.0 : from : 28 oct 1994 **/ +/** to 16 nov 1994 **/ +/** # Version 3.0 : from : 08 sep 1995 **/ +/** to 20 sep 1995 **/ +/** # Version 3.1 : from : 22 mar 1996 **/ +/** to 22 mar 1996 **/ +/** # Version 3.2 : from : 04 oct 1996 **/ +/** to 26 may 1997 **/ +/** # Version 3.3 : from : 06 oct 1998 **/ +/** to : 21 dec 1998 **/ +/** # Version 3.4 : from : 05 oct 1999 **/ +/** to : 03 feb 2000 **/ +/** # Version 4.0 : from : 29 nov 2003 **/ +/** to : 19 jan 2004 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 11 jun 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GCV + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gcv.h" + +/* +** The static and global variables. +*/ + +static int C_inpFormatType = 0; /* Input graph format */ +static char * C_inpFormatData = "\0"; /* Pointer to auxiliary data */ +static const C_Format C_inpFormatTab[] = { /* Table of input formats */ + { 'B', SCOTCH_graphGeomLoadHabo }, + { 'b', SCOTCH_graphGeomLoadHabo }, + { 'C', SCOTCH_graphGeomLoadChac }, + { 'c', SCOTCH_graphGeomLoadChac }, + { 'M', SCOTCH_graphGeomLoadMmkt }, + { 'm', SCOTCH_graphGeomLoadMmkt }, + { 'S', SCOTCH_graphGeomLoadScot }, + { 's', SCOTCH_graphGeomLoadScot }, + { '\0', NULL } }; + +static int C_outFormatType = 4; /* Output graph format */ +static char * C_outFormatData = "\0"; /* Pointer to auxiliary data */ +static C_Format C_outFormatTab[] = { /* Table of output formats */ + { 'C', SCOTCH_graphGeomSaveChac }, + { 'c', SCOTCH_graphGeomSaveChac }, + { 'M', SCOTCH_graphGeomSaveMmkt }, + { 'm', SCOTCH_graphGeomSaveMmkt }, + { 'S', SCOTCH_graphGeomSaveScot }, + { 's', SCOTCH_graphGeomSaveScot }, + { '\0', NULL } }; + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[3] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gcv [ [ []]] ", + " -h : Display this help", + " -i : Select input file format", + " b : Boeing-Harwell format (matrices)", + " c : Chaco v2.0 format (adjacency)", + " m : Matrix Market format (edges, symmetrized)", + " s : Scotch v3.0 format (adjacency)", + " -o : Select output file format", + " c : Chaco v2.0 format (adjacency)", + " m : Matrix Market symmetric pattern format (edges)", + " s : Scotch v3.0 format (adjacency)", + " -V : Print program version and copyright", + "", + "Default option set is : '-Ib -Os'", + NULL }; + +/*****************************/ +/* */ +/* This is the main function */ +/* */ +/*****************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Graph grafdat; + SCOTCH_Geom geomdat; + int i, j; + + errorProg ("gcv"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give help */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'I' : /* Select input file type */ + case 'i' : + for (j = 0; C_inpFormatTab[j].code != '\0'; j ++) { /* Find proper format code */ + if (C_inpFormatTab[j].code == argv[i][2]) { + C_inpFormatType = j; + C_inpFormatData = &argv[i][3]; + break; + } + } + if (C_inpFormatTab[j].code == '\0') { + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + break; + case 'O' : /* Select input file type */ + case 'o' : + for (j = 0; C_outFormatTab[j].code != '\0'; j ++) { /* Find proper format code */ + if (C_outFormatTab[j].code == argv[i][2]) { + C_outFormatType = j; + C_outFormatData = &argv[i][3]; + break; + } + } + if (C_inpFormatTab[j].code == '\0') { + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + break; + case 'V' : + fprintf (stderr, "gcv, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 Universite de Bordeaux, INRIA & CNRS\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_graphInit (&grafdat); + SCOTCH_geomInit (&geomdat); + C_inpFormatTab[C_inpFormatType].func (&grafdat, &geomdat, C_filepntrsrcinp, NULL, C_inpFormatData); +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_graphCheck (&grafdat) != 0) { + errorPrint ("main: bad graph structure"); + return (1); + } +#endif /* SCOTCH_DEBUG_ALL */ + C_outFormatTab[C_outFormatType].func (&grafdat, &geomdat, C_filepntrsrcout, C_filepntrgeoout, C_outFormatData); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_geomExit (&geomdat); + SCOTCH_graphExit (&grafdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gcv.h b/scotch_6.0.3/src/scotch/gcv.h new file mode 100644 index 00000000..73fe2d7c --- /dev/null +++ b/scotch_6.0.3/src/scotch/gcv.h @@ -0,0 +1,87 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gcv.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a graph file converter. **/ +/** This module contains the data declara- **/ +/** tions for the main module. **/ +/** **/ +/** DATES : # Version 0.0 : from : 02 apr 1993 **/ +/** to 02 apr 1993 **/ +/** # Version 2.0 : from : 28 oct 1994 **/ +/** to 16 nov 1994 **/ +/** # Version 3.0 : from : 08 sep 1995 **/ +/** to 17 sep 1995 **/ +/** # Version 3.1 : from : 22 mar 1996 **/ +/** to 22 mar 1996 **/ +/** # Version 3.2 : from : 04 oct 1996 **/ +/** to 04 mar 1997 **/ +/** # Version 3.3 : from : 06 oct 1998 **/ +/** to : 06 oct 1998 **/ +/** # Version 3.4 : from : 13 oct 1999 **/ +/** to : 14 oct 1999 **/ +/** # Version 4.0 : from : 29 nov 2003 **/ +/** to : 29 nov 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 3 /* Number of files in list */ +#define C_FILEARGNBR 3 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* External graph input file name */ +#define C_filenamesrcout C_fileTab[1].name /* Source graph output file name */ +#define C_filenamegeoout C_fileTab[2].name /* Source graph geometry file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* External graph input file */ +#define C_filepntrsrcout C_fileTab[1].pntr /* Source graph output file */ +#define C_filepntrgeoout C_fileTab[2].pntr /* Source graph geometry file */ + +/* +** The type and structure definitions. +*/ + +/*+ This structure defines the method array element. +*/ + +typedef struct C_Format_ { + char code; /* Format type code */ + int (* func) (); /* Function to call */ +} C_Format; diff --git a/scotch_6.0.3/src/scotch/gmap.c b/scotch_6.0.3/src/scotch/gmap.c new file mode 100644 index 00000000..689ba9f6 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmap.c @@ -0,0 +1,707 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmap.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : Part of a graph mapping software. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 0.0 : from : 05 jan 1993 **/ +/** to 12 may 1993 **/ +/** # Version 1.1 : from : 15 oct 1993 **/ +/** to 15 oct 1993 **/ +/** # Version 1.3 : from : 06 apr 1994 **/ +/** to 18 may 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 17 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 18 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 02 oct 1995 **/ +/** # Version 3.1 : from : 07 nov 1995 **/ +/** to 25 apr 1996 **/ +/** # Version 3.2 : from : 24 sep 1996 **/ +/** to 26 may 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to : 30 mar 1999 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 4.0 : from : 16 jan 2004 **/ +/** to : 27 dec 2004 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 18 jun 2008 **/ +/** # Version 5.1 : from : 30 jun 2010 **/ +/** to : 31 aug 2011 **/ +/** # Version 6.0 : from : 29 may 2010 **/ +/** to : 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GMAP + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gmap.h" + +/* +** The static variables. +*/ + +static int C_partNbr = 1; /* Default number of parts / cluster size */ +static int C_paraNum = 0; /* Number of parameters */ +static int C_paraNbr = 0; /* No parameters for mapping */ +static int C_fileNum = 0; /* Number of file in arg list */ +static int C_fileNbr = 4; /* Number of files for mapping */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "r" }, + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { /* Usage */ + "gmap [ [ [ []]]] ", + "gpart [] [ [ []]] ", + " -b : Load imbalance tolerance (default: 0.05)", + " -c : Choose default mapping strategy according to one or several of :", + " b : enforce load balance as much as possible", + " q : privilege quality over speed (default)", + " r : use only recursive bipartitioning", + " s : privilege speed over quality", + " t : enforce safety", + " -f : Fixed vertices input file", + " -h : Display this help", + " -m : Set mapping strategy (see user's manual)", + " -o : Use partitioning with overlap (only for gpart)", + " -q : Do graph clustering instead of graph partitioning (for gpart)", + " -q : Do graph clustering instead of static mapping (for gmap)", + " -ro : Old mapping input file (for remapping)", + " -rr : Edge migration ratio (for remapping, default: 1)", + " -rv : Vertex migration cost input file (for remapping)", + " -s : Force unity weights on :", + " e : edges", + " v : vertices", + " -V : Print program version and copyright", + " -v : Set verbose mode to :", + " m : mapping information", + " s : strategy information", + " t : timing information", + "", + "See default strategy with option '-vs'", + NULL }; + +static const SCOTCH_Num C_loadOne = 1; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Graph grafdat; /* Source graph */ + SCOTCH_Num grafflag; /* Source graph properties */ + SCOTCH_Arch archdat; /* Target architecture */ + SCOTCH_Strat stradat; /* Mapping strategy */ + char * straptr; /* Strategy string to use */ + SCOTCH_Num straval; + SCOTCH_Mapping mappdat; /* Mapping data */ + SCOTCH_Mapping mapodat; /* Old mapping data */ + SCOTCH_Num * restrict parttab; /* Partition array */ + SCOTCH_Num * restrict vmlotab; /* Vertex migration cost array */ + SCOTCH_Num vertnbr; /* Number of graph vertices */ + Clock runtime[2]; /* Timing variables */ + int flagval; + double kbalval; /* Imbalance tolerance value */ + double emraval; /* Edge migration ratio */ + File vfixfil = { "-", NULL, "r" }; /* Fixed vertex file */ + File mapofil = { "-", NULL, "r" }; /* Old mapping file */ + File vmlofil = { "-", NULL, "r" }; /* Vertex migration cost file */ + int i, j; + + flagval = C_FLAGNONE; /* Default behavior */ + kbalval = 0.01; /* Default imbalance */ + emraval = 1; /* Default edge migration ratio */ + straval = 0; /* No strategy flags */ + straptr = NULL; + + vmlotab = NULL; + +#ifdef SCOTCH_COMPILE_PART + flagval |= C_FLAGPART; + C_paraNbr = 1; /* One more parameter */ + C_fileNbr = 3; /* One less file to provide */ + errorProg ("gpart"); +#else + errorProg ("gmap"); +#endif /* SCOTCH_COMPILE_PART */ + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + grafflag = 0; /* Use vertex and edge weights */ + SCOTCH_stratInit (&stradat); /* Set default mapping strategy */ + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < C_paraNbr) { /* If number of parameters not reached */ + if ((C_partNbr = atoi (argv[i])) < 1) /* Get the number of parts */ + errorPrint ("main: invalid number of parts '%s'", argv[i]); + C_paraNum ++; + continue; /* Process the other parameters */ + } + if (C_fileNum < C_fileNbr) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else + errorPrint ("main: too many file names given"); + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'B' : + case 'b' : + flagval |= C_FLAGKBALVAL; + kbalval = atof (&argv[i][2]); + if ((kbalval < 0.0) || + (kbalval > 1.0) || + ((kbalval == 0.0) && + ((argv[i][2] != '0') && (argv[i][2] != '.')))) { + errorPrint ("main: invalid load imbalance ratio"); + } + break; + case 'C' : + case 'c' : /* Strategy selection parameters */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'B' : + case 'b' : + straval |= SCOTCH_STRATBALANCE; + break; + case 'Q' : + case 'q' : + straval |= SCOTCH_STRATQUALITY; + break; + case 'R' : + case 'r' : + straval |= SCOTCH_STRATRECURSIVE; + break; + case 'S' : + case 's' : + straval |= SCOTCH_STRATSPEED; + break; + case 'T' : + case 't' : + straval |= SCOTCH_STRATSAFETY; + break; + default : + errorPrint ("main: invalid strategy selection option '%c' after '-C'", argv[i][j]); + } + } + break; + case 'F' : + case 'f' : /* Fixed vertex file */ + flagval |= C_FLAGFIXED; + vfixfil.pntr = stdin; + vfixfil.name = &argv[i][2]; + break; + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'M' : + case 'm' : + straptr = &argv[i][2]; + break; + case 'O' : + case 'o' : + flagval |= C_FLAGPARTOVL; + break; + case 'Q' : + case 'q' : + flagval |= C_FLAGCLUSTER; + if ((flagval & C_FLAGPART) != 0) { /* If partitioning program */ + if (argv[i][2] != '\0') + errorPrint ("main: invalid parameter '%s' after '-q' for gpart", argv[i] + 2); + } + else { + if (argv[i][1] == '\0') + errorPrint ("main: missing parameter after '-q' for gmap"); + if ((C_partNbr = atoi (argv[i] + 2)) < 1) /* Get maximum cluster load */ + errorPrint ("main: invalid cluster load '%s'", argv[i] + 2); + } + break; + case 'R' : + case 'r' : /* Remapping parameters */ + switch (argv[i][2]) { + case 'O' : + case 'o' : /* Old mapping input file */ + flagval |= C_FLAGRMAPOLD; + mapofil.pntr = stdin; + mapofil.name = &argv[i][3]; + break; + case 'R' : + case 'r' : /* Edge migration ratio */ + flagval |= C_FLAGRMAPRAT; + emraval = atof (&argv[i][3]); + if (emraval <= 0.0) + errorPrint ("main: invalid edge migration ratio"); + break; + case 'V' : + case 'v' : /* Vertex migration cost */ + flagval |= C_FLAGRMAPCST; + vmlofil.pntr = stdin; + vmlofil.name = &argv[i][3]; + break; + default : + errorPrint ("main: invalid remapping option '%c'", argv[i][2]); + } + break; + case 'S' : + case 's' : /* Source graph parameters */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'E' : + case 'e' : + grafflag |= 2; /* Do not load edge weights */ + break; + case 'V' : + case 'v' : + grafflag |= 1; /* Do not load vertex weights */ + break; + default : + errorPrint ("main: invalid source graph option '%c'", argv[i][j]); + } + } + break; + case 'V' : + fprintf (stderr, "gmap/gpart, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + case 'v' : /* Output control info */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'M' : + case 'm' : + flagval |= C_FLAGVERBMAP; + break; + case 'S' : + case 's' : + flagval |= C_FLAGVERBSTR; + break; + case 'T' : + case 't' : + flagval |= C_FLAGVERBTIM; + break; + default : + errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); + } + } + break; + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + } + } + } + + if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ + C_fileTab[3].name = C_fileTab[2].name; /* Put provided file names at their right place */ + C_fileTab[2].name = C_fileTab[1].name; + C_fileTab[1].name = "-"; + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + if ((flagval & C_FLAGFIXED) != 0) + fileBlockOpen (&vfixfil, 1); + if ((flagval & C_FLAGRMAPOLD) != 0) { + fileBlockOpen (&mapofil, 1); + if ((flagval & C_FLAGRMAPCST) != 0) + fileBlockOpen (&vmlofil, 1); + } + + clockInit (&runtime[0]); + clockStart (&runtime[0]); + + SCOTCH_graphInit (&grafdat); /* Create graph structure */ + SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, grafflag); /* Read source graph */ + + SCOTCH_archInit (&archdat); /* Create architecture structure */ + if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ + if ((flagval & C_FLAGCLUSTER) != 0) /* If program run as graph clustering */ + SCOTCH_archVcmplt (&archdat); /* Create a variable-sized complete graph */ + else /* Program is run as plain graph partitioner */ + SCOTCH_archCmplt (&archdat, C_partNbr); /* Create a complete graph of proper size */ + } + else { + SCOTCH_archLoad (&archdat, C_filepntrtgtinp); /* Read target architecture */ + if ((flagval & C_FLAGCLUSTER) == 0) /* If part size not to be preserved */ + C_partNbr = SCOTCH_archSize (&archdat); + else { + if (SCOTCH_archVar (&archdat) == 0) + errorPrint ("main: non variable-sized architecture provided while '-q' flag set"); + } + } + + if (((flagval & (C_FLAGPART | C_FLAGPARTOVL)) == C_FLAGPARTOVL) && /* If the mapper was asked to compute an overlap */ + (strcmp (SCOTCH_archName (&archdat), "cmplt") != 0)) /* And the given target architecture is not a complete graph */ + errorPrint ("main: option '-o' only valid for graph partitioning"); + + if ((flagval & (C_FLAGPARTOVL | C_FLAGCLUSTER)) == (C_FLAGPARTOVL | C_FLAGCLUSTER)) + errorPrint ("main: options '-o' and '-q' are exclusive"); + + if ((flagval & (C_FLAGPARTOVL | C_FLAGFIXED)) == (C_FLAGPARTOVL | C_FLAGFIXED)) + errorPrint ("main: options '-o' and '-f' are exclusive"); + + if ((flagval & (C_FLAGPARTOVL | C_FLAGRMAPOLD)) == (C_FLAGPARTOVL | C_FLAGRMAPOLD)) + errorPrint ("main: options '-o' and '-ro' are exclusive"); + + if (((flagval & C_FLAGRMAPOLD) == 0) && + (((flagval & C_FLAGRMAPRAT) != 0) || ((flagval & C_FLAGRMAPCST) != 0))) + errorPrint ("main: an old mapping file must be provided ('-ro' flag) when '-rr' or '-rv' flags are set"); + + if ((straval != 0) || ((flagval & C_FLAGKBALVAL) != 0)) { + if (straptr != NULL) + errorPrint ("main: options '-b' / '-c' and '-m' are exclusive"); + + if ((flagval & C_FLAGPARTOVL) != 0) /* If overlap partitioning wanted */ + SCOTCH_stratGraphPartOvlBuild (&stradat, straval, (SCOTCH_Num) C_partNbr, kbalval); + else if ((flagval & C_FLAGCLUSTER) != 0) /* If clustering wanted */ + SCOTCH_stratGraphClusterBuild (&stradat, straval, (SCOTCH_Num) C_partNbr, 1.0, kbalval); + else + SCOTCH_stratGraphMapBuild (&stradat, straval, (SCOTCH_Num) C_partNbr, kbalval); + } + + SCOTCH_graphSize (&grafdat, &vertnbr, NULL); + if ((parttab = memAlloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) /* Allocate by hand in case of overlap partitioning */ + errorPrint ("main: out of memory"); + + if ((flagval & C_FLAGPARTOVL) == 0) { + if ((flagval & C_FLAGFIXED) != 0) + SCOTCH_graphTabLoad (&grafdat, parttab, vfixfil.pntr); + + if ((flagval & C_FLAGRMAPOLD) != 0) { + SCOTCH_graphMapInit (&grafdat, &mapodat, &archdat, NULL); + SCOTCH_graphMapLoad (&grafdat, &mapodat, mapofil.pntr); + if ((flagval & C_FLAGRMAPCST) != 0) { + if ((vmlotab = memAlloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) + errorPrint ("main: out of memory (2)"); + SCOTCH_graphTabLoad (&grafdat, vmlotab, vmlofil.pntr); + } + } + } + + clockStop (&runtime[0]); /* Get input time */ + clockInit (&runtime[1]); + clockStart (&runtime[1]); + + if ((flagval & C_FLAGPARTOVL) != 0) { /* If overlap partitioning wanted */ + SCOTCH_graphPartOvl (&grafdat, C_partNbr, &stradat, parttab); /* Perform overlap partitioning */ + + clockStop (&runtime[1]); /* Get computation time */ + clockStart (&runtime[0]); + + C_partSave (&grafdat, parttab, C_filepntrmapout); /* Write partitioning */ + } + else { /* Regular partitioning / mapping / clustering wanted */ + if (straptr != NULL) /* Set static mapping strategy if needed */ + SCOTCH_stratGraphMap (&stradat, straptr); + + SCOTCH_graphMapInit (&grafdat, &mappdat, &archdat, parttab); + + if ((flagval & C_FLAGRMAPOLD) != 0) { + if ((flagval & C_FLAGFIXED) != 0) + SCOTCH_graphRemapFixedCompute (&grafdat, &mappdat, &mapodat, emraval, vmlotab, &stradat); /* Perform remapping */ + else + SCOTCH_graphRemapCompute (&grafdat, &mappdat, &mapodat, emraval, vmlotab, &stradat); + } + else { + if ((flagval & C_FLAGFIXED) != 0) + SCOTCH_graphMapFixedCompute (&grafdat, &mappdat, &stradat); /* Perform mapping */ + else + SCOTCH_graphMapCompute (&grafdat, &mappdat, &stradat); + } + + clockStop (&runtime[1]); /* Get computation time */ + clockStart (&runtime[0]); + + SCOTCH_graphMapSave (&grafdat, &mappdat, C_filepntrmapout); /* Write mapping */ + } + + clockStop (&runtime[0]); /* Get output time */ + + if (flagval & C_FLAGVERBSTR) { + fprintf (C_filepntrlogout, "S\tStrat="); + SCOTCH_stratSave (&stradat, C_filepntrlogout); + putc ('\n', C_filepntrlogout); + } + if (flagval & C_FLAGVERBTIM) { + fprintf (C_filepntrlogout, "T\tMapping\t\t%g\nT\tI/O\t\t%g\nT\tTotal\t\t%g\n", + (double) clockVal (&runtime[1]), + (double) clockVal (&runtime[0]), + (double) clockVal (&runtime[0]) + + (double) clockVal (&runtime[1])); + } + if ((flagval & C_FLAGPARTOVL) != 0) { /* If overlap partitioning wanted */ + if (flagval & C_FLAGVERBMAP) + C_partViewOvl (&grafdat, parttab, C_filepntrlogout); + } + else { /* Regular partitioning / mapping wanted */ + if (flagval & C_FLAGVERBMAP) { + if ((flagval & C_FLAGRMAPOLD) != 0) + SCOTCH_graphRemapView (&grafdat, &mappdat, &mapodat, emraval, vmlotab, C_filepntrlogout); + else + SCOTCH_graphMapView (&grafdat, &mappdat, C_filepntrlogout); + } + + SCOTCH_graphMapExit (&grafdat, &mappdat); /* Free mapping structure only when used, that is, not for overlay */ + if ((flagval & C_FLAGRMAPOLD) != 0) { + SCOTCH_graphMapExit (&grafdat, &mapodat); + if ((flagval & C_FLAGRMAPCST) != 0) + memFree (vmlotab); + } + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + if ((flagval & C_FLAGFIXED) != 0) + fileBlockClose (&vfixfil, 1); + if ((flagval & C_FLAGRMAPOLD) != 0) { + fileBlockClose (&mapofil, 1); + if ((flagval & C_FLAGRMAPCST) != 0) + fileBlockClose (&vmlofil, 1); + } + + SCOTCH_graphExit (&grafdat); + SCOTCH_stratExit (&stradat); + SCOTCH_archExit (&archdat); + + memFree (parttab); /* Free hand-made partition array */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} + +/* This routine writes a partition to +** the given stream. +** It returns : +** - void : in case of success +** - exit : on error (because of errorPrint) +*/ + +void +C_partSave ( +SCOTCH_Graph * restrict const grafptr, +SCOTCH_Num * restrict const parttab, +FILE * const stream) +{ + SCOTCH_Num baseval; + const SCOTCH_Num * restrict parttax; + SCOTCH_Num * vlbltab; + const SCOTCH_Num * restrict vlbltax; + SCOTCH_Num vertnbr; + SCOTCH_Num vertnum; + + SCOTCH_graphData (grafptr, &baseval, &vertnbr, NULL, NULL, NULL, &vlbltab, NULL, NULL, NULL); + + parttax = parttab - baseval; + vlbltax = (vlbltab != NULL) ? (vlbltab - baseval) : NULL; + + if (fprintf (stream, SCOTCH_NUMSTRING "\n", (SCOTCH_Num) vertnbr) == EOF) + errorPrint ("C_partSave: bad output (1)"); + + for (vertnum = baseval; vertnum < (vertnbr + baseval); vertnum ++) { + if (fprintf (stream, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) ((vlbltax != NULL) ? vlbltax[vertnum] : vertnum), + (SCOTCH_Num) parttax[vertnum]) == EOF) { + errorPrint ("C_mapSave: bad output (2)"); + } + } +} + +/* This routine writes the characteristics +** of the given overlap partition to the +** given stream. +** It returns : +** - void : in case of success +** - exit : on error (because of errorPrint) +*/ + +void +C_partViewOvl ( +SCOTCH_Graph * restrict const grafptr, +SCOTCH_Num * restrict const parttab, +FILE * const stream) +{ + SCOTCH_Num baseval; + SCOTCH_Num vertnbr; + SCOTCH_Num vertnum; + SCOTCH_Num * verttab; + const SCOTCH_Num * restrict verttax; + SCOTCH_Num * vendtab; + const SCOTCH_Num * restrict vendtax; + SCOTCH_Num * velotab; + SCOTCH_Num velomsk; + const SCOTCH_Num * restrict velobax; /* Data for handling of optional arrays */ + SCOTCH_Num * edgetab; + const SCOTCH_Num * restrict edgetax; + const SCOTCH_Num * restrict parttax; + SCOTCH_Num partnum; + C_PartList * restrict listtab; + SCOTCH_Num fronnbr; + SCOTCH_Num fronload; + SCOTCH_Num * restrict compload; + SCOTCH_Num * restrict compsize; + SCOTCH_Num comploadsum; + SCOTCH_Num comploadmax; + SCOTCH_Num comploadmin; + double comploadavg; + + if (memAllocGroup ((void **) (void *) + &compload, (size_t) (C_partNbr * sizeof (SCOTCH_Num)), + &compsize, (size_t) (C_partNbr * sizeof (SCOTCH_Num)), + &listtab, (size_t) ((C_partNbr + 1) * sizeof (C_PartList)), NULL) == NULL) { + errorPrint ("C_partViewOvl: out of memory"); + } + listtab ++; /* TRICK: Trim array so that listtab[-1] is valid */ + memSet (listtab, ~0, C_partNbr * sizeof (C_PartList)); /* Set vertex indices to ~0 */ + memSet (compload, 0, C_partNbr * sizeof (SCOTCH_Num)); + memSet (compsize, 0, C_partNbr * sizeof (SCOTCH_Num)); + + SCOTCH_graphData (grafptr, &baseval, + &vertnbr, &verttab, &vendtab, &velotab, NULL, + NULL, &edgetab, NULL); + + if (velotab == NULL) { /* Set accesses to optional arrays */ + velobax = &C_loadOne; /* In case vertices not weighted (least often) */ + velomsk = 0; + } + else { + velobax = velotab - baseval; + velomsk = ~((SCOTCH_Num) 0); + } + verttax = verttab - baseval; + vendtax = vendtab - baseval; + edgetax = edgetab - baseval; + parttax = parttab - baseval; + + fronnbr = + fronload = 0; + for (vertnum = baseval; vertnum < (vertnbr + baseval); vertnum ++) { + SCOTCH_Num partval; + + partval = parttax[vertnum]; + if (partval >= 0) { + compload[partval] += velobax[vertnum & velomsk]; + compsize[partval] ++; + } + else { /* Vertex is in separator */ + SCOTCH_Num listidx; /* Index of first neighbor part */ + SCOTCH_Num edgenum; + SCOTCH_Num veloval; + + fronnbr ++; /* Add vertex to frontier */ + fronload += velobax[vertnum & velomsk]; + + listidx = -1; /* No neighboring parts recorded yet */ + listtab[-1].vertnum = vertnum; /* Separator neighbors will not be considered */ + for (edgenum = verttax[vertnum]; + edgenum < vendtax[vertnum]; edgenum ++) { /* Compute gain */ + SCOTCH_Num vertend; + SCOTCH_Num partend; + + vertend = edgetax[edgenum]; + partend = parttax[vertend]; + if (listtab[partend].vertnum != vertnum) { /* If part not yet considered */ + listtab[partend].vertnum = vertnum; /* Link it in list of neighbors */ + listtab[partend].nextidx = listidx; + listidx = partend; + } + } + + veloval = velobax[vertnum & velomsk]; + + while (listidx != -1) { /* For all neighboring parts found */ + compload[listidx] += veloval; /* Add load of separator vertex to part */ + compsize[listidx] ++; + listidx = listtab[listidx].nextidx; + } + } + } + + comploadsum = 0; + for (partnum = 0; partnum < C_partNbr; partnum ++) + comploadsum += compload[partnum]; + + comploadmax = 0; + comploadmin = comploadsum; + for (partnum = 0; partnum < C_partNbr; partnum ++) { + if (compload[partnum] > comploadmax) + comploadmax = compload[partnum]; + if (compload[partnum] < comploadmin) + comploadmin = compload[partnum]; + } + comploadavg = (double) comploadsum / (double) C_partNbr; + fprintf (stream, "P\tsep=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) fronload); + fprintf (stream, "P\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tavg=%g\n", + (SCOTCH_Num) comploadmin, + (SCOTCH_Num) comploadmax, + (double) comploadavg); +#if 0 /* TODO REMOVE */ + for (partnum = 0; partnum < C_partNbr; partnum ++) + fprintf (stream, "P\tload[" SCOTCH_NUMSTRING "]=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) partnum, + (SCOTCH_Num) compload[partnum]); +#endif + fprintf (stream, "P\tmaxavg=%g\tminavg=%g\n", + ((double) comploadmax / comploadavg), + ((double) comploadmin / comploadavg)); + + memFree (compload); +} diff --git a/scotch_6.0.3/src/scotch/gmap.h b/scotch_6.0.3/src/scotch/gmap.h new file mode 100644 index 00000000..631835a2 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmap.h @@ -0,0 +1,119 @@ +/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmap.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** Sebastien FOURESTIER (v6.0) **/ +/** **/ +/** FUNCTION : Part of a graph static mapper. **/ +/** These lines are the data declaration **/ +/** for the main routine. **/ +/** **/ +/** DATES : # Version 0.0 : from : 05 jan 1993 **/ +/** to 12 may 1993 **/ +/** # Version 1.3 : from : 09 apr 1994 **/ +/** to 30 apr 1994 **/ +/** # Version 2.0 : from : 06 jun 1994 **/ +/** to 08 nov 1994 **/ +/** # Version 2.1 : from : 07 apr 1995 **/ +/** to 09 jun 1995 **/ +/** # Version 3.0 : from : 01 jul 1995 **/ +/** to 15 aug 1995 **/ +/** # Version 3.1 : from : 07 nov 1995 **/ +/** to 10 nov 1995 **/ +/** # Version 3.2 : from : 04 oct 1996 **/ +/** to 18 jul 1997 **/ +/** # Version 3.3 : from : 07 oct 1998 **/ +/** to : 31 may 1999 **/ +/** # Version 4.0 : from : 16 jan 2004 **/ +/** to : 16 jan 2004 **/ +/** # Version 5.0 : from : 12 jun 2008 **/ +/** to : 18 jun 2008 **/ +/** # Version 5.1 : from : 28 aug 2010 **/ +/** to : 18 jul 2011 **/ +/** # Version 6.0 : from : 29 may 2010 **/ +/** to : 25 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 4 /* Number of files in list */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenametgtinp C_fileTab[1].name /* Target architecture input file name */ +#define C_filenamemapout C_fileTab[2].name /* Mapping result output file name */ +#define C_filenamelogout C_fileTab[3].name /* Log file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrtgtinp C_fileTab[1].pntr /* Target architecture input file */ +#define C_filepntrmapout C_fileTab[2].pntr /* Mapping result output file */ +#define C_filepntrlogout C_fileTab[3].pntr /* Log file */ + +/*+ Process flags. +*/ + +#define C_FLAGNONE 0x0000 /* No flags */ +#define C_FLAGPART 0x0001 /* Partitioning */ +#define C_FLAGPARTOVL 0x0002 /* Partitioning with overlap */ +#define C_FLAGVERBSTR 0x0004 /* Verbose flags */ +#define C_FLAGVERBTIM 0x0008 +#define C_FLAGVERBMAP 0x0010 +#define C_FLAGKBALVAL 0x0020 /* Imbalance tolerance */ +#define C_FLAGCLUSTER 0x0040 /* Clustering */ +#define C_FLAGFIXED 0x0080 /* Fixed vertices input file */ +#define C_FLAGRMAPOLD 0x0100 /* Old mapping file */ +#define C_FLAGRMAPRAT 0x0200 /* Edge migration ratio */ +#define C_FLAGRMAPCST 0x0400 /* Vertex migration cost file */ + +/* +** The type and structure definitions. +*/ + +/*+ This structure stores part lists. +*/ + +typedef struct C_PartList_ { + SCOTCH_Num vertnum; /*+ Number of vertex of which part is neighbor +*/ + SCOTCH_Num nextidx; /*+ Pointer to index of next recorded neighbor +*/ +} C_PartList; + +/* +** The function prototypes. +*/ + +void C_partSave (SCOTCH_Graph * restrict const, SCOTCH_Num * restrict const, FILE * const); +void C_partViewOvl (SCOTCH_Graph * restrict const, SCOTCH_Num * restrict const, FILE * const); diff --git a/scotch_6.0.3/src/scotch/gmk_hy.c b/scotch_6.0.3/src/scotch/gmk_hy.c new file mode 100644 index 00000000..04e1200d --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_hy.c @@ -0,0 +1,173 @@ +/* Copyright 2004,2007,2008,2010-2012 Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_hy.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the source graph for hypercube **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 2.0 : from : 03 nov 1994 **/ +/** to 03 nov 1994 **/ +/** # Version 3.0 : from : 11 jul 1995 **/ +/** to 11 jul 1995 **/ +/** # Version 3.2 : from : 03 jun 1997 **/ +/** to : 03 jun 1997 **/ +/** # Version 3.3 : from : 06 oct 1998 **/ +/** to : 06 oct 1998 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 map 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GMK_HY + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gmk_hy.h" + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gmk_hy [] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/****************************************/ +/* */ +/* The main routine, which computes the */ +/* source graph description. */ +/* */ +/****************************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num hdim = 1; /* Graph dimension */ + SCOTCH_Num hnbr; /* Number of vertices */ + SCOTCH_Num hbit; /* Most significant bit */ + SCOTCH_Num hvrt; + SCOTCH_Num hngb; + int i; + + errorProg ("gmk_hy"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + exit (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 1) { /* If number of parameters not reached */ + if ((hdim = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + exit (1); + } + C_paraNum ++; + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + exit (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + exit (0); + case 'V' : + fprintf (stderr, "gmk_hy, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + exit (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + hnbr = 1 << hdim; /* Compute number of vertices */ + hbit = 1 << (hdim - 1); /* Compute highest bit value */ + + fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n0\t000\n", + (SCOTCH_Num) hnbr, /* Print number of vertices */ + (SCOTCH_Num) (hdim * hnbr)); /* Print number of edges (arcs) */ + + for (hvrt = 0; hvrt < hnbr; hvrt ++) { /* For all vertices */ + fprintf (C_filepntrsrcout, "" SCOTCH_NUMSTRING "", + (SCOTCH_Num) hdim); /* Output number of neighbors */ + for (hngb = hbit; hngb > 0; hngb >>= 1) /* For all vertex bits */ + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, /* Write corresponding neighbor */ + (SCOTCH_Num) (hvrt ^ hngb)); + fprintf (C_filepntrsrcout, "\n"); + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gmk_hy.h b/scotch_6.0.3/src/scotch/gmk_hy.h new file mode 100644 index 00000000..4b41b7a1 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_hy.h @@ -0,0 +1,64 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_hy.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the hypercube source graph **/ +/** building program. **/ +/** **/ +/** DATES : # Version 2.0 : from : 03 nov 1994 **/ +/** to 03 nov 1994 **/ +/** # Version 3.0 : from : 11 jul 1995 **/ +/** to 11 jul 1995 **/ +/** # Version 3.2 : from : 03 jun 1997 **/ +/** to : 03 jun 1997 **/ +/** # Version 3.3 : from : 06 oct 1998 **/ +/** to : 06 oct 1998 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 1 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenamesrcout C_fileTab[0].name /* Source graph output file name */ + +#define C_filepntrsrcout C_fileTab[0].pntr /* Source graph output file */ diff --git a/scotch_6.0.3/src/scotch/gmk_m2.c b/scotch_6.0.3/src/scotch/gmk_m2.c new file mode 100644 index 00000000..a8959ff6 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_m2.c @@ -0,0 +1,267 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_m2.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the source graph for 2D mesh **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 2.0 : from : 30 oct 1994 **/ +/** to 08 nov 1994 **/ +/** # Version 3.0 : from : 11 jul 1995 **/ +/** to 02 oct 1995 **/ +/** # Version 3.2 : from : 03 jun 1997 **/ +/** to : 03 jun 1997 **/ +/** # Version 3.3 : from : 06 oct 1998 **/ +/** to : 06 oct 1998 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 18 may 2004 **/ +/** # Version 5.0 : from : 13 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/** NOTES : # The vertices of the (dX,dY) mesh are **/ +/** numbered as terminals so that **/ +/** t(0,0) = 0, t(1,0) = 1, **/ +/** t(dX - 1, 0) = dX - 1, t(0,1) = dX, **/ +/** and t(x,y) = (y * dX) + x. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GMK_M2 + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gmk_m2.h" + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gmk_m2 [ []] ", + " -b : Set base value for output (0 or 1)", + " -e : Build a 8-neighbor grid rather than a 4-neighbor one", + " -g : Output the geometry to ", + " -h : Display this help", + " -t : Build a torus rather than a mesh", + " -V : Print program version and copyright", + NULL }; + +/****************************************/ +/* */ +/* The main routine, which computes the */ +/* source graph description. */ +/* */ +/****************************************/ + +int +main ( +int argc, +char * argv[]) +{ + int flagval; /* Process flags */ + SCOTCH_Num baseval; /* Base value */ + SCOTCH_Num d[2] = { 1, 1 }; /* Mesh dimensions */ + SCOTCH_Num c[2]; /* Vertex coordinates */ + int i; + + errorProg ("gmk_m2"); + + flagval = C_FLAGDEFAULT; /* Set default flags */ + baseval = 0; + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 2) { /* If number of parameters not reached */ + if ((d[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'B' : /* Set base value */ + case 'b' : + baseval = (SCOTCH_Num) atol (&argv[i][2]); + if ((baseval < 0) || (baseval > 1)) { + errorPrint ("main: invalid base value '" SCOTCH_NUMSTRING "'", (SCOTCH_Num) baseval); + } + break; + case 'E' : /* Build a finite-element grid */ + case 'e' : + flagval |= C_FLAGELEM; + break; + case 'G' : /* Output the geometry */ + case 'g' : + flagval |= C_FLAGGEOOUT; + if (argv[i][2] != '\0') + C_filenamegeoout = &argv[i][2]; + break; + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'T' : /* Build a torus */ + case 't' : + flagval |= C_FLAGTORUS; + break; + case 'V' : + fprintf (stderr, "gmk_m2, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + if (flagval & C_FLAGELEM) { /* Build a 8-neighbor grid */ + errorPrint ("main: elements not supported"); + return (1); + } + + if (flagval & C_FLAGTORUS) { /* Build a torus */ + fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t000\n", + (SCOTCH_Num) (d[0] * d[1]), /* Print number of vertices */ + (SCOTCH_Num) ((4 * d[0] * d[1]) - /* Print number of edges (arcs) */ + ((d[0] < 3) ? (2 * d[1]) : 0) - + ((d[1] < 3) ? (2 * d[0]) : 0)), + (SCOTCH_Num) baseval); + + for (c[1] = 0; c[1] < d[1]; c[1] ++) { /* Output neighbor list */ + for (c[0] = 0; c[0] < d[0]; c[0] ++) { + fprintf (C_filepntrsrcout, SCOTCH_NUMSTRING, + (SCOTCH_Num) (((d[0] > 2) ? 3 : d[0]) + /* Output number of neighbors */ + ((d[1] > 2) ? 3 : d[1]) - 2)); + if (d[1] > 2) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, /* Output the neighbors */ + (SCOTCH_Num) (((c[1] + d[1] - 1) % d[1]) * d[0] + c[0] + baseval)); + if (d[0] > 2) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[1] * d[0] + (c[0] + d[0] - 1) % d[0]) + baseval)); + if (d[0] > 1) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (c[1] * d[0] + ((c[0] + 1) % d[0]) + baseval)); + if (d[1] > 1) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (((c[1] + 1) % d[1]) * d[0] + c[0] + baseval)); + fprintf (C_filepntrsrcout, "\n"); + } + } + } + else { /* Build a mesh */ + fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t000\n", + (SCOTCH_Num) (d[0] * d[1]), + (SCOTCH_Num) ((d[0] * d[1] * 2 - (d[0] + d[1])) * 2), + (SCOTCH_Num) baseval); + + for (c[1] = 0; c[1] < d[1]; c[1] ++) { /* Output neighbor list */ + for (c[0] = 0; c[0] < d[0]; c[0] ++) { + fprintf (C_filepntrsrcout, "%d", + ((c[0] == 0) ? 0 : 1) + /* Output number of neighbors */ + ((c[0] == (d[0] - 1)) ? 0 : 1) + + ((c[1] == 0) ? 0 : 1) + + ((c[1] == (d[1] - 1)) ? 0 : 1)); + if (c[1] != 0) /* Output the neighbors */ + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[1] - 1) * d[0] + c[0] + baseval)); + if (c[0] != 0) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (c[1] * d[0] + (c[0] - 1) + baseval)); + if (c[0] != (d[0] - 1)) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (c[1] * d[0] + (c[0] + 1) + baseval)); + if (c[1] != (d[1] - 1)) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[1] + 1) * d[0] + c[0] + baseval)); + fprintf (C_filepntrsrcout, "\n"); + } + } + } + + if (flagval & C_FLAGGEOOUT) { /* If geometry is wanted */ + fprintf (C_filepntrgeoout, "2\n" SCOTCH_NUMSTRING "\n", /* Output geometry file header */ + (SCOTCH_Num) (d[0] * d[1])); + + for (c[1] = 0; c[1] < d[1]; c[1] ++) { /* Output mesh coordinates */ + for (c[0] = 0; c[0] < d[0]; c[0] ++) + fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) (c[1] * d[0] + c[0] + baseval), + (SCOTCH_Num) c[0], + (SCOTCH_Num) (d[1] - 1 - c[1])); + } + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gmk_m2.h b/scotch_6.0.3/src/scotch/gmk_m2.h new file mode 100644 index 00000000..41f150af --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_m2.h @@ -0,0 +1,74 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_m2.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the bidimensional mesh source **/ +/** graph building program. **/ +/** **/ +/** DATES : # Version 2.0 : from : 30 oct 1994 **/ +/** to 08 nov 1994 **/ +/** # Version 3.0 : from : 11 jul 1995 **/ +/** to 11 jul 1995 **/ +/** # Version 3.2 : from : 03 jun 1997 **/ +/** to : 03 jun 1997 **/ +/** # Version 3.3 : from : 06 oct 1998 **/ +/** to : 06 oct 1998 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenamesrcout C_fileTab[0].name /* Source graph output file name */ +#define C_filenamegeoout C_fileTab[1].name /* Geometry graph output file name */ + +#define C_filepntrsrcout C_fileTab[0].pntr /* Source graph output file */ +#define C_filepntrgeoout C_fileTab[1].pntr /* Geometry graph output file */ + +/*+ Process flags. +*/ + +#define C_FLAGGEOOUT 0x0001 /* Output the geometry graph */ +#define C_FLAGTORUS 0x0002 /* Build a torus rather than a mesh */ +#define C_FLAGELEM 0x0004 /* Build a 8-neighbor grid rather than a 4-neighbor one */ + +#define C_FLAGDEFAULT 0x0000 /* Default flags */ diff --git a/scotch_6.0.3/src/scotch/gmk_m3.c b/scotch_6.0.3/src/scotch/gmk_m3.c new file mode 100644 index 00000000..2d4a56a4 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_m3.c @@ -0,0 +1,273 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_m3.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the source graph for **/ +/** tridimensional mesh source graphs. **/ +/** **/ +/** DATES : # Version 4.0 : from : 11 feb 2002 **/ +/** to : 18 may 2004 **/ +/** # Version 5.0 : from : 13 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/** NOTES : # The vertices of the (dX,dY,dZ) mesh **/ +/** are numbered as terminals so that **/ +/** t(0,0,0) = 0, t(1,0,0) = 1, **/ +/** t(dX - 1, 0, 0) = dX - 1, t(0,1,0) = **/ +/** dX, t (0, 0, 1) = dX * dY - 1, **/ +/** and t(x,y,z) = (z * dY + y) * dX + x. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GMK_M3 + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gmk_m3.h" + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gmk_m3 [ [ []]] ", + " -b : Set base value for output (0 or 1)", + " -g : Output the geometry to ", + " -h : Display this help", + " -t : Build a torus rather than a mesh", + " -V : Print program version and copyright", + NULL }; + +/****************************************/ +/* */ +/* The main routine, which computes the */ +/* source graph description. */ +/* */ +/****************************************/ + +int +main ( +int argc, +char * argv[]) +{ + int flagval; /* Process flags */ + SCOTCH_Num baseval; /* Base value */ + SCOTCH_Num d[3] = { 1, 1, 1 }; /* Mesh dimensions */ + SCOTCH_Num c[3]; /* Vertex coordinates */ + int i; + + errorProg ("gmk_m3"); + + flagval = C_FLAGDEFAULT; /* Set default flags */ + baseval = 0; + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 3) { /* If number of parameters not reached */ + if ((d[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'B' : /* Set base value */ + case 'b' : + baseval = (SCOTCH_Num) atol (&argv[i][2]); + if ((baseval < 0) || (baseval > 1)) { + errorPrint ("main: invalid base value '" SCOTCH_NUMSTRING "'", (SCOTCH_Num) baseval); + } + break; + case 'G' : /* Output the geometry */ + case 'g' : + flagval |= C_FLAGGEOOUT; + if (argv[i][2] != '\0') + C_filenamegeoout = &argv[i][2]; + break; + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'T' : /* Build a torus */ + case 't' : + flagval |= C_FLAGTORUS; + break; + case 'V' : + fprintf (stderr, "gmk_m3, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + if (flagval & C_FLAGTORUS) { /* Build a torus */ + fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t000\n", + (SCOTCH_Num) (d[0] * d[1] * d[2]), /* Print number of vertices */ + (SCOTCH_Num) ((6 * d[0] * d[1] * d[2]) - /* Print number of edges (arcs) */ + ((d[0] < 3) ? (2 * d[1] * d[2]) : 0) - + ((d[1] < 3) ? (2 * d[0] * d[2]) : 0) - + ((d[2] < 3) ? (2 * d[0] * d[1]) : 0)), + (SCOTCH_Num) baseval); + + for (c[2] = 0; c[2] < d[2]; c[2] ++) { /* Output neighbor list */ + for (c[1] = 0; c[1] < d[1]; c[1] ++) { + for (c[0] = 0; c[0] < d[0]; c[0] ++) { + fprintf (C_filepntrsrcout, SCOTCH_NUMSTRING, + (SCOTCH_Num) (((d[0] > 2) ? 3 : d[0]) + /* Output number of neighbors */ + ((d[1] > 2) ? 3 : d[1]) + + ((d[2] > 2) ? 3 : d[2]) - 3)); + if (d[2] > 2) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, /* Output the neighbors */ + (SCOTCH_Num) ((((c[2] + d[2] - 1) % d[2]) * d[1] + c[1]) * d[0] + c[0] + baseval)); + if (d[1] > 2) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * d[1] + ((c[1] + d[1] - 1) % d[1])) * d[0] + c[0] + baseval)); + if (d[0] > 2) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (((c[2] * d[1] + c[1]) * d[0] + (c[0] + d[0] - 1) % d[0])) + baseval); + if (d[0] > 1) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * d[1] + c[1]) * d[0] + ((c[0] + 1) % d[0]) + baseval)); + if (d[1] > 1) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * d[1] + ((c[1] + 1) % d[1])) * d[0] + c[0] + baseval)); + if (d[2] > 1) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((((c[2] + 1) % d[2]) * d[1] + c[1]) * d[0] + c[0] + baseval)); + fprintf (C_filepntrsrcout, "\n"); + } + } + } + } + else { /* Build a mesh */ + fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t000\n", + (SCOTCH_Num) (d[0] * d[1] * d[2]), + (SCOTCH_Num) ((d[0] * d[1] * d[2] * 3 - (d[0] * d[1] + d[0] * d[2] + d[1] * d[2])) * 2), + (SCOTCH_Num) baseval); + + for (c[2] = 0; c[2] < d[2]; c[2] ++) { /* Output neighbor list */ + for (c[1] = 0; c[1] < d[1]; c[1] ++) { + for (c[0] = 0; c[0] < d[0]; c[0] ++) { + fprintf (C_filepntrsrcout, "%d", + ((c[0] == 0) ? 0 : 1) + /* Output number of neighbors */ + ((c[0] == (d[0] - 1)) ? 0 : 1) + + ((c[1] == 0) ? 0 : 1) + + ((c[1] == (d[1] - 1)) ? 0 : 1) + + ((c[2] == 0) ? 0 : 1) + + ((c[2] == (d[2] - 1)) ? 0 : 1)); + if (c[2] != 0) /* Output the neighbors */ + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (((c[2] - 1) * d[1] + c[1]) * d[0] + c[0] + baseval)); + if (c[1] != 0) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * d[1] + c[1] - 1) * d[0] + c[0] + baseval)); + if (c[0] != 0) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * d[1] + c[1]) * d[0] + c[0] - 1 + baseval)); + if (c[0] != (d[0] - 1)) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * d[1] + c[1]) * d[0] + c[0] + 1 + baseval)); + if (c[1] != (d[1] - 1)) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * d[1] + c[1] + 1) * d[0] + c[0] + baseval)); + if (c[2] != (d[2] - 1)) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (((c[2] + 1) * d[1] + c[1]) * d[0] + c[0] + baseval)); + fprintf (C_filepntrsrcout, "\n"); + } + } + } + } + + if (flagval & C_FLAGGEOOUT) { /* If geometry is wanted */ + fprintf (C_filepntrgeoout, "3\n" SCOTCH_NUMSTRING "\n", /* Output geometry file header */ + (SCOTCH_Num) (d[0] * d[1] * d[2])); + + for (c[2] = 0; c[2] < d[2]; c[2] ++) { /* Output mesh coordinates */ + for (c[1] = 0; c[1] < d[1]; c[1] ++) { + for (c[0] = 0; c[0] < d[0]; c[0] ++) + fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) ((c[2] * d[1] + c[1]) * d[0] + c[0] + baseval), + (SCOTCH_Num) c[0], + (SCOTCH_Num) (d[1] - 1 - c[1]), + (SCOTCH_Num) c[2]); + } + } + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gmk_m3.h b/scotch_6.0.3/src/scotch/gmk_m3.h new file mode 100644 index 00000000..d93180de --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_m3.h @@ -0,0 +1,67 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_m3.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the tridimensional mesh **/ +/** source graph building program. **/ +/** **/ +/** DATES : # Version 4.0 : from : 11 feb 2002 **/ +/** to : 11 feb 2002 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenamesrcout C_fileTab[0].name /* Source graph output file name */ +#define C_filenamegeoout C_fileTab[1].name /* Geometry graph output file name */ + +#define C_filepntrsrcout C_fileTab[0].pntr /* Source graph output file */ +#define C_filepntrgeoout C_fileTab[1].pntr /* Geometry graph output file */ + +/*+ Process flags. +*/ + +#define C_FLAGGEOOUT 0x0001 /* Output the geometry graph */ +#define C_FLAGTORUS 0x0002 /* Build a torus rather than a mesh */ + +#define C_FLAGDEFAULT 0x0000 /* Default flags */ diff --git a/scotch_6.0.3/src/scotch/gmk_msh.c b/scotch_6.0.3/src/scotch/gmk_msh.c new file mode 100644 index 00000000..55319d58 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_msh.c @@ -0,0 +1,154 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_msh.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a mesh-to-graph converter. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 4.0 : from : 21 jan 2004 **/ +/** to : 21 jan 2004 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GMK_MSH + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gmk_msh.h" + +/* +** The static and global variables. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[2] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gmk_msh [ []] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/*****************************/ +/* */ +/* This is the main function */ +/* */ +/*****************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Mesh meshdat; + SCOTCH_Graph grafdat; + int i; + + errorProg ("gmk_msh"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give help */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "gmk_msh, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_meshInit (&meshdat); + SCOTCH_graphInit (&grafdat); + + SCOTCH_meshLoad (&meshdat, C_filepntrmshinp, -1); + SCOTCH_meshCheck (&meshdat); + SCOTCH_meshGraph (&meshdat, &grafdat); +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_graphCheck (&grafdat) != 0) { + errorPrint ("main: bad graph structure"); + return (1); + } +#endif /* SCOTCH_DEBUG_ALL */ + SCOTCH_graphSave (&grafdat, C_filepntrgrfout); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_graphExit (&grafdat); + SCOTCH_meshExit (&meshdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gmk_msh.h b/scotch_6.0.3/src/scotch/gmk_msh.h new file mode 100644 index 00000000..25567434 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_msh.h @@ -0,0 +1,71 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_msh.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a mesh-to-graph converter. **/ +/** This module contains the data declara- **/ +/** tions for the main module. **/ +/** **/ +/** DATES : # Version 4.0 : from : 21 jan 2004 **/ +/** to : 21 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamemshinp C_fileTab[0].name /* External graph input file name */ +#define C_filenamegrfout C_fileTab[1].name /* Source graph output file name */ + +#define C_filepntrmshinp C_fileTab[0].pntr /* External graph input file */ +#define C_filepntrgrfout C_fileTab[1].pntr /* Source graph output file */ + +/* +** The type and structure definitions. +*/ + +/*+ This structure defines the method array element. +*/ + +typedef struct C_Format_ { + char code; /* Format type code */ + int (* func) (); /* Function to call */ +} C_Format; diff --git a/scotch_6.0.3/src/scotch/gmk_ub2.c b/scotch_6.0.3/src/scotch/gmk_ub2.c new file mode 100644 index 00000000..bd6f2f10 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_ub2.c @@ -0,0 +1,192 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_ub2.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the source graph for undirected **/ +/** de Bruijn graphs, to be used to build **/ +/** the architecture description files for **/ +/** these graphs. **/ +/** **/ +/** DATES : # Version 1.2 : from : 11 feb 1994 **/ +/** to : 11 feb 1994 **/ +/** # Version 2.0 : from : 05 nov 1994 **/ +/** to 05 nov 1994 **/ +/** # Version 3.0 : from : 11 jul 1995 **/ +/** to 12 jul 1995 **/ +/** # Version 3.2 : from : 03 jun 1997 **/ +/** to : 03 jun 1997 **/ +/** # Version 3.3 : from : 07 jun 1999 **/ +/** to : 07 jun 1999 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 5.0 : from : 22 jan 2008 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GMK_UB2 + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gmk_ub2.h" + +#define ngbadd(v) if ((v) != vertnum) { \ + int k; \ + for (k = 0; k < ngbnbr; k ++) \ + if ((v) == ngbtab[k]) \ + break; \ + if (k == ngbnbr) \ + ngbtab[ngbnbr ++] = (v); \ + } + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gmk_ub2 [] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/****************************************/ +/* */ +/* The main routine, which computes the */ +/* source graph description. */ +/* */ +/****************************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num ubdim = 1; /* Graph dimension */ + SCOTCH_Num ubnbr; /* Number of vertices */ + SCOTCH_Num ubbit; /* Most significant bit */ + SCOTCH_Num ngbtab[4]; /* Array of neighbors */ + int ngbnbr; /* Current number of neighbors */ + SCOTCH_Num vertnum; /* Current vertex number */ + int i, j; + + errorProg ("gmk_ub2"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 1) { /* If number of parameters not reached */ + if ((ubdim = (SCOTCH_Num) atol (argv[i])) < 1) { /* Get dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + C_paraNum ++; + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "gmk_ub2, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + ubnbr = 1 << ubdim; /* Compute number of vertices */ + ubbit = 1 << (ubdim - 1); /* Bit to add on the left */ + + fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n0\t000\n", + (SCOTCH_Num) ubnbr, /* Print number of vertices */ + (SCOTCH_Num) (4 * ubnbr - 6)); /* Print number of edges (arcs) */ + + for (vertnum = 0; vertnum < ubnbr; vertnum ++) { /* For all vertices */ + ngbnbr = 0; /* No neighbors defined yet */ + ngbadd ((vertnum << 1) & (ubnbr - 1)); /* Register vertex neighbors */ + ngbadd (((vertnum << 1) & (ubnbr - 1)) | 1); + ngbadd ((vertnum >> 1) & (ubnbr - 1)); + ngbadd (((vertnum >> 1) & (ubnbr - 1)) | ubbit); + + fprintf (C_filepntrsrcout, "%d", ngbnbr); /* Output number of neighbors */ + for (j = 0; j < ngbnbr; j ++) + fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ngbtab[j]); + fprintf (C_filepntrsrcout, "\n"); + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gmk_ub2.h b/scotch_6.0.3/src/scotch/gmk_ub2.h new file mode 100644 index 00000000..fac1412a --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmk_ub2.h @@ -0,0 +1,64 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmk_ub2.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the de Bruijn source graph **/ +/** building program. **/ +/** **/ +/** DATES : # Version 2.0 : from : 05 nov 1994 **/ +/** to 05 nov 1994 **/ +/** # Version 3.2 : from : 03 jun 1997 **/ +/** to : 03 jun 1997 **/ +/** # Version 3.3 : from : 07 jun 1999 **/ +/** to : 07 jun 1999 **/ +/** # Version 3.3 : from : 07 jun 1999 **/ +/** to : 07 jun 1999 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 1 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenamesrcout C_fileTab[0].name /* Source graph output file name */ + +#define C_filepntrsrcout C_fileTab[0].pntr /* Source graph output file */ diff --git a/scotch_6.0.3/src/scotch/gmtst.c b/scotch_6.0.3/src/scotch/gmtst.c new file mode 100644 index 00000000..f7c32854 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmtst.c @@ -0,0 +1,180 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmtst.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program computes statistics on **/ +/** graph mappings. **/ +/** **/ +/** DATES : # Version 3.1 : from : 17 jul 1996 **/ +/** to 23 jul 1996 **/ +/** # Version 3.2 : from : 02 jun 1997 **/ +/** to : 16 jul 1997 **/ +/** # Version 3.3 : from : 07 jun 1999 **/ +/** to : 07 jun 1999 **/ +/** # Version 4.0 : from : 12 feb 2004 **/ +/** to 16 nov 2005 **/ +/** # Version 5.0 : from : 22 jan 2008 **/ +/** to 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GMTST + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gmtst.h" + +/* +** The static variables. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "r" }, + { "-", NULL, "r" }, + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { /* Usage */ + "gmtst [ [ [ []]]] ", + " -h : Display this help", + " -V : Print program version and copyright", + "", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Graph grafdat; /* Source graph */ + SCOTCH_Num vertnbr; /* Source graph size */ + SCOTCH_Num * vlbltab; /* Source graph vertex label array */ + SCOTCH_Arch archdat; /* Target architecture */ + SCOTCH_Num archnbr; /* Size of the target architecture */ + SCOTCH_Mapping mappdat; /* Mapping data */ + int i; + + errorProg ("gmtst"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'M' : /* No mapping flag */ + case 'm' : + C_filenamemapinp = "-"; /* Default name to avoid opening */ + C_filepntrmapinp = NULL; /* NULL file pointer means no file */ + break; + case 'V' : + fprintf (stderr, "gmtst, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_graphInit (&grafdat); /* Create graph structure */ + SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, 0); /* Read source graph */ + SCOTCH_graphData (&grafdat, NULL, /* Get graph characteristics */ + &vertnbr, NULL, NULL, NULL, &vlbltab, + NULL, NULL, NULL); + + SCOTCH_archInit (&archdat); /* Create architecture structure */ + SCOTCH_archLoad (&archdat, C_filepntrtgtinp); /* Read target architecture */ + if (strcmp (SCOTCH_archName (&archdat), "term") == 0) { /* If target architecture is variable-sized */ + errorPrint ("main: variable-sized architectures cannot be mapped"); + return (1); + } + + archnbr = SCOTCH_archSize (&archdat); /* Get architecture size */ + + SCOTCH_graphMapInit (&grafdat, &mappdat, &archdat, NULL); /* Create mapping structure */ + if (SCOTCH_graphMapLoad (&grafdat, &mappdat, C_filepntrmapinp) != 0) + errorPrint ("main: bad input (1)"); + + SCOTCH_graphMapView (&grafdat, &mappdat, C_filepntrdatout); /* Display mapping statistics */ + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_graphMapExit (&grafdat, &mappdat); + SCOTCH_archExit (&archdat); + SCOTCH_graphExit (&grafdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gmtst.h b/scotch_6.0.3/src/scotch/gmtst.h new file mode 100644 index 00000000..f805d1ca --- /dev/null +++ b/scotch_6.0.3/src/scotch/gmtst.h @@ -0,0 +1,70 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gmtst.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program computes statistics on **/ +/** graph mappings. **/ +/** **/ +/** DATES : # Version 3.1 : from : 17 jul 1996 **/ +/** to 23 jul 1996 **/ +/** # Version 3.2 : from : 02 jun 1997 **/ +/** to 02 jun 1997 **/ +/** # Version 3.3 : from : 06 jun 1999 **/ +/** to 07 jun 1999 **/ +/** # Version 4.0 : from : 12 feb 2004 **/ +/** to 29 nov 2005 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 4 /* Number of files in list */ +#define C_FILEARGNBR 4 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph file name */ +#define C_filenametgtinp C_fileTab[1].name /* Target architecture file name */ +#define C_filenamemapinp C_fileTab[2].name /* Mapping result file name */ +#define C_filenamedatout C_fileTab[3].name /* Statistics file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrtgtinp C_fileTab[1].pntr /* Target architecture file */ +#define C_filepntrmapinp C_fileTab[2].pntr /* Mapping result input file */ +#define C_filepntrdatout C_fileTab[3].pntr /* Statistics output file */ + diff --git a/scotch_6.0.3/src/scotch/gord.c b/scotch_6.0.3/src/scotch/gord.c new file mode 100644 index 00000000..74b403b0 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gord.c @@ -0,0 +1,289 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gord.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a sparse matrix graph ordering **/ +/** software. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 3.2 : from : 24 aug 1996 **/ +/** to : 21 aug 1998 **/ +/** # Version 3.3 : from : 07 oct 1998 **/ +/** to : 31 may 1999 **/ +/** # Version 3.4 : from : 07 oct 1998 **/ +/** to : 03 feb 2000 **/ +/** # Version 4.0 : from : 02 feb 2002 **/ +/** to : 08 jan 2006 **/ +/** # Version 5.0 : from : 26 jan 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GORD + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gord.h" + +/* +** The static and global definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" }, + { "-", NULL, "w" }, + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gord [ [ []]] ", + " -c : Choose default ordering strategy according to one or several of :", + " b : enforce load balance as much as possible", + " q : privilege quality over speed (default)", + " s : privilege speed over quality", + " t : enforce safety", + " -h : Display this help", + " -m : Save column block mapping data to ", + " -o : Set ordering strategy (see user's manual)", + " -t : Save partitioning tree data to ", + " -V : Print program version and copyright", + " -v : Set verbose mode to :", + " s : strategy information", + " t : timing information", + "", + "See default strategy with option '-vs'", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num vertnbr; /* Number of vertices */ + SCOTCH_Graph grafdat; /* Source graph */ + SCOTCH_Ordering ordedat; /* Graph ordering */ + SCOTCH_Num * permtab; /* Permutation array */ + SCOTCH_Strat stradat; /* Ordering strategy */ + SCOTCH_Num straval; + char * straptr; + int flagval; + Clock runtime[2]; /* Timing variables */ + int i, j; + + errorProg ("gord"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + flagval = C_FLAGNONE; /* Default behavior */ + straval = 0; /* No strategy flags */ + straptr = NULL; + SCOTCH_stratInit (&stradat); + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else + errorPrint ("main: too many file names given"); + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'C' : + case 'c' : /* Strategy selection parameters */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'B' : + case 'b' : + straval |= SCOTCH_STRATBALANCE; + break; + case 'Q' : + case 'q' : + straval |= SCOTCH_STRATQUALITY; + break; + case 'S' : + case 's' : + straval |= SCOTCH_STRATSPEED; + break; + case 'T' : + case 't' : + straval |= SCOTCH_STRATSAFETY; + break; + default : + errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); + } + } + break; + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'M' : /* Output separator mapping */ + case 'm' : + flagval |= C_FLAGMAPOUT; + if (argv[i][2] != '\0') + C_filenamemapout = &argv[i][2]; + break; + case 'O' : /* Ordering strategy */ + case 'o' : + straptr = &argv[i][2]; + SCOTCH_stratExit (&stradat); + SCOTCH_stratInit (&stradat); + SCOTCH_stratGraphOrder (&stradat, straptr); + break; + case 'T' : /* Output separator tree */ + case 't' : + flagval |= C_FLAGTREOUT; + if (argv[i][2] != '\0') + C_filenametreout = &argv[i][2]; + break; + case 'V' : + fprintf (stderr, "gord, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + case 'v' : /* Output control info */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'S' : + case 's' : + flagval |= C_FLAGVERBSTR; + break; + case 'T' : + case 't' : + flagval |= C_FLAGVERBTIM; + break; + default : + errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); + } + } + break; + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + clockInit (&runtime[0]); + clockStart (&runtime[0]); + + SCOTCH_graphInit (&grafdat); /* Create graph structure */ + SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, 2); /* Read source graph */ + SCOTCH_graphSize (&grafdat, &vertnbr, NULL); /* Get graph characteristics */ + + if (straval != 0) { + if (straptr != NULL) + errorPrint ("main: options '-c' and '-o' are exclusive"); + + SCOTCH_stratGraphOrderBuild (&stradat, straval, 0, 0.2); + } + + clockStop (&runtime[0]); /* Get input time */ + clockInit (&runtime[1]); + clockStart (&runtime[1]); + + if ((permtab = (SCOTCH_Num *) memAlloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) { + errorPrint ("main: out of memory"); + return (1); + } + SCOTCH_graphOrderInit (&grafdat, &ordedat, permtab, NULL, NULL, NULL, NULL); /* Create ordering */ + SCOTCH_graphOrderCompute (&grafdat, &ordedat, &stradat); /* Perform ordering */ + + clockStop (&runtime[1]); /* Get ordering time */ + +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) + return (1); +#endif /* SCOTCH_DEBUG_ALL */ + + clockStart (&runtime[0]); + + SCOTCH_graphOrderSave (&grafdat, &ordedat, C_filepntrordout); /* Write ordering */ + if (flagval & C_FLAGMAPOUT) /* If mapping wanted */ + SCOTCH_graphOrderSaveMap (&grafdat, &ordedat, C_filepntrmapout); /* Write mapping */ + if (flagval & C_FLAGTREOUT) /* If separator tree wanted */ + SCOTCH_graphOrderSaveTree (&grafdat, &ordedat, C_filepntrtreout); /* Write tree */ + + clockStop (&runtime[0]); /* Get output time */ + + if (flagval & C_FLAGVERBSTR) { + fprintf (C_filepntrlogout, "S\tStrat="); + SCOTCH_stratSave (&stradat, C_filepntrlogout); + putc ('\n', C_filepntrlogout); + } + if (flagval & C_FLAGVERBTIM) { + fprintf (C_filepntrlogout, "T\tOrder\t\t%g\nT\tI/O\t\t%g\nT\tTotal\t\t%g\n", + (double) clockVal (&runtime[1]), + (double) clockVal (&runtime[0]), + (double) clockVal (&runtime[0]) + + (double) clockVal (&runtime[1])); + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_graphOrderExit (&grafdat, &ordedat); + SCOTCH_stratExit (&stradat); + SCOTCH_graphExit (&grafdat); + memFree (permtab); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gord.h b/scotch_6.0.3/src/scotch/gord.h new file mode 100644 index 00000000..9e849e0e --- /dev/null +++ b/scotch_6.0.3/src/scotch/gord.h @@ -0,0 +1,78 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gord.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a sparse matrix graph orderer. **/ +/** This module contains the data declara- **/ +/** tions for the main routine. **/ +/** **/ +/** DATES : # Version 3.2 : from : 24 aug 1996 **/ +/** to : 20 oct 1997 **/ +/** # Version 3.3 : from : 07 oct 1998 **/ +/** to : 31 may 1999 **/ +/** # Version 4.0 : from : 11 dec 2002 **/ +/** to : 27 dec 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 5 /* Number of files in list */ +#define C_FILEARGNBR 3 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenameordout C_fileTab[1].name /* Ordering output file name */ +#define C_filenamelogout C_fileTab[2].name /* Log file name */ +#define C_filenamemapout C_fileTab[3].name /* Separator mapping file name */ +#define C_filenametreout C_fileTab[4].name /* Separator tree file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrordout C_fileTab[1].pntr /* Ordering output file */ +#define C_filepntrlogout C_fileTab[2].pntr /* Log file */ +#define C_filepntrmapout C_fileTab[3].pntr /* Separator mapping file */ +#define C_filepntrtreout C_fileTab[4].pntr /* Separator tree file */ + +/*+ Process flags. +*/ + +#define C_FLAGNONE 0x0000 /* No flags */ +#define C_FLAGMAPOUT 0x0001 /* Output mapping data */ +#define C_FLAGTREOUT 0x0002 /* Output separator tree data */ +#define C_FLAGVERBSTR 0x0004 /* Output strategy string */ +#define C_FLAGVERBTIM 0x0008 /* Output timing information */ diff --git a/scotch_6.0.3/src/scotch/gotst.c b/scotch_6.0.3/src/scotch/gotst.c new file mode 100644 index 00000000..2ba3af1e --- /dev/null +++ b/scotch_6.0.3/src/scotch/gotst.c @@ -0,0 +1,452 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gotst.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** Bruno MARCUSSEAU (v3.1) **/ +/** **/ +/** FUNCTION : Graph symbolic factorizer. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 4.0 : from : 27 jan 2004 **/ +/** to : 28 nov 2005 **/ +/** # Version 5.0 : from : 25 jun 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 20 apr 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/** NOTES : # The cost analysis routine leaves the **/ +/** memory management to malloc and free **/ +/** because it is assumed to be the most **/ +/** efficient to merge free blocks and **/ +/** reallocate them. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GOTST + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gotst.h" + +/* +** The static and global variables. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[3] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gotst [ [ []]] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/*****************************/ +/* */ +/* This is the main function */ +/* */ +/*****************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Graph grafdat; + SCOTCH_Num vertnbr; + SCOTCH_Num * verttab; + SCOTCH_Num * vendtab; + SCOTCH_Num edgenbr; + SCOTCH_Num * edgetab; + SCOTCH_Num baseval; + SCOTCH_Ordering ordedat; + SCOTCH_Num * permtab; + SCOTCH_Num * peritab; + int i; + + errorProg ("gotst"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give help */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "gotst, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_graphInit (&grafdat); + SCOTCH_graphLoad (&grafdat, C_filepntrgrfinp, -1, 3); + SCOTCH_graphData (&grafdat, &baseval, &vertnbr, &verttab, &vendtab, NULL, NULL, &edgenbr, &edgetab, NULL); +#ifdef SCOTCH_DEBUG_ALL + if (vendtab != (verttab + 1)) { + errorPrint ("main: graph should be compact"); + return (1); + } +#endif /* SCOTCH_DEBUG_ALL */ + if (memAllocGroup ((void **) (void *) + &peritab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), + &permtab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), NULL) == NULL) { + errorPrint ("main: out of memory"); + return (1); + } + SCOTCH_graphOrderInit (&grafdat, &ordedat, permtab, peritab, NULL, NULL, NULL); + SCOTCH_graphOrderLoad (&grafdat, &ordedat, C_filepntrordinp); + if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) { + errorPrint ("main: invalid ordering"); + return (1); + } + + factorView (baseval, vertnbr, verttab, edgenbr, edgetab, permtab, peritab, C_filepntrdatout); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + memFree (peritab); + SCOTCH_graphOrderExit (&grafdat, &ordedat); + SCOTCH_graphExit (&grafdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} + +/*************************************/ +/* */ +/* These routines compute statistics */ +/* on orderings. */ +/* */ +/*************************************/ + +static +int +factorView ( +const SCOTCH_Num baseval, +const SCOTCH_Num vertnbr, +const SCOTCH_Num * const verttab, +const SCOTCH_Num edgenbr, +const SCOTCH_Num * const edgetab, +const SCOTCH_Num * const permtab, +const SCOTCH_Num * const peritab, +FILE * restrict const stream) +{ + SCOTCH_Num * restrict ldadtab; + SCOTCH_Num * restrict lsontab; + SCOTCH_Num * restrict lbrotab; + SCOTCH_Num * restrict fnnztab; + double fopcsum; + double heigsum; + FactorStat statdat; + SCOTCH_Num vertnum; + int o; + + if (memAllocGroup ((void **) (void *) + &ldadtab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), + &lsontab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), + &lbrotab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), + &fnnztab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), NULL) == NULL) { + errorPrint ("factorView: out of memory"); + return (1); + } + statdat.ldadtax = ldadtab - baseval; + statdat.lsontax = lsontab - baseval; + statdat.lbrotax = lbrotab - baseval; + statdat.fnnztax = fnnztab - baseval; + + if (factorView2 (baseval, vertnbr, verttab - baseval, edgetab - baseval, permtab - baseval, peritab - baseval, + ldadtab - baseval, lsontab - baseval, lbrotab - baseval, fnnztab - baseval) != 0) { + errorPrint ("factorView: factored matrix too large"); + memFree (ldadtab); /* Free group leader */ + return (1); + } + + statdat.heigmin = SCOTCH_NUMMAX; + statdat.heigmax = + statdat.heignbr = 0; + heigsum = 0.0L; + for (vertnum = 0; vertnum < vertnbr; vertnum ++) { /* Get height sum */ + if (ldadtab[vertnum] == -1) /* If column is a root */ + factorView3 (&statdat, 1, vertnum + baseval, &heigsum); /* Scan subtree */ + } + statdat.heigavg = heigsum / (double) statdat.heignbr; + statdat.heigdlt = 0.0L; + statdat.fnnzsum = 0.0L; + fopcsum = 0.0L; + for (vertnum = 0; vertnum < vertnbr; vertnum ++) { /* Get delta */ + if (ldadtab[vertnum] == -1) /* If column is a root */ + factorView4 (&statdat, 1, vertnum + baseval, &fopcsum); + } + statdat.heigdlt /= (double) statdat.heignbr; + + o = (fprintf (stream, "O\tLeaf=" SCOTCH_NUMSTRING "\nO\tHeight min=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tavg=%f\tdlt=%f (%5.2f)\n", /* Write tree height statistics */ + (SCOTCH_Num) statdat.heignbr, (SCOTCH_Num) statdat.heigmin, (SCOTCH_Num) statdat.heigmax, + statdat.heigavg, statdat.heigdlt, ((statdat.heigdlt / statdat.heigavg) * (double) 100.0L)) == EOF); + + o |= (fprintf (stream, "O\tNNZ=%e\nO\tOPC=%e\n", + statdat.fnnzsum, + fopcsum) == EOF); + + if (o != 0) + errorPrint ("factorView: bad output"); + + memFree (ldadtab); /* Free group leader */ + + return (o); +} + +static +int +factorView2 ( +const SCOTCH_Num baseval, +const SCOTCH_Num vertnbr, +const SCOTCH_Num * const verttax, +const SCOTCH_Num * const edgetax, +const SCOTCH_Num * const permtax, +const SCOTCH_Num * const peritax, +SCOTCH_Num * restrict ldadtax, +SCOTCH_Num * restrict lsontax, +SCOTCH_Num * restrict lbrotax, +SCOTCH_Num * restrict fnnztax) +{ + SCOTCH_Num * restrict frowtab; + SCOTCH_Num * restrict fnxttab; + SCOTCH_Num ** restrict facttax; + SCOTCH_Num vertnnd; + SCOTCH_Num pcolnum; + + memSet (lsontax + baseval, ~0, vertnbr * sizeof (SCOTCH_Num)); /* Assume columns have no sons at all */ + + if (memAllocGroup ((void **) (void *) + &frowtab, (size_t) ((vertnbr + 1) * sizeof (SCOTCH_Num)), + &fnxttab, (size_t) ((vertnbr + 1) * sizeof (SCOTCH_Num)), + &facttax, (size_t) (vertnbr * sizeof (SCOTCH_Num *)), NULL) == NULL) { + errorPrint ("factorView2: out of memory (1)"); + return (1); + } + memSet (facttax, 0, vertnbr * sizeof (SCOTCH_Num *)); /* Set all factored column pointers to NULL */ + facttax -= baseval; + + vertnnd = vertnbr + baseval; + for (pcolnum = baseval; pcolnum < vertnnd; pcolnum ++) { /* For all columns of the permuted matrix */ + SCOTCH_Num * fcoltab; + SCOTCH_Num * restrict fcolptr; + SCOTCH_Num frownbr; + SCOTCH_Num frowidx; + SCOTCH_Num frowidd; + SCOTCH_Num scolnum; + SCOTCH_Num icolnum; + SCOTCH_Num irownum; + SCOTCH_Num dcolnum; + + icolnum = peritax[pcolnum]; /* Get the original number of the column */ + + frownbr = 1; /* Start array of factored terms for column */ + frowtab[0] = pcolnum; /* Add diagonal element as unmoveable starter */ + for (irownum = verttax[icolnum]; irownum < verttax[icolnum + 1]; irownum ++) { + SCOTCH_Num prownum; + + prownum = permtax[edgetax[irownum]]; /* Get permuted row */ + + if (prownum >= pcolnum) + frowtab[frownbr ++] = prownum; + } + intSort1asc1 (frowtab + 1, frownbr - 1); /* Sort rows in ascending order */ + + frowtab[frownbr ++] = vertnnd; /* Add trailer */ + for (frowidx = 0; frowidx < (frownbr - 1); frowidx ++) /* Create initial links */ + fnxttab[frowidx] = frowidx + 1; + frowidd = frowidx; /* Save index of trailer */ + + for (scolnum = lsontax[pcolnum]; scolnum != -1; scolnum = lbrotax[scolnum]) { /* For all son columns in elimination tree */ + const SCOTCH_Num * restrict srowtab; + SCOTCH_Num srownbr; + SCOTCH_Num srowidx; + SCOTCH_Num frowidx; + SCOTCH_Num foldidx; + SCOTCH_Num frownum; + + srowtab = facttax[scolnum]; /* Point to array of factors for son column */ + srownbr = fnnztax[scolnum]; /* Get size of array */ + for (srowidx = 1, frowidx = 0, foldidx = -1, frownum = frowtab[frowidx]; + srowidx < srownbr; srowidx ++) { + SCOTCH_Num srownum; + + srownum = srowtab[srowidx]; + + while (frownum < srownum) { /* While factor to add not in place */ + foldidx = frowidx; /* Skip to next position */ + frowidx = fnxttab[frowidx]; + frownum = frowtab[frowidx]; + } + if (srownum == frownum) /* If factor already in column */ + continue; + + frowtab[frownbr] = srownum; /* Add new slot */ + fnxttab[frownbr] = frowidx; /* Link new slot */ + fnxttab[foldidx] = frownbr; + foldidx = frownbr ++; + } + + memFree ((void *) srowtab); /* Free now useless factored column */ +#ifdef SCOTCH_DEBUG_ALL + facttax[scolnum] = NULL; +#endif /* SCOTCH_DEBUG_ALL */ + } + + frownbr -= 2; /* Remove markers from number of extra-diagonals */ + fnnztax[pcolnum] = frownbr; /* Save number of extra-diagonals */ + + if (frownbr <= 0) { /* If factored column has no extra-diagonals */ + ldadtax[pcolnum] = -1; /* Column has no father */ +#ifdef SCOTCH_DEBUG_ALL + lbrotax[pcolnum] = -1; +#endif /* SCOTCH_DEBUG_ALL */ + continue; /* Skip to next column without allocating or linking */ + } + + if ((fcoltab = memAlloc (frownbr * sizeof (SCOTCH_Num))) == NULL) { /* Allocate array for factored column */ + errorPrint ("factorView2: out of memory (2)"); + return (1); + } + for (frowidx = fnxttab[0], fcolptr = fcoltab; frowidx != frowidd; frowidx = fnxttab[frowidx]) /* Fill factored array for column */ + *fcolptr ++ = frowtab[frowidx]; + + dcolnum = fcoltab[0]; /* Get number of father, that it, first extra-diagonal */ + ldadtax[pcolnum] = dcolnum; /* Link factored column to the separation tree */ + lbrotax[pcolnum] = lsontax[dcolnum]; + lsontax[dcolnum] = pcolnum; + + facttax[pcolnum] = fcoltab; /* Save factored array */ + } + + memFree (frowtab); /* Free group leader */ + + return (0); +} + +static +void +factorView3 ( +FactorStat * restrict const statptr, +SCOTCH_Num levlnum, +SCOTCH_Num vertnum, +double * restrict const hsumptr) +{ + double hsumtmp; + + hsumtmp = 0.0; + if (statptr->lsontax[vertnum] != -1) { /* If node has descendants */ + SCOTCH_Num csonnum; + + for (csonnum = statptr->lsontax[vertnum]; csonnum != -1; csonnum = statptr->lbrotax[csonnum]) + factorView3 (statptr, levlnum + 1, csonnum, &hsumtmp); + } + else { + hsumtmp = (double) levlnum; + + statptr->heignbr ++; + if (levlnum < statptr->heigmin) + statptr->heigmin = levlnum; + if (levlnum > statptr->heigmax) + statptr->heigmax = levlnum; + } + + *hsumptr += hsumtmp; +} + +static +void +factorView4 ( +FactorStat * restrict const statptr, +SCOTCH_Num levlnum, +SCOTCH_Num vertnum, +double * restrict const fopcptr) +{ + SCOTCH_Num fnnztmp; + double fopctmp; + + fnnztmp = statptr->fnnztax[vertnum] + 1; /* Get extra-diagonals, plus diagonal */ + fopctmp = (double) fnnztmp; + statptr->fnnzsum += fopctmp; + fopctmp *= fopctmp; + + if (statptr->lsontax[vertnum] != -1) { /* If node has descendants */ + SCOTCH_Num csonnum; + + for (csonnum = statptr->lsontax[vertnum]; csonnum != -1; csonnum = statptr->lbrotax[csonnum]) + factorView4 (statptr, levlnum + 1, csonnum, &fopctmp); /* Accumulate OPC on local sum */ + } + else + statptr->heigdlt += fabs ((double) levlnum - statptr->heigavg); + + *fopcptr += fopctmp; /* Aggregate local sum at higher level */ +} diff --git a/scotch_6.0.3/src/scotch/gotst.h b/scotch_6.0.3/src/scotch/gotst.h new file mode 100644 index 00000000..3538b48b --- /dev/null +++ b/scotch_6.0.3/src/scotch/gotst.h @@ -0,0 +1,100 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gotst.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a graph scalar factorizer. **/ +/** This module contains the data declara- **/ +/** tions for the main module. **/ +/** **/ +/** DATES : # Version 4.0 : from : 27 jan 2004 **/ +/** to : 27 jan 2004 **/ +/** # Version 5.0 : from : 25 jun 2007 **/ +/** to : 25 jul 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 3 /* Number of files in list */ +#define C_FILEARGNBR 3 /* Number of files which can be arguments */ + +#define C_filenamegrfinp C_fileTab[0].name /* Graph input file name */ +#define C_filenamesrcout C_fileTab[1].name /* Ordering input file name */ +#define C_filenamedatout C_fileTab[2].name /* Output data file name */ + +#define C_filepntrgrfinp C_fileTab[0].pntr /* Graph input file */ +#define C_filepntrordinp C_fileTab[1].pntr /* Ordering output file */ +#define C_filepntrdatout C_fileTab[2].pntr /* Output data file */ + +/* +** The type and structure definitions. +*/ + +/* Factorization node */ + +typedef struct C_FactorNode_ { + struct C_FactorNode_ * linkdad; /*+ Father of node +*/ + struct C_FactorNode_ * linkson; /*+ First son of node +*/ + struct C_FactorNode_ * linkbro; /*+ Brother of node +*/ +} C_FactorNode; + +/* Data structure for computing factored matrix statistics. */ + +typedef struct FactorStat_ { + const SCOTCH_Num * ldadtax; + const SCOTCH_Num * lsontax; + const SCOTCH_Num * lbrotax; + SCOTCH_Num heigmin; + SCOTCH_Num heigmax; + SCOTCH_Num heignbr; + double heigavg; + double heigdlt; + const SCOTCH_Num * fnnztax; + double fnnzsum; +} FactorStat; + +/* +** The function prototypes. +*/ + +static int factorView (const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, FILE * restrict const); +static int factorView2 (const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * restrict, SCOTCH_Num * restrict, SCOTCH_Num * restrict, SCOTCH_Num * restrict); +static void factorView3 (FactorStat * restrict const, SCOTCH_Num, SCOTCH_Num, double * restrict const); +static void factorView4 (FactorStat * restrict const, SCOTCH_Num, SCOTCH_Num, double * restrict const); diff --git a/scotch_6.0.3/src/scotch/gout_c.c b/scotch_6.0.3/src/scotch/gout_c.c new file mode 100644 index 00000000..c602f5cf --- /dev/null +++ b/scotch_6.0.3/src/scotch/gout_c.c @@ -0,0 +1,731 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gout_c.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a result viewer. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 2.0 : from : 06 oct 1994 **/ +/** to 23 dec 1994 **/ +/** # Version 3.0 : from : 14 jul 1995 **/ +/** to 11 oct 1995 **/ +/** # Version 3.1 : from : 27 mar 1996 **/ +/** to 03 apr 1996 **/ +/** # Version 3.2 : from : 02 dec 1996 **/ +/** to 05 jun 1998 **/ +/** # Version 3.3 : from : 29 may 1999 **/ +/** to : 03 jun 1999 **/ +/** # Version 3.4 : from : 03 feb 2000 **/ +/** to : 03 feb 2000 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 08 feb 2004 **/ +/** # Version 5.0 : from : 25 may 2007 **/ +/** to 25 may 2007 **/ +/** # Version 5.1 : from : 25 oct 2007 **/ +/** to 14 feb 2011 **/ +/** # Version 6.0 : from : 16 oct 2010 **/ +/** to 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes +*/ + +#define GOUT + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gout_c.h" +#include "gout_o.h" + +/* +** The static and global variables +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +File C_fileTab[C_FILENBR] = { /* The file array; public */ + { "-", NULL, "r" }, + { "-", NULL, "r" }, + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static unsigned int C_geoFlag = C_GEOFLAGDEFAULT; /* Geometry flag */ + +static const char * C_usageList[] = { /* Usage */ + "gout [ [ [ []]]] ", + " -g : Geometry parameters :", + " n : do not read geometry data (matrix display)", + " p : permute Y and Z geometry dimensions", + " r : rotate geometry by 90 degrees", + " -h : Display this help", + " -mn : Do not read mapping data", + " -Oi[{}] : Open Inventor mesh file :", + " c : color output", + " g : gray level output", + " r : remove cut edges", + " v : view cut edges", + " -Om[{}] : PostScript matrix file :", + " e : EPSF-type output", + " f : full-page output", + " -Op[{}] : PostScript mesh file :", + " c : color output", + " g : gray level output", + " e : EPSF-type output", + " f : full-page output", + " s : short clipping (disks excluded)", + " l : large clipping (disks included)", + " a : avoid displaying disks", + " d : display disks", + " r : remove cut edges", + " v : view cut edges", + " X= : maximum x clipping ratio (in [0.0;1.0])", + " x= : minimum x clipping ratio", + " Y= : maximum y clipping ratio", + " y= : minimum y clipping ratio", + " -Ot[{}] : Tulip graph file :", + " b : b/w output", + " c : color output", + " a : avoid displaying disks", + " d : display disks", + " r : remove cut edges", + " v : view cut edges", + " -V : Print program version and copyright", + "", + "Default option set is : -Oi{c,v}", + NULL }; + +/*****************************/ +/* */ +/* This is the main function */ +/* */ +/*****************************/ + +int +main ( +int argc, +char * argv[]) +{ + C_Graph grafdat; /* Source graph */ + C_Geometry geo; /* Graph geometry */ + C_Mapping map; /* Result mapping */ + int i, j; + + errorProg ("gout"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else + errorPrint ("main: too many file names given"); + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'G' : /* Geometry parameters */ + case 'g' : + if ((j = C_geoParse (&argv[i][2])) != 0) + errorPrint ("main: error in geometry option string '%d'", j); + break; + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'M' : /* No-mapping flag */ + case 'm' : + if (((argv[i][2] != 'N') && (argv[i][2] != 'n')) || (argv[i][3] != '\0')) + errorPrint ("main: error in mapping option string '%s'", &argv[i][2]); + C_filenamemapinp = "-"; /* Default name to avoid opening */ + C_filepntrmapinp = NULL; /* NULL file pointer means no file */ + break; + case 'O' : /* Output parameters */ + case 'o' : + if ((j = outDrawParse (&argv[i][2])) != 0) + errorPrint ("main: error in output option string (%d)", j); + break; + case 'V' : + fprintf (stderr, "gout, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: Unprocessed option '%s'", argv[i]); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_graphInit (&grafdat.grafdat); /* Create graph structure */ + SCOTCH_graphLoad (&grafdat.grafdat, C_filepntrsrcinp, 0, 3); /* Read source graph */ + SCOTCH_graphData (&grafdat.grafdat, &grafdat.baseval, + &grafdat.vertnbr, &grafdat.verttab, &grafdat.vendtab, NULL, &grafdat.vlbltab, + &grafdat.edgenbr, &grafdat.edgetab, NULL); + + C_geoInit (&geo, &grafdat); /* Create geometry structure */ + if (C_geoFlag & C_GEOFLAGUSE) /* If geometry is wanted */ + C_geoLoad (&geo, C_filepntrgeoinp); /* Read graph geometry */ + + C_mapInit (&map, &grafdat); /* Create mapping structure */ + C_mapLoad (&map, C_filepntrmapinp); /* Read result mapping */ + + outDraw (&grafdat, &geo, &map, C_filepntrdatout); /* Build and write the output */ + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + C_mapExit (&map); /* Free data structures */ + C_geoExit (&geo); + SCOTCH_graphExit (&grafdat.grafdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} + +/***********************************/ +/* */ +/* These routines handle geometry. */ +/* */ +/***********************************/ + +/* This routine parses the source graph +** option string. +** It returns: +** - 0 : if string successfully scanned. +** - 1 : if invalid options +** - 2 : if invalid option arguments. +** - 3 : if syntax error in string. +*/ + +int +C_geoParse ( +const char * const string) +{ + const char * cptr; + + for (cptr = string; ; cptr ++) { + switch (*cptr) { + case 'N' : /* Do not read geometry data */ + case 'n' : + C_geoFlag &= ~C_GEOFLAGUSE; + break; + case 'P' : /* Permute Y and Z */ + case 'p' : + C_geoFlag |= C_GEOFLAGPERMUT; + break; + case 'R' : /* If want to rotate */ + case 'r' : + C_geoFlag |= C_GEOFLAGROTATE; + break; + case '\0' : + return (0); + default : + return (1); + } + } +} + +/* This routine creates a geometry with +** respect to a given source graph. +** It returns: +** - VOID : in all cases. +*/ + +void +C_geoInit ( +C_Geometry * const geomptr, +const C_Graph * const grafptr) +{ + geomptr->grafptr = grafptr; + geomptr->verttab = NULL; +} + +/* This routine deletes a geometry. +** It returns: +** - VOID : in all cases. +*/ + +void +C_geoExit ( +C_Geometry * const geomptr) +{ + if (geomptr->verttab != NULL) /* If there is a geometry array */ + memFree (geomptr->verttab); /* Free it */ +} + +/* This routine loads a mapping. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +/* This is the comparison function used by the + quicksort algorithm, to sort by increasing + labels. */ + +static +int +C_geoLoad2 ( +const C_VertSort * const vert0, +const C_VertSort * const vert1) +{ + return ((vert0->labl > vert1->labl) ? 1 : -1); +} + +/** This is the loading routine. **/ + +int +C_geoLoad ( +C_Geometry * const geomptr, +FILE * const stream) +{ + C_VertSort * vertsorttab; /* Pointer to graph sorting array */ + int vertsortflag; /* Flag set if graph data sorted by label */ + C_VertSort * geomsorttab; /* Pointer to geometric data sorting array */ + int geomsortflag; /* Flag set if geometric data sorted by label */ + int geomfiletype; /* Type of geometry file */ + SCOTCH_Num geomfilenbr; /* Number of geometric coordinates in file */ + SCOTCH_Num geomfileval; /* Value of maximum size for compatibility */ + C_GeoVert * geomfiletab; /* Pointer to geometric data read from file */ + SCOTCH_Num vertlablval; /* Value of maximum size for compatibility */ + SCOTCH_Num i, j; + int o; + + if ((geomptr->verttab == NULL) && /* Allocate geometry if necessary */ + ((geomptr->verttab = (C_GeoVert *) memAlloc (geomptr->grafptr->vertnbr * sizeof (C_GeoVert))) == NULL)) { + errorPrint ("C_geoLoad: out of memory (1)"); + return (1); + } + + if ((fscanf (stream, "%d" SCOTCH_NUMSTRING, /* Read type and number of geometry items */ + &geomfiletype, + &geomfileval) != 2) || + (geomfiletype < 1) || + (geomfiletype > 3) || + (geomfileval < 1)) { + errorPrint ("C_geoLoad: bad input (1)"); + return (1); + } + geomfilenbr = (SCOTCH_Num) geomfileval; + + if (memAllocGroup ((void **) (void *) + &geomfiletab, (size_t) (geomfilenbr * sizeof (C_GeoVert)), + &geomsorttab, (size_t) (geomfilenbr * sizeof (C_VertSort)), + &vertsorttab, (size_t) (geomptr->grafptr->vertnbr * sizeof (C_VertSort)), NULL) == NULL) { + errorPrint ("C_geoLoad: out of memory (2)"); + return (1); + } + + o = 0; + geomsortflag = 1; /* Assume geometry data sorted */ + switch (geomfiletype) { + case 1 : /* Load 2D coordinates array */ + for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { + if (fscanf (stream, SCOTCH_NUMSTRING "%lf", + &vertlablval, + &geomfiletab[i].x) != 2) + o = 1; + geomsorttab[i].labl = (SCOTCH_Num) vertlablval; + geomfiletab[i].y = /* No Y and Z coordinates */ + geomfiletab[i].z = 0.0; + geomsorttab[i].num = i; + + if (C_geoFlag & C_GEOFLAGROTATE) { /* Rotate picture if necessary */ + double t; /* Temporary swap variable */ + + t = geomfiletab[i].y; + geomfiletab[i].y = geomfiletab[i].x; + geomfiletab[i].x = - t; + } + + if ((i > 0) && /* Check if geometry data sorted */ + (geomsorttab[i].labl < geomsorttab[i - 1].labl)) + geomsortflag = 0; /* Geometry data not sorted */ + } + break; + case 2 : /* Load 2D coordinates array */ + for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { + if (fscanf (stream, SCOTCH_NUMSTRING "%lf%lf", + &vertlablval, + &geomfiletab[i].x, + &geomfiletab[i].y) != 3) + o = 1; + geomsorttab[i].labl = (SCOTCH_Num) vertlablval; + geomfiletab[i].z = 0.0; /* No Z coordinate */ + geomsorttab[i].num = i; + + if (C_geoFlag & C_GEOFLAGROTATE) { /* Rotate picture if necessary */ + double t; /* Temporary swap variable */ + + t = geomfiletab[i].y; + geomfiletab[i].y = geomfiletab[i].x; + geomfiletab[i].x = - t; + } + + if ((i > 0) && /* Check if geometry data sorted */ + (geomsorttab[i].labl < geomsorttab[i - 1].labl)) + geomsortflag = 0; /* Geometry data are not sorted */ + } + break; + case 3 : /* Load 3D coordinates array */ + for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { + if (fscanf (stream, SCOTCH_NUMSTRING "%lf%lf%lf", + &vertlablval, + &geomfiletab[i].x, + &geomfiletab[i].y, + &geomfiletab[i].z) != 4) + o = 1; + geomsorttab[i].labl = (SCOTCH_Num) vertlablval; + geomsorttab[i].num = i; + + if (C_geoFlag & C_GEOFLAGPERMUT) { /* Rotate picture if necessary */ + double t; /* Temporary swap variable */ + + t = geomfiletab[i].z; + geomfiletab[i].z = geomfiletab[i].y; + geomfiletab[i].y = t; + } + if ((i > 0) && /* Check if geometry data sorted */ + (geomsorttab[i].labl < geomsorttab[i - 1].labl)) + geomsortflag = 0; /* Geometry data not sorted */ + } + break; + default : + errorPrint ("C_geoLoad: invalid geometry type (%d)", geomfiletype); + memFree (geomfiletab); /* Free group leader */ + return (1); + } + if (o != 0) { + errorPrint ("C_geoLoad: bad input (2)"); + memFree (geomfiletab); /* Free group leader */ + return (1); + } + + if (geomsortflag != 1) /* If geometry data not sorted */ + qsort ((char *) geomsorttab, geomfilenbr, /* Sort sort area by ascending labels */ + sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); + for (i = 1; i < geomfilenbr; i ++) { /* Check geometric data integrity */ + if (geomsorttab[i].labl == geomsorttab[i - 1].labl) { + errorPrint ("C_geoLoad: duplicate vertex label"); + memFree (geomfiletab); /* Free group leader */ + return (1); + } + } + + if (geomptr->grafptr->vlbltab != NULL) { /* If graph has vertex labels */ + vertsortflag = 1; /* Assume graph data sorted */ + for (i = 0; i < geomptr->grafptr->vertnbr; i ++) { + vertsorttab[i].labl = geomptr->grafptr->vlbltab[i]; + vertsorttab[i].num = i; + if ((i > 0) && /* Check if graph data sorted */ + (vertsorttab[i].labl < vertsorttab[i - 1].labl)) + vertsortflag = 0; /* Graph data not sorted */ + } + if (vertsortflag != 1) /* If graph data not sorted */ + qsort ((char *) vertsorttab, geomptr->grafptr->vertnbr, /* Sort sort area by ascending labels */ + sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); + } + else { /* Graph does not have vertex labels */ + for (i = 0; i < geomptr->grafptr->vertnbr; i ++) { + vertsorttab[i].labl = i + geomsorttab[0].labl; /* Use first index as base value */ + vertsorttab[i].num = i; + } + } + + for (i = 0, j = 0; i < geomptr->grafptr->vertnbr; i ++) { /* For all vertices in graph */ + while ((j < geomfilenbr) && (geomsorttab[j].labl < vertsorttab[i].labl)) + j ++; /* Search geometry vertex with same label */ + if ((j >= geomfilenbr) || (geomsorttab[j].labl > vertsorttab[i].labl)) { /* If label does not exist */ + errorPrint ("C_geoLoad: vertex geometry data not found for label '" SCOTCH_NUMSTRING "'", + vertsorttab[i].labl); + memFree (geomfiletab); /* Free group leader */ + return (1); + } + geomptr->verttab[vertsorttab[i].num] = geomfiletab[geomsorttab[j ++].num]; + } + + memFree (geomfiletab); /* Free group leader */ + + return (0); +} + +/***********************************/ +/* */ +/* These routines handle mappings. */ +/* */ +/***********************************/ + +/* This routine creates a mapping with +** respect to a given source graph. +** It returns: +** - VOID : in all cases. +*/ + +void +C_mapInit ( +C_Mapping * const mapptr, +const C_Graph * const grafptr) +{ + mapptr->grafptr = grafptr; + mapptr->labltab = NULL; +} + +/* This routine deletes a mapping. +** It returns: +** - VOID : in all cases. +*/ + +void +C_mapExit ( +C_Mapping * const mapptr) +{ + if (mapptr->labltab != NULL) /* If there is a domain array */ + memFree (mapptr->labltab); /* Free it */ +} + +/* This routine loads a mapping. +** It returns: +** - 0 : on success. +** - !0 : on error. +*/ + +int +C_mapLoad ( +C_Mapping * const mapptr, +FILE * const stream) +{ + C_VertSort * vertsorttab; /* Pointer to graph sorting array */ + int vertsortflag; /* Flag set if graph data sorted by label */ + C_VertSort * mapsorttab; /* Pointer to mapping data sorting array */ + int mapsortflag; /* Flag set if mapping data sorted by label */ + SCOTCH_Num mapsortval; /* Value of maximum size for compatibility */ + SCOTCH_Num mapfileval; /* Value of maximum size for compatibility */ + SCOTCH_Num mapfilenbr; /* Number of mapping pairs in file */ + SCOTCH_Num * mapfiletab; /* Pointer to mapping data read from file */ + SCOTCH_Num i, j; + + if ((mapptr->labltab == NULL) && /* Allocate array if necessary */ + ((mapptr->labltab = (SCOTCH_Num *) memAlloc (mapptr->grafptr->vertnbr * sizeof (SCOTCH_Num))) == NULL)) { + errorPrint ("C_mapLoad: out of memory (1)"); + return (1); + } + + memset (mapptr->labltab, ~0, mapptr->grafptr->vertnbr * sizeof (SCOTCH_Num)); /* Pre-initialize mapping */ + + if (stream == NULL) /* If stream is invalid */ + return (0); + + if ((fscanf (stream, SCOTCH_NUMSTRING, /* Read number of mapping pairs */ + &mapfileval) != 1) || + (mapfileval < 1)) { + errorPrint ("C_mapLoad: bad input (1)"); + return (1); + } + mapfilenbr = (SCOTCH_Num) mapfileval; + + if (memAllocGroup ((void **) (void *) + &mapfiletab, (size_t) (mapfilenbr * sizeof (SCOTCH_Num)), + &mapsorttab, (size_t) (mapfilenbr * sizeof (C_VertSort)), + &vertsorttab, (size_t) (mapptr->grafptr->vertnbr * sizeof (C_VertSort)), NULL) == NULL) { + errorPrint ("C_mapLoad: out of memory (2)"); + return (1); + } + + mapsortflag = 1; /* Assume mapping data sorted */ + for (i = 0; i < mapfilenbr; i ++) { + if (fscanf (stream, SCOTCH_NUMSTRING SCOTCH_NUMSTRING, + &mapsortval, + &mapfileval) != 2) { + errorPrint ("C_mapLoad: bad input (2)"); + memFree (mapfiletab); /* Free group leader */ + return (1); + } + mapsorttab[i].labl = mapsortval; + mapsorttab[i].num = i; + mapfiletab[i] = mapfileval; + + if ((i > 0) && /* Check if mapping data sorted */ + (mapsorttab[i].labl < mapsorttab[i - 1].labl)) + mapsortflag = 0; /* Mapping data not sorted */ + } + if (mapsortflag != 1) /* If mapping data not sorted */ + qsort ((char *) mapsorttab, mapfilenbr, /* Sort sort area by ascending labels */ + sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); + for (i = 1; i < mapfilenbr; i ++) { /* Check mapping data integrity */ + if (mapsorttab[i].labl == mapsorttab[i - 1].labl) { + errorPrint ("C_mapLoad: duplicate vertex label"); + memFree (mapfiletab); /* Free group leader */ + return (1); + } + } + + if (mapptr->grafptr->vlbltab != NULL) { /* If graph has vertex labels */ + vertsortflag = 1; /* Assume graph data sorted */ + for (i = 0; i < mapptr->grafptr->vertnbr; i ++) { + vertsorttab[i].labl = mapptr->grafptr->vlbltab[i]; + vertsorttab[i].num = i; + if ((i > 0) && /* Check if graph data sorted */ + (vertsorttab[i].labl < vertsorttab[i - 1].labl)) + vertsortflag = 0; /* Graph data not sorted */ + } + if (vertsortflag != 1) /* If graph data not sorted */ + qsort ((char *) vertsorttab, mapptr->grafptr->vertnbr, /* Sort sort area by ascending labels */ + sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); + } + else { /* Graph does not have vertex labels */ + for (i = 0; i < mapptr->grafptr->vertnbr; i ++) { + vertsorttab[i].labl = i + mapptr->grafptr->baseval; + vertsorttab[i].num = i; + } + } + + for (i = 0, j = 0; i < mapptr->grafptr->vertnbr; i ++) { /* For all vertices in graph */ + while ((j < mapfilenbr) && (mapsorttab[j].labl < vertsorttab[i].labl)) + j ++; /* Search mapping vertex with same label */ + if ((j >= mapfilenbr) || (mapsorttab[j].labl > vertsorttab[i].labl)) /* If label does not exist */ + continue; /* This vertex has no related mapping data */ + mapptr->labltab[vertsorttab[i].num] = mapfiletab[mapsorttab[j ++].num]; + } + + memFree (mapfiletab); /* Free group leader */ + + return (0); +} + +/**************************************/ +/* */ +/* The option string parsing routine. */ +/* */ +/**************************************/ + +/* This routine parses an option string. +** It returns: +** - 0 : if string successfully scanned. +** - 1 : if invalid code name. +** - 2 : if invalid arguments for the code. +** - 3 : if syntax error in string. +*/ + +int +C_parse ( +const C_ParseCode * const codeptr, /* Pointer to the code array */ +const C_ParseArg * const argptr, /* Pointer to the code argument array */ +int * const codeval, /* Pointer to the code value to set */ +char * const string) /* Pointer to the string to parse */ +{ + int code; /* Code found */ + int codelen; /* Code name length */ + char argbuf[128]; /* Buffer for argument scanning */ + int arglen; /* Length of the current argument */ + char * argbeg; /* Pointer to beginning of argument */ + char * argend; /* Pointer to end of argument */ + char * argequ; /* Position of the '=' character */ + int i, j; + + code = + codelen = 0; /* No code recognized yet */ + for (i = 0; codeptr[i].name != NULL; i ++) { /* For all the codes */ + if ((strncasecmp (string, /* Find the longest matching code name */ + codeptr[i].name, + j = strlen (codeptr[i].name)) == 0) && + (j > codelen)) { + code = codeptr[i].code; + codelen = j; + } + } + if (codelen == 0) /* If no code recognized */ + return (1); /* Return the error value */ + *codeval = code; /* Set the code value */ + + argbeg = string + codelen; /* Point to the end of the code name */ + if (*argbeg == '{') { /* If there are arguments */ + argbeg ++; /* Point to argument beginning */ + do { /* For all arguments */ + argend = strpbrk (argbeg, ",}\0"); /* Search for the argument end */ + if (*argend == '\0') /* If there is no end delimiter */ + return (3); /* Return the syntax error value */ + + arglen = ((argend - argbeg) < 127) /* Get argument bounded length */ + ? (argend - argbeg) + : 127; + strncpy (argbuf, argbeg, arglen); /* Copy the argument to the buffer */ + argbuf[arglen] = '\0'; /* Mark the end of the argument */ + argequ = strpbrk (argbuf, "="); /* Search for the '=' character */ + if (argequ != NULL) /* If it exists */ + *argequ++ = '\0'; /* Turn it into a separating null */ + + for (i = 0, j = -1; argptr[i].name != NULL; i ++) { /* Scan all the possible arguments */ + if ((argptr[i].code == code) && /* If the proper name is found */ + (strcmp (argbuf, argptr[i].name) == 0)) { + j = i; /* Record the position */ + break; /* Exit the loop */ + } + } + if (j == -1) /* If invalid argument */ + return (2); /* Return the proper value */ + + if (argptr[j].format != NULL) { /* If there is a value to read */ + if (argequ == NULL) /* If none has been given however */ + return (2); /* Return the error value */ + if (sscanf (argequ, /* Try to read the argument value */ + argptr[j].format, + argptr[j].ptr) != 1) + return (2); /* Return if error */ + if (argptr[j].func != NULL) /* If there is a control function */ + if (argptr[j].func (argptr[j].ptr) != 0) /* If the function fails */ + return (2); /* Return the error value */ + } + else { /* If no value needed */ + if (argequ != NULL) /* If there is one however */ + return (2); /* Return the error code */ + *((char *) argptr[j].ptr) = argbuf[0]; /* Copy the first argument char */ + } + + argbeg = argend + 1; /* Skip the processed argument */ + } while (*argend != '}'); /* Loop as long as there are arguments */ + } + + return ((*argbeg == '\0') ? 0 : 3); /* Check if no extraneous characters */ +} diff --git a/scotch_6.0.3/src/scotch/gout_c.h b/scotch_6.0.3/src/scotch/gout_c.h new file mode 100644 index 00000000..5775f569 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gout_c.h @@ -0,0 +1,177 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gout_c.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a result viewer. **/ +/** This module contains the data declara- **/ +/** tions for the main module. **/ +/** **/ +/** DATES : # Version 2.0 : from : 06 oct 1994 **/ +/** to 01 nov 1994 **/ +/** # Version 3.0 : from : 14 jul 1995 **/ +/** to 02 oct 1995 **/ +/** # Version 3.2 : from : 02 dec 1996 **/ +/** to 05 jun 1998 **/ +/** # Version 3.3 : from : 01 jun 1999 **/ +/** to 01 jun 1999 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 11 dec 2001 **/ +/** # Version 5.0 : from : 13 dec 2007 **/ +/** to 15 mar 2008 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 4 /* Number of files in list */ +#define C_FILEARGNBR 4 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph file name */ +#define C_filenamegeoinp C_fileTab[1].name /* Source graph geometry file name */ +#define C_filenamemapinp C_fileTab[2].name /* Mapping result file name */ +#define C_filenamedatout C_fileTab[3].name /* Output data file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrgeoinp C_fileTab[1].pntr /* Source graph geometry file */ +#define C_filepntrmapinp C_fileTab[2].pntr /* Mapping result input file */ +#define C_filepntrdatout C_fileTab[3].pntr /* Data output file */ + +#define C_filemodemapinp C_fileTab[2].mode /* Mapping result mode */ + +/*+ Dimension definitions. +*/ + +#define x c[0] +#define y c[1] +#define z c[2] + +/*+ Geometry flags. +*/ + +#define C_GEOFLAGDEFAULT 0x0001 /* Default geometry flag */ +#define C_GEOFLAGUSE 0x0001 /* Use geometry */ +#define C_GEOFLAGROTATE 0x0002 /* Rotate the picture by 90 degrees */ +#define C_GEOFLAGPERMUT 0x0004 /* Permute Y and Z dimensions */ + +/* +** The type and structure definitions. +*/ + +/*+ This structure defines a source graph. +*/ + +typedef struct C_Graph_ { + SCOTCH_Graph grafdat; /*+ Source graph data +*/ + SCOTCH_Num baseval; /*+ Base value +*/ + SCOTCH_Num vertnbr; /*+ Number of vertices +*/ + SCOTCH_Num * verttab; /*+ Vertex array +*/ + SCOTCH_Num * vendtab; /*+ Vertex end array +*/ + SCOTCH_Num * vlbltab; /*+ Vertex label array +*/ + SCOTCH_Num edgenbr; /*+ Number of edges +*/ + SCOTCH_Num * edgetab; /*+ Edge array +*/ +} C_Graph; + +/*+ This structure defines a geometrical vertex. +*/ + +typedef struct C_GeoVert_ { + double c[3]; /*+ Vertex coordinates (x,y,z) +*/ +} C_GeoVert; + +/*+ This structure defines a geometrical + mapping which contains the positions + of the graph vertices. +*/ + +typedef struct C_Geometry_ { + const C_Graph * grafptr; /*+ Pointer to source graph +*/ + C_GeoVert * verttab; /*+ Pointer to coordinates array +*/ +} C_Geometry; + +/*+ This structure defines a domain label + mapping, which contains the reference + to the mapping source graph. +*/ + +typedef struct C_Mapping_ { + const C_Graph * grafptr; /*+ Pointer to source graph +*/ + SCOTCH_Num * labltab; /*+ Pointer to label array +*/ +} C_Mapping; + +/*+ The sort structure, used to sort graph vertices by label. +*/ + +typedef struct C_VertSort_ { + SCOTCH_Num labl; /*+ Vertex label +*/ + SCOTCH_Num num; /*+ Vertex number +*/ +} C_VertSort; + +/*+ This structure is the code + name array entries. +*/ + +typedef struct C_ParseCode_ { + int code; /*+ Code value +*/ + char * name; /*+ Code name +*/ +} C_ParseCode; + +/* This structure defines the + code argument array entries. */ + +typedef struct C_ParseArg_ { + const char * name; /*+ Name of the argument +*/ + int code; /*+ Code value +*/ + const char * format; /*+ scanf-like format; NULL means char, no value +*/ + const void * ptr; /*+ Pointer to the argument location +*/ + int (* func) (); /*+ Pointer to the argument test function +*/ +} C_ParseArg; + +/* +** The global data declarations. +*/ + +extern File C_fileTab[C_FILENBR]; /*+ File array +*/ + +/* +** The function prototypes. +*/ + +int C_geoParse (const char * const); +void C_geoInit (C_Geometry * const, const C_Graph * const); +void C_geoExit (C_Geometry * const); +int C_geoLoad (C_Geometry * const, FILE * const); + +void C_mapInit (C_Mapping * const, const C_Graph * const); +void C_mapExit (C_Mapping * const); +int C_mapLoad (C_Mapping * const, FILE * const); + +int C_parse (const C_ParseCode * const, const C_ParseArg * const, int * const, char * const); diff --git a/scotch_6.0.3/src/scotch/gout_o.c b/scotch_6.0.3/src/scotch/gout_o.c new file mode 100644 index 00000000..fd771b1f --- /dev/null +++ b/scotch_6.0.3/src/scotch/gout_o.c @@ -0,0 +1,941 @@ +/* Copyright 2004,2007,2008,2011,2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gout_o.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a result viewer. **/ +/** This module contains output routines. **/ +/** **/ +/** DATES : # Version 2.0 : from : 07 oct 1994 **/ +/** to 23 dec 1994 **/ +/** # Version 3.0 : from : 14 jul 1995 **/ +/** to 03 oct 1995 **/ +/** # Version 3.1 : from : 28 mar 1996 **/ +/** to 03 jun 1996 **/ +/** # Version 3.2 : from : 02 dec 1996 **/ +/** to 05 jun 1998 **/ +/** # Version 3.3 : from : 29 may 1999 **/ +/** to : 03 jun 1999 **/ +/** # Version 4.0 : from : 11 dec 2001 **/ +/** to 11 dec 2001 **/ +/** # Version 5.0 : from : 25 may 2007 **/ +/** to 18 jun 2007 **/ +/** # Version 5.1 : from : 25 oct 2007 **/ +/** to 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes +*/ + +#define GOUT + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gout_c.h" +#include "gout_o.h" + +/* +** The static and global variables +*/ + +static O_OutParam O_outParam = { /* Parameter structure */ + O_OUTTYPEINVMESH, /* Default output type */ + { 'c', 'v' }, /* OpenInventor mesh defaults */ + { 'f' }, /* PostScript matrix defaults */ + { 'f', 'g', /* PostScript mesh defaults */ + 'v', 'd', + 's', + { { 0.0, 0.0 } }, + { { 1.0, 1.0 } } }, + { 'c', 'v', 'a' } }; /* Tulip graph defaults */ + +static C_ParseCode O_outList[] = { /* Output code list */ + { O_OUTTYPEINVMESH, "i" }, + { O_OUTTYPEPOSMATR, "m" }, + { O_OUTTYPEPOSMESH, "p" }, + { O_OUTTYPETULMESH, "t" }, + { O_OUTTYPENBR, NULL } }; + +static C_ParseArg O_outArg[] = { /* Output type argument list */ + { "c", O_OUTTYPEINVMESH, NULL, &O_outParam.InvMesh.color }, + { "g", O_OUTTYPEINVMESH, NULL, &O_outParam.InvMesh.color }, + { "r", O_OUTTYPEINVMESH, NULL, &O_outParam.InvMesh.edge }, + { "v", O_OUTTYPEINVMESH, NULL, &O_outParam.InvMesh.edge }, + { "e", O_OUTTYPEPOSMATR, NULL, &O_outParam.PosMatr.type }, + { "f", O_OUTTYPEPOSMATR, NULL, &O_outParam.PosMatr.type }, + { "c", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.color }, + { "g", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.color }, + { "e", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.type }, + { "f", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.type }, + { "l", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.clip }, + { "s", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.clip }, + { "a", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.disk }, + { "d", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.disk }, + { "r", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.edge }, + { "v", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.edge }, + { "x", O_OUTTYPEPOSMESH, "%lf", &O_outParam.PosMesh.min.x }, + { "X", O_OUTTYPEPOSMESH, "%lf", &O_outParam.PosMesh.max.x }, + { "y", O_OUTTYPEPOSMESH, "%lf", &O_outParam.PosMesh.min.y }, + { "Y", O_OUTTYPEPOSMESH, "%lf", &O_outParam.PosMesh.max.y }, + { "b", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.color }, + { "c", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.color }, + { "r", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.edge }, + { "v", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.edge }, + { "a", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.disk }, + { "d", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.disk }, + { NULL, O_OUTTYPENBR, "", NULL } }; + +static double outcolorcoltab[16][3] = { /* Color list */ + { 1.00, 0.00, 0.00 }, /* Red */ + { 0.00, 1.00, 0.00 }, /* Green */ + { 1.00, 1.00, 0.00 }, /* Yellow */ + { 0.00, 0.00, 1.00 }, /* Blue */ + { 1.00, 0.00, 1.00 }, /* Magenta */ + { 0.00, 1.00, 1.00 }, /* Cyan */ + { 1.00, 0.50, 0.20 }, /* Orange */ + { 0.30, 0.55, 0.00 }, /* Olive */ + { 0.72, 0.47, 0.47 }, /* Dark pink */ + { 0.33, 0.33, 0.81 }, /* Sea blue */ + { 1.00, 0.63, 0.63 }, /* Pink */ + { 0.62, 0.44, 0.65 }, /* Violet */ + { 0.60, 0.80, 0.70 }, /* Pale green */ + { 0.47, 0.20, 0.00 }, /* Brown */ + { 0.00, 0.68, 0.68 }, /* Turquoise */ + { 0.81, 0.00, 0.40 } }; /* Purple */ + +static double outcolorblwtab[8][3] = { /* Grey list */ + { 1.00, 1.00, 1.00 }, + { 0.20, 0.20, 0.20 }, + { 0.50, 0.50, 0.50 }, + { 0.80, 0.80, 0.80 }, + { 0.30, 0.30, 0.30 }, + { 0.90, 0.90, 0.90 }, + { 0.40, 0.40, 0.40 }, + { 0.70, 0.70, 0.70 } }; + +/****************************************/ +/* */ +/* This is the color selection routine. */ +/* */ +/****************************************/ + +void +outColorBlw ( +const SCOTCH_Num labl, +double color[]) +{ + if (labl == (-1)) { + color[0] = + color[1] = + color[2] = 1.0L; + } + else { + color[0] = (double) outcolorblwtab[labl % 8][0]; + color[1] = (double) outcolorblwtab[labl % 8][1]; + color[2] = (double) outcolorblwtab[labl % 8][2]; + } +} + +void +outColorColor ( +const SCOTCH_Num labl, +double color[]) +{ + if (labl == (-1)) { + color[0] = + color[1] = + color[2] = 1.0L; + } + else { + color[0] = (double) outcolorcoltab[labl % 16][0]; + color[1] = (double) outcolorcoltab[labl % 16][1]; + color[2] = (double) outcolorcoltab[labl % 16][2]; + } +} + +/****************************/ +/* */ +/* The main output routine. */ +/* */ +/****************************/ + +/* This routine parses the output +** option string. +** It returns: +** - 0 : if string successfully scanned. +** - 1 : if invalid options +** - 2 : if invalid option arguments. +** - 3 : if syntax error in string. +*/ + +int +outDrawParse ( +char * const string) +{ + return (C_parse (O_outList, O_outArg, (int * const) (void *) &O_outParam.type, string)); +} + + +/* This routine is the generic output call. +** It returns: +** - VOID : in all cases. +*/ + +void +outDraw ( +const C_Graph * const grafptr, /* Graph structure */ +const C_Geometry * const geomptr, /* Graph geometry */ +const C_Mapping * const mapptr, /* Result mapping */ +FILE * const stream) /* Output stream */ +{ + switch (O_outParam.type) { + case O_OUTTYPEINVMESH : /* Mesh OpenInventor output type */ + outDrawInvMesh (grafptr, geomptr, mapptr, stream); + break; + case O_OUTTYPEPOSMATR : /* Matrix PostScript output type */ + outDrawPosMatr (grafptr, geomptr, mapptr, stream); + break; + case O_OUTTYPEPOSMESH : /* Mesh PostScript output type */ + outDrawPosMesh (grafptr, geomptr, mapptr, stream); + break; + case O_OUTTYPETULMESH : /* Mesh Tulip output type */ + outDrawTulMesh (grafptr, geomptr, mapptr, stream); + break; + default : + errorPrint ("outDraw: invalid output method '%d'", O_outParam.type); + } +} + +/****************************************/ +/* */ +/* This is the Inventor output routine. */ +/* */ +/****************************************/ + +int +outDrawInvMesh ( +const C_Graph * const grafptr, /* Graph structure, sorted by vertex index */ +const C_Geometry * const geomptr, /* Graph geometry, sorted by vertex label */ +const C_Mapping * const mapptr, /* Result mapping, sorted by vertex label */ +FILE * const stream) /* Output stream */ +{ + void (* outcolor) (const SCOTCH_Num, double[]); /* Color routine */ + O_InvMeshPath * pattab; /* Array of path building data */ + int * idxtab; /* Array of indexes */ + int idxnbr; /* Number of indexes */ + time_t pictime; /* Creation time */ + double color[3]; /* Vertex color */ + int i, j, k; + + if (geomptr->verttab == NULL) { + errorPrint ("outDrawInvMesh: geometry not provided"); + return (1); + } + + time (&pictime); /* Get current time */ + + outcolor = (O_outParam.InvMesh.color == 'c') ? outColorColor : outColorBlw; /* Select color output routine */ + + if (((idxtab = (int *) memAlloc ((grafptr->edgenbr / 2) * 3 * sizeof (int))) == NULL) || + ((pattab = (O_InvMeshPath *) memAlloc (grafptr->vertnbr * sizeof (O_InvMeshPath))) == NULL)) { + errorPrint ("outDrawInvMesh: out of memory"); + if (idxtab != NULL) + memFree (idxtab); + return (1); + } + idxnbr = 0; /* No indexes yet */ + + for (i = 0, j = 0; i < grafptr->vertnbr; i ++) { /* For all vertices */ + pattab[i].nbr = 0; /* Compute the number of output paths */ + pattab[i].idx = grafptr->verttab[i]; + for ( ; j < grafptr->vendtab[i]; j ++) { + if ((grafptr->edgetab[j] > i) && /* If it can be an output edge */ + ((O_outParam.InvMesh.edge != 'r') || /* And this edge can be drawn */ + (mapptr->labltab[i] == mapptr->labltab[grafptr->edgetab[j]]))) + pattab[i].nbr ++; /* One more path to higher vertices */ + } + } + for (i = 0; i < grafptr->vertnbr; ) { /* For all vertices */ + if (pattab[i].nbr == 0) { /* If no output path for this vertex */ + i ++; /* Skip to next vertex */ + continue; + } + + j = i; /* Begin with this vertex */ + idxtab[idxnbr ++] = j; /* Add it to the current segment */ + do { + for (k = pattab[j].idx; k < grafptr->vendtab[j]; k ++) { /* Search for first output */ + if ((grafptr->edgetab[k] > j) && /* If it can be an output edge */ + ((O_outParam.InvMesh.edge != 'r') || /* And this edge can be drawn */ + (mapptr->labltab[j] == mapptr->labltab[grafptr->edgetab[k]]))) + break; + } + pattab[j].nbr --; /* One less output path remaining */ + pattab[j].idx = k + 1; /* Search from the next position */ + j = grafptr->edgetab[k]; /* Get the path end vertex number */ + idxtab[idxnbr ++] = j; /* Add it to the current segment */ + } while (pattab[j].nbr > 0); /* As long as there is a path */ + idxtab[idxnbr ++] = ~0; /* Mark end of path */ + } + + fprintf (stream, "#Inventor V2.0 ascii\n"); /* Write header */ + fprintf (stream, "#Title: %s %s %s\n", + C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); + fprintf (stream, "#Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); + fprintf (stream, "#CreationDate: %s", ctime (&pictime)); + + if (idxnbr == 0) /* If nothing to write */ + return (0); + + fprintf (stream, "Separator {\n"); + fprintf (stream, " LightModel {\n model\t\tBASE_COLOR\n }\n"); + fprintf (stream, " DrawStyle {\n style\t\tLINES\n }\n"); + fprintf (stream, " MaterialBinding {\n value\t\tPER_VERTEX\n }\n"); + + fprintf (stream, " Coordinate3 {\n point [\n\t%g\t%g\t%g", /* Write vertex coordinates */ + geomptr->verttab[0].x, + geomptr->verttab[0].y, + geomptr->verttab[0].z); + for (i = 1; i < grafptr->vertnbr; i ++) + fprintf (stream, ",\n\t%g\t%g\t%g", + geomptr->verttab[i].x, + geomptr->verttab[i].y, + geomptr->verttab[i].z); + fprintf (stream, " ]\n }\n"); + + fprintf (stream, " BaseColor {\n rgb ["); /* Write color vector */ + for (i = 0; i < idxnbr - 2; i ++) { + if (idxtab[i] != ~0) { + outcolor (mapptr->labltab[idxtab[i]], color); + fprintf (stream, "\n\t%g\t%g\t%g,", + (double) color[0], + (double) color[1], + (double) color[2]); + } + } + outcolor (mapptr->labltab[idxtab[idxnbr - 2]], color); + fprintf (stream, "\n\t%g\t%g\t%g ]\n }\n", + (double) color[0], + (double) color[1], + (double) color[2]); + + fprintf (stream, " IndexedLineSet {\n coordIndex ["); /* Write set of lines */ + for (i = 0; i < idxnbr - 1; i ++) { + if ((i % 8) == 0) + fprintf (stream, "\n"); + if (idxtab[i] == ~0) + fprintf (stream, "\t-1,"); + else + fprintf (stream, "\t%u,", idxtab[i]); + } + if (((idxnbr - 1) % 8) == 0) + fprintf (stream, "\n"); + fprintf (stream, "\t-1 ]\n }\n"); + + fprintf (stream, "}\n"); /* Write end of separator */ + + +#if 0 + for (i = 0; i < grafptr->vertnbr; i ++) { /* For all vertices */ + outcolor (mapptr->labltab[i], color); + fprintf (stream, "Separator { Translation { translation %lg %lg %lg } BaseColor { rgb [ %lg %lg %lg ] } Sphere { radius 0.3 } }\n", + geomptr->verttab[i].x, + geomptr->verttab[i].y, + geomptr->verttab[i].z, + (double) color[0], + (double) color[1], + (double) color[2]); + } +#endif + + memFree (pattab); /* Free path array */ + memFree (idxtab); /* Free index array */ + + return (0); +} + +/*************************************************/ +/* */ +/* This is the PostScript matrix output routine. */ +/* */ +/*************************************************/ + +int +outDrawPosMatr ( +const C_Graph * const grafptr, /* Graph structure, sorted by vertex index */ +const C_Geometry * const geomptr, /* Graph geometry, sorted by vertex label */ +const C_Mapping * const mapptr, /* Result mapping, sorted by vertex label */ +FILE * const stream) /* Output stream */ +{ + SCOTCH_Num * nonztab; /* Array of non-zero entries */ + SCOTCH_Num nonzfrst; /* First non-zero entry of area */ + SCOTCH_Num nonzlast; /* Last non-zero entry of area */ + double pictsize; /* Number of distinct coordinates */ + double pictdisp; /* Size of the matrix display (in inches) */ + time_t picttime; /* Creation time */ + SCOTCH_Num colnum; + SCOTCH_Num vertnum; + SCOTCH_Num * edgeptr; + + if ((nonztab = memAlloc ((grafptr->vertnbr + 1) * sizeof (SCOTCH_Num))) == NULL) { + errorPrint ("outDrawPosMatr: out of memory"); + return (1); + } + + time (&picttime); /* Get current time */ + pictsize = (double) (grafptr->vertnbr + 1); /* Get matrix size */ + pictdisp = MIN (O_PSPICTWIDTH, O_PSPICTHEIGHT); + + if (O_outParam.PosMatr.type == 'e') { /* EPSF-type output */ + fprintf (stream, "%%!PS-Adobe-2.0 EPSF-2.0\n"); + fprintf (stream, "%%%%Title: %s %s %s\n", + C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); + fprintf (stream, "%%%%Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); + fprintf (stream, "%%%%CreationDate: %s", ctime (&picttime)); + fprintf (stream, "%%%%BoundingBox: 0 0 %d %d\n", + (int) (pictdisp * O_PSDPI), (int) (pictdisp * O_PSDPI)); + fprintf (stream, "%%%%Pages: 0\n"); + fprintf (stream, "%%%%EndComments\n"); + } + else { /* Full page output */ + fprintf (stream, "%%!PS-Adobe-2.0\n"); + fprintf (stream, "%%%%Title: %s %s %s\n", + C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); + fprintf (stream, "%%%%Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); + fprintf (stream, "%%%%CreationDate: %s", ctime (&picttime)); + } + + fprintf (stream, "/p { pop } bind def\n"); + fprintf (stream, "/h { 3 1 roll exch 2 copy moveto 2 copy 1 add 5 -3 roll 3 1 roll add exch 2 copy lineto 1 add lineto lineto fill } bind def\n"); + fprintf (stream, "/v { 3 copy pop moveto 2 copy add exch pop exch 3 copy pop pop 1 add dup 3 -1 roll lineto exch dup 3 1 roll lineto lineto fill } bind def\n"); + fprintf (stream, "/b { 3 copy v 3 copy h pop pop } bind def\n"); + fprintf (stream, "/c { 1 3 copy v 3 copy h pop pop } bind def\n"); + + fprintf (stream, "gsave\n"); /* Save the context */ + fprintf (stream, "0 setlinecap\n"); /* Perform miter caps */ + if (O_outParam.PosMatr.type == 'f') /* If full page output */ + fprintf (stream, "%d %d translate\n", /* Center the picture */ + (int) (O_PSDPI * (O_PSPAGEWIDTH - pictdisp)) / 2, + (int) (O_PSDPI * (O_PSPAGEWIDTH - pictdisp)) / 2); + fprintf (stream, "%f %f scale\n", /* Print scaling factor */ + (double) O_PSDPI * pictdisp / pictsize, + (double) O_PSDPI * pictdisp / pictsize); + fprintf (stream, "[ 1 0 0 -1 0 %d ] concat\n", /* Reverse Y coordinate */ + (int) (grafptr->vertnbr + 1)); + fprintf (stream, "0 setgray newpath\n"); /* Select black color */ + + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { + colnum = (mapptr->labltab[vertnum] == ~0) ? vertnum : mapptr->labltab[vertnum]; + + fprintf (stream, SCOTCH_NUMSTRING "\n", /* Set column value */ + (SCOTCH_Num) colnum); + memset (nonztab, 0, (colnum + 2) * sizeof (SCOTCH_Num)); + for (edgeptr = grafptr->edgetab + grafptr->verttab[colnum]; + edgeptr < grafptr->edgetab + grafptr->vendtab[colnum]; edgeptr ++) { + if (*edgeptr < colnum) + nonztab[*edgeptr] = 1; + } + nonztab[colnum] = 1; /* Diagonal is non-zero */ + for (nonzfrst = 0; nonzfrst <= vertnum; nonzfrst ++) { + if (nonztab[nonzfrst] != 0) { /* A non-zero has been found */ + for (nonzlast = nonzfrst; nonztab[nonzlast] != 0; nonzlast ++) ; + if ((nonzlast - nonzfrst) > 1) /* Draw row block coefficient */ + fprintf (stream, SCOTCH_NUMSTRING " " SCOTCH_NUMSTRING " b\n", + (SCOTCH_Num) nonzfrst, + (SCOTCH_Num) (nonzlast - nonzfrst)); + else + fprintf (stream, SCOTCH_NUMSTRING " c\n", + (SCOTCH_Num) nonzfrst); + nonzfrst = nonzlast - 1; + } + } + fprintf (stream, "p "); /* Close the column */ + } + + fprintf (stream, "\ngrestore\n"); /* Restore context */ + if (O_outParam.PosMatr.type == 'f') /* If full page output */ + fprintf (stream, "showpage\n"); /* Display the page */ + + memFree (nonztab); + + return (0); +} + +/***********************************************/ +/* */ +/* This is the PostScript mesh output routine. */ +/* */ +/***********************************************/ + +int +outDrawPosMesh ( +const C_Graph * const grafptr, /* Graph structure, sorted by vertex index */ +const C_Geometry * const geomptr, /* Graph geometry, sorted by vertex label */ +const C_Mapping * const mapptr, /* Result mapping, sorted by vertex label */ +FILE * const stream) /* Output stream */ +{ + int idxnbr; /* Number of indexes */ + int * idxtab; /* Array of indexes */ + O_PosMeshPath * pattab; /* Array of path building data */ + O_PosMeshVertex * pictab; /* Array of 2D coordinates, sorted by vertex index */ + O_Point picmin; /* Picture minimum and maximum coordinates */ + O_Point picmax; + O_Point picdelt; + double picscale; /* Scaling factor */ + double picsrad; /* Square of circle radius */ + time_t pictime; /* Creation time */ + double color[3]; /* Color values */ + int i, j, k; + + if (geomptr->verttab == NULL) { + errorPrint ("outDrawPosMesh: geometry not provided"); + return (1); + } + + time (&pictime); /* Get current time */ + + if (((pictab = (O_PosMeshVertex *) memAlloc (grafptr->vertnbr * sizeof (O_PosMeshVertex))) == NULL) || + ((idxtab = (int *) memAlloc ((grafptr->edgenbr / 2) * 3 * sizeof (int))) == NULL) || + ((pattab = (O_PosMeshPath *) memAlloc (grafptr->vertnbr * sizeof (O_PosMeshPath))) == NULL)) { + errorPrint ("outDrawPosMesh: out of memory"); + if (pictab != NULL) { + if (idxtab != NULL) + memFree (idxtab); + memFree (pictab); + } + return (1); + } + + for (i = 0; i < grafptr->vertnbr; i ++) { /* For all vertex indices */ + pictab[i].pos.x = geomptr->verttab[i].x + /* Project 3D coordinates into 2D ones */ + geomptr->verttab[i].z * (O_POSMESHISOCOS * O_POSMESHISOREDUC); + pictab[i].pos.y = geomptr->verttab[i].y + + geomptr->verttab[i].z * (O_POSMESHISOSIN * O_POSMESHISOREDUC); + } + + picmin.x = picmin.y = 1e30; /* Pre-set coordinates extrema */ + picmax.x = picmax.y = -1e30; + + if (O_outParam.PosMesh.clip == 'l') { /* If clipping encompasses disks */ + for (i = 0, j = 0; i < grafptr->vertnbr; i ++) { + pictab[i].rad = 1e30; /* Assume a huge square of radius */ + for ( ; j < grafptr->vendtab[i]; j ++) { + k = grafptr->edgetab[j]; + picsrad = (pictab[i].pos.x - pictab[k].pos.x) * + (pictab[i].pos.x - pictab[k].pos.x) + + (pictab[i].pos.y - pictab[k].pos.y) * + (pictab[i].pos.y - pictab[k].pos.y); + if (picsrad < pictab[i].rad) /* Get the smallest square of radius */ + pictab[i].rad = picsrad; + } + pictab[i].rad = sqrt (pictab[i].rad) / 2.0; /* Keep the half-distance for radius */ + + if ((pictab[i].pos.x - pictab[i].rad) < picmin.x) /* Update extrema if necessary */ + picmin.x = pictab[i].pos.x - pictab[i].rad; + if ((pictab[i].pos.y - pictab[i].rad) < picmin.y) + picmin.y = pictab[i].pos.y - pictab[i].rad; + if ((pictab[i].pos.x + pictab[i].rad) > picmax.x) + picmax.x = pictab[i].pos.x + pictab[i].rad; + if ((pictab[i].pos.y + pictab[i].rad) > picmax.y) + picmax.y = pictab[i].pos.y + pictab[i].rad; + } + } + else { /* Border clipping */ + for (i = 0; i < grafptr->vertnbr; i ++) { /* For all vertex indices */ + if (pictab[i].pos.x < picmin.x) /* Update extrema if necessary */ + picmin.x = pictab[i].pos.x; + if (pictab[i].pos.y < picmin.y) + picmin.y = pictab[i].pos.y; + if (pictab[i].pos.x > picmax.x) + picmax.x = pictab[i].pos.x; + if (pictab[i].pos.y > picmax.y) + picmax.y = pictab[i].pos.y; + } + } + + picdelt.x = picmax.x - picmin.x; /* Compute picture extents */ + picdelt.y = picmax.y - picmin.y; + picmin.x += picdelt.x * O_outParam.PosMesh.min.x; /* Resize picture (if necessary) */ + picmin.y += picdelt.y * O_outParam.PosMesh.min.y; + picmax.x -= picdelt.x * (1.0L - O_outParam.PosMesh.max.x); + picmax.y -= picdelt.y * (1.0L - O_outParam.PosMesh.max.y); + picdelt.x = picmax.x - picmin.x; /* Recompute picture extents */ + picdelt.y = picmax.y - picmin.y; + + picscale = (picdelt.x == 0.0L) /* Compute scaling factor */ + ? ((picdelt.y == 0.0L) + ? 1.0L + : (O_PSPICTHEIGHT / picdelt.y)) + : ((picdelt.y == 0.0L) + ? (O_PSPICTWIDTH / picdelt.x) + : MIN (O_PSPICTWIDTH / picdelt.x, O_PSPICTHEIGHT / picdelt.y)); + + picdelt.x *= picscale * O_POSMESHPICTRESOL; /* Rescale extents */ + picdelt.y *= picscale * O_POSMESHPICTRESOL; + + for (i = 0; i < grafptr->vertnbr; i ++) { + pictab[i].pos.x = (pictab[i].pos.x - picmin.x) * picscale * O_POSMESHPICTRESOL; /* Rescale coordinates */ + pictab[i].pos.y = (pictab[i].pos.y - picmin.y) * picscale * O_POSMESHPICTRESOL; + } + + if (O_outParam.PosMesh.disk == 'd') { /* If disks wanted */ + for (i = 0, j = 0; i < grafptr->vertnbr; i ++) { + pictab[i].rad = 1e30; /* Assume huge square of radius */ + for ( ; j < grafptr->vendtab[i]; j ++) { + k = grafptr->edgetab[j]; + picsrad = (pictab[i].pos.x - pictab[k].pos.x) * + (pictab[i].pos.x - pictab[k].pos.x) + + (pictab[i].pos.y - pictab[k].pos.y) * + (pictab[i].pos.y - pictab[k].pos.y); + if (picsrad < pictab[i].rad) /* Get smallest square of radius */ + pictab[i].rad = picsrad; + } + pictab[i].rad = sqrt (pictab[i].rad) / 2.0; /* Keep the half-distance for radius */ + if (pictab[i].rad < 1.0L) /* Always get a non-zero radius */ + pictab[i].rad = 1.0L; + + pictab[i].vis = ((pictab[i].pos.x > - pictab[i].rad) && /* Compute vertex visibility */ + (pictab[i].pos.x < picdelt.x + pictab[i].rad) && + (pictab[i].pos.y > - pictab[i].rad) && + (pictab[i].pos.y < picdelt.y + pictab[i].rad)) ? 1 : 0; + } + } + else { /* If disks not wanted */ + for (i = 0; i < grafptr->vertnbr; i ++) + pictab[i].vis = ((pictab[i].pos.x > 0.0L) && /* Compute vertex visibility */ + (pictab[i].pos.x < picdelt.x) && + (pictab[i].pos.y > 0.0L) && + (pictab[i].pos.y < picdelt.y)) ? 1 : 0; + } + for (i = 0; i < grafptr->vertnbr; i ++) { + pictab[i].pos.x += 0.5L; /* Prepare to switch to integer coordinates */ + pictab[i].pos.y += 0.5L; + } + picdelt.x += 0.5L; + picdelt.y += 0.5L; + + if (O_outParam.PosMesh.color == 'c') { /* If color output */ + for (i = 0; i < grafptr->vertnbr; i ++) /* Select color for all vertices */ + pictab[i].col = mapptr->labltab[i] % O_POSMESHCOLNBR; + } + else { /* If gray level output */ + for (i = 0; i < grafptr->vertnbr; i ++) { /* Select color for all vertices */ + for (j = mapptr->labltab[i] & 255, k = 7, pictab[i].col = 0; /* Half-tone color */ + j > 0; /* As long as there are subdivision bits */ + j >>= 1, k --) /* (Same as reversing the last 8 bits ) */ + pictab[i].col |= ((j & 1) << k); + } + } + + for (i = 0, j = 0; i < grafptr->vertnbr; i ++) { /* For all vertices */ + pattab[i].nbr = 0; /* Compute the number of output paths */ + pattab[i].idx = grafptr->verttab[i]; + for ( ; j < grafptr->vendtab[i]; j ++) { + if ((grafptr->edgetab[j] > i) && /* If it can be an output edge */ + ((pictab[i].vis | pictab[grafptr->edgetab[j]].vis) != 0) && /* And it is visible */ + ((O_outParam.PosMesh.edge != 'r') || /* And it can be drawn */ + (mapptr->labltab[i] == mapptr->labltab[grafptr->edgetab[j]]))) + pattab[i].nbr ++; /* One more path to higher vertices */ + } + } + idxnbr = 0; /* No indexes yet */ + for (i = 0; i < grafptr->vertnbr; ) { + if (pattab[i].nbr == 0) { /* If no output path */ + i ++; /* Skip to the next vertex */ + continue; + } + + j = i; /* Begin with this vertex */ + idxtab[idxnbr ++] = j; /* Add it to the current segment */ + do { + for (k = pattab[j].idx; k < grafptr->vendtab[j]; k ++) { /* Search for first output */ + if ((grafptr->edgetab[k] > j) && /* If it can be an output edge */ + ((pictab[j].vis | pictab[grafptr->edgetab[k]].vis) != 0) && /* And it is visible */ + ((O_outParam.InvMesh.edge != 'r') || /* And it can be drawn */ + (mapptr->labltab[j] == mapptr->labltab[grafptr->edgetab[k]]))) + break; + } + pattab[j].nbr --; /* One less output path remaining */ + pattab[j].idx = k + 1; /* Search from the next position */ + j = grafptr->edgetab[k]; /* Get the path end vertex number */ + idxtab[idxnbr ++] = j; /* Add it to the current segment */ + } while (pattab[j].nbr > 0); /* As long as there is a path */ + idxtab[idxnbr ++] = ~0; /* Mark end of path */ + } + + if (O_outParam.PosMesh.type == 'e') { /* EPSF-type output */ + fprintf (stream, "%%!PS-Adobe-2.0 EPSF-2.0\n"); + fprintf (stream, "%%%%Title: %s %s %s\n", + C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); + fprintf (stream, "%%%%Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); + fprintf (stream, "%%%%CreationDate: %s", ctime (&pictime)); + fprintf (stream, "%%%%BoundingBox: 0 0 %d %d\n", + (int) ((picdelt.x * O_PSDPI) / O_POSMESHPICTRESOL), + (int) ((picdelt.y * O_PSDPI) / O_POSMESHPICTRESOL)); + fprintf (stream, "%%%%Pages: 0\n"); + fprintf (stream, "%%%%EndComments\n"); + } + else { /* Full page output */ + fprintf (stream, "%%!PS-Adobe-2.0\n"); + fprintf (stream, "%%%%Title: %s %s %s\n", + C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); + fprintf (stream, "%%%%Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); + fprintf (stream, "%%%%CreationDate: %s", ctime (&pictime)); + } + + fprintf (stream, "/A { 0 360 arc fill } bind def\n"); /* Macro definitions */ + if (O_outParam.PosMesh.color == 'c') { /* If color output */ + for (i = 0; i < O_POSMESHCOLNBR; i ++) { /* Build color indexes */ + outColorColor (i, color); + fprintf (stream, "/C%c { %g %g %g setrgbcolor } bind def\n", + ('a' + i), color[0], color[1], color[2]); + } + } + fprintf (stream, "/G { 255 div setgray } bind def\n"); + fprintf (stream, "/L { lineto stroke } bind def\n"); + fprintf (stream, "/l { lineto } bind def\n"); + fprintf (stream, "/m { moveto } bind def\n"); + + fprintf (stream, "gsave\n"); /* Save the context */ + fprintf (stream, "1 setlinecap\n"); /* Perform round caps */ + if (O_outParam.PosMesh.type == 'f') /* If full page output */ + fprintf (stream, "%d %d translate\n", /* Center the picture */ + (int) ((O_PSDPI * (O_PSPAGEWIDTH * O_POSMESHPICTRESOL - picdelt.x)) / + (2 * O_POSMESHPICTRESOL)), + (int) ((O_PSDPI * (O_PSPAGEHEIGHT * O_POSMESHPICTRESOL - picdelt.y)) / + (2 * O_POSMESHPICTRESOL))); + fprintf (stream, "%f %f scale\n", /* Print scaling factor */ + (double) O_PSDPI / O_POSMESHPICTRESOL, + (double) O_PSDPI / O_POSMESHPICTRESOL); + fprintf (stream, "newpath 0 0 m %d 0 l %d %d l 0 %d l closepath clip\n", /* Clip picture */ + (int) picdelt.x, (int) picdelt.x, + (int) picdelt.y, (int) picdelt.y); + + fprintf (stream, "0 G\n"); /* Select black color */ + for (i = 0; i < idxnbr; i ++) { + fprintf (stream, "%d\t%d\tm\n", /* Set initial point */ + (int) pictab[idxtab[i]].pos.x, + (int) pictab[idxtab[i]].pos.y); + for (i ++; idxtab[i] != ~0; i ++ ) { /* Build path */ + fprintf (stream, "%d\t%d\t%c\n", + (int) pictab[idxtab[i]].pos.x, + (int) pictab[idxtab[i]].pos.y, + (idxtab[i + 1] == ~0) ? 'L' : 'l'); + } + } + + if (O_outParam.PosMesh.disk == 'd') { /* If disks wanted */ + for (i = 0, j = ~0; i < grafptr->vertnbr; i ++) { + if ((pictab[i].vis > 0) && /* If disk is visible */ + (mapptr->labltab[i] != (-1))) { /* And is mapped */ + if ((j == ~0) || (pictab[i].col != pictab[j].col)) { /* Update drawing color */ + if (O_outParam.PosMesh.color == 'c') + fprintf (stream, "C%c\n", 'a' + pictab[i].col); + else + fprintf (stream, "%u G\n", pictab[i].col); + j = i; /* Record the new current color */ + } + + fprintf (stream, "%d %d %d A\n", /* Draw the disk */ + (int) pictab[i].pos.x, + (int) pictab[i].pos.y, + (int) pictab[i].rad); + } + } + } + + fprintf (stream, "grestore\n"); /* Restore the context */ + if (O_outParam.PosMesh.type == 'f') /* If full page output */ + fprintf (stream, "showpage\n"); /* Display the page */ + + memFree (pattab); + memFree (idxtab); + memFree (pictab); + + return (0); +} + +/*************************************/ +/* */ +/* This is the Tulip output routine. */ +/* */ +/*************************************/ + +int +outDrawTulMesh ( +const C_Graph * const grafptr, /* Graph structure, sorted by vertex index */ +const C_Geometry * const geomptr, /* Graph geometry, sorted by vertex label */ +const C_Mapping * const mapptr, /* Result mapping, sorted by vertex label */ +FILE * const stream) /* Output stream */ +{ + time_t pictime; /* Creation time */ + char * pictimeptr; + char pictimestr[64]; + double color[3]; /* Vertex color */ + SCOTCH_Num vertnum; + const SCOTCH_Num * edgetax; + SCOTCH_Num edgeidx; + char c; + + if (geomptr->verttab == NULL) { + errorPrint ("outDrawInvMesh: geometry not provided"); + return (1); + } + + time (&pictime); /* Get current time */ + pictimeptr = ctime (&pictime); + strncpy (pictimestr, pictimeptr, 63); + pictimestr[63] = '\0'; + pictimestr[strlen (pictimestr) - 1] = '\0'; + + fprintf (stream, "(tlp \"2.0\"\n(author \"out (F. Pellegrini, LaBRI, Bordeaux)\")\n(date \"%s\")\n(comment \"%s %s %s\")\n", /* Write header */ + pictimestr, + C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); + + if (grafptr->vertnbr == 0) { /* If nothing to write */ + fprintf (stream, ")\n"); + return (0); + } + + fprintf (stream, "(nodes\n"); /* Write node list */ + for (vertnum = 0; vertnum < (grafptr->vertnbr - 1); vertnum ++) + fprintf (stream, SCOTCH_NUMSTRING "%c", + (SCOTCH_Num) (vertnum + grafptr->baseval), + ((vertnum & 7) == 7) ? '\n' : '\t'); + fprintf (stream, SCOTCH_NUMSTRING ")\n", + (SCOTCH_Num) (vertnum + grafptr->baseval)); + + edgetax = grafptr->edgetab - grafptr->baseval; + for (vertnum = 0, edgeidx = grafptr->baseval; vertnum < grafptr->vertnbr; vertnum ++) { + SCOTCH_Num edgenum; + SCOTCH_Num edgennd; + + for (edgenum = grafptr->verttab[vertnum], edgennd = grafptr->vendtab[vertnum]; + edgenum < edgennd; edgenum ++) { + SCOTCH_Num vertend; + + vertend = edgetax[edgenum]; + if (vertend <= vertnum) /* True even if baseval=1 and as vertnum unbased */ + continue; + + fprintf (stream, "(edge " SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING ")\n", + (SCOTCH_Num) (edgeidx ++), + (SCOTCH_Num) (vertnum + grafptr->baseval), + (SCOTCH_Num) vertend); + } + } + + fprintf (stream, "(property 0 layout \"viewLayout\"\n"); /* Write node coordinates */ + c = '\n'; + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { + if (vertnum == (grafptr->vertnbr - 1)) + c = ')'; + fprintf (stream, "(node " SCOTCH_NUMSTRING "\t\"(%lf,%lf,%lf)\")%c", + (SCOTCH_Num) (vertnum + grafptr->baseval), + (double) geomptr->verttab[vertnum].x, + (double) geomptr->verttab[vertnum].y, + (double) geomptr->verttab[vertnum].z, + c); + } + fprintf (stream, "\n"); + + if (O_outParam.TulMesh.color == 'c') { + fprintf (stream, "(property 0 color \"viewColor\"\n(default \"(255,255,255,255)\" \"(0,0,0,0)\")\n"); /* Write node color values */ + c = '\n'; + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { + if (vertnum == (grafptr->vertnbr - 1)) + c = ')'; + outColorColor (mapptr->labltab[vertnum], color); + fprintf (stream, "(node " SCOTCH_NUMSTRING " \"(%d,%d,%d,255)\")%c", + (SCOTCH_Num) (vertnum + grafptr->baseval), + (int) (color[0] * 255.0), + (int) (color[1] * 255.0), + (int) (color[2] * 255.0), + c); + } + fprintf (stream, "\n"); + } + + fprintf (stream, "(property 0 size \"viewSize\"\n(default \"(0,0,0)\" \"(0,0,0)\")"); /* Write default node size */ + if (O_outParam.TulMesh.disk == 'd') { /* If disks wanted */ + const C_GeoVert * geomtax; + + geomtax = geomptr->verttab - grafptr->baseval; + fprintf (stream, "\n"); + c = '\n'; + for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { + SCOTCH_Num edgenum; + SCOTCH_Num edgennd; + double distmin; + C_GeoVert vertpos; + + if (vertnum == (grafptr->vertnbr - 1)) + c = ')'; + + distmin = 1e30; /* Huge distance assumed */ + vertpos.x = geomptr->verttab[vertnum].x; + vertpos.y = geomptr->verttab[vertnum].y; + vertpos.z = geomptr->verttab[vertnum].z; + for (edgenum = grafptr->verttab[vertnum], edgennd = grafptr->vendtab[vertnum]; + edgenum < edgennd; edgenum ++) { + SCOTCH_Num vertend; + double distval; + + vertend = edgetax[edgenum]; + distval = (geomtax[vertend].x - vertpos.x) * (geomtax[vertend].x - vertpos.x) + + (geomtax[vertend].y - vertpos.y) * (geomtax[vertend].y - vertpos.y) + + (geomtax[vertend].z - vertpos.z) * (geomtax[vertend].z - vertpos.z); + if (distval < distmin) + distmin = distval; + } + distmin = sqrt (distmin) * (0.5 * O_TULMESHDISKRATIO); + fprintf (stream, "(node " SCOTCH_NUMSTRING " \"(%lf,%lf,%lf)\")%c", + (SCOTCH_Num) (vertnum + grafptr->baseval), + distmin, distmin, distmin, c); + } + fprintf (stream, "\n"); + } + else + fprintf (stream, ")\n"); + + fprintf (stream, ")\n"); + + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gout_o.h b/scotch_6.0.3/src/scotch/gout_o.h new file mode 100644 index 00000000..ce1f3939 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gout_o.h @@ -0,0 +1,167 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gout_o.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a result viewer. **/ +/** This module contains the data declara- **/ +/** tions for the output module. **/ +/** **/ +/** DATES : # Version 2.0 : from : 08 oct 1994 **/ +/** to 02 nov 1994 **/ +/** # Version 3.0 : from : 14 jul 1995 **/ +/** to 03 oct 1995 **/ +/** # Version 3.1 : from : 05 apr 1996 **/ +/** to 05 apr 1996 **/ +/** # Version 3.2 : from : 03 dec 1996 **/ +/** to 05 jun 1998 **/ +/** # Version 3.3 : from : 02 jun 1999 **/ +/** to 02 jun 1999 **/ +/** # Version 5.0 : from : 25 may 2007 **/ +/** to 25 may 2007 **/ +/** # Version 5.1 : from : 25 oct 2007 **/ +/** to 26 oct 2007 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ Generic PostScript output definitions. +*/ + +#define O_PSDPI 72 /* PostScript dots-per-inch */ +#define O_PSPAGEHEIGHT 11.6 /* PostScript page height (in inches) */ +#define O_PSPAGEWIDTH 8.2 /* PostScript page witdh (in inches) */ +#define O_PSPICTHEIGHT 10.0 /* PostScript picture height (in inches) */ +#define O_PSPICTWIDTH 6.6 /* PostScript picture witdh (in inches) */ + +/*+ PostScript mesh output definitions. +*/ + +#define O_POSMESHPICTRESOL 10000.0 /* Picture resolution */ + +#define O_POSMESHISOCOS 0.866025404 /* cos(30 degrees) */ +#define O_POSMESHISOSIN 0.5 /* sin(30 degrees) */ +#define O_POSMESHISOREDUC 0.20 /* Z-axis reduction coefficient */ + +#define O_POSMESHCOLNBR 16 /* Number of colors */ + +/*+ Tulip graph output definitions. +*/ + +#define O_TULMESHDISKRATIO 0.1 /* Node disk ratio */ + +/* +** The type and structure definitions. +*/ + +/*+ The 2D point type. +*/ + +typedef struct O_Point_ { + double c[2]; /*+ Page coordinates +*/ +} O_Point; + +/*+ The output type type. +*/ + +typedef enum O_OutType_ { + O_OUTTYPEINVMESH, /*+ Mesh SGI Open Inventor (3D) +*/ + O_OUTTYPEPOSMATR, /*+ Matrix PostScript (2D) +*/ + O_OUTTYPEPOSMESH, /*+ Mesh PostScript (2D) +*/ + O_OUTTYPETULMESH, /*+ Mesh Tulip (3D) +*/ + O_OUTTYPENBR /*+ Number of output types +*/ +} O_OutType; + +/*+ The output parameter data structure. +*/ + +typedef struct O_OutParam_ { + O_OutType type; /*+ Output type +*/ + struct { /*+ Inventor mesh structure +*/ + char color; /*+ 'c' : color; 'g' : gray +*/ + char edge; /*+ 'r' : remove; 'v' : view +*/ + } InvMesh; + struct { /*+ PostScript matrix structure +*/ + char type; /*+ 'f' : page; 'e' : EPSF +*/ + } PosMatr; + struct { /*+ PostScript mesh structure +*/ + char type; /*+ 'f' : page; 'e' : EPSF +*/ + char color; /*+ 'c' : color; 'g' : gray +*/ + char edge; /*+ 'r' : remove; 'v' : view +*/ + char disk; /*+ 'd' : draw; 'a' : avoid +*/ + char clip; /*+ 'l' : large; 's' : short +*/ + O_Point min; /*+ Clipping ratios +*/ + O_Point max; + } PosMesh; + struct { /*+ Tulip graph structure +*/ + char color; /*+ 'b' : b/w; 'c' : color +*/ + char edge; /*+ 'r' : remove; 'v' : view +*/ + char disk; /*+ 'd' : draw; 'a' : avoid +*/ + } TulMesh; +} O_OutParam; + +/*+ The Inventor path array element. +*/ + +typedef struct O_InvMeshPath_ { + SCOTCH_Num nbr; /*+ Number of output paths +*/ + SCOTCH_Num idx; /*+ Index from which to search +*/ +} O_InvMeshPath; + +/*+ The PostScript path array element. +*/ + +typedef struct O_PosMeshPath_ { + SCOTCH_Num nbr; /*+ Number of output paths +*/ + SCOTCH_Num idx; /*+ Index from which to search +*/ +} O_PosMeshPath; + +/*+ The PostScript mesh graph vertex. +*/ + +typedef struct O_PosMeshVertex_ { + int vis; /*+ Visibility flag +*/ + O_Point pos; /*+ Point position +*/ + double rad; /*+ Disk radius +*/ + int col; /*+ Disk color index +*/ +} O_PosMeshVertex; + +/* +** The function prototypes. +*/ + +void outColorBlw (const SCOTCH_Num, double[]); +void outColorColor (const SCOTCH_Num, double[]); + +int outDrawParse (char * const); +void outDraw (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); +int outDrawInvMesh (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); +int outDrawPosMatr (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); +int outDrawPosMesh (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); +int outDrawTulMesh (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); diff --git a/scotch_6.0.3/src/scotch/gscat.c b/scotch_6.0.3/src/scotch/gscat.c new file mode 100644 index 00000000..b56eae74 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gscat.c @@ -0,0 +1,290 @@ +/* Copyright 2009-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gscat.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program writes a centralized **/ +/** source graph file in the form of a **/ +/** distributed source graph. **/ +/** **/ +/** DATES : # Version 5.1 : from : 26 apr 2009 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GSCAT + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gscat.h" + +/* +** The static variables. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { /* Usage */ + "gscat ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num p[1] = { 1 }; /* Number of parts */ + int i; + + errorProg ("gscat"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 1) { /* If number of parameters not reached */ + if ((p[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get number of parts */ + errorPrint ("main: invalid number of parts '%s'", argv[i]); + return (1); + } + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "gscat, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2009-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, 1); /* Open input graph file */ + + C_graphScat (C_filepntrsrcinp, p[0], C_filenamesrcout); + + fileBlockClose (C_fileTab, 1); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} + +static +int +C_graphScat ( +FILE * const stream, +SCOTCH_Num procnbr, +char * const nameptr) +{ + SCOTCH_Num versval; + SCOTCH_Num propval; + char proptab[4]; + int flagtab[3]; + SCOTCH_Num baseval; + SCOTCH_Num vertglbnbr; + SCOTCH_Num edgeglbnbr; + SCOTCH_Num procnum; + + if (intLoad (stream, &versval) != 1) { /* Read version number */ + errorPrint ("C_graphScat: bad input (1)"); + return (1); + } + if (versval != 0) { /* If version not zero */ + errorPrint ("C_graphScat: only centralized graphs supported"); + return (1); + } + + if ((intLoad (stream, &vertglbnbr) != 1) || /* Read rest of header */ + (intLoad (stream, &edgeglbnbr) != 1) || + (intLoad (stream, &baseval) != 1) || + (intLoad (stream, &propval) != 1) || + (propval < 0) || + (propval > 111)) { + errorPrint ("C_graphScat: bad input (2)"); + return (1); + } + sprintf (proptab, "%3.3d", (int) propval); /* Compute file properties */ + flagtab[0] = proptab[0] - '0'; /* Vertex labels flag */ + flagtab[1] = proptab[1] - '0'; /* Edge weights flag */ + flagtab[2] = proptab[2] - '0'; /* Vertex loads flag */ + + for (procnum = 0; procnum < procnbr; procnum ++) { + char * nametmp; + FILE * ostream; + SCOTCH_Num vertlocnbr; + SCOTCH_Num vertlocnum; + SCOTCH_Num edgelocnbr; + + nametmp = nameptr; + if ((fileNameDistExpand (&nametmp, procnbr, procnum, -1) != 0) || + ((ostream = fopen (nametmp, "w+")) == NULL)) { + errorPrint ("C_graphScat: cannot open file"); + return (1); + } + memFree (nametmp); /* Expanded name no longer needed */ + + vertlocnbr = DATASIZE (vertglbnbr, procnbr, procnum); + + if (fprintf (ostream, "2\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t%015d\n" SCOTCH_NUMSTRING "\t%3s\n", /* Write file header */ + (SCOTCH_Num) procnbr, + (SCOTCH_Num) procnum, + (SCOTCH_Num) vertglbnbr, + (SCOTCH_Num) edgeglbnbr, + (SCOTCH_Num) vertlocnbr, + 0, /* Number of edges not yet known */ + (SCOTCH_Num) baseval, + proptab) == EOF) { + errorPrint ("C_graphScat: bad output (1)"); + return (1); + } + + for (vertlocnum = edgelocnbr = 0; vertlocnum < vertlocnbr; vertlocnum ++) { + SCOTCH_Num degrval; + + if (flagtab[0] != 0) { /* If must read label */ + SCOTCH_Num vlblval; /* Value where to read vertex label */ + + if (intLoad (stream, &vlblval) != 1) { /* Read label data */ + errorPrint ("C_graphScat: bad input (3)"); + return (1); + } + intSave (ostream, vlblval); + putc ('\t', ostream); + } + if (flagtab[2] != 0) { /* If must read vertex load */ + SCOTCH_Num veloval; /* Value where to read vertex load */ + + if (intLoad (stream, &veloval) != 1) { /* Read vertex load data */ + errorPrint ("C_graphScat: bad input (4)"); + return (1); + } + intSave (ostream, veloval); + putc ('\t', ostream); + } + if (intLoad (stream, °rval) != 1) { /* Read vertex degree */ + errorPrint ("C_graphScat: bad input (5)"); + return (1); + } + intSave (ostream, degrval); + + edgelocnbr += degrval; + + for ( ; degrval > 0; degrval --) { + SCOTCH_Num edgeval; /* Value where to read edge end */ + + if (flagtab[1] != 0) { /* If must read edge load */ + SCOTCH_Num edloval; /* Value where to read edge load */ + + if (intLoad (stream, &edloval) != 1) { /* Read edge load data */ + errorPrint ("C_graphScat: bad input (6)"); + return (1); + } + putc ('\t', ostream); + intSave (ostream, edloval); + } + + if (intLoad (stream, &edgeval) != 1) { /* Read edge data */ + errorPrint ("C_graphScat: bad input (7)"); + return (1); + } + putc ('\t', ostream); + intSave (ostream, edgeval); + } + putc ('\n', ostream); + } + + rewind (ostream); + + if (fprintf (ostream, "2\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t%015lld\n" SCOTCH_NUMSTRING "\t%3s\n", /* Write file header */ + (SCOTCH_Num) procnbr, + (SCOTCH_Num) procnum, + (SCOTCH_Num) vertglbnbr, + (SCOTCH_Num) edgeglbnbr, + (SCOTCH_Num) vertlocnbr, + (long long) edgelocnbr, /* Now we know the exact number of edges */ + (SCOTCH_Num) baseval, + proptab) == EOF) { + errorPrint ("C_graphScat: bad output (2)"); + return (1); + } + + fclose (ostream); + } + + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gscat.h b/scotch_6.0.3/src/scotch/gscat.h new file mode 100644 index 00000000..61c0262f --- /dev/null +++ b/scotch_6.0.3/src/scotch/gscat.h @@ -0,0 +1,66 @@ +/* Copyright 2009 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gscat.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the sequential graph scatter- **/ +/** ing program. **/ +/** **/ +/** DATES : # Version 5.1 : from : 26 apr 2009 **/ +/** to : 26 apr 2009 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Centralized source graph input file name */ +#define C_filenamesrcout C_fileTab[1].name /* Distributed source graph output file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Centralized source graph input file */ +#define C_filepntrsrcout C_fileTab[1].pntr /* Distributed source graph output file */ + +/* +** The function prototypes. +*/ + +static int C_graphScat (FILE * const, SCOTCH_Num, char * const); diff --git a/scotch_6.0.3/src/scotch/gtst.c b/scotch_6.0.3/src/scotch/gtst.c new file mode 100644 index 00000000..e9a1af26 --- /dev/null +++ b/scotch_6.0.3/src/scotch/gtst.c @@ -0,0 +1,186 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gtst.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program gives statistics on source **/ +/** graphs. **/ +/** **/ +/** DATES : # Version 2.0 : from : 31 oct 1994 **/ +/** to 03 nov 1994 **/ +/** # Version 3.0 : from : 15 sep 1995 **/ +/** to 19 sep 1995 **/ +/** # Version 3.2 : from : 03 jun 1997 **/ +/** to : 25 may 1998 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to : 19 oct 1998 **/ +/** # Version 3.4 : from : 10 oct 1999 **/ +/** to 12 oct 1999 **/ +/** # Version 4.0 : from : 10 sep 2003 **/ +/** to : 10 sep 2003 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define GTST + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "gtst.h" + +/* +** The static definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "gtst [ []] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Graph grafdat; /* Source graph */ + SCOTCH_Num vertnbr; + SCOTCH_Num velomin; + SCOTCH_Num velomax; + SCOTCH_Num velosum; + double veloavg; + double velodlt; + SCOTCH_Num degrmin; + SCOTCH_Num degrmax; + double degravg; + double degrdlt; + SCOTCH_Num edgenbr; + SCOTCH_Num edlomin; + SCOTCH_Num edlomax; + SCOTCH_Num edlosum; + double edloavg; + double edlodlt; + int i; + + errorProg ("gtst"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + exit (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + exit (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + exit (0); + case 'V' : + fprintf (stderr, "gtst, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + exit (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_graphInit (&grafdat); + SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, 0); + SCOTCH_graphCheck (&grafdat); + + SCOTCH_graphSize (&grafdat, &vertnbr, &edgenbr); + SCOTCH_graphStat (&grafdat, &velomin, &velomax, &velosum, &veloavg, &velodlt, + °rmin, °rmax, °ravg, °rdlt, + &edlomin, &edlomax, &edlosum, &edloavg, &edlodlt); + + if (C_filepntrdatout != NULL) { + fprintf (C_filepntrdatout, "S\tVertex\tnbr=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) vertnbr); + fprintf (C_filepntrdatout, "S\tVertex load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) velomin, (SCOTCH_Num) velomax, (SCOTCH_Num) velosum, veloavg, velodlt); + fprintf (C_filepntrdatout, "S\tVertex degree\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) degrmin, (SCOTCH_Num) degrmax, (SCOTCH_Num) edgenbr, degravg, degrdlt); + fprintf (C_filepntrdatout, "S\tEdge\tnbr=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) (edgenbr / 2)); + fprintf (C_filepntrdatout, "S\tEdge load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) edlomin, (SCOTCH_Num) edlomax, (SCOTCH_Num) edlosum, edloavg, edlodlt); + } + + SCOTCH_graphExit (&grafdat); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/gtst.h b/scotch_6.0.3/src/scotch/gtst.h new file mode 100644 index 00000000..873e904a --- /dev/null +++ b/scotch_6.0.3/src/scotch/gtst.h @@ -0,0 +1,65 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : gtst.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the declarations **/ +/** for the source graph analyzer. **/ +/** **/ +/** DATES : # Version 2.0 : from : 31 oct 1993 **/ +/** to 31 oct 1993 **/ +/** # Version 3.2 : from : 03 jun 1997 **/ +/** to : 03 jun 1997 **/ +/** # Version 3.3 : from : 19 oct 1998 **/ +/** to : 19 oct 1998 **/ +/** # Version 4.0 : from : 10 sep 2003 **/ +/** to : 10 sep 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** File name aliases. **/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenamedatout C_fileTab[1].name /* Statistics output file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrdatout C_fileTab[1].pntr /* Statistics output file */ diff --git a/scotch_6.0.3/src/scotch/mcv.c b/scotch_6.0.3/src/scotch/mcv.c new file mode 100644 index 00000000..468556dc --- /dev/null +++ b/scotch_6.0.3/src/scotch/mcv.c @@ -0,0 +1,203 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mcv.c **/ +/** **/ +/** AUTHORS : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a mesh file converter. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 jan 2004 **/ +/** to : 19 jan 2004 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MCV + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "mcv.h" + +/* +** The static and global variables. +*/ + +static int C_inpFormatType = 0; /* Input mesh format */ +static char * C_inpFormatData = "\0"; /* Pointer to auxiliary data */ +static const C_Format C_inpFormatTab[] = { /* Table of input formats */ + { 'B', SCOTCH_meshGeomLoadHabo }, + { 'b', SCOTCH_meshGeomLoadHabo }, + { 'S', SCOTCH_meshGeomLoadScot }, + { 's', SCOTCH_meshGeomLoadScot }, + { '\0', NULL } }; + +static int C_outFormatType = 0; /* Output mesh format */ +static char * C_outFormatData = "\0"; /* Pointer to auxiliary data */ +static C_Format C_outFormatTab[] = { /* Table of output formats */ + { 'S', SCOTCH_meshGeomSaveScot }, + { 's', SCOTCH_meshGeomSaveScot }, + { '\0', NULL } }; + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[3] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "mcv [ [ []]] ", + " -h : Display this help", + " -i : Select input file format", + " b : Boeing-Harwell format (elemental)", + " s : Scotch format", + " -o : Select output file format", + " s : Scotch format", + " -V : Print program version and copyright", + "", + "Default option set is : '-Ib -Os'", + NULL }; + +/*****************************/ +/* */ +/* This is the main function */ +/* */ +/*****************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Mesh meshdat; + SCOTCH_Geom geomdat; + int i, j; + + errorProg ("mcv"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give help */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'I' : /* Select input file type */ + case 'i' : + for (j = 0; C_inpFormatTab[j].code != '\0'; j ++) { /* Find proper format code */ + if (C_inpFormatTab[j].code == argv[i][2]) { + C_inpFormatType = j; + C_inpFormatData = &argv[i][3]; + break; + } + } + if (C_inpFormatTab[j].code == '\0') { + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + break; + case 'O' : /* Select input file type */ + case 'o' : + for (j = 0; C_outFormatTab[j].code != '\0'; j ++) { /* Find proper format code */ + if (C_outFormatTab[j].code == argv[i][2]) { + C_outFormatType = j; + C_outFormatData = &argv[i][3]; + break; + } + } + if (C_inpFormatTab[j].code == '\0') { + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + break; + case 'V' : + fprintf (stderr, "mcv, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_meshInit (&meshdat); + SCOTCH_geomInit (&geomdat); + C_inpFormatTab[C_inpFormatType].func (&meshdat, &geomdat, C_filepntrsrcinp, NULL, C_inpFormatData); +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_meshCheck (&meshdat) != 0) { + errorPrint ("main: bad graph structure"); + return (1); + } +#endif /* SCOTCH_DEBUG_ALL */ + C_outFormatTab[C_outFormatType].func (&meshdat, &geomdat, C_filepntrsrcout, C_filepntrgeoout, C_outFormatData); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_geomExit (&geomdat); + SCOTCH_meshExit (&meshdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/mcv.h b/scotch_6.0.3/src/scotch/mcv.h new file mode 100644 index 00000000..d2c13362 --- /dev/null +++ b/scotch_6.0.3/src/scotch/mcv.h @@ -0,0 +1,73 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mcv.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a mesh file converter. **/ +/** This module contains the data declara- **/ +/** tions for the main module. **/ +/** **/ +/** DATES : # Version 4.0 : from : 19 jan 2004 **/ +/** to : 19 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 3 /* Number of files in list */ +#define C_FILEARGNBR 3 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* External mesh input file name */ +#define C_filenamesrcout C_fileTab[1].name /* Source mesh output file name */ +#define C_filenamegeoout C_fileTab[2].name /* Source mesh geometry file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* External mesh input file */ +#define C_filepntrsrcout C_fileTab[1].pntr /* Source mesh output file */ +#define C_filepntrgeoout C_fileTab[2].pntr /* Source mesh geometry file */ + +/* +** The type and structure definitions. +*/ + +/*+ This structure defines the method array element. +*/ + +typedef struct C_Format_ { + char code; /* Format type code */ + int (* func) (); /* Function to call */ +} C_Format; diff --git a/scotch_6.0.3/src/scotch/mmk_m2.c b/scotch_6.0.3/src/scotch/mmk_m2.c new file mode 100644 index 00000000..4286d22e --- /dev/null +++ b/scotch_6.0.3/src/scotch/mmk_m2.c @@ -0,0 +1,230 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mmk_m2.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates source meshes for tridimen- **/ +/** sional finite element grids. **/ +/** **/ +/** DATES : # Version 4.0 : from : 26 sep 2002 **/ +/** to : 06 feb 2003 **/ +/** # Version 5.0 : from : 13 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/** NOTES : # The nodes and elements of the **/ +/** (dX,dY) mesh are numbered so that **/ +/** t(0,0) = 0, t(1,0) = 1, **/ +/** t(dX - 1, 0) = dX - 1, t(0,1) = **/ +/** dX, and t(x,y) = y * dX + x. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MMK_M2 + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "mmk_m2.h" + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const int C_nghbTab[3] = { 4, 2, 1 }; + +static const char * C_usageList[] = { + "mmk_m2 [ []] ", + " -g : Output mesh geometry to ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/****************************************/ +/* */ +/* The main routine, which computes the */ +/* source mesh description. */ +/* */ +/****************************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num e[2] = { 1, 1 }; /* Mesh element dimensions */ + SCOTCH_Num n[2]; /* Mesh node dimensions */ + SCOTCH_Num c[2]; /* Vertex coordinates */ + SCOTCH_Num velmnbr; /* First node number */ + int flagval; /* Process flags */ + int i; + + errorProg ("mmk_m2"); + + flagval = C_FLAGDEFAULT; /* Set default flags */ + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 2) { /* If number of parameters not reached */ + if ((e[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'G' : /* Output mesh geometry */ + case 'g' : + flagval |= C_FLAGGEOOUT; + if (argv[i][2] != '\0') + C_filenamegeoout = &argv[i][2]; + break; + case 'H' : /* Give program usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "mmk_m2, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + n[0] = e[0] + 1; + n[1] = e[1] + 1; + velmnbr = e[0] * e[1]; + + fprintf (C_filepntrmshout, "1\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n0\t" SCOTCH_NUMSTRING "\t000\n", /* Print mesh file header */ + (SCOTCH_Num) velmnbr, + (SCOTCH_Num) (n[0] * n[1]), + (SCOTCH_Num) (((velmnbr + n[0] * n[1]) - (e[0] + e[1] + 1)) * 4), + (SCOTCH_Num) velmnbr); + + for (c[1] = 0; c[1] < e[1]; c[1] ++) { /* Output element neighbor list */ + for (c[0] = 0; c[0] < e[0]; c[0] ++) { + fprintf (C_filepntrmshout, "4\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Output neighbors of element */ + (SCOTCH_Num) (c[1] * n[0] + c[0]), + (SCOTCH_Num) (c[1] * n[0] + c[0] + 1), + (SCOTCH_Num) ((c[1] + 1) * n[0] + c[0]), + (SCOTCH_Num) ((c[1] + 1) * n[0] + c[0] + 1)); + } + } + for (c[1] = 0; c[1] < n[1]; c[1] ++) { /* Output node neighbor list */ + for (c[0] = 0; c[0] < n[0]; c[0] ++) { + fprintf (C_filepntrmshout, "%d", /* Output number of neighboring elements */ + C_nghbTab[(((c[0] != 0) && (c[0] != e[0])) ? 0 : 1) + + (((c[1] != 0) && (c[1] != e[1])) ? 0 : 1)]); + if (c[1] != 0) { /* Output neighbors of nodes */ + if (c[0] != 0) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[1] - 1) * e[0] + (c[0] - 1))); + if (c[0] != e[0]) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[1] - 1) * e[0] + c[0])); + } + if (c[1] != e[1]) { + if (c[0] != 0) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (c[1] * e[0] + (c[0] - 1))); + if (c[0] != e[0]) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (c[1] * e[0] + c[0])); + } + fprintf (C_filepntrmshout, "\n"); + } + } + + if (flagval & C_FLAGGEOOUT) { /* If geometry is wanted */ + fprintf (C_filepntrgeoout, "2\n" SCOTCH_NUMSTRING "\n", /* Output geometry file header */ + (SCOTCH_Num) (velmnbr + n[0] * n[1])); + + for (c[1] = 0; c[1] < e[1]; c[1] ++) { /* Output element coordinates */ + for (c[0] = 0; c[0] < e[0]; c[0] ++) + fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING ".5\t" SCOTCH_NUMSTRING ".5\n", + (SCOTCH_Num) (c[1] * e[0] + c[0]), + (SCOTCH_Num) c[0], + (SCOTCH_Num) (e[1] - 1 - c[1])); + } + for (c[1] = 0; c[1] < n[1]; c[1] ++) { /* Output node coordinates */ + for (c[0] = 0; c[0] < n[0]; c[0] ++) + fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) (velmnbr + c[1] * n[0] + c[0]), + (SCOTCH_Num) c[0], + (SCOTCH_Num) (e[1] - c[1])); + } + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/mmk_m2.h b/scotch_6.0.3/src/scotch/mmk_m2.h new file mode 100644 index 00000000..747de9ca --- /dev/null +++ b/scotch_6.0.3/src/scotch/mmk_m2.h @@ -0,0 +1,66 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mmk_m2.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the bidimensional finite **/ +/** element grid mesh building program. **/ +/** **/ +/** DATES : # Version 4.0 : from : 26 sep 2002 **/ +/** to : 26 sep 2002 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenamemshout C_fileTab[0].name /* Source mesh output file name */ +#define C_filenamegeoout C_fileTab[1].name /* Geometry mesh output file name */ + +#define C_filepntrmshout C_fileTab[0].pntr /* Source mesh output file */ +#define C_filepntrgeoout C_fileTab[1].pntr /* Geometry mesh output file */ + +/*+ Process flags. +*/ + +#define C_FLAGGEOOUT 0x0001 /* Output mesh geometry */ + +#define C_FLAGDEFAULT 0x0000 /* Default flags */ diff --git a/scotch_6.0.3/src/scotch/mmk_m3.c b/scotch_6.0.3/src/scotch/mmk_m3.c new file mode 100644 index 00000000..90cb4ab3 --- /dev/null +++ b/scotch_6.0.3/src/scotch/mmk_m3.c @@ -0,0 +1,268 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mmk_m3.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Creates the source meshes for **/ +/** tridimensional mesh source graphs. **/ +/** **/ +/** DATES : # Version 4.0 : from : 26 sep 2002 **/ +/** to : 17 feb 2004 **/ +/** # Version 5.0 : from : 13 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/** NOTES : # The nodes and elements of the **/ +/** (dX,dY,dZ) mesh are numbered so that **/ +/** t(0,0,0) = 0, t(1,0,0) = 1, **/ +/** t(dX - 1, 0, 0) = dX - 1, t(0,1,0) = **/ +/** dX, t (0, 0, 1) = dX * dY - 1, **/ +/** and t(x,y,z) = (z * dY + y) * dX + x. **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MMK_M3 + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "mmk_m3.h" + +/* +** The static definitions. +*/ + +static int C_paraNum = 0; /* Number of parameters */ +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const int C_nghbTab[4] = { 8, 4, 2, 1 }; + +static const char * C_usageList[] = { + "mmk_m3 [ [ []]] ", + " -g : Output mesh geometry to ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/****************************************/ +/* */ +/* The main routine, which computes the */ +/* source graph description. */ +/* */ +/****************************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num e[3] = { 1, 1, 1 }; /* Mesh element dimensions */ + SCOTCH_Num n[3]; /* Mesh node dimensions */ + SCOTCH_Num c[3]; /* Vertex coordinates */ + SCOTCH_Num velmnbr; /* First node number */ + int flagval; /* Process flags */ + int i; + + errorProg ("mmk_m3"); + + flagval = C_FLAGDEFAULT; /* Set default flags */ + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_paraNum < 3) { /* If number of parameters not reached */ + if ((e[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ + errorPrint ("main: invalid dimension '%s'", argv[i]); + return (1); + } + continue; /* Process the other parameters */ + } + if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'G' : /* Output mesh geometry */ + case 'g' : + flagval |= C_FLAGGEOOUT; + if (argv[i][2] != '\0') + C_filenamegeoout = &argv[i][2]; + break; + case 'H' : /* Give program usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'V' : + fprintf (stderr, "mmk_m3, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + n[0] = e[0] + 1; + n[1] = e[1] + 1; + n[2] = e[2] + 1; + velmnbr = e[0] * e[1] * e[2]; + + fprintf (C_filepntrmshout, "1\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n0\t" SCOTCH_NUMSTRING "\t000\n", /* Print mesh file header */ + (SCOTCH_Num) velmnbr, + (SCOTCH_Num) (n[0] * n[1] * n[2]), + (SCOTCH_Num) ((velmnbr + (n[0] * n[1] * n[2]) - + (n[0] * n[1] + n[0] * n[2] + n[1] * n[2]) + + n[0] + n[1] + n[2] - 1) * 8), + (SCOTCH_Num) velmnbr); + + for (c[2] = 0; c[2] < e[2]; c[2] ++) { /* Output element neighbor list */ + for (c[1] = 0; c[1] < e[1]; c[1] ++) { + for (c[0] = 0; c[0] < e[0]; c[0] ++) + fprintf (C_filepntrmshout, "8\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Output neighbors of element */ + (SCOTCH_Num) ((c[2] * n[1] + c[1]) * n[0] + c[0]), + (SCOTCH_Num) ((c[2] * n[1] + c[1]) * n[0] + (c[0] + 1)), + (SCOTCH_Num) ((c[2] * n[1] + (c[1] + 1)) * n[0] + c[0]), + (SCOTCH_Num) ((c[2] * n[1] + (c[1] + 1)) * n[0] + (c[0] + 1)), + (SCOTCH_Num) (((c[2] + 1) * n[1] + c[1]) * n[0] + c[0]), + (SCOTCH_Num) (((c[2] + 1) * n[1] + c[1]) * n[0] + (c[0] + 1)), + (SCOTCH_Num) (((c[2] + 1) * n[1] + (c[1] + 1)) * n[0] + c[0]), + (SCOTCH_Num) (((c[2] + 1) * n[1] + (c[1] + 1)) * n[0] + (c[0] + 1))); + } + } + for (c[2] = 0; c[2] < n[2]; c[2] ++) { /* Output node neighbor list */ + for (c[1] = 0; c[1] < n[1]; c[1] ++) { + for (c[0] = 0; c[0] < n[0]; c[0] ++) { + fprintf (C_filepntrmshout, "%d", /* Output number of neighboring elements */ + C_nghbTab[(((c[0] != 0) && (c[0] != e[0])) ? 0 : 1) + + (((c[1] != 0) && (c[1] != e[1])) ? 0 : 1) + + (((c[2] != 0) && (c[2] != e[2])) ? 0 : 1)]); + if (c[2] != 0) { /* Output neighbors of nodes */ + if (c[1] != 0) { + if (c[0] != 0) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (((c[2] - 1) * e[1] + (c[1] - 1)) * e[0] + (c[0] - 1))); + if (c[0] != e[0]) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (((c[2] - 1) * e[1] + (c[1] - 1)) * e[0] + c[0])); + } + if (c[1] != e[1]) { + if (c[0] != 0) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (((c[2] - 1) * e[1] + c[1]) * e[0] + (c[0] - 1))); + if (c[0] != e[0]) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) (((c[2] - 1) * e[1] + c[1]) * e[0] + c[0])); + } + } + if (c[2] != e[2]) { + if (c[1] != 0) { + if (c[0] != 0) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * e[1] + (c[1] - 1)) * e[0] + (c[0] - 1))); + if (c[0] != e[0]) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * e[1] + (c[1] - 1)) * e[0] + c[0])); + } + if (c[1] != e[1]) { + if (c[0] != 0) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * e[1] + c[1]) * e[0] + (c[0] - 1))); + if (c[0] != e[0]) + fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, + (SCOTCH_Num) ((c[2] * e[1] + c[1]) * e[0] + c[0])); + } + } + fprintf (C_filepntrmshout, "\n"); + } + } + } + + if (flagval & C_FLAGGEOOUT) { /* If geometry is wanted */ + fprintf (C_filepntrgeoout, "3\n" SCOTCH_NUMSTRING "\n", /* Output geometry file header */ + (SCOTCH_Num) (velmnbr + n[0] * n[1] * n[2])); + + for (c[2] = 0; c[2] < e[2]; c[2] ++) { /* Output element coordinates */ + for (c[1] = 0; c[1] < e[1]; c[1] ++) { + for (c[0] = 0; c[0] < e[0]; c[0] ++) + fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING ".5\t" SCOTCH_NUMSTRING ".5\t" SCOTCH_NUMSTRING ".5\n", + (SCOTCH_Num) (((c[2] * e[1]) + c[1]) * e[0] + c[0]), + (SCOTCH_Num) c[0], + (SCOTCH_Num) (e[1] - 1 - c[1]), + (SCOTCH_Num) c[2]); + } + } + for (c[2] = 0; c[2] <= e[2]; c[2] ++) { /* Output node coordinates */ + for (c[1] = 0; c[1] <= e[1]; c[1] ++) { + for (c[0] = 0; c[0] <= e[0]; c[0] ++) + fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) (velmnbr + ((c[2] * n[1]) + c[1]) * n[0] + c[0]), + (SCOTCH_Num) c[0], + (SCOTCH_Num) (e[1] - c[1]), + (SCOTCH_Num) c[2]); + } + } + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/mmk_m3.h b/scotch_6.0.3/src/scotch/mmk_m3.h new file mode 100644 index 00000000..d4a6ef41 --- /dev/null +++ b/scotch_6.0.3/src/scotch/mmk_m3.h @@ -0,0 +1,66 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mmk_m3.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the data declara- **/ +/** tions for the tridimensional finite **/ +/** element grid mesh building program. **/ +/** **/ +/** DATES : # Version 4.0 : from : 26 sep 2002 **/ +/** to : 26 sep 2002 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 1 /* Number of files which can be arguments */ + +#define C_filenamemshout C_fileTab[0].name /* Source mesh output file name */ +#define C_filenamegeoout C_fileTab[1].name /* Geometry mesh output file name */ + +#define C_filepntrmshout C_fileTab[0].pntr /* Source mesh output file */ +#define C_filepntrgeoout C_fileTab[1].pntr /* Geometry mesh output file */ + +/*+ Process flags. +*/ + +#define C_FLAGGEOOUT 0x0001 /* Output mesh geometry */ + +#define C_FLAGDEFAULT 0x0000 /* Default flags */ diff --git a/scotch_6.0.3/src/scotch/mord.c b/scotch_6.0.3/src/scotch/mord.c new file mode 100644 index 00000000..23d92ea9 --- /dev/null +++ b/scotch_6.0.3/src/scotch/mord.c @@ -0,0 +1,325 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mord.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a mesh reordering software. **/ +/** This module contains the main function. **/ +/** **/ +/** DATES : # Version 4.0 : from : 15 nov 2002 **/ +/** to : 06 jan 2006 **/ +/** # Version 5.0 : from : 22 jan 2008 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 08 sep 2008 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 14 nov 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MORD + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "mord.h" + +/* +** The static and global definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* File array */ + { "-", NULL, "r" }, + { "-", NULL, "w" }, + { "-", NULL, "w" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "mord [ [ []]] ", + " -c : Choose default ordering strategy according to one or several of :", + " b : enforce load balance as much as possible", + " q : privilege quality over speed (default)", + " s : privilege speed over quality", + " t : enforce safety", + " -h : Display this help", + " -m : Save column block mapping data to ", + " -o : Use mesh ordering strategy (see user's manual)", + " (see default strategy with option '-vs')", + " -t : Save partitioning tree data to ", + " -V : Print program version and copyright", + " -v : Set verbose mode to :", + " s : strategy information", + " t : timing information", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Num vnodnbr; /* Number of nodes */ + SCOTCH_Mesh meshdat; /* Source graph */ + SCOTCH_Ordering ordedat; /* Graph ordering */ + SCOTCH_Num * permtab; /* Permutation array */ + SCOTCH_Strat stradat; /* Ordering strategy */ + SCOTCH_Num straval; + char * straptr; + int flagval; + Clock runtime[2]; /* Timing variables */ + int i, j; + + errorProg ("mord"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + return (0); + } + + flagval = C_FLAGNONE; /* Default behavior */ + straval = 0; /* No strategy flags */ + straptr = NULL; + SCOTCH_stratInit (&stradat); + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + return (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'C' : + case 'c' : /* Strategy selection parameters */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'B' : + case 'b' : + straval |= SCOTCH_STRATBALANCE; + break; + case 'Q' : + case 'q' : + straval |= SCOTCH_STRATQUALITY; + break; + case 'S' : + case 's' : + straval |= SCOTCH_STRATSPEED; + break; + case 'T' : + case 't' : + straval |= SCOTCH_STRATSAFETY; + break; + default : + errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); + } + } + break; + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + return (0); + case 'M' : /* Output separator mapping */ + case 'm' : + flagval |= C_FLAGMAPOUT; + if (argv[i][2] != '\0') + C_filenamemapout = &argv[i][2]; + break; + case 'O' : /* Ordering strategy */ + case 'o' : + straptr = &argv[i][2]; + SCOTCH_stratExit (&stradat); + SCOTCH_stratInit (&stradat); + if ((SCOTCH_stratMeshOrder (&stradat, straptr)) != 0) { + errorPrint ("main: invalid ordering strategy"); + return (1); + } + break; + case 'V' : + fprintf (stderr, "mord, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + break; + case 'v' : /* Output control info */ + for (j = 2; argv[i][j] != '\0'; j ++) { + switch (argv[i][j]) { + case 'S' : + case 's' : + flagval |= C_FLAGVERBSTR; + break; + case 'T' : + case 't' : + flagval |= C_FLAGVERBTIM; + break; + default : + errorPrint ("main: unprocessed parameter '%c' in '%s'", + argv[i][j], argv[i]); + return (1); + } + } + break; + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + return (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + clockInit (&runtime[0]); + clockStart (&runtime[0]); + + SCOTCH_meshInit (&meshdat); /* Create mesh structure */ + SCOTCH_meshLoad (&meshdat, C_filepntrsrcinp, -1); /* Read source mesh */ + SCOTCH_meshSize (&meshdat, NULL, &vnodnbr, NULL); /* Get number of nodes */ + + if (straval != 0) { + if (straptr != NULL) + errorPrint ("main: options '-c' and '-o' are exclusive"); + + SCOTCH_stratMeshOrderBuild (&stradat, straval, 0.1); + } + + clockStop (&runtime[0]); /* Get input time */ + clockInit (&runtime[1]); + clockStart (&runtime[1]); + + if ((permtab = (SCOTCH_Num *) memAlloc (vnodnbr * sizeof (SCOTCH_Num))) == NULL) { + errorPrint ("main: out of memory"); + return (1); + } + SCOTCH_meshOrderInit (&meshdat, &ordedat, permtab, NULL, NULL, NULL, NULL); /* Create ordering */ + SCOTCH_meshOrderCompute (&meshdat, &ordedat, &stradat); /* Perform ordering */ + + clockStop (&runtime[1]); /* Get ordering time */ + +#ifdef SCOTCH_DEBUG_ALL + if (SCOTCH_meshOrderCheck (&meshdat, &ordedat) != 0) + return (1); +#endif /* SCOTCH_DEBUG_ALL */ + + clockStart (&runtime[0]); + + SCOTCH_meshOrderSave (&meshdat, &ordedat, C_filepntrordout); /* Write ordering */ + if (flagval & C_FLAGMAPOUT) /* If mapping wanted */ + SCOTCH_meshOrderSaveMap (&meshdat, &ordedat, C_filepntrmapout); /* Write mapping */ + + clockStop (&runtime[0]); /* Get output time */ + + if (flagval & C_FLAGVERBSTR) { + fprintf (C_filepntrlogout, "S\tStrat="); + SCOTCH_stratSave (&stradat, C_filepntrlogout); + putc ('\n', C_filepntrlogout); + } + if (flagval & C_FLAGVERBTIM) { + fprintf (C_filepntrlogout, "T\tOrder\t\t%g\nT\tI/O\t\t%g\nT\tTotal\t\t%g\n", + (double) clockVal (&runtime[1]), + (double) clockVal (&runtime[0]), + (double) clockVal (&runtime[0]) + + (double) clockVal (&runtime[1])); + } + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_meshOrderExit (&meshdat, &ordedat); + SCOTCH_stratExit (&stradat); + SCOTCH_meshExit (&meshdat); + memFree (permtab); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} + +/*******************************************/ +/* */ +/* Stubs to avoid including target module. */ +/* */ +/*******************************************/ + +SCOTCH_Num +T_domWght ( +const void * const arch, +const void * const dom) +{ + errorPrint ("T_domWghtMord: internal error"); + return (1); +} + +SCOTCH_Num +_SCOTCHTdomWght ( +const void * const arch, +const void * const dom) +{ + errorPrint ("T_domWghtMord: internal error"); + return (1); +} + +SCOTCH_Num +T_domDist ( +const void * const arch, +const void * const dom0, +const void * const dom1) +{ + errorPrint ("T_domDistMord: internal error"); + return (1); +} + +SCOTCH_Num +_SCOTCHTdomDist ( +const void * const arch, +const void * const dom0, +const void * const dom1) +{ + errorPrint ("T_domDistMord: internal error"); + return (1); +} diff --git a/scotch_6.0.3/src/scotch/mord.h b/scotch_6.0.3/src/scotch/mord.h new file mode 100644 index 00000000..7540ca72 --- /dev/null +++ b/scotch_6.0.3/src/scotch/mord.h @@ -0,0 +1,71 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mord.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : Part of a mesh orderer. **/ +/** This module contains the data declara- **/ +/** tions for the main routine. **/ +/** **/ +/** DATES : # Version 4.0 : from : 15 nov 2002 **/ +/** to : 22 oct 2003 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/*+ File name aliases. +*/ + +#define C_FILENBR 4 /* Number of files in list */ +#define C_FILEARGNBR 3 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ +#define C_filenameordout C_fileTab[1].name /* Ordering output file name */ +#define C_filenamelogout C_fileTab[2].name /* Log file name */ +#define C_filenamemapout C_fileTab[3].name /* Separator mapping file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ +#define C_filepntrordout C_fileTab[1].pntr /* Ordering output file */ +#define C_filepntrlogout C_fileTab[2].pntr /* Log file */ +#define C_filepntrmapout C_fileTab[3].pntr /* Separator mapping file */ + +/*+ Process flags. +*/ + +#define C_FLAGNONE 0x0000 /* No flags */ +#define C_FLAGMAPOUT 0x0001 /* Output mapping data */ +#define C_FLAGVERBSTR 0x0002 /* Output strategy string */ +#define C_FLAGVERBTIM 0x0004 /* Output timing information */ diff --git a/scotch_6.0.3/src/scotch/mtst.c b/scotch_6.0.3/src/scotch/mtst.c new file mode 100644 index 00000000..dfefca52 --- /dev/null +++ b/scotch_6.0.3/src/scotch/mtst.c @@ -0,0 +1,176 @@ +/* Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mtst.c **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This program gives statistics on source **/ +/** meshes. **/ +/** **/ +/** DATES : # Version 4.0 : from : 25 feb 2003 **/ +/** to 27 jan 2004 **/ +/** # Version 5.0 : from : 23 dec 2007 **/ +/** to : 16 mar 2008 **/ +/** # Version 5.1 : from : 01 jul 2010 **/ +/** to : 14 feb 2011 **/ +/** # Version 6.0 : from : 01 jan 2012 **/ +/** to : 01 jan 2012 **/ +/** **/ +/************************************************************/ + +/* +** The defines and includes. +*/ + +#define MTST + +#include "module.h" +#include "common.h" +#include "scotch.h" +#include "mtst.h" + +/* +** The static definitions. +*/ + +static int C_fileNum = 0; /* Number of file in arg list */ +static File C_fileTab[C_FILENBR] = { /* The file array */ + { "-", NULL, "r" }, + { "-", NULL, "w" } }; + +static const char * C_usageList[] = { + "mtst [ []] ", + " -h : Display this help", + " -V : Print program version and copyright", + NULL }; + +/******************************/ +/* */ +/* This is the main function. */ +/* */ +/******************************/ + +int +main ( +int argc, +char * argv[]) +{ + SCOTCH_Mesh meshdat; + SCOTCH_Num velmnbr; + SCOTCH_Num vnodnbr; + SCOTCH_Num vnlomin; + SCOTCH_Num vnlomax; + SCOTCH_Num vnlosum; + double vnloavg; + double vnlodlt; + SCOTCH_Num edegmin; + SCOTCH_Num edegmax; + double edegavg; + double edegdlt; + SCOTCH_Num ndegmin; + SCOTCH_Num ndegmax; + double ndegavg; + double ndegdlt; + SCOTCH_Num edgenbr; + int i; + + errorProg ("mtst"); + + if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ + usagePrint (stdout, C_usageList); + exit (0); + } + + for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ + C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; + for (i = 1; i < argc; i ++) { /* Loop for all option codes */ + if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ + if (C_fileNum < C_FILEARGNBR) /* File name has been given */ + C_fileTab[C_fileNum ++].name = argv[i]; + else { + errorPrint ("main: too many file names given"); + exit (1); + } + } + else { /* If found an option name */ + switch (argv[i][1]) { + case 'H' : /* Give the usage message */ + case 'h' : + usagePrint (stdout, C_usageList); + exit (0); + case 'V' : + fprintf (stderr, "mtst, version " SCOTCH_VERSION_STRING "\n"); + fprintf (stderr, "Copyright 2004,2007,2008,2010-2012 IPB, Universite de Bordeaux, INRIA & CNRS, France\n"); + fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); + return (0); + default : + errorPrint ("main: unprocessed option '%s'", argv[i]); + exit (1); + } + } + } + + fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ + + SCOTCH_meshInit (&meshdat); + SCOTCH_meshLoad (&meshdat, C_filepntrsrcinp, -1); + SCOTCH_meshCheck (&meshdat); + + SCOTCH_meshSize (&meshdat, &velmnbr, &vnodnbr, &edgenbr); + SCOTCH_meshStat (&meshdat, &vnlomin, &vnlomax, &vnlosum, &vnloavg, &vnlodlt, + &edegmin, &edegmax, &edegavg, &edegdlt, + &ndegmin, &ndegmax, &ndegavg, &ndegdlt); + + fprintf (C_filepntrdatout, "S\tElements\tnbr=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) velmnbr); + fprintf (C_filepntrdatout, "S\tNodes\tnbr=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) vnodnbr); + fprintf (C_filepntrdatout, "S\tNode load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) vnlomin, (SCOTCH_Num) vnlomax, (SCOTCH_Num) vnlosum, vnloavg, vnlodlt); + fprintf (C_filepntrdatout, "S\tElement degree\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) edegmin, (SCOTCH_Num) edegmax, (SCOTCH_Num) (edgenbr / 2), edegavg, edegdlt); + fprintf (C_filepntrdatout, "S\tNode degree\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", + (SCOTCH_Num) ndegmin, (SCOTCH_Num) ndegmax, (SCOTCH_Num) (edgenbr / 2), ndegavg, ndegdlt); + fprintf (C_filepntrdatout, "S\tEdge\tnbr=" SCOTCH_NUMSTRING "\n", + (SCOTCH_Num) (edgenbr / 2)); + + fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ + + SCOTCH_meshExit (&meshdat); + +#ifdef COMMON_PTHREAD + pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ +#endif /* COMMON_PTHREAD */ + return (0); +} diff --git a/scotch_6.0.3/src/scotch/mtst.h b/scotch_6.0.3/src/scotch/mtst.h new file mode 100644 index 00000000..e0145b48 --- /dev/null +++ b/scotch_6.0.3/src/scotch/mtst.h @@ -0,0 +1,59 @@ +/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS +** +** This file is part of the Scotch software package for static mapping, +** graph partitioning and sparse matrix ordering. +** +** This software is governed by the CeCILL-C license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-C license and that you accept its terms. +*/ +/************************************************************/ +/** **/ +/** NAME : mtst.h **/ +/** **/ +/** AUTHOR : Francois PELLEGRINI **/ +/** **/ +/** FUNCTION : This file contains the declarations **/ +/** for the source mesh analyzer. **/ +/** **/ +/** DATES : # Version 4.0 : from : 25 feb 2003 **/ +/** to 27 jan 2004 **/ +/** **/ +/************************************************************/ + +/* +** The defines. +*/ + +/** File name aliases. **/ + +#define C_FILENBR 2 /* Number of files in list */ +#define C_FILEARGNBR 2 /* Number of files which can be arguments */ + +#define C_filenamesrcinp C_fileTab[0].name /* Source mesh input file name */ +#define C_filenamedatout C_fileTab[1].name /* Statistics output file name */ + +#define C_filepntrsrcinp C_fileTab[0].pntr /* Source mesh input file */ +#define C_filepntrdatout C_fileTab[1].pntr /* Statistics output file */ diff --git a/scotch_6.0.3/tgt/SP2_16.txt b/scotch_6.0.3/tgt/SP2_16.txt new file mode 100644 index 00000000..5f5fa4b1 --- /dev/null +++ b/scotch_6.0.3/tgt/SP2_16.txt @@ -0,0 +1 @@ +leaf 4 diff --git a/scotch_6.0.3/tgt/T3D_64.tgt b/scotch_6.0.3/tgt/T3D_64.tgt new file mode 100644 index 00000000..5dd70549 --- /dev/null +++ b/scotch_6.0.3/tgt/T3D_64.tgt @@ -0,0 +1 @@ +torus3D 4 4 4 diff --git a/scotch_6.0.3/tgt/h1.tgt b/scotch_6.0.3/tgt/h1.tgt new file mode 100644 index 00000000..ef5930c2 --- /dev/null +++ b/scotch_6.0.3/tgt/h1.tgt @@ -0,0 +1 @@ +hcub 1 diff --git a/scotch_6.0.3/tgt/h10.tgt b/scotch_6.0.3/tgt/h10.tgt new file mode 100644 index 00000000..70b269a2 --- /dev/null +++ b/scotch_6.0.3/tgt/h10.tgt @@ -0,0 +1 @@ +hcub 10 diff --git a/scotch_6.0.3/tgt/h2.tgt b/scotch_6.0.3/tgt/h2.tgt new file mode 100644 index 00000000..caf2c85f --- /dev/null +++ b/scotch_6.0.3/tgt/h2.tgt @@ -0,0 +1 @@ +hcub 2 diff --git a/scotch_6.0.3/tgt/h3.tgt b/scotch_6.0.3/tgt/h3.tgt new file mode 100644 index 00000000..0aa75028 --- /dev/null +++ b/scotch_6.0.3/tgt/h3.tgt @@ -0,0 +1 @@ +hcub 3 diff --git a/scotch_6.0.3/tgt/h4.tgt b/scotch_6.0.3/tgt/h4.tgt new file mode 100644 index 00000000..eb5a2f65 --- /dev/null +++ b/scotch_6.0.3/tgt/h4.tgt @@ -0,0 +1 @@ +hcub 4 diff --git a/scotch_6.0.3/tgt/h5.tgt b/scotch_6.0.3/tgt/h5.tgt new file mode 100644 index 00000000..3585e9ac --- /dev/null +++ b/scotch_6.0.3/tgt/h5.tgt @@ -0,0 +1 @@ +hcub 5 diff --git a/scotch_6.0.3/tgt/h6.tgt b/scotch_6.0.3/tgt/h6.tgt new file mode 100644 index 00000000..cea374bf --- /dev/null +++ b/scotch_6.0.3/tgt/h6.tgt @@ -0,0 +1 @@ +hcub 6 diff --git a/scotch_6.0.3/tgt/h7.tgt b/scotch_6.0.3/tgt/h7.tgt new file mode 100644 index 00000000..6ee3e3c5 --- /dev/null +++ b/scotch_6.0.3/tgt/h7.tgt @@ -0,0 +1 @@ +hcub 7 diff --git a/scotch_6.0.3/tgt/h8.tgt b/scotch_6.0.3/tgt/h8.tgt new file mode 100644 index 00000000..0333b078 --- /dev/null +++ b/scotch_6.0.3/tgt/h8.tgt @@ -0,0 +1 @@ +hcub 8 diff --git a/scotch_6.0.3/tgt/h9.tgt b/scotch_6.0.3/tgt/h9.tgt new file mode 100644 index 00000000..f61cce0b --- /dev/null +++ b/scotch_6.0.3/tgt/h9.tgt @@ -0,0 +1 @@ +hcub 9 diff --git a/scotch_6.0.3/tgt/k1.tgt b/scotch_6.0.3/tgt/k1.tgt new file mode 100644 index 00000000..70dcb4ba --- /dev/null +++ b/scotch_6.0.3/tgt/k1.tgt @@ -0,0 +1 @@ +cmplt 1 diff --git a/scotch_6.0.3/tgt/k12.tgt b/scotch_6.0.3/tgt/k12.tgt new file mode 100644 index 00000000..829f1f6f --- /dev/null +++ b/scotch_6.0.3/tgt/k12.tgt @@ -0,0 +1 @@ +cmplt 12 diff --git a/scotch_6.0.3/tgt/k128.tgt b/scotch_6.0.3/tgt/k128.tgt new file mode 100644 index 00000000..e4ec5e45 --- /dev/null +++ b/scotch_6.0.3/tgt/k128.tgt @@ -0,0 +1 @@ +cmplt 128 diff --git a/scotch_6.0.3/tgt/k16.tgt b/scotch_6.0.3/tgt/k16.tgt new file mode 100644 index 00000000..c463ecff --- /dev/null +++ b/scotch_6.0.3/tgt/k16.tgt @@ -0,0 +1 @@ +cmplt 16 diff --git a/scotch_6.0.3/tgt/k2.tgt b/scotch_6.0.3/tgt/k2.tgt new file mode 100644 index 00000000..49bc6cf7 --- /dev/null +++ b/scotch_6.0.3/tgt/k2.tgt @@ -0,0 +1 @@ +cmplt 2 diff --git a/scotch_6.0.3/tgt/k24.tgt b/scotch_6.0.3/tgt/k24.tgt new file mode 100644 index 00000000..101fbab0 --- /dev/null +++ b/scotch_6.0.3/tgt/k24.tgt @@ -0,0 +1 @@ +cmplt 24 diff --git a/scotch_6.0.3/tgt/k256.tgt b/scotch_6.0.3/tgt/k256.tgt new file mode 100644 index 00000000..2e75b04d --- /dev/null +++ b/scotch_6.0.3/tgt/k256.tgt @@ -0,0 +1 @@ +cmplt 256 diff --git a/scotch_6.0.3/tgt/k32.tgt b/scotch_6.0.3/tgt/k32.tgt new file mode 100644 index 00000000..c5485ba2 --- /dev/null +++ b/scotch_6.0.3/tgt/k32.tgt @@ -0,0 +1 @@ +cmplt 32 diff --git a/scotch_6.0.3/tgt/k4.tgt b/scotch_6.0.3/tgt/k4.tgt new file mode 100644 index 00000000..04fe59e3 --- /dev/null +++ b/scotch_6.0.3/tgt/k4.tgt @@ -0,0 +1 @@ +cmplt 4 diff --git a/scotch_6.0.3/tgt/k48.tgt b/scotch_6.0.3/tgt/k48.tgt new file mode 100644 index 00000000..af898ef6 --- /dev/null +++ b/scotch_6.0.3/tgt/k48.tgt @@ -0,0 +1 @@ +cmplt 48 diff --git a/scotch_6.0.3/tgt/k512.tgt b/scotch_6.0.3/tgt/k512.tgt new file mode 100644 index 00000000..bcd87ae6 --- /dev/null +++ b/scotch_6.0.3/tgt/k512.tgt @@ -0,0 +1 @@ +cmplt 512 diff --git a/scotch_6.0.3/tgt/k6.tgt b/scotch_6.0.3/tgt/k6.tgt new file mode 100644 index 00000000..81c9717e --- /dev/null +++ b/scotch_6.0.3/tgt/k6.tgt @@ -0,0 +1 @@ +cmplt 6 diff --git a/scotch_6.0.3/tgt/k64.tgt b/scotch_6.0.3/tgt/k64.tgt new file mode 100644 index 00000000..3fa865bd --- /dev/null +++ b/scotch_6.0.3/tgt/k64.tgt @@ -0,0 +1 @@ +cmplt 64 diff --git a/scotch_6.0.3/tgt/k7.tgt b/scotch_6.0.3/tgt/k7.tgt new file mode 100644 index 00000000..b601c252 --- /dev/null +++ b/scotch_6.0.3/tgt/k7.tgt @@ -0,0 +1 @@ +cmplt 7 diff --git a/scotch_6.0.3/tgt/k8.tgt b/scotch_6.0.3/tgt/k8.tgt new file mode 100644 index 00000000..7a231fbf --- /dev/null +++ b/scotch_6.0.3/tgt/k8.tgt @@ -0,0 +1 @@ +cmplt 8 diff --git a/scotch_6.0.3/tgt/k96.tgt b/scotch_6.0.3/tgt/k96.tgt new file mode 100644 index 00000000..573db2c7 --- /dev/null +++ b/scotch_6.0.3/tgt/k96.tgt @@ -0,0 +1 @@ +cmplt 96 diff --git a/scotch_6.0.3/tgt/m10x10.tgt b/scotch_6.0.3/tgt/m10x10.tgt new file mode 100644 index 00000000..a59f702a --- /dev/null +++ b/scotch_6.0.3/tgt/m10x10.tgt @@ -0,0 +1 @@ +mesh2D 10 10 diff --git a/scotch_6.0.3/tgt/m10x20.tgt b/scotch_6.0.3/tgt/m10x20.tgt new file mode 100644 index 00000000..9fe6b244 --- /dev/null +++ b/scotch_6.0.3/tgt/m10x20.tgt @@ -0,0 +1 @@ +mesh2D 10 20 diff --git a/scotch_6.0.3/tgt/m11x13.tgt b/scotch_6.0.3/tgt/m11x13.tgt new file mode 100644 index 00000000..ffdba186 --- /dev/null +++ b/scotch_6.0.3/tgt/m11x13.tgt @@ -0,0 +1 @@ +mesh2D 11 13 diff --git a/scotch_6.0.3/tgt/m16x16.tgt b/scotch_6.0.3/tgt/m16x16.tgt new file mode 100644 index 00000000..9ffe3acc --- /dev/null +++ b/scotch_6.0.3/tgt/m16x16.tgt @@ -0,0 +1 @@ +mesh2D 16 16 diff --git a/scotch_6.0.3/tgt/m16x32.tgt b/scotch_6.0.3/tgt/m16x32.tgt new file mode 100644 index 00000000..6fc0bf68 --- /dev/null +++ b/scotch_6.0.3/tgt/m16x32.tgt @@ -0,0 +1 @@ +mesh2D 16 32 diff --git a/scotch_6.0.3/tgt/m17x19.tgt b/scotch_6.0.3/tgt/m17x19.tgt new file mode 100644 index 00000000..ca9f52fb --- /dev/null +++ b/scotch_6.0.3/tgt/m17x19.tgt @@ -0,0 +1 @@ +mesh2D 17 19 diff --git a/scotch_6.0.3/tgt/m19x21.tgt b/scotch_6.0.3/tgt/m19x21.tgt new file mode 100644 index 00000000..a4fab7e4 --- /dev/null +++ b/scotch_6.0.3/tgt/m19x21.tgt @@ -0,0 +1 @@ +mesh2D 19 21 diff --git a/scotch_6.0.3/tgt/m19x31.tgt b/scotch_6.0.3/tgt/m19x31.tgt new file mode 100644 index 00000000..4da8082c --- /dev/null +++ b/scotch_6.0.3/tgt/m19x31.tgt @@ -0,0 +1 @@ +mesh2D 19 31 diff --git a/scotch_6.0.3/tgt/m21x23.tgt b/scotch_6.0.3/tgt/m21x23.tgt new file mode 100644 index 00000000..1058ddde --- /dev/null +++ b/scotch_6.0.3/tgt/m21x23.tgt @@ -0,0 +1 @@ +mesh2D 21 23 diff --git a/scotch_6.0.3/tgt/m23x25.tgt b/scotch_6.0.3/tgt/m23x25.tgt new file mode 100644 index 00000000..878d7260 --- /dev/null +++ b/scotch_6.0.3/tgt/m23x25.tgt @@ -0,0 +1 @@ +mesh2D 23 25 diff --git a/scotch_6.0.3/tgt/m24x24.tgt b/scotch_6.0.3/tgt/m24x24.tgt new file mode 100644 index 00000000..8b7e5509 --- /dev/null +++ b/scotch_6.0.3/tgt/m24x24.tgt @@ -0,0 +1 @@ +mesh2D 24 24 diff --git a/scotch_6.0.3/tgt/m25x27.tgt b/scotch_6.0.3/tgt/m25x27.tgt new file mode 100644 index 00000000..b1d9e923 --- /dev/null +++ b/scotch_6.0.3/tgt/m25x27.tgt @@ -0,0 +1 @@ +mesh2D 25 27 diff --git a/scotch_6.0.3/tgt/m27x29.tgt b/scotch_6.0.3/tgt/m27x29.tgt new file mode 100644 index 00000000..0c6c991f --- /dev/null +++ b/scotch_6.0.3/tgt/m27x29.tgt @@ -0,0 +1 @@ +mesh2D 27 29 diff --git a/scotch_6.0.3/tgt/m29x31.tgt b/scotch_6.0.3/tgt/m29x31.tgt new file mode 100644 index 00000000..61752581 --- /dev/null +++ b/scotch_6.0.3/tgt/m29x31.tgt @@ -0,0 +1 @@ +mesh2D 29 31 diff --git a/scotch_6.0.3/tgt/m2x2.tgt b/scotch_6.0.3/tgt/m2x2.tgt new file mode 100644 index 00000000..1bb16bc1 --- /dev/null +++ b/scotch_6.0.3/tgt/m2x2.tgt @@ -0,0 +1 @@ +mesh2D 2 2 diff --git a/scotch_6.0.3/tgt/m2x4x8.tgt b/scotch_6.0.3/tgt/m2x4x8.tgt new file mode 100644 index 00000000..386d4986 --- /dev/null +++ b/scotch_6.0.3/tgt/m2x4x8.tgt @@ -0,0 +1 @@ +mesh3D 2 4 8 diff --git a/scotch_6.0.3/tgt/m32x32.tgt b/scotch_6.0.3/tgt/m32x32.tgt new file mode 100644 index 00000000..c06a639a --- /dev/null +++ b/scotch_6.0.3/tgt/m32x32.tgt @@ -0,0 +1 @@ +mesh2D 32 32 diff --git a/scotch_6.0.3/tgt/m3x3.tgt b/scotch_6.0.3/tgt/m3x3.tgt new file mode 100644 index 00000000..3b974cca --- /dev/null +++ b/scotch_6.0.3/tgt/m3x3.tgt @@ -0,0 +1 @@ +mesh2D 3 3 diff --git a/scotch_6.0.3/tgt/m4x4.tgt b/scotch_6.0.3/tgt/m4x4.tgt new file mode 100644 index 00000000..4e7623bd --- /dev/null +++ b/scotch_6.0.3/tgt/m4x4.tgt @@ -0,0 +1 @@ +mesh2D 4 4 diff --git a/scotch_6.0.3/tgt/m4x8.tgt b/scotch_6.0.3/tgt/m4x8.tgt new file mode 100644 index 00000000..b06bc007 --- /dev/null +++ b/scotch_6.0.3/tgt/m4x8.tgt @@ -0,0 +1 @@ +mesh2D 4 8 diff --git a/scotch_6.0.3/tgt/m5x5.tgt b/scotch_6.0.3/tgt/m5x5.tgt new file mode 100644 index 00000000..7abb300a --- /dev/null +++ b/scotch_6.0.3/tgt/m5x5.tgt @@ -0,0 +1 @@ +mesh2D 5 5 diff --git a/scotch_6.0.3/tgt/m5x7.tgt b/scotch_6.0.3/tgt/m5x7.tgt new file mode 100644 index 00000000..18de1ee6 --- /dev/null +++ b/scotch_6.0.3/tgt/m5x7.tgt @@ -0,0 +1 @@ +mesh2D 5 7 diff --git a/scotch_6.0.3/tgt/m64x64.tgt b/scotch_6.0.3/tgt/m64x64.tgt new file mode 100644 index 00000000..5014e438 --- /dev/null +++ b/scotch_6.0.3/tgt/m64x64.tgt @@ -0,0 +1 @@ +mesh2D 64 64 diff --git a/scotch_6.0.3/tgt/m8x16.tgt b/scotch_6.0.3/tgt/m8x16.tgt new file mode 100644 index 00000000..07cea1f3 --- /dev/null +++ b/scotch_6.0.3/tgt/m8x16.tgt @@ -0,0 +1 @@ +mesh2D 8 16 diff --git a/scotch_6.0.3/tgt/m8x8.tgt b/scotch_6.0.3/tgt/m8x8.tgt new file mode 100644 index 00000000..69953b8d --- /dev/null +++ b/scotch_6.0.3/tgt/m8x8.tgt @@ -0,0 +1 @@ +mesh2D 8 8 diff --git a/scotch_6.0.3/tgt/m9x11.tgt b/scotch_6.0.3/tgt/m9x11.tgt new file mode 100644 index 00000000..9adc330b --- /dev/null +++ b/scotch_6.0.3/tgt/m9x11.tgt @@ -0,0 +1 @@ +mesh2D 9 11 diff --git a/scotch_6.0.3/tgt/m9x7.tgt b/scotch_6.0.3/tgt/m9x7.tgt new file mode 100644 index 00000000..c1fa97db --- /dev/null +++ b/scotch_6.0.3/tgt/m9x7.tgt @@ -0,0 +1 @@ +mesh2D 9 7 diff --git a/scotch_6.0.3/tgt/p128.tgt b/scotch_6.0.3/tgt/p128.tgt new file mode 100644 index 00000000..cfdae6b2 --- /dev/null +++ b/scotch_6.0.3/tgt/p128.tgt @@ -0,0 +1 @@ +mesh2D 128 1 diff --git a/scotch_6.0.3/tgt/p16.tgt b/scotch_6.0.3/tgt/p16.tgt new file mode 100644 index 00000000..16f4fc39 --- /dev/null +++ b/scotch_6.0.3/tgt/p16.tgt @@ -0,0 +1 @@ +mesh2D 16 1 diff --git a/scotch_6.0.3/tgt/p2.tgt b/scotch_6.0.3/tgt/p2.tgt new file mode 100644 index 00000000..53c9aa67 --- /dev/null +++ b/scotch_6.0.3/tgt/p2.tgt @@ -0,0 +1 @@ +mesh2D 2 1 diff --git a/scotch_6.0.3/tgt/p256.tgt b/scotch_6.0.3/tgt/p256.tgt new file mode 100644 index 00000000..ff3aec37 --- /dev/null +++ b/scotch_6.0.3/tgt/p256.tgt @@ -0,0 +1 @@ +mesh2D 256 1 diff --git a/scotch_6.0.3/tgt/p32.tgt b/scotch_6.0.3/tgt/p32.tgt new file mode 100644 index 00000000..0717b810 --- /dev/null +++ b/scotch_6.0.3/tgt/p32.tgt @@ -0,0 +1 @@ +mesh2D 32 1 diff --git a/scotch_6.0.3/tgt/p4.tgt b/scotch_6.0.3/tgt/p4.tgt new file mode 100644 index 00000000..e0a46689 --- /dev/null +++ b/scotch_6.0.3/tgt/p4.tgt @@ -0,0 +1 @@ +mesh2D 4 1 diff --git a/scotch_6.0.3/tgt/p512.tgt b/scotch_6.0.3/tgt/p512.tgt new file mode 100644 index 00000000..50160f57 --- /dev/null +++ b/scotch_6.0.3/tgt/p512.tgt @@ -0,0 +1 @@ +mesh2D 512 1 diff --git a/scotch_6.0.3/tgt/p64.tgt b/scotch_6.0.3/tgt/p64.tgt new file mode 100644 index 00000000..a263309f --- /dev/null +++ b/scotch_6.0.3/tgt/p64.tgt @@ -0,0 +1 @@ +mesh2D 64 1 diff --git a/scotch_6.0.3/tgt/p8.tgt b/scotch_6.0.3/tgt/p8.tgt new file mode 100644 index 00000000..ad4a31a5 --- /dev/null +++ b/scotch_6.0.3/tgt/p8.tgt @@ -0,0 +1 @@ +mesh2D 8 1 diff --git a/scotch_6.0.3/tgt/t2x4x8.tgt b/scotch_6.0.3/tgt/t2x4x8.tgt new file mode 100644 index 00000000..0df19a64 --- /dev/null +++ b/scotch_6.0.3/tgt/t2x4x8.tgt @@ -0,0 +1 @@ +torus3D 2 4 8 diff --git a/scotch_6.0.3/tgt/t4x4x4.tgt b/scotch_6.0.3/tgt/t4x4x4.tgt new file mode 100644 index 00000000..5dd70549 --- /dev/null +++ b/scotch_6.0.3/tgt/t4x4x4.tgt @@ -0,0 +1 @@ +torus3D 4 4 4 diff --git a/scotch_6.0.3/tgt/vcmplt.tgt b/scotch_6.0.3/tgt/vcmplt.tgt new file mode 100644 index 00000000..6fc03c70 --- /dev/null +++ b/scotch_6.0.3/tgt/vcmplt.tgt @@ -0,0 +1 @@ +varcmplt diff --git a/scotch_6.0.3/tgt/vhcub.tgt b/scotch_6.0.3/tgt/vhcub.tgt new file mode 100644 index 00000000..bfb340ee --- /dev/null +++ b/scotch_6.0.3/tgt/vhcub.tgt @@ -0,0 +1 @@ +varhcub diff --git a/scotch_6.0.3/tgt/void.tgt b/scotch_6.0.3/tgt/void.tgt new file mode 100644 index 00000000..70dcb4ba --- /dev/null +++ b/scotch_6.0.3/tgt/void.tgt @@ -0,0 +1 @@ +cmplt 1