// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2014 Benoit Steiner // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COMPLEX_CUDA_H #define EIGEN_COMPLEX_CUDA_H // clang-format off namespace Eigen { namespace internal { #if defined(EIGEN_CUDACC) && defined(EIGEN_USE_GPU) // Many std::complex methods such as operator+, operator-, operator* and // operator/ are not constexpr. Due to this, clang does not treat them as device // functions and thus Eigen functors making use of these operators fail to // compile. Here, we manually specialize these functors for complex types when // building for CUDA to avoid non-constexpr methods. // Sum template struct scalar_sum_op, const std::complex > : binary_op_base, const std::complex > { typedef typename std::complex result_type; EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex operator() (const std::complex& a, const std::complex& b) const { return std::complex(numext::real(a) + numext::real(b), numext::imag(a) + numext::imag(b)); } }; template struct scalar_sum_op, std::complex > : scalar_sum_op, const std::complex > {}; // Difference template struct scalar_difference_op, const std::complex > : binary_op_base, const std::complex > { typedef typename std::complex result_type; EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex operator() (const std::complex& a, const std::complex& b) const { return std::complex(numext::real(a) - numext::real(b), numext::imag(a) - numext::imag(b)); } }; template struct scalar_difference_op, std::complex > : scalar_difference_op, const std::complex > {}; // Product template struct scalar_product_op, const std::complex > : binary_op_base, const std::complex > { enum { Vectorizable = packet_traits >::HasMul }; typedef typename std::complex result_type; EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex operator() (const std::complex& a, const std::complex& b) const { const T a_real = numext::real(a); const T a_imag = numext::imag(a); const T b_real = numext::real(b); const T b_imag = numext::imag(b); return std::complex(a_real * b_real - a_imag * b_imag, a_real * b_imag + a_imag * b_real); } }; template struct scalar_product_op, std::complex > : scalar_product_op, const std::complex > {}; // Quotient template struct scalar_quotient_op, const std::complex > : binary_op_base, const std::complex > { enum { Vectorizable = packet_traits >::HasDiv }; typedef typename std::complex result_type; EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex operator() (const std::complex& a, const std::complex& b) const { const T a_real = numext::real(a); const T a_imag = numext::imag(a); const T b_real = numext::real(b); const T b_imag = numext::imag(b); const T norm = T(1) / (b_real * b_real + b_imag * b_imag); return std::complex((a_real * b_real + a_imag * b_imag) * norm, (a_imag * b_real - a_real * b_imag) * norm); } }; template struct scalar_quotient_op, std::complex > : scalar_quotient_op, const std::complex > {}; #endif } // end namespace internal } // end namespace Eigen #endif // EIGEN_COMPLEX_CUDA_H