METIS is written in C by using
int and when one uses a solver on a 64-bit system that employs 8-byte integers this must be changed. Recently I have compiled MUMPS with
-i8 and this was exactly this case. The newest version of METIS seems have an option to compile METIS with
long but it is still alpha so I have decided to hack METIS 4 by myself. My experience in this respect is written below.
All the METIS code is in the directory
metis-4.0/Lib/ and below it is assumed that we are already in this directory.
First thing is to change
long in the code. The simplest solution is to insert somewhere
#define int long
There are several headers in the directory but quick inspection
$ grep #include *.c
$ grep #include *.h
shows us that the c-files includes only
metis.h and the latter includes other headers. This shows that we have to include the statement
#define int long in
metis.h after it includes the standard headers and before it includes other headers in this directory, that is, in the line 31.
If you find the solution with
#define int long too tricky there is another way to do it. It is possible to use
sed to change
long in the code directly. A simple script that does it is changeid. With it
$ changeid int long *.h *.c
does the job.
So far it was an easy job. Now the question is whether the code will work. The problem is that a programmer could assume the length of
int in the code explicitly and in this case we have serious problems.
Quick inspection of memory allocation
$ grep malloc *.c
shows that the author uses its own functions to allocate memory that in turn uses
sizeof(int). This gives us the hope that this should probably be okay.
Now the compilation with gcc produces a warning in
ometis.c: In function `__MMDOrder':
ometis.c:641: warning: left shift count >= width of type
At the first glance the warning looks strange, as the statement is
genmmd(nvtxs, xadj, adjncy, iperm, perm, 1, head, qsize, list, marker, MAXIDX, &nofsub);
However if we recognize that MAXIDX is a macro (a common practice in C is to write macros uppercase), then
$ grep MAXIDX *.h
struct.h:#define MAXIDX (1<<8*sizeof(idxtype)-2)
we find the reason in struct.h.
1 has type
int and we have to change it to
long, that is, to
1l. This is quite important as otherwise MAXIDX will be defined just wrong.
Then there are problems in
minitpart.c:340: error: conflicting types for 'SelectQueueOneWay'
minitpart.c:248: error: previous implicit declaration of 'SelectQueueOneWay' was here
The inspection of these lines shows the reason. In C a function can be declared implicitly (line 248) and here it is implicitly assumed that it returns
int. On the other hand the function by itself (line 340) return
long (do not forget about
#define int long). So we have to add a function declaration before its use at the beginning of the file
int SelectQueueOneWay(int , float *, float *, int , PQueueType queues[MAXNCON]);
You see, warnings are very important and it is important to pay attention to them. In
gcc one can obtain all warning with
-Wall. Then we see more warning but most of them are not related to the change at all and
warning: int format, different type arg (arg 8)
is related to
printf and can be ignored.
In my case all the tests have shown that METIS is working just fine and from that I conclude that the fixes described above were enough. Well, MUMPS does not use all the METIS functionality, so you have to run your own tests as well.
Microsoft Visual Studio C++
Please note that in Microsoft Visual Studio C++ sizeof(int) == sizeof(long) == 4. Thereafter in order to declare an 8 Byte integer, one has to use __int64 instead of long.