From 376cb7f478a2d2a1d75097106c985c63afe6b2d8 Mon Sep 17 00:00:00 2001
From: Sebastian Eibl <sebastian.eibl@fau.de>
Date: Fri, 28 Apr 2017 17:23:46 +0200
Subject: [PATCH] introduced new macros to check floats with precision

WALBERLA_CHECK_FLOAT_EQUAL_EPSILON
WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON
WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON
WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON
---
 src/core/debug/CheckFunctions.h      | 119 +++++++++++++++++----------
 src/core/debug/CheckFunctions.impl.h |  80 +++++++++++++++++-
 src/core/debug/Debug.h               |  69 ++++++++++------
 src/core/math/Matrix2.h              |  21 +++++
 src/core/math/Matrix3.h              |  33 +++++++-
 src/core/math/Quaternion.h           |  29 +++++++
 src/core/math/Vector3.h              |   9 +-
 7 files changed, 284 insertions(+), 76 deletions(-)

diff --git a/src/core/debug/CheckFunctions.h b/src/core/debug/CheckFunctions.h
index 023f1b3a6..54efea20b 100644
--- a/src/core/debug/CheckFunctions.h
+++ b/src/core/debug/CheckFunctions.h
@@ -26,6 +26,7 @@
 #include "core/Macros.h"
 #include "core/math/MathTrait.h"
 #include "core/math/Utility.h"
+#include "core/VectorTrait.h"
 
 //#include <boost/math/special_functions/next.hpp>
 #include <boost/static_assert.hpp>
@@ -79,35 +80,39 @@
  *
  **********************************************************************************************************************/
 
