[test-suite] r285245 - [CUDA] [test-suite] Add tests for std::complex.

Justin Lebar via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 26 15:01:57 PDT 2016


Author: jlebar
Date: Wed Oct 26 17:01:57 2016
New Revision: 285245

URL: http://llvm.org/viewvc/llvm-project?rev=285245&view=rev
Log:
[CUDA] [test-suite] Add tests for std::complex.

Reviewers: jhen

Subscribers: beanz, llvm-commits, mgorny

Differential Revision: https://reviews.llvm.org/D24971

Added:
    test-suite/trunk/External/CUDA/complex.cu
    test-suite/trunk/External/CUDA/complex.reference_output
Modified:
    test-suite/trunk/External/CUDA/CMakeLists.txt

Modified: test-suite/trunk/External/CUDA/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/External/CUDA/CMakeLists.txt?rev=285245&r1=285244&r2=285245&view=diff
==============================================================================
--- test-suite/trunk/External/CUDA/CMakeLists.txt (original)
+++ test-suite/trunk/External/CUDA/CMakeLists.txt Wed Oct 26 17:01:57 2016
@@ -47,6 +47,7 @@ macro(create_local_cuda_tests VariantSuf
   create_one_local_test(axpy axpy.cu)
   create_one_local_test(algorithm algorithm.cu)
   create_one_local_test(cmath cmath.cu)
+  create_one_local_test(complex complex.cu)
   create_one_local_test(math_h math_h.cu)
   create_one_local_test(empty empty.cu)
   create_one_local_test(printf printf.cu)
@@ -250,7 +251,7 @@ macro(create_cuda_tests)
       set(_Std_LDFLAGS -std=${_Std})
       foreach(_GccPath IN LISTS GCC_PATHS)
         get_version(_GccVersion ${_GccPath})
-        # Our <algorithm> tests don't work with libstdc++ earlier than 5.0.
+        # libstdc++ seems not to support C++14 before version 5.0.
         if (${_Std} STREQUAL "c++14" AND ${_GccVersion} VERSION_LESS "5.0")
           continue()
         endif()

Added: test-suite/trunk/External/CUDA/complex.cu
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/External/CUDA/complex.cu?rev=285245&view=auto
==============================================================================
--- test-suite/trunk/External/CUDA/complex.cu (added)
+++ test-suite/trunk/External/CUDA/complex.cu Wed Oct 26 17:01:57 2016
@@ -0,0 +1,444 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <stdio.h>
+#include <complex>
+
+// These are loosely adapted from libc++'s tests.  In general, we don't care a
+// ton about verifying the return types or results we get, on the assumption
+// that our standard library is correct. But we care deeply about calling every
+// overload of every function (so that we verify that everything compiles).
+//
+// We do care about the results of complex multiplication / division, since
+// these use code we've written.
+
+// These tests are pretty annoying to write without C++11, so we require that.
+// In addition, these tests currently don't compile with libc++, because of the
+// issue in https://reviews.llvm.org/D25403.
+//
+// TODO: Once that issue is resolved, take out !defined(_LIBCPP_VERSION) here.
+#if __cplusplus >= 201103L && !defined(_LIBCPP_VERSION)
+
+#include <type_traits>
+
+template <class T>
+__device__ double promote(
+    T, typename std::enable_if<std::is_integral<T>::value>::type* = 0);
+__device__ float promote(float);
+__device__ double promote(double);
+
+__device__ void is_about(float x, float y) {
+  assert(std::abs((x - y) / (x + y)) < 1.e-6);
+}
+__device__ void is_about(double x, double y) {
+  assert(std::abs((x - y) / (x + y)) < 1.e-14);
+}
+
+template <class T>
+__device__ void test_promotion_impl(T x) {
+  assert(std::imag(x) == 0);
+  assert(std::real(x) == x);
+
+  using Promoted = decltype(promote(x));
+  assert(std::arg(x) == arg(std::complex<Promoted>(x, 0)));
+  assert(std::conj(x) == conj(std::complex<Promoted>(x, 0)));
+  assert(std::norm(x) == norm(std::complex<Promoted>(x, 0)));
+#ifndef __GLIBCXX__
+  // libstdc++'s implementation of proj is completely broken, see
+  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61761.
+  assert(std::proj(x) == proj(std::complex<Promoted>(x, 0)));
+#endif
+}
+
+__device__ void test_promotion() {
+  int vals[] = {0, 1, 10};
+  for (int i : vals) {
+    test_promotion_impl<float>(i);
+    test_promotion_impl<double>(i);
+    test_promotion_impl<int>(i);
+    test_promotion_impl<unsigned>(i);
+    test_promotion_impl<long long>(i);
+  }
+}
+
+__device__ void test_literals() {
+#if __cplusplus >= 201402L
+  using namespace std::literals::complex_literals;
+
+  {
+    std::complex<double> c1 = 3.0i;
+    assert(c1 == std::complex<double>(0, 3.0));
+    auto c2 = 3i;
+    assert(c1 == c2);
+  }
+
+  {
+    std::complex<float> c1 = 3.0if;
+    assert(c1 == std::complex<float>(0, 3.0));
+    auto c2 = 3if;
+    assert(c1 == c2);
+  }
+#endif
+}
+
+template <class T>
+__device__ void test_assignment_real() {
+  std::complex<T> c;
+  c = 1.5;
+  assert(c.real() == 1.5);
+  assert(c.imag() == 0);
+}
+
+template <class T, class U>
+__device__ void test_assignment_complex() {
+  std::complex<T> c;
+  std::complex<T> c2(1.5, 2.5);
+  c = c2;
+  assert(c.real() == 1.5);
+  assert(c.imag() == 2.5);
+}
+
+template <class T>
+__device__ void test_plus_equals() {
+  {
+    std::complex<T> c;
+    c += 1.5;
+    assert(c.real() == 1.5);
+    assert(c.imag() == 0);
+  }
+
+  {
+    std::complex<T> c;
+    const std::complex<T> c2(1.5, 2.5);
+    c += c2;
+    c += c2;
+    assert(c.real() == 3);
+    assert(c.imag() == 5);
+
+    std::complex<T> c3;
+
+    c3 = c;
+    std::complex<int> ic(1, 1);
+    c3 += ic;
+    assert(c3.real() == 4);
+    assert(c3.imag() == 6);
+
+    c3 = c;
+    std::complex<float> fc(1, 1);
+    c3 += fc;
+    assert(c3.real() == 4);
+    assert(c3.imag() == 6);
+  }
+}
+
+template <class T>
+__device__ void test_minus_equals() {
+  {
+    std::complex<T> c;
+    c -= 1.5;
+    assert(c.real() == -1.5);
+    assert(c.imag() == 0);
+  }
+
+  {
+    std::complex<T> c;
+    const std::complex<T> c2(1.5, 2.5);
+    assert(c.real() == 0);
+    assert(c.imag() == 0);
+    c -= c2;
+    assert(c.real() == -1.5);
+    assert(c.imag() == -2.5);
+    c -= c2;
+    assert(c.real() == -3);
+    assert(c.imag() == -5);
+
+    std::complex<T> c3;
+
+    c3 = c;
+    std::complex<int> ic (1,1);
+    c3 -= ic;
+    assert(c3.real() == -4);
+    assert(c3.imag() == -6);
+
+    c3 = c;
+    std::complex<float> fc (1,1);
+    c3 -= fc;
+    assert(c3.real() == -4);
+    assert(c3.imag() == -6);
+  }
+}
+
+template <class T>
+__device__ void test_times_equals() {
+  {
+    std::complex<T> c(1);
+    c *= 1.5;
+    c *= 1.5;
+    c *= -1.5;
+    c.imag(2);
+    c *= 1.5;
+    assert(c.real() == -5.0625);
+    assert(c.imag() == 3);
+  }
+
+  {
+    std::complex<T> c(1);
+    const std::complex<T> c2(1.5, 2.5);
+    c *= c2;
+    c *= c2;
+    assert(c.real() == -4);
+    assert(c.imag() == 7.5);
+
+    std::complex<T> c3;
+
+    c3 = c;
+    std::complex<int> ic (1,1);
+    c3 *= ic;
+    assert(c3.real() == -11.5);
+    assert(c3.imag() ==   3.5);
+
+    c3 = c;
+    std::complex<float> fc (1,1);
+    c3 *= fc;
+    assert(c3.real() == -11.5);
+    assert(c3.imag() ==   3.5);
+  }
+}
+
+template <class T>
+__device__ void test_divide_equals() {
+  {
+    std::complex<T> c(1);
+    c /= 0.5;
+    c /= 0.5;
+    c /= -0.5;
+    c.imag(2);
+    c /= 0.5;
+    assert(c.real() == -16);
+    assert(c.imag() == 4);
+  }
+
+  {
+    std::complex<T> c(-4, 7.5);
+    const std::complex<T> c2(1.5, 2.5);
+    assert(c.real() == -4);
+    assert(c.imag() == 7.5);
+    c /= c2;
+    assert(c.real() == 1.5);
+    assert(c.imag() == 2.5);
+    c /= c2;
+    assert(c.real() == 1);
+    assert(c.imag() == 0);
+
+    std::complex<T> c3;
+
+    c3 = c;
+    std::complex<int> ic (1,1);
+    c3 /= ic;
+    assert(c3.real() ==  0.5);
+    assert(c3.imag() == -0.5);
+
+    c3 = c;
+    std::complex<float> fc (1,1);
+    c3 /= fc;
+    assert(c3.real() ==  0.5);
+    assert(c3.imag() == -0.5);
+  }
+}
+
+template <class T>
+__device__ void test_construct() {
+  {
+    const std::complex<T> c;
+    assert(c.real() == 0);
+    assert(c.imag() == 0);
+  }
+  {
+    const std::complex<T> c = 7.5;
+    assert(c.real() == 7.5);
+    assert(c.imag() == 0);
+  }
+  {
+    const std::complex<T> c(8.5);
+    assert(c.real() == 8.5);
+    assert(c.imag() == 0);
+  }
+  {
+    const std::complex<T> c(10.5, -9.5);
+    assert(c.real() == 10.5);
+    assert(c.imag() == -9.5);
+  }
+#if __cplusplus >= 201103L
+  {
+    constexpr std::complex<T> c;
+    static_assert(c.real() == 0, "");
+    static_assert(c.imag() == 0, "");
+  }
+  {
+    constexpr std::complex<T> c = 7.5;
+    static_assert(c.real() == 7.5, "");
+    static_assert(c.imag() == 0, "");
+  }
+  {
+    constexpr std::complex<T> c(8.5);
+    static_assert(c.real() == 8.5, "");
+    static_assert(c.imag() == 0, "");
+  }
+  {
+    constexpr std::complex<T> c(10.5, -9.5);
+    static_assert(c.real() == 10.5, "");
+    static_assert(c.imag() == -9.5, "");
+  }
+#endif
+}
+
+template <class T>
+__device__ void test_construct_integral() {
+#if __cplusplus >= 201402L
+  constexpr std::complex<T> c1;
+  static_assert(c1.real() == 0, "");
+  static_assert(c1.imag() == 0, "");
+  constexpr std::complex<T> c2(3);
+  static_assert(c2.real() == 3, "");
+  static_assert(c2.imag() == 0, "");
+  constexpr std::complex<T> c3(3, 4);
+  static_assert(c3.real() == 3, "");
+  static_assert(c3.imag() == 4, "");
+#endif
+}
+
+template <class T>
+__device__ void test_set_real_imag() {
+  std::complex<T> c;
+  c.real(3.5);
+  assert(c.real() == 3.5);
+  assert(c.imag() == 0);
+  c.imag(4.5);
+  assert(c.real() == 3.5);
+  assert(c.imag() == 4.5);
+}
+
+template <class T>
+__device__ void test_transcendentals_etc() {
+  assert(sin(std::complex<T>(0, 0)) == std::complex<T>(0, 0));
+  assert(sinh(std::complex<T>(0, 0)) == std::complex<T>(0, 0));
+  assert(asin(std::complex<T>(0, 0)) == std::complex<T>(0, 0));
+  assert(asinh(std::complex<T>(0, 0)) == std::complex<T>(0, 0));
+
+  assert(cos(std::complex<T>(0, 0)) == std::complex<T>(1, 0));
+  assert(cosh(std::complex<T>(0, 0)) == std::complex<T>(1, 0));
+  {
+    std::complex<T> c = acos(std::complex<T>(0, 0));
+    is_about(real(c), T(M_PI_2));
+    assert(std::abs(imag(c)) < 1.e-6);
+  }
+  {
+    std::complex<T> c = acosh(std::complex<T>(0, 0));
+    assert(std::abs(real(c)) < 1.e-6);
+    is_about(imag(c), T(M_PI_2));
+  }
+
+  assert(tan(std::complex<T>(0, 0)) == std::complex<T>(0, 0));
+  assert(tanh(std::complex<T>(0, 0)) == std::complex<T>(0, 0));
+  assert(atan(std::complex<T>(0, 0)) == std::complex<T>(0, 0));
+  assert(atanh(std::complex<T>(0, 0)) == std::complex<T>(0, 0));
+
+  assert(exp(std::complex<T>(0, 0)) == std::complex<T>(1, 0));
+  assert(log10(std::complex<T>(0, 0)) == std::complex<T>(-INFINITY, 0));
+  assert(log(std::complex<T>(0, 0)) == std::complex<T>(-INFINITY, 0));
+
+  {
+    std::complex<T> c = pow(std::complex<T>(2, 3), std::complex<T>(2, 0));
+    is_about(real(c), -5);
+    is_about(imag(c), 12);
+  }
+  {
+    std::complex<T> c = pow(std::complex<T>(2, 3), T(2));
+    is_about(real(c), -5);
+    is_about(imag(c), 12);
+  }
+  {
+    std::complex<T> c = pow(T(2), std::complex<T>(2));
+    is_about(real(c), 4);
+    assert(std::abs(imag(c)) < 1.e-6);
+  }
+  {
+    std::complex<T> c = sqrt(std::complex<T>(64, 0));
+    is_about(real(c), 8);
+    assert(std::abs(imag(c)) < 1.e-6);
+  }
+
+  // "etc."
+  assert(abs(std::complex<T>(3, 4)) == 5);
+  assert(norm(std::complex<T>(3, 4)) == 25);
+  assert(arg(std::complex<T>(1, 0)) == 0);
+  assert(conj(std::complex<T>(1, 2)) == std::complex<T>(1, -2));
+
+  assert(std::polar(T(0)) == std::complex<T>(0, 0));
+  assert(std::polar(T(1)) == std::complex<T>(1, 0));
+  assert(std::polar(T(100)) == std::complex<T>(100, 0));
+  assert(std::polar(T(0), T(0)) == std::complex<T>(0, 0));
+  assert(std::polar(T(1), T(0)) == std::complex<T>(1, 0));
+  assert(std::polar(T(100), T(0)) == std::complex<T>(100, 0));
+
+#ifndef __GLIBCXX__
+  // libstdc++'s implementation of proj is completely broken, see
+  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61761.
+  assert(std::proj(std::complex<T>(1, 2)) == std::complex<T>(1, 2));
+  assert(std::proj(std::complex<T>(-1, 2)) == std::complex<T>(-1, 2));
+  assert(std::proj(std::complex<T>(1, -2)) == std::complex<T>(1, -2));
+  assert(std::proj(std::complex<T>(-1, -2)) == std::complex<T>(-1, -2));
+#endif
+}
+
+__global__ void tests() {
+  test_promotion();
+  test_literals();
+  test_assignment_real<float>();
+  test_assignment_real<double>();
+
+  test_assignment_complex<float, float>();
+  test_assignment_complex<float, double>();
+  test_assignment_complex<double, float>();
+  test_assignment_complex<double, double>();
+
+  test_plus_equals<float>();
+  test_plus_equals<double>();
+  test_minus_equals<float>();
+  test_minus_equals<double>();
+  test_times_equals<float>();
+  test_times_equals<double>();
+  test_divide_equals<float>();
+  test_divide_equals<double>();
+
+  test_construct<float>();
+  test_construct<double>();
+  test_construct_integral<int>();
+
+  test_set_real_imag<float>();
+  test_set_real_imag<double>();
+
+  test_transcendentals_etc<float>();
+  test_transcendentals_etc<double>();
+}
+#else
+__global__ void tests() {}
+#endif
+
+int main() {
+  tests<<<1, 1>>>();
+  cudaError_t err = cudaDeviceSynchronize();
+  if (err != cudaSuccess) {
+    printf("CUDA error %d\n", (int)err);
+    return 1;
+  }
+  printf("Success!\n");
+  return 0;
+}

Added: test-suite/trunk/External/CUDA/complex.reference_output
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/External/CUDA/complex.reference_output?rev=285245&view=auto
==============================================================================
--- test-suite/trunk/External/CUDA/complex.reference_output (added)
+++ test-suite/trunk/External/CUDA/complex.reference_output Wed Oct 26 17:01:57 2016
@@ -0,0 +1,2 @@
+Success!
+exit 0




More information about the llvm-commits mailing list