Compiling METIS 4 for 64-bit computing with long int

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 int to 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 int to 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

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:

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][2]);

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.


Comments are closed.