GEOSX
limits.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020, Lawrence Livermore National Security, LLC and LvArray contributors.
3  * All rights reserved.
4  * See the LICENSE file for details.
5  * SPDX-License-Identifier: (BSD-3-Clause)
6  */
7 
14 #pragma once
15 
16 // Source includes
17 #include "Macros.hpp"
18 
19 // System includes
20 #include <limits>
21 
22 namespace LvArray
23 {
24 
31 template< typename T >
32 struct NumericLimits : public std::numeric_limits< T >
33 {
35  static constexpr T min = std::numeric_limits< T >::min();
37  static constexpr T lowest = std::numeric_limits< T >::lowest();
39  static constexpr T max = std::numeric_limits< T >::max();
41  static constexpr T epsilon = std::numeric_limits< T >::epsilon();
43  static constexpr T round_error = std::numeric_limits< T >::round_error();
45  static constexpr T infinity = std::numeric_limits< T >::infinity();
47  static constexpr T quiet_NaN = std::numeric_limits< T >::quiet_NaN();
49  static constexpr T signaling_NaN = std::numeric_limits< T >::signaling_NaN();
51  static constexpr T denorm_min = std::numeric_limits< T >::denorm_min();
52 };
53 
60 template< typename T >
61 struct NumericLimitsNC : public std::numeric_limits< T >
62 {
66  T const lowest = std::numeric_limits< T >::lowest();
70  T const epsilon = std::numeric_limits< T >::epsilon();
72  T const round_error = std::numeric_limits< T >::round_error();
74  T const infinity = std::numeric_limits< T >::infinity();
76  T const quiet_NaN = std::numeric_limits< T >::quiet_NaN();
78  T const signaling_NaN = std::numeric_limits< T >::signaling_NaN();
80  T const denorm_min = std::numeric_limits< T >::denorm_min();
81 };
82 
83 namespace internal
84 {
85 
91 template< typename T, typename U >
92 constexpr bool sameSignedness = ( std::is_signed< T >::value && std::is_signed< U >::value ) ||
93  ( std::is_unsigned< T >::value && std::is_unsigned< U >::value );
94 
100 template< typename INPUT, typename OUTPUT >
101 constexpr bool canEasilyConvert = sizeof( INPUT ) < sizeof( OUTPUT ) ||
102  ( sizeof( INPUT ) == sizeof( OUTPUT ) && sameSignedness< INPUT, OUTPUT > );
103 
104 } // namespace internal
105 
112 template< typename OUTPUT, typename INPUT >
113 std::enable_if_t< internal::canEasilyConvert< INPUT, OUTPUT >, OUTPUT >
114 inline constexpr LVARRAY_HOST_DEVICE
115 integerConversion( INPUT input )
116 {
117  static_assert( std::is_integral< INPUT >::value, "INPUT must be an integral type." );
118  static_assert( std::is_integral< OUTPUT >::value, "OUTPUT must be an integral type." );
119 
120  return OUTPUT{ input };
121 }
122 
129 template< typename OUTPUT, typename INPUT >
130 std::enable_if_t< !internal::canEasilyConvert< INPUT, OUTPUT > &&
131  std::is_unsigned< INPUT >::value,
132  OUTPUT >
133 inline LVARRAY_HOST_DEVICE
134 integerConversion( INPUT input )
135 {
136  static_assert( std::is_integral< INPUT >::value, "INPUT must be an integral type." );
137  static_assert( std::is_integral< OUTPUT >::value, "OUTPUT must be an integral type." );
138 
140 
141  return static_cast< OUTPUT >( input );
142 }
143 
150 template< typename OUTPUT, typename INPUT >
151 std::enable_if_t< !internal::canEasilyConvert< INPUT, OUTPUT > &&
152  !std::is_unsigned< INPUT >::value,
153  OUTPUT >
154 inline LVARRAY_HOST_DEVICE
155 integerConversion( INPUT input )
156 {
157  static_assert( std::is_integral< INPUT >::value, "INPUT must be an integral type." );
158  static_assert( std::is_integral< OUTPUT >::value, "OUTPUT must be an integral type." );
159 
160  LVARRAY_ERROR_IF_LT( input, std::make_signed_t< OUTPUT >{ NumericLimits< OUTPUT >::min } );
161 
162  // If OUTPUT is unsigned we convert input to an unsigned type. This is safe because it must be
163  // positive due to the check above.
164  using ConditionallyUnsigned = std::conditional_t< std::is_unsigned< OUTPUT >::value, std::make_unsigned_t< INPUT >, INPUT >;
165  LVARRAY_ERROR_IF_GT( ConditionallyUnsigned( input ), NumericLimits< OUTPUT >::max );
166 
167  return static_cast< OUTPUT >( input );
168 }
169 
170 }
static constexpr T min
The smallest finite value T can hold.
Definition: limits.hpp:35
#define LVARRAY_ERROR_IF_LT(lhs, rhs)
Raise a hard error if one value compares less than the other.
Definition: Macros.hpp:282
static constexpr T signaling_NaN
A signaling NaN (if T is a floating point).
Definition: limits.hpp:49
static constexpr T infinity
A positive infinity value (if T is a floating point).
Definition: limits.hpp:45
#define LVARRAY_ERROR_IF_GT(lhs, rhs)
Raise a hard error if one value compares greater than the other.
Definition: Macros.hpp:252
static constexpr T denorm_min
The smallest positive subnormal value (if T is a floating point).
Definition: limits.hpp:51
static constexpr T round_error
The maximum rounding error (if T is a floating point).
Definition: limits.hpp:43
The same as NumericLimits except the entries are not static or constexpr.
Definition: limits.hpp:61
The top level namespace.
Definition: Array.hpp:24
A wrapper for the std::numeric_limits< T > member functions, this allows their values to be used on d...
Definition: limits.hpp:32
static constexpr T quiet_NaN
A quiet NaN (if T is a floating point).
Definition: limits.hpp:47
Contains a bunch of macro definitions.
static constexpr T lowest
The lowest finite value T can hold.
Definition: limits.hpp:37
static constexpr T epsilon
The difference between 1.0 and the next representable value (if T is floating point).
Definition: limits.hpp:41
constexpr std::enable_if_t< std::is_arithmetic< T >::value, T > min(T const a, T const b)
Definition: math.hpp:65
constexpr std::enable_if_t< std::is_arithmetic< T >::value, T > max(T const a, T const b)
Definition: math.hpp:46
std::enable_if_t< internal::canEasilyConvert< INPUT, OUTPUT >, OUTPUT > constexpr integerConversion(INPUT input)
Definition: limits.hpp:115
#define LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.
Definition: Macros.hpp:389
static constexpr T max
The largest finite value T can hold.
Definition: limits.hpp:39