This is an automated email from the git hooks/post-receive script.

logari81 pushed a commit to branch master
in repository getfem.

The following commit(s) were added to refs/heads/master by this push:
     new 17dd4ee3 Fix regression from previous commit due to incompatible ABI 
between GNU and Intel BLAS
17dd4ee3 is described below

commit 17dd4ee38d0878f3c2451f355b2c1f8e8b88f278
Author: Konstantinos Poulios <logar...@gmail.com>
AuthorDate: Tue Mar 26 12:46:29 2024 +0100

    Fix regression from previous commit due to incompatible ABI between GNU and 
Intel BLAS
    
      - autoconf detects if BLAS fortran functions return complex reals by
        value or as argument, and sets the GMM_BLAS_RETURN_COMPLEX_AS_ARGUMENT
        macro if necessary
      - detection in CMake still needs to be implemented, until then the user
        has to define GMM_BLAS_RETURN_COMPLEX_AS_ARGUMENT at configure time
        manually, if necessary
      - BLAS ABI should not be changed after gmm has been configured, if the
        user wants to switch to a BLAS with a different ABI nevertheless,
        the only option is to edit the gmm_arch_config.h file manually
---
 cmake/gmm_arch_config.h.in   |  3 +++
 configure.ac                 | 26 ++++++++++++++++++++++++++
 src/gmm/gmm_arch_config.h.in |  3 +++
 src/gmm/gmm_blas_interface.h | 15 +++++++++++----
 4 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/cmake/gmm_arch_config.h.in b/cmake/gmm_arch_config.h.in
index 50f47daa..dff9b566 100644
--- a/cmake/gmm_arch_config.h.in
+++ b/cmake/gmm_arch_config.h.in
@@ -22,5 +22,8 @@
 /* Use blas with 64 bits integers */
 #cmakedefine GMM_USE_BLAS64_INTERFACE
 
+/* defined if the BLAS fortran ABI does not return complex values directly 
(e.g. Intel's MKL) */
+#cmakedefine GMM_BLAS_RETURN_COMPLEX_AS_ARGUMENT
+
 /* GMM version */
 #define GMM_VERSION "@GMM_VERSION@"
diff --git a/configure.ac b/configure.ac
index 6f7d6c82..ea077f22 100644
--- a/configure.ac
+++ b/configure.ac
@@ -688,6 +688,32 @@ if test x$useblas64support = xYES; then
   AC_DEFINE(GMM_USE_BLAS64_INTERFACE,,[Use blas with 64 bits integers])
 fi
 
