YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
numeric.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#ifndef YARP_CONFIG_NUMERIC_H
7#define YARP_CONFIG_NUMERIC_H
8
9#define YARP_HAS_SYS_TYPES_H
10
11#if defined(YARP_HAS_SYS_TYPES_H)
12# include <sys/types.h>
13#endif
14
15#include <cfloat>
16#include <cinttypes>
17#include <clocale>
18#include <cstdint>
19#include <cstddef>
20#include <cstdlib>
21#include <cstring>
22#include <limits>
23#include <sstream>
24#include <string>
25#if defined (_MSC_VER)
26# include <BaseTsd.h>
27#endif
28
29/* #undef YARP_BIG_ENDIAN */
30#define YARP_LITTLE_ENDIAN
31
32#define YARP_HAS_FLOAT128_T
33#define YARP_FLOAT32_IS_IEC559 1
34#define YARP_FLOAT64_IS_IEC559 1
35#define YARP_FLOAT128_IS_IEC559 1
36
37// Ensure that float32_t, float64_t, and float128_t are not defined by some
38// other header, included before this one.
39#if defined(float32_t)
40# undef float32_t
41#endif
42#if defined(float64_t)
43# undef float64_t
44#endif
45#if defined(float128_t)
46# undef float128_t
47#endif
48
49
50#define YARP_FLT_EXP_DIG 3
51#define YARP_DBL_EXP_DIG 4
52#define YARP_LDBL_EXP_DIG 5
53
54/*
55 * The maximum string length for a 'double' printed as a string using ("%.*g", DECIMAL_DIG) will be:
56 * Initial +/- sign 1 char
57 * First digit for exponential notation 1 char
58 * '.' decimal separator char 1 char
59 * DECIMAL_DIG digits for the mantissa DECIMAL_DIG chars
60 * 'e+/-' 2 chars
61 * YARP_DBL_EXP_DIG for the exponential YARP_DBL_EXP_DIG chars (YARP_LDBL_EXP_DIG if 128 bit float is available)
62 * string terminator 1 char
63 * FILLER 10 chars (you know, for safety)
64 * -----------------------------------------------------
65 * TOTAL is 16 + DECIMAL_DIG + YARP_DBL_EXP_DIG
66 */
67#if defined(YARP_HAS_FLOAT128_T)
68# define YARP_DOUBLE_TO_STRING_MAX_LENGTH (16 + DECIMAL_DIG + YARP_LDBL_EXP_DIG)
69#else
70# define YARP_DOUBLE_TO_STRING_MAX_LENGTH (16 + DECIMAL_DIG + YARP_DBL_EXP_DIG)
71#endif
72
73namespace yarp {
74namespace conf {
75
76typedef float float32_t;
77typedef double float64_t;
78typedef std::int32_t vocab32_t;
79typedef std::int64_t vocab64_t;
80#if defined(YARP_HAS_FLOAT128_T)
81typedef long double float128_t;
82#endif
83
84#if defined (_MSC_VER)
85typedef ::SSIZE_T ssize_t;
86#else
88#endif
89
90// Define `clamp` algorithm, available in c++17
91template<class T>
92constexpr const T& clamp( const T& v, const T& lo, const T& hi )
93{
94 // assert( !(hi < lo) );
95 return (v < lo) ? lo : (hi < v) ? hi : v;
96}
97
98template<class T, class Compare>
99constexpr const T& clamp( const T& v, const T& lo, const T& hi, Compare comp )
100{
101 // assert( !comp(hi, lo) );
102 return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
103}
104
105namespace numeric {
106
107#if !defined(SWIG)
108
109/*
110 * Converts an integer number to a string
111 */
112template <typename IntegerType,
113 std::enable_if_t<
114 std::is_integral<IntegerType>::value &&
115 !std::is_same<IntegerType, bool>::value, bool> = true>
116inline std::string to_string(IntegerType x)
117{
118 return std::to_string(x);
119}
120
121/*
122 * Converts a boolean to a string
123 */
124template <typename BoolType,
125 std::enable_if_t<std::is_same<BoolType, bool>::value, bool> = true>
126inline std::string to_string(BoolType x)
127{
128 return {x ? "true" : "false"};
129}
130
131/*
132 * Converts a floating point number to a string, dealing with locale issues
133 */
134template <typename FloatingType,
135 std::enable_if_t<std::is_floating_point<FloatingType>::value, bool> = true>
136inline std::string to_string(FloatingType x)
137{
138 char buf[YARP_DOUBLE_TO_STRING_MAX_LENGTH]; // -> see comment at the top of the file
139 std::snprintf(buf, YARP_DOUBLE_TO_STRING_MAX_LENGTH, "%.*g", DECIMAL_DIG, x);
140 std::string str(buf);
141
142 // If locale is set, the locale version of the decimal point is used.
143 // In this case we change it to the standard "."
144 // If there is no decimal point, and it is not being used the exponential
145 // notation (i.e. the number is in integer form, for example 100000 and not
146 // 1e5) we add ".0" to ensure that it will be interpreted as a double.
147 struct lconv* lc = localeconv();
148 size_t offset = str.find(lc->decimal_point);
149 if (offset != std::string::npos) {
150 str[offset] = '.';
151 } else if (str.find('e') == std::string::npos && str != "inf" && str != "-inf" && str != "nan") {
152 str += ".0";
153 }
154 return str;
155}
156
157/*
158 * Converts a string to a signed integer number
159 */
160template <typename IntegerType,
161 std::enable_if_t<
162 std::is_integral<IntegerType>::value &&
163 std::is_signed<IntegerType>::value &&
164 !std::is_same<IntegerType, bool>::value, bool> = true>
165inline IntegerType from_string(const std::string& src, IntegerType defaultValue = static_cast<IntegerType>(0))
166{
167 char *endptr = nullptr;
168 const char* startptr = src.c_str();
169 static constexpr int base = 10;
170
171 errno = 0;
172 auto ret = std::strtoll(startptr, &endptr, base);
173
174 if (errno != 0) {
175 // An error occurred
176 return defaultValue;
177 }
178
179 if (endptr == startptr) {
180 // No digits were found
181 return defaultValue;
182 }
183
184 if (endptr != startptr + src.size()) {
185 // Not all the string was interpreted
186 return defaultValue;
187 }
188
189 if (ret < (std::numeric_limits<IntegerType>::min)() || ret > (std::numeric_limits<IntegerType>::max)()) {
190 // Out of bound
191 return defaultValue;
192 }
193
194 return static_cast<IntegerType>(ret);
195}
196
197/*
198 * Converts a string to an unsigned integer number
199 */
200template <typename IntegerType,
201 std::enable_if_t<
202 std::is_integral<IntegerType>::value &&
203 !std::is_signed<IntegerType>::value &&
204 !std::is_same<IntegerType, bool>::value, bool> = true>
205inline IntegerType from_string(const std::string& src, IntegerType defaultValue = static_cast<IntegerType>(0))
206{
207 char *endptr = nullptr;
208 const char* startptr = src.c_str();
209 static constexpr int base = 10;
210
211 errno = 0;
212 auto ret = std::strtoull(startptr, &endptr, base);
213
214 if (errno != 0) {
215 // An error occurred
216 return defaultValue;
217 }
218
219 if (endptr == startptr) {
220 // No digits were found
221 return defaultValue;
222 }
223
224 if (endptr != startptr + src.size()) {
225 // Not all the string was interpreted
226 return defaultValue;
227 }
228
229 if (ret > (std::numeric_limits<IntegerType>::max)()) {
230 // Out of bound
231 return defaultValue;
232 }
233
234 if (ret > (std::numeric_limits<long long>::max)() && std::strtoll(startptr, &endptr, base) < 0) {
235 // This is a negative number silently converted to unsigned
236 return defaultValue;
237 }
238
239 return static_cast<IntegerType>(ret);
240}
241
242
243/*
244 * Converts a string to a boolean
245 */
246template <typename BoolType,
247 std::enable_if_t<std::is_same<BoolType, bool>::value, bool> = true>
248inline BoolType from_string(const std::string& src, BoolType defaultValue = false)
249{
250 if (src == "1") { return true; }
251 if (src == "true") { return true; }
252 if (src == "True") { return true; }
253 if (src == "TRUE") { return true; }
254 if (src == "yes") { return true; }
255 if (src == "Yes") { return true; }
256 if (src == "YES") { return true; }
257 if (src == "on") { return true; }
258 if (src == "On") { return true; }
259 if (src == "ON") { return true; }
260
261 if (src == "0") { return false; }
262 if (src == "false") { return false; }
263 if (src == "False") { return false; }
264 if (src == "FALSE") { return false; }
265 if (src == "no") { return false; }
266 if (src == "No") { return false; }
267 if (src == "NO") { return false; }
268 if (src == "off") { return false; }
269 if (src == "Off") { return false; }
270 if (src == "OFF") { return false; }
271
272 return defaultValue;
273}
274
275/*
276 * Converts a string to a floating point number, dealing with locale issues
277 */
278template <typename FloatingType,
279 std::enable_if_t<std::is_floating_point<FloatingType>::value, bool> = true>
280inline FloatingType from_string(const std::string& src, FloatingType defaultValue = static_cast<FloatingType>(0.0))
281{
282 if (src == "inf") {
283 return std::numeric_limits<FloatingType>::infinity();
284 }
285 if (src == "-inf") {
286 return -std::numeric_limits<FloatingType>::infinity();
287 }
288 if (src == "nan") {
289 return std::numeric_limits<FloatingType>::quiet_NaN();
290 }
291 // Need to deal with alternate versions of the decimal point.
292 // We need a copy of the string where the decimal point can be replaced.
293 std::string src_c = src;
294 size_t offset = src.find('.');
295 if (offset != std::string::npos) {
296 struct lconv* lc = localeconv();
297 src_c[offset] = lc->decimal_point[0];
298 }
299
300 char *endptr = nullptr;
301 const char* startptr = src_c.c_str();
302 auto ret = static_cast<FloatingType>(strtod(startptr, &endptr));
303
304 if (endptr == startptr) {
305 // No digits were found
306 return defaultValue;
307 }
308
309 if (endptr != startptr + src.size()) {
310 // Not all the string was interpreted
311 return defaultValue;
312 }
313
314 return ret;
315}
316
317template <typename IntegerType,
318 std::enable_if_t<
319 std::is_integral<IntegerType>::value &&
320 sizeof(IntegerType) != 1 &&
321 !std::is_same<IntegerType, bool>::value, bool> = true>
322std::string to_hex_string(IntegerType i)
323{
324 std::stringstream stream;
325 stream << std::hex << i;
326 return stream.str();
327}
328
329// FIXME C++17 use constexpr if
330template <typename IntegerType,
331 std::enable_if_t<sizeof(IntegerType) == 1, bool> = true>
332std::string to_hex_string(IntegerType i)
333{
334 // char and unsigned char are interpreted as characters, and therefore
335 // printed as the corresponding character
336 return to_hex_string<int>(static_cast<int>(static_cast<uint8_t>(i)));
337}
338
339#endif // !defined(SWIG)
340
341} // namespace numeric
342} // namespace conf
343} // namespace yarp
344
345
346#ifndef YARP_NO_DEPRECATED // since YARP 3.0.0
347#include <yarp/conf/api.h> // For YARP_DEPRECATED_TYPEDEF_MSG
348YARP_DEPRECATED_TYPEDEF_MSG("Use std::int8_t instead") std::int8_t YARP_INT8;
349YARP_DEPRECATED_TYPEDEF_MSG("Use std::int16_t instead") std::int16_t YARP_INT16;
350YARP_DEPRECATED_TYPEDEF_MSG("Use std::int32_t instead") std::int32_t YARP_INT32;
351YARP_DEPRECATED_TYPEDEF_MSG("Use std::int64_t instead") std::int64_t YARP_INT64;
352YARP_DEPRECATED_TYPEDEF_MSG("Use yarp::conf::float32_t instead") yarp::conf::float32_t YARP_FLOAT32;
353YARP_DEPRECATED_TYPEDEF_MSG("Use yarp::conf::float64_t instead") yarp::conf::float64_t YARP_FLOAT64;
354YARP_DEPRECATED_TYPEDEF_MSG("Use yarp::conf::ssize_t instead") yarp::conf::ssize_t YARP_SSIZE_T;
355#define YARP_INT32_FMT PRId32
356#define YARP_INT64_FMT PRId64
357#endif // YARP_NO_DEPRECATED
358
359
360#endif
bool ret
STL namespace.
std::string to_hex_string(IntegerType i)
Definition numeric.h:322
IntegerType from_string(const std::string &src, IntegerType defaultValue=static_cast< IntegerType >(0))
Definition numeric.h:165
std::string to_string(IntegerType x)
Definition numeric.h:116
std::int32_t vocab32_t
Definition numeric.h:78
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
Definition numeric.h:92
::ssize_t ssize_t
Definition numeric.h:87
double float64_t
Definition numeric.h:77
long double float128_t
Definition numeric.h:81
float float32_t
Definition numeric.h:76
std::int64_t vocab64_t
Definition numeric.h:79
The main, catch-all namespace for YARP.
Definition dirs.h:16
yarp::conf::float32_t YARP_FLOAT32
Definition numeric.h:352
std::int8_t YARP_INT8
Definition numeric.h:348
std::int64_t YARP_INT64
Definition numeric.h:351
std::int16_t YARP_INT16
Definition numeric.h:349
std::int32_t YARP_INT32
Definition numeric.h:350
#define YARP_DOUBLE_TO_STRING_MAX_LENGTH
Definition numeric.h:68
yarp::conf::ssize_t YARP_SSIZE_T
Definition numeric.h:354
yarp::conf::float64_t YARP_FLOAT64
Definition numeric.h:353
#define YARP_DEPRECATED_TYPEDEF_MSG(x)
Definition api.h:99