From e73c51aa214659d1386eb4aa32daef3ac1ab8c03 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Thu, 7 Jun 2018 19:12:06 +0200
Subject: [PATCH] remove assert.h usage in Pastis

First stage done:
- we replaced assert by homemade Assert macro which performs the same

Remaining work:
- one will replace abort/exit by exceptions throws
- finally will had quality code checker to forbid use of cassert within Pastis
---
 src/algebra/TinyMatrix.hpp    | 18 +++++++++---------
 src/algebra/TinyVector.hpp    |  6 +++---
 src/main.cpp                  |  1 -
 src/mesh/Connectivity1D.hpp   | 11 ++++++-----
 src/mesh/Connectivity2D.hpp   |  3 ++-
 src/scheme/AcousticSolver.hpp | 11 ++++++-----
 src/utils/PastisAssert.hpp    | 28 ++++++++++++++++++++++++++++
 tests/test_TinyVector.cpp     | 16 +++++++++++-----
 8 files changed, 65 insertions(+), 29 deletions(-)
 create mode 100644 src/utils/PastisAssert.hpp

diff --git a/src/algebra/TinyMatrix.hpp b/src/algebra/TinyMatrix.hpp
index 05cbd6813..577bd4fa0 100644
--- a/src/algebra/TinyMatrix.hpp
+++ b/src/algebra/TinyMatrix.hpp
@@ -1,7 +1,7 @@
 #ifndef TINY_MATRIX_HPP
 #define TINY_MATRIX_HPP
 
-#include <cassert>
+#include <PastisAssert.hpp>
 #include <iostream>
 
 #include <Types.hpp>
@@ -62,7 +62,7 @@ public:
     return std::move(AB);
   }
 
-  
+
   KOKKOS_INLINE_FUNCTION
   TinyVector<N,T> operator*(const TinyVector<N,T>& x) const
   {
@@ -98,7 +98,7 @@ public:
     }
     return os;
   }