-#define WALBERLA_CHECK_1(X)                 { if( !walberla::debug::check_functions_detail::check              ( (X)      ) ) { walberla::debug::check_functions_detail::check              (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_NULLPTR_1(X)         { if( !walberla::debug::check_functions_detail::check_nullptr      ( (X)      ) ) { walberla::debug::check_functions_detail::check_nullptr      ( (X),      #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_NOT_NULLPTR_1(X)     { if( !walberla::debug::check_functions_detail::check_not_nullptr  ( (X)      ) ) { walberla::debug::check_functions_detail::check_not_nullptr  (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_EQUAL_2(X,Y)         { if( !walberla::debug::check_functions_detail::check_equal        ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_equal        ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_UNEQUAL_2(X,Y)       { if( !walberla::debug::check_functions_detail::check_unequal      ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_unequal      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_FLOAT_EQUAL_2(X,Y)   { if( !walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_FLOAT_UNEQUAL_2(X,Y) { if( !walberla::debug::check_functions_detail::check_float_unequal( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_float_unequal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_IDENTICAL_2(X,Y)     { if( !walberla::debug::check_functions_detail::check_identical    ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_identical    ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_NOT_IDENTICAL_2(X,Y) { if( !walberla::debug::check_functions_detail::check_not_identical( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_not_identical( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_LESS_2(X,Y)          { if( !walberla::debug::check_functions_detail::check_less         ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_less         ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_GREATER_2(X,Y)       { if( !walberla::debug::check_functions_detail::check_greater      ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_greater      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_LESS_EQUAL_2(X,Y)    { if( !walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-#define WALBERLA_CHECK_GREATER_EQUAL_2(X,Y) { if( !walberla::debug::check_functions_detail::check_greater_equal( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_greater_equal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
-
-
-
-#define WALBERLA_CHECK_2(X,MSG)                 { if( !walberla::debug::check_functions_detail::check              ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check              (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_NULLPTR_2(X,MSG)         { if( !walberla::debug::check_functions_detail::check_nullptr      ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_nullptr      ( (X),      #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_NOT_NULLPTR_2(X,MSG)     { if( !walberla::debug::check_functions_detail::check_not_nullptr  ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_not_nullptr  (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_EQUAL_3(X,Y,MSG)         { if( !walberla::debug::check_functions_detail::check_equal        ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_equal        ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_UNEQUAL_3(X,Y,MSG)       { if( !walberla::debug::check_functions_detail::check_unequal      ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_unequal      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_FLOAT_EQUAL_3(X,Y,MSG)   { if( !walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_FLOAT_UNEQUAL_3(X,Y,MSG) { if( !walberla::debug::check_functions_detail::check_float_unequal( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_unequal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_IDENTICAL_3(X,Y,MSG)     { if( !walberla::debug::check_functions_detail::check_identical    ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_identical    ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_NOT_IDENTICAL_3(X,Y,MSG) { if( !walberla::debug::check_functions_detail::check_not_identical( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_not_identical( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_LESS_3(X,Y,MSG)          { if( !walberla::debug::check_functions_detail::check_less         ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_less         ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_GREATER_3(X,Y,MSG)       { if( !walberla::debug::check_functions_detail::check_greater      ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_greater      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_LESS_EQUAL_3(X,Y,MSG)    { if( !walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_CHECK_GREATER_EQUAL_3(X,Y,MSG) { if( !walberla::debug::check_functions_detail::check_greater_equal( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_greater_equal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_1(X)                             { if( !walberla::debug::check_functions_detail::check              ( (X)      ) ) { walberla::debug::check_functions_detail::check              (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_NULLPTR_1(X)                     { if( !walberla::debug::check_functions_detail::check_nullptr      ( (X)      ) ) { walberla::debug::check_functions_detail::check_nullptr      ( (X),      #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_NOT_NULLPTR_1(X)                 { if( !walberla::debug::check_functions_detail::check_not_nullptr  ( (X)      ) ) { walberla::debug::check_functions_detail::check_not_nullptr  (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_EQUAL_2(X,Y)                     { if( !walberla::debug::check_functions_detail::check_equal        ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_equal        ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_UNEQUAL_2(X,Y)                   { if( !walberla::debug::check_functions_detail::check_unequal      ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_unequal      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_FLOAT_EQUAL_2(X,Y)               { if( !walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_2(X,Y)             { if( !walberla::debug::check_functions_detail::check_float_unequal( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_float_unequal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_FLOAT_EQUAL_EPSILON_3(X,Y,EPS)   { if( !walberla::debug::check_functions_detail::check_float_equal_eps  ( (X), (Y), (EPS) ) ) { walberla::debug::check_functions_detail::check_float_equal_eps  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler(), (EPS) ); } }
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON_3(X,Y,EPS) { if( !walberla::debug::check_functions_detail::check_float_unequal_eps( (X), (Y), (EPS) ) ) { walberla::debug::check_functions_detail::check_float_unequal_eps( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler(), (EPS) ); } }
+#define WALBERLA_CHECK_IDENTICAL_2(X,Y)                 { if( !walberla::debug::check_functions_detail::check_identical    ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_identical    ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_NOT_IDENTICAL_2(X,Y)             { if( !walberla::debug::check_functions_detail::check_not_identical( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_not_identical( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_LESS_2(X,Y)                      { if( !walberla::debug::check_functions_detail::check_less         ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_less         ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_GREATER_2(X,Y)                   { if( !walberla::debug::check_functions_detail::check_greater      ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_greater      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_LESS_EQUAL_2(X,Y)                { if( !walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+#define WALBERLA_CHECK_GREATER_EQUAL_2(X,Y)             { if( !walberla::debug::check_functions_detail::check_greater_equal( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_greater_equal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
+
+
+
+#define WALBERLA_CHECK_2(X,MSG)                             { if( !walberla::debug::check_functions_detail::check              ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check              (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_NULLPTR_2(X,MSG)                     { if( !walberla::debug::check_functions_detail::check_nullptr      ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_nullptr      ( (X),      #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_NOT_NULLPTR_2(X,MSG)                 { if( !walberla::debug::check_functions_detail::check_not_nullptr  ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_not_nullptr  (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_EQUAL_3(X,Y,MSG)                     { if( !walberla::debug::check_functions_detail::check_equal        ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_equal        ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_UNEQUAL_3(X,Y,MSG)                   { if( !walberla::debug::check_functions_detail::check_unequal      ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_unequal      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_FLOAT_EQUAL_3(X,Y,MSG)               { if( !walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_3(X,Y,MSG)             { if( !walberla::debug::check_functions_detail::check_float_unequal( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_unequal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_FLOAT_EQUAL_EPSILON_4(X,Y,EPS,MSG)   { if( !walberla::debug::check_functions_detail::check_float_equal_eps  ( (X), (Y), (EPS) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_equal_eps  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ), (EPS) ); } }
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON_4(X,Y,EPS,MSG) { if( !walberla::debug::check_functions_detail::check_float_unequal_eps( (X), (Y), (EPS) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_unequal_eps( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ), (EPS) ); } }
+#define WALBERLA_CHECK_IDENTICAL_3(X,Y,MSG)                 { if( !walberla::debug::check_functions_detail::check_identical    ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_identical    ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_NOT_IDENTICAL_3(X,Y,MSG)             { if( !walberla::debug::check_functions_detail::check_not_identical( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_not_identical( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_LESS_3(X,Y,MSG)                      { if( !walberla::debug::check_functions_detail::check_less         ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_less         ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_GREATER_3(X,Y,MSG)                   { if( !walberla::debug::check_functions_detail::check_greater      ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_greater      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_LESS_EQUAL_3(X,Y,MSG)                { if( !walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_CHECK_GREATER_EQUAL_3(X,Y,MSG)             { if( !walberla::debug::check_functions_detail::check_greater_equal( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_greater_equal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
 
 
 
