| // This file is part of Eigen, a lightweight C++ template library | |
| // for linear algebra. | |
| // | |
| // Copyright (C) 2016 Benoit Steiner <benoit.steiner.goog@gmail.com> | |
| // | |
| // 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/. | |
| #define EIGEN_TEST_NO_LONGDOUBLE | |
| #define EIGEN_USE_GPU | |
| #include "main.h" | |
| #include <unsupported/Eigen/Tensor> | |
| using Eigen::Tensor; | |
| template <typename T> | |
| void test_cuda_complex_cwise_ops() { | |
| const int kNumItems = 2; | |
| std::size_t complex_bytes = kNumItems * sizeof(std::complex<T>); | |
| std::complex<T>* d_in1; | |
| std::complex<T>* d_in2; | |
| std::complex<T>* d_out; | |
| cudaMalloc((void**)(&d_in1), complex_bytes); | |
| cudaMalloc((void**)(&d_in2), complex_bytes); | |
| cudaMalloc((void**)(&d_out), complex_bytes); | |
| Eigen::GpuStreamDevice stream; | |
| Eigen::GpuDevice gpu_device(&stream); | |
| Eigen::TensorMap<Eigen::Tensor<std::complex<T>, 1, 0, int>, Eigen::Aligned> gpu_in1(d_in1, kNumItems); | |
| Eigen::TensorMap<Eigen::Tensor<std::complex<T>, 1, 0, int>, Eigen::Aligned> gpu_in2(d_in2, kNumItems); | |
| Eigen::TensorMap<Eigen::Tensor<std::complex<T>, 1, 0, int>, Eigen::Aligned> gpu_out(d_out, kNumItems); | |
| const std::complex<T> a(static_cast<T>(3.14), static_cast<T>(2.7)); | |
| const std::complex<T> b(static_cast<T>(-10.6), static_cast<T>(1.4)); | |
| gpu_in1.device(gpu_device) = gpu_in1.constant(a); | |
| gpu_in2.device(gpu_device) = gpu_in2.constant(b); | |
| enum CwiseOp { Add = 0, Sub, Mul, Div, Neg, NbOps }; | |
| Tensor<std::complex<T>, 1, 0, int> actual(kNumItems); | |
| for (int op = Add; op < NbOps; op++) { | |
| std::complex<T> expected; | |
| switch (static_cast<CwiseOp>(op)) { | |
| case Add: | |
| gpu_out.device(gpu_device) = gpu_in1 + gpu_in2; | |
| expected = a + b; | |
| break; | |
| case Sub: | |
| gpu_out.device(gpu_device) = gpu_in1 - gpu_in2; | |
| expected = a - b; | |
| break; | |
| case Mul: | |
| gpu_out.device(gpu_device) = gpu_in1 * gpu_in2; | |
| expected = a * b; | |
| break; | |
| case Div: | |
| gpu_out.device(gpu_device) = gpu_in1 / gpu_in2; | |
| expected = a / b; | |
| break; | |
| case Neg: | |
| gpu_out.device(gpu_device) = -gpu_in1; | |
| expected = -a; | |
| break; | |
| case NbOps: | |
| break; | |
| } | |
| assert(cudaMemcpyAsync(actual.data(), d_out, complex_bytes, cudaMemcpyDeviceToHost, gpu_device.stream()) == | |
| cudaSuccess); | |
| assert(cudaStreamSynchronize(gpu_device.stream()) == cudaSuccess); | |
| for (int i = 0; i < kNumItems; ++i) { | |
| VERIFY_IS_APPROX(actual(i), expected); | |
| } | |
| } | |
| cudaFree(d_in1); | |
| cudaFree(d_in2); | |
| cudaFree(d_out); | |
| } | |
| EIGEN_DECLARE_TEST(test_cxx11_tensor_complex_cwise_ops) { | |
| CALL_SUBTEST(test_cuda_complex_cwise_ops<float>()); | |
| CALL_SUBTEST(test_cuda_complex_cwise_ops<double>()); | |
| } |