From 9b55a240bf41f972d678e57ed8c5523fa6093414 Mon Sep 17 00:00:00 2001
From: Christian Engwer <christian.engwer@uni-muenster.de>
Date: Wed, 25 Nov 2015 07:00:16 +0000
Subject: [PATCH] Merge branch 'feature/FS1726-complex-for-fp-only' into
 'master'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Test complex<T> for floating point T only

The standard leaves (the effect of instantiating) complex<T> for more
general T unspecified.

While we're at it, kill duplicate tests and add long double to the list.

This fixes bug flyspray/FS#1726: Now also with clang 3.7 and libstdc++ 4.9.2 on Debian 8.2, the test fvectortest can be compiled again.

See merge request !11
(cherry picked from commit 627fc0b04a130c4823dff3bade8daedc3c7bf086)

Signed-off-by: Steffen Müthing <muething@dune-project.org>
---
 dune/common/test/fvectortest.cc | 119 ++++++++++++++++++++++++++++----
 1 file changed, 106 insertions(+), 13 deletions(-)

diff --git a/dune/common/test/fvectortest.cc b/dune/common/test/fvectortest.cc
index 7cfbcf2cf..58aa2f774 100644
--- a/dune/common/test/fvectortest.cc
+++ b/dune/common/test/fvectortest.cc
@@ -17,10 +17,11 @@
 using Dune::FieldVector;
 using std::complex;
 
+// Tests that can be run without the construction of complex<rt>
 template<class ft, class rt, int d>
-struct FieldVectorMainTest
+struct FieldVectorMainTestCommons
 {
-  FieldVectorMainTest() {
+  FieldVectorMainTestCommons() {
     ft a = 1;
     FieldVector<ft,d> v(1);
     FieldVector<ft,d> w(2);
@@ -85,11 +86,6 @@ struct FieldVectorMainTest
     b = (w != v);
     b = (w == v);
 
-    // assignment to vector of complex
-    FieldVector< std::complex<rt> ,d> cv = v;
-    cv = a;
-    const FieldVector< std::complex<rt> ,d> ccv DUNE_UNUSED = x;
-
     // test istream operator
     std::stringstream s;
     for (int i=0; i<d; i++)
@@ -106,6 +102,35 @@ struct FieldVectorMainTest
   }
 };
 
+// Additional tests for floating point types, for which complex<rt> will work
+template<class ft, class rt, int d,
+         bool floating_point = std::is_floating_point<rt>::value>
+struct FieldVectorMainTest
+  : FieldVectorMainTestCommons<ft,rt,d>
+{
+  FieldVectorMainTest()
+    : FieldVectorMainTestCommons<ft,rt,d>()
+  {
+    ft a = 1;
+    FieldVector<ft,d> v(1);
+    FieldVector<ft,d> z(2);
+    const FieldVector<ft,d> x(z);
+
+    // assignment to vector of complex
+    FieldVector< std::complex<rt> ,d> cv = v;
+    cv = a;
+    const FieldVector< std::complex<rt> ,d> ccv DUNE_UNUSED = x;
+  }
+};
+
+template<class ft, class rt, int d>
+struct FieldVectorMainTest<ft,rt,d,false>
+  : FieldVectorMainTestCommons<ft,rt,d>
+{
+  FieldVectorMainTest()
+    : FieldVectorMainTestCommons<ft,rt,d>()
+  {}
+};
 
 template<class ft, class testft=ft>
 struct ScalarOperatorTest
@@ -224,7 +249,8 @@ struct Epsilon<int>
 };
 
 // scalar ordering doesn't work for complex numbers
-template <class rt, int d>
+template <class rt, int d,
+          bool floating_point = std::is_floating_point<rt>::value>
 struct DotProductTest
 {
   DotProductTest() {
@@ -290,10 +316,44 @@ struct DotProductTest
     assert(std::abs(result-ct(2)*length*I)<= myEps);
 
   }
+};
+
+// scalar ordering doesn't work for complex numbers
+template <class rt, int d>
+struct DotProductTest<rt, d, false>
+{
+  DotProductTest() {
+    DUNE_UNUSED const rt myEps = Epsilon<rt>::value();
+
+    static_assert(
+      ( Dune::is_same< typename Dune::FieldTraits<rt>::real_type, rt>::value ),
+      "DotProductTest requires real data type as template parameter!"
+      );
+
+    const FieldVector<rt,d> one(1.); // vector filled with 1
 
+    std::cout << __func__ << "\t \t ( " << Dune::className(one) << " only)" << std::endl;
+
+    const bool isRealOne = Dune::is_same<typename Dune::FieldTraits<rt>::field_type,typename Dune::FieldTraits<rt>::real_type>::value;
+    static_assert(isRealOne,"1-vector expected to be real");
+
+    rt result = rt();
+    rt length = rt(d);
+
+    // one^H*one should equal d
+    result = dot(one,one);
+    assert(abs(result-length)<= myEps);
+    result = one.dot(one);
+    assert(abs(result-length)<= myEps);
+
+    // test that dotT does not conjugate at all
+    result = dotT(one,one) + one*one;
+    assert(abs(result-rt(2)*length)<= myEps);
+  }
 };
 
-template<class ft, int d>
+template<class ft, int d,
+         bool floating_point = std::is_floating_point<ft>::value>
 struct FieldVectorTest
 {
   FieldVectorTest()
@@ -307,9 +367,23 @@ struct FieldVectorTest
   }
 };
 
-// specialization for 1d vector
+// specialisation for non-floating-point vectors
+template<class ft, int d>
+struct FieldVectorTest<ft, d, false>
+{
+  FieldVectorTest()
+  {
+    // --- test real valued vectors
+    FieldVectorMainTest<ft,ft,d>();
+    DotProductTest<ft,d>();
+    // --- test next lower dimension
+    FieldVectorTest<ft,d-1>();
+  }
+};
+
+// specialization for 1d floating point vector
 template<class ft>
-class FieldVectorTest<ft,1>
+class FieldVectorTest<ft,1,true>
 {
 public:
   FieldVectorTest()
@@ -331,6 +405,26 @@ public:
   }
 };
 
+// specialization for other 1d vectors
+template<class ft>
+class FieldVectorTest<ft,1,false>
+{
+public:
+  FieldVectorTest()
+  {
+    // --- real valued
+    FieldVectorMainTest<ft,ft,1>();
+    ScalarOperatorTest<ft>();
+    ScalarOrderingTest<ft>();
+    DotProductTest<ft,1>();
+
+    // --- test with an integer
+    ScalarOperatorTest< ft, int >();
+    // --- test next lower dimension
+    FieldVectorMainTest<ft,ft,0>();
+  }
+};
+
 // Make sure that a vector with only NaN entries has norm NaN.
 // Prior to r6914, the infinity_norm would be zero; see also FS #1147.
 void
@@ -379,8 +473,7 @@ int main()
     FieldVectorTest<int, 3>();
     FieldVectorTest<float, 3>();
     FieldVectorTest<double, 3>();
-    FieldVectorTest<int, 1>();
-    FieldVectorTest<double, 1>();
+    FieldVectorTest<long double, 3>();
 #if HAVE_GMP
     // we skip the complex test and the int test, as these will be very hard to implement with GMPField
     typedef Dune::GMPField<128u> ft;
-- 
GitLab