1e5dd7070Spatrick/*===---- complex - CUDA wrapper for <complex> ------------------------------=== 2e5dd7070Spatrick * 3e5dd7070Spatrick * Permission is hereby granted, free of charge, to any person obtaining a copy 4e5dd7070Spatrick * of this software and associated documentation files (the "Software"), to deal 5e5dd7070Spatrick * in the Software without restriction, including without limitation the rights 6e5dd7070Spatrick * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7e5dd7070Spatrick * copies of the Software, and to permit persons to whom the Software is 8e5dd7070Spatrick * furnished to do so, subject to the following conditions: 9e5dd7070Spatrick * 10e5dd7070Spatrick * The above copyright notice and this permission notice shall be included in 11e5dd7070Spatrick * all copies or substantial portions of the Software. 12e5dd7070Spatrick * 13e5dd7070Spatrick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14e5dd7070Spatrick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15e5dd7070Spatrick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16e5dd7070Spatrick * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e5dd7070Spatrick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18e5dd7070Spatrick * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19e5dd7070Spatrick * THE SOFTWARE. 20e5dd7070Spatrick * 21e5dd7070Spatrick *===-----------------------------------------------------------------------=== 22e5dd7070Spatrick */ 23e5dd7070Spatrick 24e5dd7070Spatrick#ifndef __CLANG_CUDA_WRAPPERS_COMPLEX 25e5dd7070Spatrick#define __CLANG_CUDA_WRAPPERS_COMPLEX 26e5dd7070Spatrick 27e5dd7070Spatrick// Wrapper around <complex> that forces its functions to be __host__ 28e5dd7070Spatrick// __device__. 29e5dd7070Spatrick 30e5dd7070Spatrick// First, include host-only headers we think are likely to be included by 31e5dd7070Spatrick// <complex>, so that the pragma below only applies to <complex> itself. 32e5dd7070Spatrick#if __cplusplus >= 201103L 33e5dd7070Spatrick#include <type_traits> 34e5dd7070Spatrick#endif 35e5dd7070Spatrick#include <stdexcept> 36e5dd7070Spatrick#include <cmath> 37e5dd7070Spatrick#include <sstream> 38e5dd7070Spatrick 39e5dd7070Spatrick// Next, include our <algorithm> wrapper, to ensure that device overloads of 40e5dd7070Spatrick// std::min/max are available. 41e5dd7070Spatrick#include <algorithm> 42e5dd7070Spatrick 43e5dd7070Spatrick#pragma clang force_cuda_host_device begin 44e5dd7070Spatrick 45e5dd7070Spatrick// When compiling for device, ask libstdc++ to use its own implements of 46e5dd7070Spatrick// complex functions, rather than calling builtins (which resolve to library 47e5dd7070Spatrick// functions that don't exist when compiling CUDA device code). 48e5dd7070Spatrick// 49e5dd7070Spatrick// This is a little dicey, because it causes libstdc++ to define a different 50e5dd7070Spatrick// set of overloads on host and device. 51e5dd7070Spatrick// 52e5dd7070Spatrick// // Present only when compiling for host. 53e5dd7070Spatrick// __host__ __device__ void complex<float> sin(const complex<float>& x) { 54e5dd7070Spatrick// return __builtin_csinf(x); 55e5dd7070Spatrick// } 56e5dd7070Spatrick// 57e5dd7070Spatrick// // Present when compiling for host and for device. 58e5dd7070Spatrick// template <typename T> 59e5dd7070Spatrick// void __host__ __device__ complex<T> sin(const complex<T>& x) { 60e5dd7070Spatrick// return complex<T>(sin(x.real()) * cosh(x.imag()), 61e5dd7070Spatrick// cos(x.real()), sinh(x.imag())); 62e5dd7070Spatrick// } 63e5dd7070Spatrick// 64e5dd7070Spatrick// This is safe because when compiling for device, all function calls in 65e5dd7070Spatrick// __host__ code to sin() will still resolve to *something*, even if they don't 66e5dd7070Spatrick// resolve to the same function as they resolve to when compiling for host. We 67e5dd7070Spatrick// don't care that they don't resolve to the right function because we won't 68e5dd7070Spatrick// codegen this host code when compiling for device. 69e5dd7070Spatrick 70e5dd7070Spatrick#pragma push_macro("_GLIBCXX_USE_C99_COMPLEX") 71e5dd7070Spatrick#pragma push_macro("_GLIBCXX_USE_C99_COMPLEX_TR1") 72e5dd7070Spatrick#define _GLIBCXX_USE_C99_COMPLEX 0 73e5dd7070Spatrick#define _GLIBCXX_USE_C99_COMPLEX_TR1 0 74e5dd7070Spatrick 75*a9ac8606Spatrick// Work around a compatibility issue with libstdc++ 11.1.0 76*a9ac8606Spatrick// https://bugs.llvm.org/show_bug.cgi?id=50383 77*a9ac8606Spatrick#pragma push_macro("__failed_assertion") 78*a9ac8606Spatrick#if _GLIBCXX_RELEASE == 11 79*a9ac8606Spatrick#define __failed_assertion __cuda_failed_assertion 80*a9ac8606Spatrick#endif 81*a9ac8606Spatrick 82e5dd7070Spatrick#include_next <complex> 83e5dd7070Spatrick 84*a9ac8606Spatrick#pragma pop_macro("__failed_assertion") 85e5dd7070Spatrick#pragma pop_macro("_GLIBCXX_USE_C99_COMPLEX_TR1") 86e5dd7070Spatrick#pragma pop_macro("_GLIBCXX_USE_C99_COMPLEX") 87e5dd7070Spatrick 88e5dd7070Spatrick#pragma clang force_cuda_host_device end 89e5dd7070Spatrick 90e5dd7070Spatrick#endif // include guard 91