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;
79#if defined(YARP_HAS_FLOAT128_T)
80typedef long double float128_t;
81#endif
82
83#if defined (_MSC_VER)
84typedef ::SSIZE_T ssize_t;
85#else
87#endif
88
89// Define `clamp` algorithm, available in c++17
90template<class T>
91constexpr const T& clamp( const T& v, const T& lo, const T& hi )
92{
93 // assert( !(hi < lo) );
94 return (v < lo) ? lo : (hi < v) ? hi : v;
95}
96
97template<class T, class Compare>
98constexpr const T& clamp( const T& v, const T& lo, const T& hi, Compare comp )
99{
100 // assert( !comp(hi, lo) );
101 return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
102}
103
104namespace numeric {
105
106#if !defined(SWIG)
107
108/*
109 * Converts an integer number to a string
110 */
111template <typename IntegerType,
112 std::enable_if_t<
113 std::is_integral<IntegerType>::value &&
114 !std::is_same<IntegerType, bool>::value, bool> = true>
115inline std::string to_string(IntegerType x)
116{
117 return std::to_string(x);
118}
119
120/*
121 * Converts a boolean to a string
122 */
123template <typename BoolType,
124 std::enable_if_t<std::is_same<BoolType, bool>::value, bool> = true>
125inline std::string to_string(BoolType x)
126{
127 return {x ? "true" : "false"};
128}
129
130/*
131 * Converts a floating point number to a string, dealing with locale issues
132 */
133template <typename FloatingType,
134 std::enable_if_t<std::is_floating_point<FloatingType>::value, bool> = true>
135inline std::string to_string(FloatingType x)
136{
137 char buf[YARP_DOUBLE_TO_STRING_MAX_LENGTH]; // -> see comment at the top of the file
138 std::snprintf(buf, YARP_DOUBLE_TO_STRING_MAX_LENGTH, "%.*g", DECIMAL_DIG, x);
139 std::string str(buf);
140
141 // If locale is set, the locale version of the decimal point is used.
142 // In this case we change it to the standard "."
143 // If there is no decimal point, and it is not being used the exponential
144 // notation (i.e. the number is in integer form, for example 100000 and not
145 // 1e5) we add ".0" to ensure that it will be interpreted as a double.
146 struct lconv* lc = localeconv();
147 size_t offset = str.find(lc->decimal_point);
148 if (offset != std::string::npos) {
149 str[offset] = '.';
150 } else if (str.find('e') == std::string::npos && str != "inf" && str != "-inf" && str != "nan") {
151 str += ".0";
152 }
153 return str;
154}
155
156/*
157 * Converts a string to a signed integer number
158 */
159template <typename IntegerType,
160 std::enable_if_t<
161 std::is_integral<IntegerType>::value &&
162 std::is_signed<IntegerType>::value &&
163 !std::is_same<IntegerType, bool>::value, bool> = true>
164inline IntegerType from_string(const std::string& src, IntegerType defaultValue = static_cast<IntegerType>(0))
165{
166 char *endptr = nullptr;
167 const char* startptr = src.c_str();
168 static constexpr int base = 10;
169
170 errno = 0;
171 auto ret = std::strtoll(startptr, &endptr, base);
172
173 if (errno != 0) {
174 // An error occurred
175 return defaultValue;
176 }
177
178 if (endptr == startptr) {
179 // No digits were found
180 return defaultValue;
181 }
182
183 if (endptr != startptr + src.size()) {
184 // Not all the string was interpreted
185 return defaultValue;
186 }
187
188 if (ret < (std::numeric_limits<IntegerType>::min)() || ret > (std::numeric_limits<IntegerType>::max)()) {
189 // Out of bound
190 return defaultValue;
191 }
192
193 return static_cast<IntegerType>(ret);
194}
195
196/*
197 * Converts a string to an unsigned integer number
198 */
199template <typename IntegerType,
200 std::enable_if_t<
201 std::is_integral<IntegerType>::value &&
202 !std::is_signed<IntegerType>::value &&
203 !std::is_same<IntegerType, bool>::value, bool> = true>
204inline IntegerType from_string(const std::string& src, IntegerType defaultValue = static_cast<IntegerType>(0))
205{
206 char *endptr = nullptr;
207 const char* startptr = src.c_str();
208 static constexpr int base = 10;
209
210 errno = 0;
211 auto ret = std::strtoull(startptr, &endptr, base);
212
213 if (errno != 0) {
214 // An error occurred
215 return defaultValue;
216 }
217
218 if (endptr == startptr) {
219 // No digits were found
220 return defaultValue;
221 }
222
223 if (endptr != startptr + src.size()) {
224 // Not all the string was interpreted
225 return defaultValue;
226 }
227
228 if (ret > (std::numeric_limits<IntegerType>::max)()) {
229 // Out of bound
230 return defaultValue;
231 }
232
233 if (ret > (std::numeric_limits<long long>::max)() && std::strtoll(startptr, &endptr, base) < 0) {
234 // This is a negative number silently converted to unsigned
235 return defaultValue;
236 }
237
238 return static_cast<IntegerType>(ret);
239}
240
241
242/*
243 * Converts a string to a boolean
244 */
245template <typename BoolType,
246 std::enable_if_t<std::is_same<BoolType, bool>::value, bool> = true>
247inline BoolType from_string(const std::string& src, BoolType defaultValue = false)
248{
249 if (src == "1") { return true; }
250 if (src == "true") { return true; }
251 if (src == "True") { return true; }
252 if (src == "TRUE") { return true; }
253 if (src == "yes") { return true; }
254 if (src == "Yes") { return true; }
255 if (src == "YES") { return true; }
256 if (src == "on") { return true; }
257 if (src == "On") { return true; }
258 if (src == "ON") { return true; }
259
260 if (src == "0") { return false; }
261 if (src == "false") { return false; }
262 if (src == "False") { return false; }
263 if (src == "FALSE") { return false; }
264 if (src == "no") { return false; }
265 if (src == "No") { return false; }
266 if (src == "NO") { return false; }
267 if (src == "off") { return false; }
268 if (src == "Off") { return false; }
269 if (src == "OFF") { return false; }
270
271 return defaultValue;
272}
273
274/*
275 * Converts a string to a floating point number, dealing with locale issues
276 */
277template <typename FloatingType,
278 std::enable_if_t<std::is_floating_point<FloatingType>::value, bool> = true>
279inline FloatingType from_string(const std::string& src, FloatingType defaultValue = static_cast<FloatingType>(0.0))
280{
281 if (src == "inf") {
282 return std::numeric_limits<FloatingType>::infinity();
283 }
284 if (src == "-inf") {
285 return -std::numeric_limits<FloatingType>::infinity();
286 }
287 if (src == "nan") {
288 return std::numeric_limits<FloatingType>::quiet_NaN();
289 }
290 // Need to deal with alternate versions of the decimal point.
291 // We need a copy of the string where the decimal point can be replaced.
292 std::string src_c = src;
293 size_t offset = src.find('.');
294 if (offset != std::string::npos) {
295 struct lconv* lc = localeconv();
296 src_c[offset] = lc->decimal_point[0];
297 }
298
299 char *endptr = nullptr;
300 const char* startptr = src_c.c_str();
301 auto ret = static_cast<FloatingType>(strtod(startptr, &endptr));
302
303 if (endptr == startptr) {
304 // No digits were found
305 return defaultValue;
306 }
307
308 if (endptr != startptr + src.size()) {
309 // Not all the string was interpreted
310 return defaultValue;
311 }
312
313 return ret;
314}
315
316template <typename IntegerType,
317 std::enable_if_t<
318 std::is_integral<IntegerType>::value &&
319 sizeof(IntegerType) != 1 &&
320 !std::is_same<IntegerType, bool>::value, bool> = true>
321std::string to_hex_string(IntegerType i)
322{
323 std::stringstream stream;
324 stream << std::hex << i;
325 return stream.str();
326}
327
328// FIXME C++17 use constexpr if
329template <typename IntegerType,
330 std::enable_if_t<sizeof(IntegerType) == 1, bool> = true>
331std::string to_hex_string(IntegerType i)
332{
333 // char and unsigned char are interpreted as characters, and therefore
334 // printed as the corresponding character
335 return to_hex_string<int>(static_cast<int>(static_cast<uint8_t>(i)));
336}
337
338#endif // !defined(SWIG)
339
340} // namespace numeric
341} // namespace conf
342} // namespace yarp
343
344
345#ifndef YARP_NO_DEPRECATED // since YARP 3.0.0
346#include <yarp/conf/api.h> // For YARP_DEPRECATED_TYPEDEF_MSG
347YARP_DEPRECATED_TYPEDEF_MSG("Use std::int8_t instead") std::int8_t YARP_INT8;
348YARP_DEPRECATED_TYPEDEF_MSG("Use std::int16_t instead") std::int16_t YARP_INT16;
349YARP_DEPRECATED_TYPEDEF_MSG("Use std::int32_t instead") std::int32_t YARP_INT32;
350YARP_DEPRECATED_TYPEDEF_MSG("Use std::int64_t instead") std::int64_t YARP_INT64;
351YARP_DEPRECATED_TYPEDEF_MSG("Use yarp::conf::float32_t instead") yarp::conf::float32_t YARP_FLOAT32;
352YARP_DEPRECATED_TYPEDEF_MSG("Use yarp::conf::float64_t instead") yarp::conf::float64_t YARP_FLOAT64;
353YARP_DEPRECATED_TYPEDEF_MSG("Use yarp::conf::ssize_t instead") yarp::conf::ssize_t YARP_SSIZE_T;
354#define YARP_INT32_FMT PRId32
355#define YARP_INT64_FMT PRId64
356#endif // YARP_NO_DEPRECATED
357
358
359#endif
bool ret
STL namespace.
std::string to_hex_string(IntegerType i)
Definition numeric.h:321
IntegerType from_string(const std::string &src, IntegerType defaultValue=static_cast< IntegerType >(0))
Definition numeric.h:164
std::string to_string(IntegerType x)
Definition numeric.h:115
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:91
::ssize_t ssize_t
Definition numeric.h:86
double float64_t
Definition numeric.h:77
long double float128_t
Definition numeric.h:80
float float32_t
Definition numeric.h:76
The main, catch-all namespace for YARP.
Definition dirs.h:16
yarp::conf::float32_t YARP_FLOAT32
Definition numeric.h:351
std::int8_t YARP_INT8
Definition numeric.h:347
std::int64_t YARP_INT64
Definition numeric.h:350
std::int16_t YARP_INT16
Definition numeric.h:348
std::int32_t YARP_INT32
Definition numeric.h:349
#define YARP_DOUBLE_TO_STRING_MAX_LENGTH
Definition numeric.h:68
yarp::conf::ssize_t YARP_SSIZE_T
Definition numeric.h:353
yarp::conf::float64_t YARP_FLOAT64
Definition numeric.h:352
#define YARP_DEPRECATED_TYPEDEF_MSG(x)
Definition api.h:99