@@ -146,6 +151,16 @@
 #define WALBERLA_CHECK_FLOAT_UNEQUAL_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
 #define WALBERLA_CHECK_FLOAT_UNEQUAL_6(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
 
+#define WALBERLA_CHECK_FLOAT_EQUAL_EPSILON_1(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
+#define WALBERLA_CHECK_FLOAT_EQUAL_EPSILON_2(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
+#define WALBERLA_CHECK_FLOAT_EQUAL_EPSILON_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
+#define WALBERLA_CHECK_FLOAT_EQUAL_EPSILON_6(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
+
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON_1(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON_2(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON_6(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
+
 #define WALBERLA_CHECK_IDENTICAL_1(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
 #define WALBERLA_CHECK_IDENTICAL_4(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
 #define WALBERLA_CHECK_IDENTICAL_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
@@ -176,19 +191,21 @@
 #define WALBERLA_CHECK_GREATER_EQUAL_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
 #define WALBERLA_CHECK_GREATER_EQUAL_6(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_A_CHECK_MACRO
 
-#define WALBERLA_CHECK(...)               WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_, __VA_ARGS__ )
-#define WALBERLA_CHECK_NULLPTR(...)       WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_NULLPTR_, __VA_ARGS__ )
-#define WALBERLA_CHECK_NOT_NULLPTR(...)   WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_NOT_NULLPTR_, __VA_ARGS__ )
-#define WALBERLA_CHECK_EQUAL(...)         WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_EQUAL_, __VA_ARGS__ )
-#define WALBERLA_CHECK_UNEQUAL(...)       WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_UNEQUAL_, __VA_ARGS__ )
-#define WALBERLA_CHECK_FLOAT_EQUAL(...)   WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_FLOAT_EQUAL_, __VA_ARGS__ )
-#define WALBERLA_CHECK_FLOAT_UNEQUAL(...) WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_FLOAT_UNEQUAL_, __VA_ARGS__ )
-#define WALBERLA_CHECK_IDENTICAL(...)     WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_IDENTICAL_, __VA_ARGS__ )
-#define WALBERLA_CHECK_NOT_IDENTICAL(...) WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_NOT_IDENTICAL_, __VA_ARGS__ )
-#define WALBERLA_CHECK_LESS(...)          WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_LESS_, __VA_ARGS__ )
-#define WALBERLA_CHECK_GREATER(...)       WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_GREATER_, __VA_ARGS__ )
-#define WALBERLA_CHECK_LESS_EQUAL(...)    WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_LESS_EQUAL_, __VA_ARGS__ )
-#define WALBERLA_CHECK_GREATER_EQUAL(...) WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_GREATER_EQUAL_, __VA_ARGS__ )
+#define WALBERLA_CHECK(...)                       WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_, __VA_ARGS__ )
+#define WALBERLA_CHECK_NULLPTR(...)               WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_NULLPTR_, __VA_ARGS__ )
+#define WALBERLA_CHECK_NOT_NULLPTR(...)           WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_NOT_NULLPTR_, __VA_ARGS__ )
+#define WALBERLA_CHECK_EQUAL(...)                 WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_EQUAL_, __VA_ARGS__ )
+#define WALBERLA_CHECK_UNEQUAL(...)               WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_UNEQUAL_, __VA_ARGS__ )
+#define WALBERLA_CHECK_FLOAT_EQUAL(...)           WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_FLOAT_EQUAL_, __VA_ARGS__ )
+#define WALBERLA_CHECK_FLOAT_UNEQUAL(...)         WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_FLOAT_UNEQUAL_, __VA_ARGS__ )
+#define WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(...)   WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_FLOAT_EQUAL_EPSILON_, __VA_ARGS__ )
+#define WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON(...) WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_FLOAT_UNEQUAL_EPSILON_, __VA_ARGS__ )
+#define WALBERLA_CHECK_IDENTICAL(...)             WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_IDENTICAL_, __VA_ARGS__ )
+#define WALBERLA_CHECK_NOT_IDENTICAL(...)         WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_NOT_IDENTICAL_, __VA_ARGS__ )
+#define WALBERLA_CHECK_LESS(...)                  WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_LESS_, __VA_ARGS__ )
+#define WALBERLA_CHECK_GREATER(...)               WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_GREATER_, __VA_ARGS__ )
+#define WALBERLA_CHECK_LESS_EQUAL(...)            WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_LESS_EQUAL_, __VA_ARGS__ )
+#define WALBERLA_CHECK_GREATER_EQUAL(...)         WALBERLA_MACRO_OVERLOAD( WALBERLA_CHECK_GREATER_EQUAL_, __VA_ARGS__ )
 
 
 
@@ -245,6 +262,12 @@ inline bool check_float_equal( const T & lhs, const U & rhs );
 template< typename T, typename U >
 inline bool check_float_unequal( const T & lhs, const U & rhs );
 
+template< typename T, typename U >
+inline bool check_float_equal_eps( const T & lhs, const U & rhs, const typename VectorTrait<typename math::MathTrait<T,U>::LowType>::OutputType epsilon );
+
+template< typename T, typename U >
+inline bool check_float_unequal_eps( const T & lhs, const U & rhs, const typename VectorTrait<typename math::MathTrait<T,U>::LowType>::OutputType epsilon );
+
 template< typename T, typename U >
 inline bool check_identical( const T & lhs, const U & rhs );
 
@@ -327,7 +350,17 @@ void check_float_equal( const T & lhs, const U & rhs, const char * const lhsExpr
 
 template< typename T, typename U, typename V >
 void check_float_unequal( const T & lhs, const U & rhs, const char * const lhsExpression, const char * const rhsExpression,
-                          const char * const filename, int line, V failFunc );
+                          const char * const filename, int line, V failFunc);
+
+template< typename T, typename U, typename V >
+void check_float_equal_eps( const T & lhs, const U & rhs, const char * const lhsExpression, const char * const rhsExpression,
+                            const char * const filename, int line, V failFunc,
+                            const typename VectorTrait<typename math::MathTrait<T,U>::LowType>::OutputType epsilon );
+
+template< typename T, typename U, typename V >
+void check_float_unequal_eps( const T & lhs, const U & rhs, const char * const lhsExpression, const char * const rhsExpression,
+                              const char * const filename, int line, V failFunc,
+                              const typename VectorTrait<typename math::MathTrait<T,U>::LowType>::OutputType epsilon );
 
 template< typename T, typename U, typename V >
 void check_identical( const T & lhs, const U & rhs, const char * const lhsExpression, const char * const rhsExpression,
diff --git a/src/core/debug/CheckFunctions.impl.h b/src/core/debug/CheckFunctions.impl.h
index fd8976cf8..fb67dd269 100644
--- a/src/core/debug/CheckFunctions.impl.h
+++ b/src/core/debug/CheckFunctions.impl.h
@@ -119,6 +119,36 @@ inline bool check_float_unequal( const T & lhs, const U & rhs )
    return !floatIsEqual( low_lhs, low_rhs ) && !floatIsEqual( ( low_lhs - low_rhs ) / low_lhs, LowType(0) );
 }
 
+template< typename T, typename U >
+inline bool check_float_equal_eps( const T & lhs, const U & rhs,
+                                   const typename VectorTrait<typename math::MathTrait<T,U>::LowType>::OutputType epsilon )
+{
+   static_assert( boost::is_floating_point<T>::value,  "First operand type T is not a floating point type!");
+   static_assert( boost::is_floating_point<U>::value, "Second operand type U is not a floating point type!");
+
+   typedef typename math::MathTrait<T,U>::Low LowType;
+
+   LowType low_lhs = static_cast<LowType>( lhs );
+   LowType low_rhs = static_cast<LowType>( rhs );
+
+   return floatIsEqual( low_lhs, low_rhs, epsilon ) || floatIsEqual( ( low_lhs - low_rhs ) / low_lhs, LowType(0), epsilon );
+}
+
+template< typename T, typename U >
+inline bool check_float_unequal_eps( const T & lhs, const U & rhs,
+                                     const typename VectorTrait<typename math::MathTrait<T,U>::LowType>::OutputType epsilon )
+{
+   static_assert( boost::is_floating_point<T>::value,  "First operand type T is not a floating point type!");
+   static_assert( boost::is_floating_point<U>::value, "Second operand type U is not a floating point type!");
+
+   typedef typename math::MathTrait<T,U>::Low LowType;
+
+   LowType low_lhs = static_cast<LowType>( lhs );
+   LowType low_rhs = static_cast<LowType>( rhs );
+
+   return !floatIsEqual( low_lhs, low_rhs, epsilon ) && !floatIsEqual( ( low_lhs - low_rhs ) / low_lhs, LowType(0), epsilon );
+}
+
 template< typename T, typename U >
 inline bool check_identical( const T & lhs, const U & rhs )
 {
@@ -304,7 +334,8 @@ void check_unequal( const T & lhs, const U & rhs, const char * const lhsExpressi
 }
 
 template< typename T, typename U, typename V >
-void check_float_equal( const T & lhs, const U & rhs, const char * const lhsExpression, const char * const rhsExpression,
+void check_float_equal( const T & lhs, const U & rhs,
+                        const char * const lhsExpression, const char * const rhsExpression,
                         const char * const filename, int line, V failFunc )
 {
    int length = static_cast<int>( std::max( std::strlen( lhsExpression ), std::strlen( rhsExpression ) ) );
@@ -345,6 +376,53 @@ void check_float_unequal( const T & lhs, const U & rhs, const char * const lhsEx
    failFunc( ss.str() );
 }
 
+template< typename T, typename U, typename V >
+void check_float_equal_eps( const T & lhs, const U & rhs,
+                        const char * const lhsExpression, const char * const rhsExpression,
+                        const char * const filename, int line, V failFunc,
+                        const typename VectorTrait<typename math::MathTrait<T,U>::LowType>::OutputType epsilon )
+{
+   int length = static_cast<int>( std::max( std::strlen( lhsExpression ), std::strlen( rhsExpression ) ) );
+   std::stringstream ss;
+   ss << "Assertion failed!\n"
+      << "File:       " << filename << ":" << line << '\n'
+      << "Expression: " << lhsExpression << " == " << rhsExpression << '\n'
+      << "Epsilon:    " << epsilon << '\n'
+      //<< "ULP:        " << distance << '\n'
+      << "Values:     " << std::setw(length) << std::setfill(' ') << lhsExpression << " = ";
+
+   printValue( ss, lhs ) << '\n';
+
+   ss << "            " << std::setw(length) << std::setfill(' ') << rhsExpression << " = ";
+
+   printValue( ss, rhs ) << '\n';
+
+   failFunc( ss.str() );
+}
+
+template< typename T, typename U, typename V >
+void check_float_unequal_eps( const T & lhs, const U & rhs, const char * const lhsExpression, const char * const rhsExpression,
+                          const char * const filename, int line, V failFunc,
+                          const typename VectorTrait<typename math::MathTrait<T,U>::LowType>::OutputType epsilon )
+{
+   int length = static_cast<int>( std::max( std::strlen( lhsExpression ), std::strlen( rhsExpression ) ) );
+   std::stringstream ss;
+   ss << "Assertion failed!\n"
+      << "File:       " << filename << ":" << line << '\n'
+      << "Expression: " << lhsExpression << " != " << rhsExpression << '\n'
+      << "Epsilon:    " << epsilon << '\n'
+      //<< "ULP:        " << distance << '\n'
+      << "Values:     " << std::setw(length) << std::setfill(' ') << lhsExpression << " = ";
+
+   printValue( ss, lhs ) << '\n';
+
+   ss << "            " << std::setw(length) << std::setfill(' ') << rhsExpression << " = ";
+
+   printValue( ss, rhs ) << '\n';
+
+   failFunc( ss.str() );
+}
+
 template< typename T, typename U, typename V >
 void check_identical( const T & lhs, const U & rhs, const char * const lhsExpression, const char * const rhsExpression,
                       const char * const filename, int line, V failFunc )
diff --git a/src/core/debug/Debug.h b/src/core/debug/Debug.h
index 34ef9fb1b..8bca728a3 100644
--- a/src/core/debug/Debug.h
+++ b/src/core/debug/Debug.h
@@ -81,19 +81,24 @@
 #define WALBERLA_ASSERT_LESS_EQUAL_2(X,Y)    { if( !walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
 #define WALBERLA_ASSERT_GREATER_EQUAL_2(X,Y) { if( !walberla::debug::check_functions_detail::check_greater_equal( (X), (Y) ) ) { walberla::debug::check_functions_detail::check_greater_equal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler() ); } }
 
-#define WALBERLA_ASSERT_2(X,MSG)                 { if( !walberla::debug::check_functions_detail::check              ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check              (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_NULLPTR_2(X,MSG)         { if( !walberla::debug::check_functions_detail::check_nullptr      ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_nullptr      ( (X),      #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_NOT_NULLPTR_2(X,MSG)     { if( !walberla::debug::check_functions_detail::check_not_nullptr  ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_not_nullptr  (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_EQUAL_3(X,Y,MSG)         { if( !walberla::debug::check_functions_detail::check_equal        ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_equal        ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_UNEQUAL_3(X,Y,MSG)       { if( !walberla::debug::check_functions_detail::check_unequal      ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_unequal      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_FLOAT_EQUAL_3(X,Y,MSG)   { if( !walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_FLOAT_UNEQUAL_3(X,Y,MSG) { if( !walberla::debug::check_functions_detail::check_float_unequal( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_unequal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_IDENTICAL_3(X,Y,MSG)     { if( !walberla::debug::check_functions_detail::check_identical    ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_identical    ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_NOT_IDENTICAL_3(X,Y,MSG) { if( !walberla::debug::check_functions_detail::check_not_identical( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_not_identical( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_LESS_3(X,Y,MSG)          { if( !walberla::debug::check_functions_detail::check_less         ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_less         ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_GREATER_3(X,Y,MSG)       { if( !walberla::debug::check_functions_detail::check_greater      ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_greater      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_LESS_EQUAL_3(X,Y,MSG)    { if( !walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
-#define WALBERLA_ASSERT_GREATER_EQUAL_3(X,Y,MSG) { if( !walberla::debug::check_functions_detail::check_greater_equal( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_greater_equal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_2(X,MSG)                         { if( !walberla::debug::check_functions_detail::check                  ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check              (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_NULLPTR_2(X,MSG)                 { if( !walberla::debug::check_functions_detail::check_nullptr          ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_nullptr      ( (X),      #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_NOT_NULLPTR_2(X,MSG)             { if( !walberla::debug::check_functions_detail::check_not_nullptr      ( (X)      ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_not_nullptr  (           #X,     __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_EQUAL_3(X,Y,MSG)                 { if( !walberla::debug::check_functions_detail::check_equal            ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_equal        ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_UNEQUAL_3(X,Y,MSG)               { if( !walberla::debug::check_functions_detail::check_unequal          ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_unequal      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_FLOAT_EQUAL_3(X,Y,MSG)           { if( !walberla::debug::check_functions_detail::check_float_equal      ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_equal  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL_3(X,Y,MSG)         { if( !walberla::debug::check_functions_detail::check_float_unequal    ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_unequal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON_3(X,Y,EPS)   { if( !walberla::debug::check_functions_detail::check_float_equal_eps  ( (X), (Y), (EPS) ) ) { walberla::debug::check_functions_detail::check_float_equal_eps  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ), (EPS) ); } }
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON_3(X,Y,EPS) { if( !walberla::debug::check_functions_detail::check_float_unequal_eps( (X), (Y), (EPS) ) ) { walberla::debug::check_functions_detail::check_float_unequal_eps( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ), (EPS) ); } }
+#define WALBERLA_ASSERT_IDENTICAL_3(X,Y,MSG)             { if( !walberla::debug::check_functions_detail::check_identical        ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_identical    ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_NOT_IDENTICAL_3(X,Y,MSG)         { if( !walberla::debug::check_functions_detail::check_not_identical    ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_not_identical( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_LESS_3(X,Y,MSG)                  { if( !walberla::debug::check_functions_detail::check_less             ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_less         ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_GREATER_3(X,Y,MSG)               { if( !walberla::debug::check_functions_detail::check_greater          ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_greater      ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_LESS_EQUAL_3(X,Y,MSG)            { if( !walberla::debug::check_functions_detail::check_less_equal        ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_less_equal   ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+#define WALBERLA_ASSERT_GREATER_EQUAL_3(X,Y,MSG)         { if( !walberla::debug::check_functions_detail::check_greater_equal    ( (X), (Y) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_greater_equal( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ) ); } }
+
+#define WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON_4(X,Y,EPS,MSG)   { if( !walberla::debug::check_functions_detail::check_float_equal_eps  ( (X), (Y), (EPS) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_equal_eps  ( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ), (EPS) ); } }
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON_4(X,Y,EPS,MSG) { if( !walberla::debug::check_functions_detail::check_float_unequal_eps( (X), (Y), (EPS) ) ) { std::stringstream ss; ss << MSG; walberla::debug::check_functions_detail::check_float_unequal_eps( (X), (Y), #X, #Y, __FILE__, __LINE__, walberla::debug::check_functions_detail::ExitHandler( ss.str() ), (EPS) ); } }
 
 #define WALBERLA_ASSERT_3(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
 #define WALBERLA_ASSERT_4(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
@@ -130,6 +135,16 @@
 #define WALBERLA_ASSERT_FLOAT_UNEQUAL_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
 #define WALBERLA_ASSERT_FLOAT_UNEQUAL_6(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
 
+#define WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON_1(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
+#define WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON_2(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
+#define WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
+#define WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON_6(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
+
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON_1(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON_2(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON_6(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
+
 #define WALBERLA_ASSERT_IDENTICAL_1(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
 #define WALBERLA_ASSERT_IDENTICAL_4(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
 #define WALBERLA_ASSERT_IDENTICAL_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
@@ -160,19 +175,21 @@
 #define WALBERLA_ASSERT_GREATER_EQUAL_5(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
 #define WALBERLA_ASSERT_GREATER_EQUAL_6(...) THIS_IS_SUPPOSED_TO_FAIL___YOU_MADE_AN_ERROR_WHEN_USING_AN_ASSERT_MACRO
 
-#define WALBERLA_ASSERT(...)               WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_NULLPTR(...)       WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_NULLPTR_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_NOT_NULLPTR(...)   WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_NOT_NULLPTR_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_EQUAL(...)         WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_EQUAL_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_UNEQUAL(...)       WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_UNEQUAL_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_FLOAT_EQUAL(...)   WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_FLOAT_EQUAL_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_FLOAT_UNEQUAL(...) WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_FLOAT_UNEQUAL_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_IDENTICAL(...)     WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_IDENTICAL_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_NOT_IDENTICAL(...) WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_NOT_IDENTICAL_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_LESS(...)          WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_LESS_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_GREATER(...)       WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_GREATER_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_LESS_EQUAL(...)    WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_LESS_EQUAL_, __VA_ARGS__ )
-#define WALBERLA_ASSERT_GREATER_EQUAL(...) WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_GREATER_EQUAL_, __VA_ARGS__ )
+#define WALBERLA_ASSERT(...)                       WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_NULLPTR(...)               WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_NULLPTR_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_NOT_NULLPTR(...)           WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_NOT_NULLPTR_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_EQUAL(...)                 WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_EQUAL_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_UNEQUAL(...)               WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_UNEQUAL_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_FLOAT_EQUAL(...)           WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_FLOAT_EQUAL_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL(...)         WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_FLOAT_UNEQUAL_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON(...)   WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_FLOAT_EQUAL_EPSILON_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON(...) WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_FLOAT_UNEQUAL_EPSILON_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_IDENTICAL(...)             WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_IDENTICAL_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_NOT_IDENTICAL(...)         WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_NOT_IDENTICAL_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_LESS(...)                  WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_LESS_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_GREATER(...)               WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_GREATER_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_LESS_EQUAL(...)            WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_LESS_EQUAL_, __VA_ARGS__ )
+#define WALBERLA_ASSERT_GREATER_EQUAL(...)         WALBERLA_MACRO_OVERLOAD( WALBERLA_ASSERT_GREATER_EQUAL_, __VA_ARGS__ )
 
 #else // NDBEUG
 
diff --git a/src/core/math/Matrix2.h b/src/core/math/Matrix2.h
index 7ef94244f..db66c6e2c 100644
--- a/src/core/math/Matrix2.h
+++ b/src/core/math/Matrix2.h
@@ -982,4 +982,25 @@ using math::Matrix2;
 
 } // namespace walberla
 
+//======================================================================================================================
+//
+//  Vector Trait Specialization
+//
+//======================================================================================================================
+
+namespace walberla {
+
+// Specialization of VectorTrait for Matrix2s
+template<typename T>
+struct VectorTrait< Matrix2<T> >
+{
+   typedef T OutputType;
+
+   static const uint_t F_SIZE =  4u;
+   static T    get( const Matrix2<T> & v, uint_t f )       { return v[f]; }
+   static void set(       Matrix2<T> & v, uint_t f, T val) { v[f] = val;  }
+};
+
+} // namespace walberla
+
 #undef HIGH
diff --git a/src/core/math/Matrix3.h b/src/core/math/Matrix3.h
index 2b6b8af17..6bcacc495 100644
--- a/src/core/math/Matrix3.h
+++ b/src/core/math/Matrix3.h
@@ -1725,8 +1725,6 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, Matrix3<
    return buf;
 }
 
-
-
 } // namespace math
 
 using math::Matrix3;
@@ -1735,7 +1733,28 @@ using math::Matrix3;
 
 //======================================================================================================================
 //
-//  comparison backend for Vector3<real_t>
+//  Vector Trait Specialization
+//
+//======================================================================================================================
+
+namespace walberla {
+
+// Specialization of VectorTrait for Matrix3s
+template<typename T>
+struct VectorTrait< Matrix3<T> >
+{
+   typedef T OutputType;
+
+   static const uint_t F_SIZE =  9u;
+   static T    get( const Matrix3<T> & v, uint_t f )       { return v[f]; }
+   static void set(       Matrix3<T> & v, uint_t f, T val) { v[f] = val;  }
+};
+
+} // namespace walberla
+
+//======================================================================================================================
+//
+//  comparison backend for Matrix3<real_t>
 //
 //======================================================================================================================
 
@@ -1751,6 +1770,14 @@ inline bool check_float_equal( const math::Matrix3<real_t> & lhs, const math::Ma
        && floatIsEqual( lhs[6], rhs[6] ) && floatIsEqual( lhs[7], rhs[7] ) && floatIsEqual( lhs[8], rhs[8] );
 }
 
+template< >
+inline bool check_float_equal_eps( const math::Matrix3<real_t> & lhs, const math::Matrix3<real_t> & rhs, const real_t epsilon )
+{
+   return floatIsEqual( lhs[0], rhs[0], epsilon ) && floatIsEqual( lhs[1], rhs[1], epsilon ) && floatIsEqual( lhs[2], rhs[2], epsilon )
+       && floatIsEqual( lhs[3], rhs[3], epsilon ) && floatIsEqual( lhs[4], rhs[4], epsilon ) && floatIsEqual( lhs[5], rhs[5], epsilon )
+       && floatIsEqual( lhs[6], rhs[6], epsilon ) && floatIsEqual( lhs[7], rhs[7], epsilon ) && floatIsEqual( lhs[8], rhs[8], epsilon );
+}
+
 }
 }
 }
diff --git a/src/core/math/Quaternion.h b/src/core/math/Quaternion.h
index 5bbfb3fea..fc6dd5891 100644
--- a/src/core/math/Quaternion.h
+++ b/src/core/math/Quaternion.h
@@ -1224,6 +1224,29 @@ namespace mpi {
 }
 }
 
+//======================================================================================================================
+//
+//  Vector Trait Specialization
+//
+//======================================================================================================================
+
+namespace walberla {
+
+using math::Quaternion;
+
+// Specialization of VectorTrait for Quaternions
+template<typename T>
+struct VectorTrait< Quaternion<T> >
+{
+   typedef T OutputType;
+
+   static const uint_t F_SIZE =  4u;
+   static T    get( const Quaternion<T> & v, uint_t f )       { return v[f]; }
+   static void set(       Quaternion<T> & v, uint_t f, T val) { v[f] = val;  }
+};
+
+} // namespace walberla
+
 //======================================================================================================================
 //
 //  comparison backend for Vector3<real_t>
@@ -1240,6 +1263,12 @@ inline bool check_float_equal( const math::Quaternion<real_t> & lhs, const math:
    return floatIsEqual( lhs[0], rhs[0] ) && floatIsEqual( lhs[1], rhs[1] ) && floatIsEqual( lhs[2], rhs[2] ) && floatIsEqual( lhs[3], rhs[3] );
 }
 
+template< >
+inline bool check_float_equal_eps( const math::Quaternion<real_t> & lhs, const math::Quaternion<real_t> & rhs, const real_t epsilon )
+{
+   return floatIsEqual( lhs[0], rhs[0], epsilon ) && floatIsEqual( lhs[1], rhs[1], epsilon ) && floatIsEqual( lhs[2], rhs[2], epsilon ) && floatIsEqual( lhs[3], rhs[3], epsilon );
+}
+
 }
 }
 }
diff --git a/src/core/math/Vector3.h b/src/core/math/Vector3.h
index 2ef29740b..38fbf7ef0 100644
--- a/src/core/math/Vector3.h
+++ b/src/core/math/Vector3.h
@@ -1838,9 +1838,6 @@ size_t hash_value( const Vector3<T> & v )
    return seed;
 
 }
-//**********************************************************************************************************************
-
-
 } // namespace math
 
 using math::Vector3;
@@ -1953,6 +1950,12 @@ inline bool check_float_equal( const math::Vector3<real_t> & lhs, const math::Ve
    return floatIsEqual( lhs[0], rhs[0] ) && floatIsEqual( lhs[1], rhs[1] ) && floatIsEqual( lhs[2], rhs[2] );
 }
 
+template< >
+inline bool check_float_equal_eps( const math::Vector3<real_t> & lhs, const math::Vector3<real_t> & rhs, const real_t epsilon )
+{
+   return floatIsEqual( lhs[0], rhs[0], epsilon ) && floatIsEqual( lhs[1], rhs[1], epsilon ) && floatIsEqual( lhs[2], rhs[2], epsilon );
+}
+
 }
 }
 }
-- 
GitLab