55#define IDXTYPEWIDTH 64
66#include " metis.h"
77
8+ // Weird tricks to detect the integer type width used by BLAS and Metis.
9+ // These are technically undefined behaviour, because they rely on using a
10+ // function declaration that involves int64_t, while the actual implementation
11+ // may use a different type. Their behaviour may depend on the endianness of the
12+ // CPU (?).
13+
814namespace hipo {
915
1016extern " C" {
1117int64_t cblas_isamax (const int64_t N, const float * X, const int64_t incX);
1218}
13- BlasIntegerModel getBlasIntegerModel () {
19+ IntegerModel getBlasIntegerModel () {
1420 // Test if BLAS uses 32-bit integers (LP64) or 64-bit integers (ILP64) at
1521 // runtime. Inspired by libblastrampoline's autodetection.c
1622
@@ -19,9 +25,9 @@ BlasIntegerModel getBlasIntegerModel() {
1925 // isamax returns 0. If the correct value of 3 is passed, it returns 2
2026 // instead.
2127
22- static BlasIntegerModel blas_model = BlasIntegerModel ::not_set;
28+ static IntegerModel blas_model = IntegerModel ::not_set;
2329
24- if (blas_model == BlasIntegerModel ::not_set) {
30+ if (blas_model == IntegerModel ::not_set) {
2531 // This is a very negative 64-bit number, but it is just 3 if only the lower
2632 // 32 bits are used.
2733 const int64_t n = 0xffffffff00000003 ;
@@ -36,66 +42,68 @@ BlasIntegerModel getBlasIntegerModel() {
3642
3743 if (max_idx == 0 ) {
3844 // isamax read negative n and returned 0, so it's using ilp64
39- blas_model = BlasIntegerModel ::ilp64;
45+ blas_model = IntegerModel ::ilp64;
4046
4147 } else if (max_idx == 2 ) {
4248 // isamax read correct n and returned 2, so it's using lp64
43- blas_model = BlasIntegerModel ::lp64;
49+ blas_model = IntegerModel ::lp64;
4450
4551 } else {
4652 // something went wrong
47- blas_model = BlasIntegerModel ::unknown;
53+ blas_model = IntegerModel ::unknown;
4854 }
4955 }
5056
5157 return blas_model;
5258}
53- std::string getBlasIntegerModelString () {
54- BlasIntegerModel blas_model = getBlasIntegerModel ();
5559
56- switch (blas_model) {
57- case BlasIntegerModel::not_set:
60+ std::string getIntegerModelString (IntegerModel i) {
61+ switch (i) {
62+ case IntegerModel::not_set:
5863 return " Not set" ;
5964
60- case BlasIntegerModel ::unknown:
65+ case IntegerModel ::unknown:
6166 return " Unknown" ;
6267
63- case BlasIntegerModel ::lp64:
68+ case IntegerModel ::lp64:
6469 return " LP64" ;
6570
66- case BlasIntegerModel ::ilp64:
71+ case IntegerModel ::ilp64:
6772 return " ILP64" ;
6873 }
6974}
7075
71- int getMetisIntegerType () {
72- idx_t options[METIS_NOPTIONS];
73- for (int i = 0 ; i < METIS_NOPTIONS; ++i) options[i] = -1 ;
74-
75- // if Metis is using 32-bit internally, this should set ptype to 0 and objtype
76- // to 1, which should trigger an error. If it uses 64-bit then everything
77- // should be fine.
78- options[METIS_OPTION_PTYPE] = 1 ;
79-
80- idx_t n = 3 ;
81- idx_t ptr[4 ] = {0 , 2 , 4 , 6 };
82- idx_t rows[6 ] = {1 , 2 , 0 , 2 , 0 , 1 };
83- idx_t perm[3 ], iperm[3 ];
84-
85- idx_t status = METIS_NodeND (&n, ptr, rows, NULL , options, perm, iperm);
86-
87- int metis_int = 0 ;
88- if (status == METIS_OK) {
89- if (perm[0 ] != 0 || perm[1 ] != 1 || perm[2 ] != 2 )
90- metis_int = -1 ;
91- else
92- metis_int = 64 ;
93- } else if (status == METIS_ERROR_INPUT) {
94- metis_int = 32 ;
95- } else {
96- metis_int = -1 ;
76+ IntegerModel getMetisIntegerModel () {
77+ static IntegerModel metis_model = IntegerModel::not_set;
78+
79+ if (metis_model == IntegerModel::not_set) {
80+ idx_t options[METIS_NOPTIONS];
81+ for (int i = 0 ; i < METIS_NOPTIONS; ++i) options[i] = -1 ;
82+
83+ // if Metis is using 32-bit internally, this should set ptype to 0 and
84+ // objtype to 1, which should trigger an error. If it uses 64-bit then
85+ // everything should be fine.
86+ options[METIS_OPTION_PTYPE] = 1 ;
87+
88+ idx_t n = 3 ;
89+ idx_t ptr[4 ] = {0 , 2 , 4 , 6 };
90+ idx_t rows[6 ] = {1 , 2 , 0 , 2 , 0 , 1 };
91+ idx_t perm[3 ], iperm[3 ];
92+
93+ idx_t status = METIS_NodeND (&n, ptr, rows, NULL , options, perm, iperm);
94+
95+ if (status == METIS_OK) {
96+ if (perm[0 ] != 0 || perm[1 ] != 1 || perm[2 ] != 2 )
97+ metis_model = IntegerModel::unknown;
98+ else
99+ metis_model = IntegerModel::ilp64;
100+ } else if (status == METIS_ERROR_INPUT) {
101+ metis_model = IntegerModel::lp64;
102+ } else {
103+ metis_model = IntegerModel::unknown;
104+ }
97105 }
98106
99- return metis_int ;
107+ return metis_model ;
100108}
101109} // namespace hipo
0 commit comments