t-sakashita / rokko

Integrated Interface for libraries of eigenvalue decomposition
Boost Software License 1.0
10 stars 2 forks source link

Intelコンパイラでの複素数型の変換エラー #570

Closed t-sakashita closed 4 years ago

t-sakashita commented 4 years ago
In file included from /home/k0515/k051500/development/rokko/rokko/elpa/diagonalize.hpp(18),
                 from /home/k0515/k051500/development/rokko/rokko/elpa/solver.hpp(17),
                 from /home/k0515/k051500/development/rokko/rokko/elpa/elpa.cpp(13):
/home/k0515/k051500/development/rokko/rokko/elpa.hpp(55): error: argument of type "std::complex<double> *" is incompatible with parameter of type "double __complex__ *"
    elpa_eigenvectors_dc(handle, complex_cast(a), ev, complex_cast(q), &error);
t-sakashita commented 4 years ago

https://en.cppreference.com/w/c/numeric/complex https://en.cppreference.com/w/c/language/arithmetic_types#Complex_floating_types

t-sakashita commented 4 years ago
template <typename T>
using Complex = T[2];

template <typename T>
Complex<T>* elpa_complex_cast(std::complex<T>* c) {
  return &reinterpret_cast<T(&)[2]>(*c);
}

clang++では、コンパイルエラー

/Users/sakashitatatsuya/development/rokko/rokko/elpa.hpp:63:3: error: no matching function for call to
      'elpa_eigenvectors_dc'
  elpa_eigenvectors_dc(handle, elpa_complex_cast(a), ev, complex_cast(q), &error);
  ^~~~~~~~~~~~~~~~~~~~
/Users/sakashitatatsuya/rokko/elpa/elpa-2020.05.001-1/Debug/include/elpa_openmp-2020.05.001/elpa/elpa_generated.h:140:7: note: 
      candidate function not viable: no known conversion from 'Complex<double> *' (aka 'double (*)[2]') to
      '_Complex double *' for 2nd argument
 void elpa_eigenvectors_dc(elpa_t handle, double complex *a, double *ev, double complex *q, int *error);
      ^
1 error generated.

clang++のC99では、_Complexが用いられる。

t-sakashita commented 4 years ago

C言語のみでラッパーを書く方法を検討する。

t-sakashita commented 4 years ago
template <typename T>
struct complex_type_traits {
  using type = T;
};

template <>
struct complex_type_traits<double> {
  using type = __complex__ double;
};

template <>
struct complex_type_traits<float> {
  using type = __complex__ float;
};

template<typename T>
using Complex = typename complex_type_traits<T>::type;

template <typename T>
Complex<T>* elpa_complex_cast(std::complex<T>* c) {
  return reinterpret_cast<Complex<T>*>(c);
}
t-sakashita commented 4 years ago

キーワード__complex__は、GNU互換機能である。 https://www.ibm.com/support/knowledgecenter/ja/SSXVZZ_16.1.0/com.ibm.xlcpp161.lelinux.doc/language_ref/gcc_exts_both.html

以下でも、コンパイルが通ることを確認した。GNU互換機能のためのオプションは不要であった。

t-sakashita commented 4 years ago

オーバーロードに書き換えた。エイリアステンプレートは不要。

inline auto elpa_complex_cast(std::complex<double>* c) {
  return reinterpret_cast<__complex__ double*>(c);
}

inline auto elpa_complex_cast(std::complex<float>* c) {
  return reinterpret_cast<__complex__ float*>(c);
}

const版も不要。

t-sakashita commented 4 years ago

2f891652075159a991396e1536d9c5bb14a227f1