+# check fortran ABI with regard to complex function in BLAS
+# by defult assume a fortran ABI where complex real/double functions return by 
value
+  AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <complex>
+#if defined(GMM_USE_BLAS64_INTERFACE)
+  #define INT long
+#else
+  #define INT int
+#endif
+extern "C" {
+void cdotu_(std::complex<float>*, const INT*, const std::complex<float>*, 
const INT*,
+            const std::complex<float>*, const INT*);
+}
+int main() {
+    const INT one=1;
+    std::complex<float> x(1.,2.), y(1.,-2.), result;
+    cdotu_(&result, &one, &x, &one, &y, &one);
+    return (fabs(result.real()-5.) < 1e-8) ? 0 : 1;
+}
+  ]])],[ acx_blas_fortan_abi=Intel ], [ acx_blas_fortan_abi=GNU ], [])
+
+if test x$acx_blas_fortan_abi = xIntel; then
+  echo "BLAS found to have the Intel fortran ABI, i.e. returning complex 
function value by argument";
+  AC_DEFINE(GMM_BLAS_RETURN_COMPLEX_AS_ARGUMENT,,[defined if the BLAS fortran 
ABI does not return complex values directly (e.g. Intel's MKL)])
+fi
+
 dnl ------------------------------LAPACK TEST--------------------------------
 
 if test x"$acx_blas_ok" = xyes; then
diff --git a/src/gmm/gmm_arch_config.h.in b/src/gmm/gmm_arch_config.h.in
index 0d46b9ab..ed5bb8fa 100644
--- a/src/gmm/gmm_arch_config.h.in
+++ b/src/gmm/gmm_arch_config.h.in
@@ -21,5 +21,8 @@
 /* Use blas with 64 bits integers */
 #undef GMM_USE_BLAS64_INTERFACE
 
+/* defined if the BLAS fortran ABI does not return complex values directly 
(e.g. Intel's MKL) */
+#undef GMM_BLAS_RETURN_COMPLEX_AS_ARGUMENT
+
 /* GMM version */
 #undef GMM_VERSION
diff --git a/src/gmm/gmm_blas_interface.h b/src/gmm/gmm_blas_interface.h
index 44f99ae3..cab18d7d 100644
--- a/src/gmm/gmm_blas_interface.h
+++ b/src/gmm/gmm_blas_interface.h
@@ -152,6 +152,13 @@ namespace gmm {
 # define BLAS_C std::complex<float>
 # define BLAS_Z std::complex<double>
 
+// Hack due to BLAS ABI mess
+#if defined(GMM_BLAS_RETURN_COMPLEX_AS_ARGUMENT)
+# define BLAS_CPLX_FUNC_CALL(blasname, res, ...) blasname(&res, __VA_ARGS__)
+#else
+# define BLAS_CPLX_FUNC_CALL(blasname, res, ...) res = blasname(__VA_ARGS__)
+#endif
+
   /* ********************************************************************* */
   /* BLAS functions used.                                                  */
   /* ********************************************************************* */
@@ -252,7 +259,7 @@ namespace gmm {
     GMMLAPACK_TRACE(msg);                                                  \
     base_type res;                                                         \
     BLAS_INT inc(1), n(BLAS_INT(vect_size(y)));                            \
-    blas_name(&res, &n, &y[0], &inc, &x[0], &inc);                         \
+    BLAS_CPLX_FUNC_CALL(blas_name, res, &n, &y[0], &inc, &x[0], &inc);     \
     return res;                                                            \
   }                                                                        \
   inline base_type funcname                                                \
@@ -262,7 +269,7 @@ namespace gmm {
     const std::vector<base_type> &x = *(linalg_origin(x_));                \
     base_type res, a(x_.r);                                                \
     BLAS_INT inc(1), n(BLAS_INT(vect_size(y)));                            \
-    blas_name(&res, &n, &y[0], &inc, &x[0], &inc);                         \
+    BLAS_CPLX_FUNC_CALL(blas_name, res, &n, &y[0], &inc, &x[0], &inc);     \
     return a*res;                                                          \
   }                                                                        \
   inline base_type funcname                                                \
@@ -272,7 +279,7 @@ namespace gmm {
     const std::vector<base_type> &y = *(linalg_origin(y_));                \
     base_type res, b(bdef);                                                \
     BLAS_INT inc(1), n(BLAS_INT(vect_size(y)));                            \
-    blas_name(&res, &n, &y[0], &inc, &x[0], &inc);                         \
+    BLAS_CPLX_FUNC_CALL(blas_name, res, &n, &y[0], &inc, &x[0], &inc);     \
     return b*res;                                                          \
   }                                                                        \
   inline base_type funcname                                                \
@@ -283,7 +290,7 @@ namespace gmm {
     const std::vector<base_type> &y = *(linalg_origin(y_));                \
     base_type res, a(x_.r), b(bdef);                                       \
     BLAS_INT inc(1), n(BLAS_INT(vect_size(y)));                            \
-    blas_name(&res, &n, &y[0], &inc, &x[0], &inc);                         \
+    BLAS_CPLX_FUNC_CALL(blas_name, res, &n, &y[0], &inc, &x[0], &inc);     \
     return a*b*res;                                                        \
   }
 

Reply via email to