-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathtypes.h
More file actions
186 lines (150 loc) · 5.14 KB
/
types.h
File metadata and controls
186 lines (150 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// -*- c++ -*-
/*
* Copyright (c) 2010-2012, Jim Bosch
* All rights reserved.
*
* ndarray is distributed under a simple BSD-like license;
* see the LICENSE file that should be present in the root
* of the source distribution, or alternately available at:
* https://github.com/ndarray/ndarray
*/
#ifndef NDARRAY_types_h_INCLUDED
#define NDARRAY_types_h_INCLUDED
/// @file ndarray/types.h @brief Numeric type traits.
#include <complex>
#include <limits>
#include <boost/type_traits/is_complex.hpp>
namespace ndarray {
/// @addtogroup MainGroup
/// @{
/**
* @class NumericTraits
* @brief Numeric type traits
*
* Defines Real and Complex versions of numeric types, along with
* priority values to aid in type promotion.
*/
template <typename T, typename U=typename boost::remove_const<T>::type,
typename is_complex=typename boost::is_complex<U>::type,
typename is_arithmetic=typename boost::is_arithmetic<U>::type>
struct NumericTraits {};
/// \cond SPECIALIZATIONS
template <typename T, typename U>
struct NumericTraits<T,U,boost::false_type,boost::true_type> {
typedef U Type;
typedef boost::true_type IsReal;
typedef U RealType;
typedef std::complex<U> ComplexType;
typedef U ParamType;
static const int PRIORITY = sizeof(U) + (sizeof(long long) * (!std::numeric_limits<U>::is_integer));
};
template <typename T, typename U>
struct NumericTraits<T,U,boost::true_type,boost::false_type> {
typedef U type;
typedef boost::false_type IsReal;
typedef typename U::value_type RealType;
typedef U ComplexType;
typedef U const & ParamType;
static const int PRIORITY = NumericTraits<RealType>::PRIORITY;
};
/// \endcond
/**
* @class Promote
* @brief Metafunction to compute numeric promotions.
*/
template <typename T1, typename T2,
bool winner=(NumericTraits<T1>::PRIORITY > NumericTraits<T2>::PRIORITY),
bool is_complex=(NumericTraits<T1>::IsReal::value && NumericTraits<T2>::IsReal::value)
>
struct Promote {
};
/// \cond SPECIALIZATIONS
// Real, T2 has priority
template <typename T1, typename T2>
struct Promote<T1,T2,false,true> {
typedef typename NumericTraits<T2>::Type Type;
};
// Real, T1 has priority
template <typename T1, typename T2>
struct Promote<T1,T2,true,true> {
typedef typename NumericTraits<T1>::Type Type;
};
// Complex, T2 has priority
template <typename T1, typename T2>
struct Promote<T1,T2,false,false> {
typedef typename NumericTraits<T2>::ComplexType Type;
};
// Complex, T1 has priority
template <typename T1, typename T2>
struct Promote<T1,T2,true,false> {
typedef typename NumericTraits<T1>::ComplexType Type;
};
/// \endcond
namespace detail {
/**
* @internal @ingroup ndarrayInternalGroup
* @brief Provides careful floating point operations for use in floating point comparisons.
*
* Implementation is roughly modeled after the floating point comparisons in the Boost.Test library.
*
* \sa ApproximatelyEqual
*/
template <typename T>
struct SafeFloatingPointOps {
static inline T divide(T a, T b) {
if (b < static_cast<T>(1) && a > b*std::numeric_limits<T>::max())
return std::numeric_limits<T>::max();
if (a == static_cast<T>(0) || (b > static_cast<T>(1) && a < b*std::numeric_limits<T>::min()))
return static_cast<T>(0);
return a / b;
}
static inline T abs(T a) {
return (a < static_cast<T>(0)) ? -a : a;
}
};
} // namespace detail
/**
* @ingroup ndarrayMainGroup
* @brief Binary predicate for floating point equality comparison with tolerance.
*
* Implementation is roughly modeled after the floating point comparisons in the Boost.Test library.
*/
template <typename T1, typename T2=T1>
struct ApproximatelyEqual {
typedef T1 first_argument_type;
typedef T2 second_argument_type;
typedef bool result_type;
typedef typename Promote<T1,T2>::Type Promoted;
typedef detail::SafeFloatingPointOps<Promoted> Ops;
result_type operator()(T1 a, T2 b) const {
Promoted diff = Ops::abs(a - b);
Promoted da = Ops::divide(diff,Ops::abs(a));
Promoted db = Ops::divide(diff,Ops::abs(b));
return db <= _tolerance && da <= _tolerance;
}
explicit ApproximatelyEqual(Promoted tolerance) : _tolerance(Ops::abs(tolerance)) {}
private:
Promoted _tolerance;
};
/**
* @ingroup ndarrayMainGroup
* @brief Binary predicate for complex floating point equality comparison with tolerance.
*
* Implementation is roughly modeled after the floating point comparisons in the Boost.Test library.
*/
template <typename U1, typename U2>
struct ApproximatelyEqual< std::complex<U1>, std::complex<U2> > {
typedef std::complex<U1> first_argument_type;
typedef std::complex<U2> second_argument_type;
typedef bool result_type;
typedef typename Promote<U1,U2>::Type Promoted;
result_type operator()(std::complex<U1> const & a, std::complex<U2> const & b) const {
return _real(a.real(),b.real()) && _real(a.imag(),b.imag());
}
explicit ApproximatelyEqual(Promoted tolerance) : _real(tolerance) {}
private:
ApproximatelyEqual<U1,U2> _real;
};
/// @}
} // namespace ndarray
#endif // !NDARRAY_types_h_INCLUDED