//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see .
//
//! \file DataTypes.h
//! \ingroup core
//! \author Florian Schornbaum
//
//======================================================================================================================
#pragma once
#include "waLBerlaDefinitions.h"
#include
#include
#include
#include
#include
#include
#include
namespace walberla {
#define WALBERLA_STATIC_ASSERT(x) static_assert(x, "Assertion failed")
template struct never_true : std::false_type {};
template< typename T > bool isIdentical( const T a, const T b );
// shared ptr
using std::shared_ptr;
using std::weak_ptr;
using std::make_shared;
using std::dynamic_pointer_cast;
// numeric cast (performs range checks in debug mode)
template< typename S, typename T >
inline S numeric_cast( T t ) {
#ifndef NDEBUG
if( std::is_integral::value && std::is_integral::value && !std::is_same::value )
// integer to different integer: check that forward and back conversion does not change value
{
if( !isIdentical( static_cast( static_cast(t) ), t ) )
{
throw std::range_error("out of range");
}
}
else if( !std::is_integral::value && !std::is_integral::value && sizeof(S) < sizeof(T) )
// float to shorter float: check that value within limits of shorter type
{
using H = typename std::conditional< !std::is_integral::value && !std::is_integral::value && (sizeof(S) < sizeof(T)), T, long double >::type; // always true, but makes Intel's overflow check happy
H h = static_cast(t);
if( h < static_cast(std::numeric_limits::lowest()) || h > static_cast(std::numeric_limits::max()) ) {
throw std::range_error("out of range");
}
}
else if( std::is_integral::value && !std::is_integral::value )
// float to integer: check that value within limits of integer
{
using H = typename std::conditional< std::is_integral::value && !std::is_integral::value, T, long double >::type; // always true, but makes Intel's overflow check happy
H h = static_cast(t);
if( h < static_cast(std::numeric_limits::lowest()) || h > static_cast(std::numeric_limits::max()) ) {
throw std::range_error("out of range");
}
}
#endif
return static_cast< S >(t);
}
// fixed size signed integral types
using int8_t = std::int8_t; ///< 8 bit signed integer
using int16_t = std::int16_t; ///< 16 bit signed integer
using int32_t = std::int32_t; ///< 32 bit signed integer
using int64_t = std::int64_t; ///< 64 bit signed integer
template< typename T > inline int8_t int8_c( T t ) { return numeric_cast< int8_t >(t); } ///< cast to type int8_t using "int8_c(x)"
template< typename T > inline int16_t int16_c( T t ) { return numeric_cast< int16_t >(t); } ///< cast to type int16_t using "int16_c(x)"
template< typename T > inline int32_t int32_c( T t ) { return numeric_cast< int32_t >(t); } ///< cast to type int32_t using "int32_c(x)"
template< typename T > inline int64_t int64_c( T t ) { return numeric_cast< int64_t >(t); } ///< cast to type int64_t using "int64_c(x)"
// fixed size unsigned integral types
using uint8_t = std::uint8_t; ///< 8 bit unsigned integer
using uint16_t = std::uint16_t; ///< 16 bit unsigned integer
using uint32_t = std::uint32_t; ///< 32 bit unsigned integer
using uint64_t = std::uint64_t; ///< 64 bit unsigned integer
using byte_t = uint8_t;
using id_t = uint64_t; //sid datatype for pe
template< typename T > inline uint8_t uint8_c( T t ) { return numeric_cast< uint8_t >(t); } ///< cast to type uint8_t using "uint8_c(x)"
template< typename T > inline uint16_t uint16_c( T t ) { return numeric_cast< uint16_t >(t); } ///< cast to type uint16_t using "uint16_c(x)"
template< typename T > inline uint32_t uint32_c( T t ) { return numeric_cast< uint32_t >(t); } ///< cast to type uint32_t using "uint32_c(x)"
template< typename T > inline uint64_t uint64_c( T t ) { return numeric_cast< uint64_t >(t); } ///< cast to type uint64_t using "uint64_c(x)"
// signed integral type
using ptrdiff_t = std::ptrdiff_t;
template< typename T > inline int int_c( T t ) { return numeric_cast< int >(t); } ///< cast to type int using "int_c(x)"
template< typename INT >
inline void static_assert_int_t() {
static_assert( std::numeric_limits::is_specialized && std::numeric_limits::is_integer, "Integer type required/expected!" );
}
// unsigned integral type
using uint_t = std::size_t;
using size_t = std::size_t;
static_assert( std::numeric_limits::is_specialized &&
std::numeric_limits::is_integer &&
!std::numeric_limits::is_signed, "Type \"uint_t\" must be an unsigned integer!" );
template< typename T > inline uint_t uint_c( T t ) { return numeric_cast< uint_t >(t); } ///< cast to type uint_t using "uint_c(x)"
template< typename UINT >
inline void static_assert_uint_t() {
static_assert( std::numeric_limits::is_specialized &&
std::numeric_limits::is_integer &&
!std::numeric_limits::is_signed, "Unsigned integer type required/expected!" );
}
// data structure specific data types
using cell_idx_t = int;
//typedef int64_t cell_idx_t;
WALBERLA_STATIC_ASSERT( std::numeric_limits::is_specialized &&
std::numeric_limits::is_integer &&
std::numeric_limits::is_signed );
template< typename T > inline cell_idx_t cell_idx_c( T t ) { return numeric_cast< cell_idx_t >(t); } ///< cast to type cell_idx_t using "cell_idx_c(x)"
// floating point type
#ifdef WALBERLA_DOUBLE_ACCURACY
using real_t = double;
#else
typedef float real_t;
#endif
inline constexpr real_t operator"" _r( long double t ) { return static_cast< real_t >(t); }
inline constexpr real_t operator"" _r( unsigned long long int t ) { return static_cast< real_t >(t); }
template< typename T > inline real_t real_c ( T t ) { return numeric_cast< real_t >(t); } ///< cast to type real_t using "real_c(x)"
template< typename T > inline double double_c( T t ) { return numeric_cast< double >(t); } ///< cast to type double
template< typename T > inline float float_c ( T t ) { return numeric_cast< float > (t); } ///< cast to type float
/// If you want to compare two reals using operator == and you really know what you are doing, you can use the following function:
template
inline bool isIdentical( const T a, const T b )
{
#ifdef WALBERLA_CXX_COMPILER_IS_GNU
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
return a == b;
#ifdef WALBERLA_CXX_COMPILER_IS_GNU
#pragma GCC diagnostic pop
#endif
}
inline bool realIsIdentical( const real_t a, const real_t b )
{
return isIdentical( a, b );
}
// http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
// conclusion: Comparing Floating Point Numbers - Know what you’re doing. There is no silver bullet. You have to choose wisely.
/// \cond internal
namespace real_comparison
{
template< class T > struct Epsilon;
template<> struct Epsilon< float > { static const float value; };
template<> struct Epsilon< double > { static const double value; };
template<> struct Epsilon< long double > { static const long double value; };
}
/// \endcond
inline bool realIsEqual( const real_t a, const real_t b, const real_t eps = real_comparison::Epsilon::value ) {
return std::fabs( a - b ) < eps;
}
inline bool floatIsEqual( long double lhs, long double rhs, const long double epsilon = real_comparison::Epsilon::value )
{
return std::fabs( lhs - rhs ) < epsilon;
}
inline bool floatIsEqual( double lhs, double rhs, const double epsilon = real_comparison::Epsilon::value )
{
return std::fabs( lhs - rhs ) < epsilon;
}
inline bool floatIsEqual( float lhs, float rhs, const float epsilon = real_comparison::Epsilon::value )
{
return std::fabs( lhs - rhs ) < epsilon;
}
} // namespace walberla
#define WALBERLA_UNUSED(x) (void)(x)