-  
+
   KOKKOS_INLINE_FUNCTION
   TinyMatrix operator+(const TinyMatrix& A) const
   {
@@ -140,14 +140,14 @@ public:
   KOKKOS_INLINE_FUNCTION
   T& operator()(const size_t& i, const size_t& j)
   {
-    assert((i<N) and (j<N));
+    Assert((i<N) and (j<N));
     return m_values[_index(i,j)];
   }
 
   KOKKOS_INLINE_FUNCTION
   const T& operator()(const size_t& i, const size_t& j) const
   {
-    assert((i<N) and (j<N));
+    Assert((i<N) and (j<N));
     return m_values[_index(i,j)];
   }
 
@@ -229,7 +229,7 @@ public:
 
   KOKKOS_INLINE_FUNCTION
   TinyMatrix(TinyMatrix&& A) = default;
-  
+
   KOKKOS_INLINE_FUNCTION
   ~TinyMatrix()
   {
@@ -300,7 +300,7 @@ T det(const TinyMatrix<1,T>& A)
 {
   static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non arithmetic types");
   TinyMatrix<1,T> M=A;
-  
+
   return A(0,0);
 }
 
@@ -310,7 +310,7 @@ T det(const TinyMatrix<2,T>& A)
 {
   static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non arithmetic types");
   TinyMatrix<2,T> M=A;
-  
+
   return A(0,0)*A(1,1)-A(1,0)*A(0,1);
 }
 
@@ -320,7 +320,7 @@ T det(const TinyMatrix<3,T>& A)
 {
   static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non arithmetic types");
   TinyMatrix<3,T> M=A;
-  
+
   return
     A(0,0)*(A(1,1)*A(2,2)-A(2,1)*A(1,2))
     -A(1,0)*(A(0,1)*A(2,2)-A(2,1)*A(0,2))
diff --git a/src/algebra/TinyVector.hpp b/src/algebra/TinyVector.hpp
index 0b4149428..f95d45639 100644
--- a/src/algebra/TinyVector.hpp
+++ b/src/algebra/TinyVector.hpp
@@ -1,9 +1,9 @@
 #ifndef TINY_VECTOR_HPP
 #define TINY_VECTOR_HPP
 
-#include <cassert>
 #include <iostream>
 
+#include <PastisAssert.hpp>
 #include <Kokkos_Core.hpp>
 #include <Types.hpp>
 
@@ -119,14 +119,14 @@ public:
   KOKKOS_INLINE_FUNCTION
   T& operator[](const size_t& i)
   {
-    assert(i<N);
+    Assert(i<N);
     return m_values[i];
   }
 
   KOKKOS_INLINE_FUNCTION
   const T& operator[](const size_t& i) const
   {
-    assert(i<N);
+    Assert(i<N);
     return m_values[i];
   }
 
diff --git a/src/main.cpp b/src/main.cpp
index 1ab6e36f6..ea9a348d3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -24,7 +24,6 @@
 #include <GmshReader.hpp>
 
 #include <CLI/CLI.hpp>
-#include <cassert>
 #include <limits>
 #include <map>
 
diff --git a/src/mesh/Connectivity1D.hpp b/src/mesh/Connectivity1D.hpp
index af6105ca0..4e26a0778 100644
--- a/src/mesh/Connectivity1D.hpp
+++ b/src/mesh/Connectivity1D.hpp
@@ -2,8 +2,9 @@
 #define CONNECTIVITY_1D_HPP
 
 #include <Kokkos_Core.hpp>
-#include <TinyVector.hpp>
+#include <PastisAssert.hpp>
 
+#include <TinyVector.hpp>
 #include <ConnectivityUtils.hpp>
 
 class Connectivity1D
@@ -47,7 +48,7 @@ private:
     return cell_nodes;
   }
 
-  
+
   const Kokkos::View<const unsigned short*>
   _buildCellNbNodes(const size_t& number_of_cells)
   {
@@ -79,7 +80,7 @@ public:
   {
     return m_max_nb_node_per_cell;
   }
-  
+
   const Kokkos::View<const unsigned int**> cellNodes() const
   {
     return m_cell_nodes;
@@ -136,14 +137,14 @@ public:
   }
 
   Connectivity1D(const Connectivity1D&) = delete;
-  
+
   Connectivity1D(const size_t& number_of_cells)
     : m_number_of_cells (number_of_cells),
       m_cell_nodes (_buildCellNodes(number_of_cells)),
       m_cell_nb_nodes (_buildCellNbNodes(number_of_cells)),
       m_inv_cell_nb_nodes ("inv_cell_nb_nodes", m_number_of_cells)
   {
-    assert(number_of_cells>0);
+    Assert(number_of_cells>0);
     Kokkos::parallel_for(m_number_of_cells, KOKKOS_LAMBDA(const size_t& j) {
 	m_inv_cell_nb_nodes[j] = 1./m_cell_nb_nodes[j];
       });
diff --git a/src/mesh/Connectivity2D.hpp b/src/mesh/Connectivity2D.hpp
index 1603b386c..8b53668de 100644
--- a/src/mesh/Connectivity2D.hpp
+++ b/src/mesh/Connectivity2D.hpp
@@ -2,6 +2,7 @@
 #define CONNECTIVITY_2D_HPP
 
 #include <Kokkos_Core.hpp>
+#include <PastisAssert.hpp>
 #include <TinyVector.hpp>
 
 #include <ConnectivityUtils.hpp>
@@ -389,7 +390,7 @@ size_t numberOfNodeBoundaries() const
         });
       m_inv_cell_nb_nodes = inv_cell_nb_nodes;
     }
-    assert(m_number_of_cells>0);
+    Assert(m_number_of_cells>0);
 
     ConnectivityUtils utils;
     utils.computeNodeCellConnectivity(m_cell_nodes,
diff --git a/src/scheme/AcousticSolver.hpp b/src/scheme/AcousticSolver.hpp
index 5900807bb..ebd715ab5 100644
--- a/src/scheme/AcousticSolver.hpp
+++ b/src/scheme/AcousticSolver.hpp
@@ -2,9 +2,10 @@
 #define ACOUSTIC_SOLVER_HPP
 
 #include <Kokkos_Core.hpp>
-
 #include <rang.hpp>
+
 #include <BlockPerfectGas.hpp>
+#include <PastisAssert.hpp>
 
 #include <TinyVector.hpp>
 #include <TinyMatrix.hpp>
@@ -41,7 +42,7 @@ private:
     ReduceMin(const Kokkos::View<const double*>& x) : x_ (x) {}
 
     typedef Kokkos::View<const double*>::size_type size_type;
-    
+
     KOKKOS_INLINE_FUNCTION
     void operator() (const size_type i, value_type& update) const
     {
@@ -66,7 +67,7 @@ private:
     }
   };
 
-  
+
   KOKKOS_INLINE_FUNCTION
   const Kokkos::View<const double*>
   computeRhoCj(const Kokkos::View<const double*>& rhoj,
@@ -165,7 +166,7 @@ private:
 	Kokkos::parallel_for(pressure_bc.numberOfFaces(), KOKKOS_LAMBDA(const int& l_number) {
 	    // quite ugly: node/faces are melt in a bad way... at least works in 1d...
 	    const int l = pressure_bc.faceList()[l_number];
-	    assert(m_connectivity.faceNbCells()[l] == 1);
+	    Assert(m_connectivity.faceNbCells()[l] == 1);
 	    const unsigned int j = face_cells(l,0);
 	    const unsigned int L = face_cell_local_face(l,0);
 
@@ -194,7 +195,7 @@ private:
       }
     }
   }
-  
+
   Kokkos::View<Rd*>
   computeUr(const Kokkos::View<const Rdd*>& Ar,
 	    const Kokkos::View<const Rd*>& br) {
diff --git a/src/utils/PastisAssert.hpp b/src/utils/PastisAssert.hpp
new file mode 100644
index 000000000..7acded2a5
--- /dev/null
+++ b/src/utils/PastisAssert.hpp
@@ -0,0 +1,28 @@
+#ifndef PASTIS_ASSERT_HPP
+#define PASTIS_ASSERT_HPP
+
+#ifdef NDEBUG
+
+#warning check that this test does not degrade performaces
+#define Assert(assertion)                       \
+  if (not (assertion)) false;
+
+#else // NDEBUG
+
+#include <rang.hpp>
+
+#define Assert(assertion)                       \
+  if (not (assertion)) {                        \
+    std::cerr << rang::style::bold              \
+              << "Assertion \""                 \
+              << rang::fg::red                  \
+              << #assertion                     \
+              << rang::fg::reset                \
+              << "\" failed\n"                  \
+              << rang::style::reset;            \
+    std::exit(1);                               \
+  }
+
+#endif // NDEBUG
+
+#endif // PASTIS_ASSERT_HPP
diff --git a/tests/test_TinyVector.cpp b/tests/test_TinyVector.cpp
index feb4fe26c..5b9612d34 100644
--- a/tests/test_TinyVector.cpp
+++ b/tests/test_TinyVector.cpp
@@ -1,28 +1,31 @@
 #include <catch.hpp>
 
 #include <TinyVector.hpp>
+#include <PastisAssert.hpp>
 
 TEST_CASE("TinyVector", "[algebra]") {
   TinyVector<3,int> v(1,2,3);
-  REQUIRE(((v[0] == 1) and (v[1] == 2) and (v[2] == 3)));
+  REQUIRE_NOTHROW(((v[0] == 1) and (v[1] == 2) and (v[2] == 3)));
   REQUIRE(v.dimension() == 3);
 
   const TinyVector<3,int> z = zero;
-  REQUIRE(((z[0] == 0) and (z[1] == 0) and (z[2] == 0)));
+  REQUIRE_NOTHROW(((z[0] == 0) and (z[1] == 0) and (z[2] == 0)));
 
   v = TinyVector<3,int>(3,2,4);
   TinyVector<3,int> w(1,2,6);
   REQUIRE((v,w)==31);
 
   w = 2*v;
-  REQUIRE(((w[0] == 2*v[0]) and (w[1]==2*v[1]) and (w[2]==2*v[2])));
+  REQUIRE_NOTHROW(((w[0] == 2*v[0]) and (w[1]==2*v[1]) and (w[2]==2*v[2])));
 
   TinyVector<3,int> x = v;
   REQUIRE(x==v);
 
   x = TinyVector<3,int> (6,4,8);
   REQUIRE(x==w);
+  REQUIRE_FALSE(x==v);
   REQUIRE(x!=v);
+  REQUIRE_FALSE(x!=w);
 
   x=v;
   REQUIRE(x==v);
@@ -40,7 +43,10 @@ TEST_CASE("TinyVector", "[algebra]") {
   REQUIRE(x==v);
 
   TinyVector<3,int> z1; z1 = zero;
-  REQUIRE(((z1[0] == 0) and (z1[1] == 0) and (z1[2] == 0)));
+  REQUIRE_NOTHROW(((z1[0] == 0) and (z1[1] == 0) and (z1[2] == 0)));
 
-  REQUIRE( Catch::Detail::stringify(x) == "(3,2,4)");
+  REQUIRE(Catch::Detail::stringify(x) == "(3,2,4)");
+
+  // REQUIRE_THROWS(x[4]);
+  // REQUIRE_THROWS(x[-1]);
 }
-- 
GitLab