Repository: alugowski/fast_matrix_market (language: python)

Issue:
Fix macOS complex value test fails
Something changed, either with a newer clang or newer suite-sparse from Homebrew. Now errors like this appear:

```
In file included from /Users/enos/projects/fast_matrix_market/tests/graphblas_test.cpp:18:
/Users/enos/projects/fast_matrix_market/include/fast_matrix_market/app/GraphBLAS.hpp:492:20: error: no matching function for call to 'GxB_Matrix_build_FC32'
            return GxB_Matrix_build_FC32(mat, rows, cols, vals, nvals, GxB_PLUS_FC32);
                   ^~~~~~~~~~~~~~~~~~~~~
/opt/homebrew/include/GraphBLAS.h:3232:10: note: candidate function not viable: no known conversion from 'const std::complex<float> *' to 'const GxB_FC32_t *' (aka 'const _Complex float *') for 4th argument
GrB_Info GxB_Matrix_build_FC32      // build a matrix from (I,J,X) tuples
         ^
In file included from /Users/enos/projects/fast_matrix_market/tests/graphblas_test.cpp:18:
/Users/enos/projects/fast_matrix_market/include/fast_matrix_market/app/GraphBLAS.hpp:496:20: error: no matching function for call to 'GxB_Scalar_setElement_FC32'
            return GxB_Scalar_setElement_FC32(scalar, x);
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/homebrew/include/GraphBLAS.h:2173:10: note: candidate function not viable: no known conversion from 'const std::complex<float>' to 'GxB_FC32_t' (aka '_Complex float') for 2nd argument
GrB_Info GxB_Scalar_setElement_FC32     // s = x
         ^
```

std::complex and the C99 _Complex types have compatible memory layouts.


Discussion / hints:

Fix patch:
diff --git a/include/fast_matrix_market/app/GraphBLAS.hpp b/include/fast_matrix_market/app/GraphBLAS.hpp
index 7c45fc5..611c933 100644
--- a/include/fast_matrix_market/app/GraphBLAS.hpp
+++ b/include/fast_matrix_market/app/GraphBLAS.hpp
@@ -489,56 +489,56 @@ namespace fast_matrix_market {
         static GrB_Type type() { return GxB_FC32; }
 
         static GrB_Info build_matrix(GrB_Matrix mat, const GrB_Index* rows, const GrB_Index* cols, const std::complex<float>* vals, GrB_Index nvals) {
-            return GxB_Matrix_build_FC32(mat, rows, cols, vals, nvals, GxB_PLUS_FC32);
+            return GxB_Matrix_build_FC32(mat, rows, cols, reinterpret_cast<const GxB_FC32_t *>(vals), nvals, GxB_PLUS_FC32);
         }
 
         static GrB_Info set_element(GrB_Scalar scalar, const std::complex<float>& x) {
-            return GxB_Scalar_setElement_FC32(scalar, x);
+            return GxB_Scalar_setElement_FC32(scalar, reinterpret_cast<const GxB_FC32_t &>(x));
         }
 
         static GrB_Info GrB_Matrix_extractTuples(GrB_Index *I, GrB_Index *J, std::complex<float> *X, GrB_Index *nvals, const GrB_Matrix& A) {
-            return GxB_Matrix_extractTuples_FC32(I, J, X, nvals, A);
+            return GxB_Matrix_extractTuples_FC32(I, J, reinterpret_cast<GxB_FC32_t *>(X), nvals, A);
         }
 
 #if FMM_GXB_ITERATORS
         static std::complex<float> GxB_Iterator_get(GxB_Iterator iterator) {
-            return GxB_Iterator_get_FC32(iterator);
+            return reinterpret_cast<std::complex<float>&>(GxB_Iterator_get_FC32(iterator));
         }
 #endif
         static GrB_Info build_vector(GrB_Vector vec, const GrB_Index* indices, const std::complex<float>* vals, GrB_Index nvals) {
-            return GxB_Vector_build_FC32(vec, indices, vals, nvals, GxB_PLUS_FC32);
+            return GxB_Vector_build_FC32(vec, indices, reinterpret_cast<const GxB_FC32_t*>(vals), nvals, GxB_PLUS_FC32);
         }
 
         static GrB_Info GrB_Vector_extractTuples(GrB_Index *I, std::complex<float> *X, GrB_Index *nvals, const GrB_Vector& A) {
-            return GxB_Vector_extractTuples_FC32(I, X, nvals, A);
+            return GxB_Vector_extractTuples_FC32(I, reinterpret_cast<GxB_FC32_t*>(X), nvals, A);
         }
     };
     template <> struct GraphBLAS_typed<std::complex<double>> {
         static GrB_Type type() { return GxB_FC64; }
 
         static GrB_Info build_matrix(GrB_Matrix mat, const GrB_Index* rows, const GrB_Index* cols, const std::complex<double>* vals, GrB_Index nvals) {
-            return GxB_Matrix_build_FC64(mat, rows, cols, vals, nvals, GxB_PLUS_FC64);
+            return GxB_Matrix_build_FC64(mat, rows, cols, reinterpret_cast<const GxB_FC64_t*>(vals), nvals, GxB_PLUS_FC64);
         }
 
         static GrB_Info set_element(GrB_Scalar scalar, const std::complex<double>& x) {
-            return GxB_Scalar_setElement_FC64(scalar, x);
+            return GxB_Scalar_setElement_FC64(scalar, reinterpret_cast<const GxB_FC64_t&>(x));
         }
 
         static GrB_Info GrB_Matrix_extractTuples(GrB_Index *I, GrB_Index *J, std::complex<double> *X, GrB_Index *nvals, const GrB_Matrix& A) {
-            return GxB_Matrix_extractTuples_FC64(I, J, X, nvals, A);
+            return GxB_Matrix_extractTuples_FC64(I, J, reinterpret_cast<GxB_FC64_t*>(X), nvals, A);
         }
 
 #if FMM_GXB_ITERATORS
         static std::complex<double> GxB_Iterator_get(GxB_Iterator iterator) {
-            return GxB_Iterator_get_FC64(iterator);
+            return reinterpret_cast<std::complex<double>&>(GxB_Iterator_get_FC64(iterator));
         }
 #endif
         static GrB_Info build_vector(GrB_Vector vec, const GrB_Index* indices, const std::complex<double>* vals, GrB_Index nvals) {
-            return GxB_Vector_build_FC64(vec, indices, vals, nvals, GxB_PLUS_FC64);
+            return GxB_Vector_build_FC64(vec, indices, reinterpret_cast<const GxB_FC64_t*>(vals), nvals, GxB_PLUS_FC64);
         }
 
         static GrB_Info GrB_Vector_extractTuples(GrB_Index *I, std::complex<double> *X, GrB_Index *nvals, const GrB_Vector& A) {
-            return GxB_Vector_extractTuples_FC64(I, X, nvals, A);
+            return GxB_Vector_extractTuples_FC64(I, reinterpret_cast<GxB_FC64_t*>(X), nvals, A);
         }
     };
 #endif


Test patch:
diff --git a/tests/graphblas_test.cpp b/tests/graphblas_test.cpp
index c265362..b8e2944 100644
--- a/tests/graphblas_test.cpp
+++ b/tests/graphblas_test.cpp
@@ -119,8 +119,8 @@ GrB_Index size(const GrB_Vector& m) {
 bool element_equals(const GrB_Matrix& lhs, const GrB_Matrix& rhs, GrB_Index row, GrB_Index col) {
     // every tested type can be converted to std::complex<double>
     std::complex<double> l, r;
-    auto l_ret = GxB_Matrix_extractElement_FC64(&l, lhs, row, col);
-    auto r_ret = GxB_Matrix_extractElement_FC64(&r, rhs, row, col);
+    auto l_ret = GxB_Matrix_extractElement_FC64(reinterpret_cast<GxB_FC64_t*>(&l), lhs, row, col);
+    auto r_ret = GxB_Matrix_extractElement_FC64(reinterpret_cast<GxB_FC64_t*>(&r), rhs, row, col);
     if (l_ret != r_ret) {
         return false;
     }
@@ -139,8 +139,8 @@ bool element_equals(const GrB_Matrix& lhs, const GrB_Matrix& rhs, GrB_Index row,
 bool element_equals(const GrB_Vector& lhs, const GrB_Vector& rhs, GrB_Index row) {
     // every tested type can be converted to std::complex<double>
     std::complex<double> l, r;
-    auto l_ret = GxB_Vector_extractElement_FC64(&l, lhs, row);
-    auto r_ret = GxB_Vector_extractElement_FC64(&r, rhs, row);
+    auto l_ret = GxB_Vector_extractElement_FC64(reinterpret_cast<GxB_FC64_t*>(&l), lhs, row);
+    auto r_ret = GxB_Vector_extractElement_FC64(reinterpret_cast<GxB_FC64_t*>(&r), rhs, row);
     if (l_ret != r_ret) {
         return false;
     }
@@ -160,7 +160,7 @@ bool element_equals(const array_matrix<std::complex<double>>& lhs, const GrB_Mat
     // every tested type can be converted to std::complex<double>
     std::complex<double> l, r;
     l = lhs((int64_t)row, (int64_t)col);
-    auto r_ret = GxB_Matrix_extractElement_FC64(&r, rhs, row, col);
+    auto r_ret = GxB_Matrix_extractElement_FC64(reinterpret_cast<GxB_FC64_t*>(&r), rhs, row, col);
 
     if (r_ret == GrB_NO_VALUE && l.real() == 0) {
         return true;
@@ -256,7 +256,7 @@ bool element_equals(const array_matrix<std::complex<double>>& lhs, const GrB_Vec
     // every tested type can be converted to std::complex<double>
     std::complex<double> l, r;
     l = lhs((int64_t)row, (int64_t)0);
-    auto r_ret = GxB_Vector_extractElement_FC64(&r, rhs, row);
+    auto r_ret = GxB_Vector_extractElement_FC64(reinterpret_cast<GxB_FC64_t*>(&r), rhs, row);
 
     if (r_ret == GrB_NO_VALUE && l.real() == 0) {
         return true;