T-SIMD v31.1.0
A C++ template SIMD library
Loading...
Searching...
No Matches
types.H
1// ===========================================================================
2//
3// some basic types used for SIMD programming
4//
5// This source code file is part of the following software:
6//
7// - the low-level C++ template SIMD library
8// - the SIMD implementation of the MinWarping and the 2D-Warping methods
9// for local visual homing.
10//
11// The software is provided based on the accompanying license agreement in the
12// file LICENSE.md.
13// The software is provided "as is" without any warranty by the licensor and
14// without any liability of the licensor, and the software may not be
15// distributed by the licensee; see the license agreement for details.
16//
17// (C) Ralf Möller
18// Computer Engineering
19// Faculty of Technology
20// Bielefeld University
21// www.ti.uni-bielefeld.de
22//
23// ===========================================================================
24
25// 02. Mar 23 (Jonas Keller): added doxygen documentation
26// 13. May 23 (Jonas Keller): added Double support
27
28#pragma once
29#ifndef SIMD_TYPES_H_
30#define SIMD_TYPES_H_
31
32#include "defs.H"
33
34#include <cstdint>
35#include <cstdio>
36#include <cstring>
37#include <limits>
38#include <type_traits>
39
40namespace simd {
41
42// ===========================================================================
43// data types
44// ===========================================================================
45
50using Byte = uint8_t;
51using SignedByte = int8_t;
52using Word = uint16_t;
53using Short = int16_t;
54using Int = int32_t;
55using Long = int64_t;
56using Float = float;
57using Double = double;
60// exclude from doxygen (until endcond)
62
63// 30. Mar 23 (Jonas Keller): replaced the magic numbers in these macros with
64// std::numeric_limits<T>::max() and std::numeric_limits<T>::lowest()
65// and also added SIMDFLOAT_TRUE using an immediately invoked lambda and
66// std::memcpy
67
68// 23. Nov 23 (Jonas Keller): use simd::internal::bit_cast instead of using
69// memcpy directly in SIMDFLOAT_TRUE and SIMDDOUBLE_TRUE
70
71#define SIMDBYTE_TRUE (::simd::Byte(~0))
72#define SIMDSIGNEDBYTE_TRUE (::simd::SignedByte(~0))
73#define SIMDWORD_TRUE (::simd::Word(~0))
74#define SIMDSHORT_TRUE (::simd::Short(~0))
75#define SIMDINT_TRUE (::simd::Int(~0))
76#define SIMDLONG_TRUE (::simd::Long(~0))
77#define SIMDFLOAT_TRUE (::simd::internal::bit_cast<::simd::Float>(SIMDINT_TRUE))
78#define SIMDDOUBLE_TRUE \
79 (::simd::internal::bit_cast<::simd::Double>(SIMDLONG_TRUE))
80
81#define SIMDBYTE_MIN (::std::numeric_limits<Byte>::lowest())
82#define SIMDSIGNEDBYTE_MIN (::std::numeric_limits<SignedByte>::lowest())
83#define SIMDWORD_MIN (::std::numeric_limits<Word>::lowest())
84#define SIMDSHORT_MIN (::std::numeric_limits<Short>::lowest())
85#define SIMDINT_MIN (::std::numeric_limits<Int>::lowest())
86#define SIMDLONG_MIN (::std::numeric_limits<Long>::lowest())
87#define SIMDFLOAT_MIN (::std::numeric_limits<Float>::lowest())
88#define SIMDDOUBLE_MIN (::std::numeric_limits<Double>::lowest())
89
90#define SIMDBYTE_MAX (::std::numeric_limits<Byte>::max())
91#define SIMDSIGNEDBYTE_MAX (::std::numeric_limits<SignedByte>::max())
92#define SIMDWORD_MAX (::std::numeric_limits<Word>::max())
93#define SIMDSHORT_MAX (::std::numeric_limits<Short>::max())
94#define SIMDINT_MAX (::std::numeric_limits<Int>::max())
95#define SIMDLONG_MAX (::std::numeric_limits<Long>::max())
96#define SIMDFLOAT_MAX (::std::numeric_limits<Float>::max())
97#define SIMDDOUBLE_MAX (::std::numeric_limits<Double>::max())
98
99// 0x7fffff80
100#define MAX_POS_FLOAT_CONVERTIBLE_TO_INT32 2147483520.0f
101// 0x7fffff8000000000
102#define MAX_POS_FLOAT_CONVERTIBLE_TO_INT64 9223371487098961920.0f
103// 0x7fffffff
104#define MAX_POS_DOUBLE_CONVERTIBLE_TO_INT32 2147483647.0
105// 0x7ffffffffffffc00
106#define MAX_POS_DOUBLE_CONVERTIBLE_TO_INT64 9223372036854774784.0
108
109// 28. Feb 23 (Jonas Keller): added SortSlope enum
110
115enum class SortSlope { ASCENDING = 0, DESCENDING = 1 };
116
117// ===========================================================================
118// TypeInfo
119// ===========================================================================
120
121// NOTE: min() and max() are functions since "floating-point literals are not
122// allowed in constant expressions according to -pedantic
123
124// defaultFormat() returns a full format specifier with % and space, can be
125// used for tests
126
132// 27. Jan 23 (Jonas Keller): added wrapper class for TypeInfo for doxygen
133// documentation
134// 30. Mar 23 (Jonas Keller): deprecated isSigned, isInteger, isFloatingPoint,
135// min() and max() in TypeInfo in favor of the corresponding functions in
136// the std library and used those functions in the implementation of
137// TypeInfo
138
139namespace internal {
140namespace types {
141template <typename T>
142struct TypeInfo;
143
144template <>
145struct TypeInfo<Byte>
146{
147 static constexpr SIMD_INLINE const char *name() { return "Byte"; }
148 static constexpr SIMD_INLINE const char *format() { return "u"; }
149 static constexpr SIMD_INLINE const char *defaultFormat() { return "%u "; }
150 static constexpr SIMD_INLINE const char *hexFormat() { return "%02x "; }
151 static constexpr SIMD_INLINE Byte trueval() { return SIMDBYTE_TRUE; }
152 using NextLargerType = Word;
153 using UnsignedType = Byte;
154 using SignedType = SignedByte;
155};
156
157template <>
158struct TypeInfo<SignedByte>
159{
160 static constexpr SIMD_INLINE const char *name() { return "SignedByte"; }
161 static constexpr SIMD_INLINE const char *format() { return "d"; }
162 static constexpr SIMD_INLINE const char *defaultFormat() { return "%d "; }
163 static constexpr SIMD_INLINE const char *hexFormat() { return "%02x "; }
164 static constexpr SIMD_INLINE SignedByte trueval()
165 {
166 return SIMDSIGNEDBYTE_TRUE;
167 }
168 using NextLargerType = Short;
169 using UnsignedType = Byte;
170 using SignedType = SignedByte;
171};
172
173template <>
174struct TypeInfo<Word>
175{
176 static constexpr SIMD_INLINE const char *name() { return "Word"; }
177 static constexpr SIMD_INLINE const char *format() { return "u"; }
178 static constexpr SIMD_INLINE const char *defaultFormat() { return "%u "; }
179 static constexpr SIMD_INLINE const char *hexFormat() { return "%04x "; }
180 static constexpr SIMD_INLINE Word trueval() { return SIMDWORD_TRUE; }
181 using NextLargerType = Int; // no larger unsigned type, use Int
182 using UnsignedType = Word;
183 using SignedType = Short;
184};
185
186template <>
187struct TypeInfo<Short>
188{
189 static constexpr SIMD_INLINE const char *name() { return "Short"; }
190 static constexpr SIMD_INLINE const char *format() { return "d"; }
191 static constexpr SIMD_INLINE const char *defaultFormat() { return "%d "; }
192 static constexpr SIMD_INLINE const char *hexFormat() { return "%04x "; }
193 static constexpr SIMD_INLINE Short trueval() { return SIMDSHORT_TRUE; }
194 using NextLargerType = Int;
195 using UnsignedType = Word;
196 using SignedType = Short;
197};
198
199template <>
200struct TypeInfo<Int>
201{
202 static constexpr SIMD_INLINE const char *name() { return "Int"; }
203 static constexpr SIMD_INLINE const char *format() { return "d"; }
204 static constexpr SIMD_INLINE const char *defaultFormat() { return "%d "; }
205 static constexpr SIMD_INLINE const char *hexFormat() { return "%08x "; }
206 static constexpr SIMD_INLINE Int trueval() { return SIMDINT_TRUE; }
207 using NextLargerType = Long;
208 using UnsignedType = uint32_t; // not a SIMD type
209 using SignedType = Int;
210};
211
212template <>
213struct TypeInfo<Long>
214{
215 static constexpr SIMD_INLINE const char *name() { return "Long"; }
216 static constexpr SIMD_INLINE const char *format() { return "ld"; }
217 static constexpr SIMD_INLINE const char *defaultFormat() { return "%ld "; }
218 static constexpr SIMD_INLINE const char *hexFormat() { return "%016lx "; }
219 static constexpr SIMD_INLINE Long trueval() { return SIMDLONG_TRUE; }
220 using NextLargerType = Long; // no larger integer type than Long
221 using UnsignedType = uint64_t; // not a SIMD type
222 using SignedType = Long;
223};
224
225template <>
226struct TypeInfo<Float>
227{
228 static constexpr SIMD_INLINE const char *name() { return "Float"; }
229 static constexpr SIMD_INLINE const char *format() { return ".9g"; }
230 static constexpr SIMD_INLINE const char *defaultFormat() { return "%.9g "; }
231 static SIMD_INLINE Float trueval() { return SIMDFLOAT_TRUE; }
232 using NextLargerType = Double;
233 using UnsignedType = Float; // no unsigned float type
234 using SignedType = Float;
235};
236
237template <>
238struct TypeInfo<Double>
239{
240 static constexpr SIMD_INLINE const char *name() { return "Double"; };
241 static constexpr SIMD_INLINE const char *format() { return ".17g"; };
242 static constexpr SIMD_INLINE const char *defaultFormat() { return "%.17g "; };
243 static SIMD_INLINE Double trueval() { return SIMDDOUBLE_TRUE; }
244 using NextLargerType = Double; // no larger double type than Double
245 using UnsignedType = Double; // no unsigned double type
246 using SignedType = Double;
247};
248
249} // namespace types
250} // namespace internal
251
255template <typename T>
257{
259 static constexpr SIMD_INLINE const char *name()
260 {
261 return internal::types::TypeInfo<T>::name();
262 };
264 static constexpr SIMD_INLINE const char *format()
265 {
266 return internal::types::TypeInfo<T>::format();
267 };
270 static constexpr SIMD_INLINE const char *defaultFormat()
271 {
272 return internal::types::TypeInfo<T>::defaultFormat();
273 };
275 static constexpr SIMD_INLINE const char *hexFormat()
276 {
277 return internal::types::TypeInfo<T>::hexFormat();
278 }
284 static constexpr bool isSigned = std::is_signed<T>::value;
290 static constexpr bool isInteger = std::is_integral<T>::value;
296 static constexpr bool isFloatingPoint = std::is_floating_point<T>::value;
301 static constexpr SIMD_INLINE T min()
302 {
303 return std::numeric_limits<T>::lowest();
304 }
309 static constexpr SIMD_INLINE T max() { return std::numeric_limits<T>::max(); }
311 static constexpr SIMD_INLINE T trueval()
312 {
313 return internal::types::TypeInfo<T>::trueval();
314 }
317 using NextLargerType = typename internal::types::TypeInfo<T>::NextLargerType;
320 using UnsignedType = typename internal::types::TypeInfo<T>::UnsignedType;
323 using SignedType = typename internal::types::TypeInfo<T>::SignedType;
324};
325
326// ===========================================================================
327// formatting
328// ===========================================================================
329
330// note that for T=Float, TypeInfo<T>::format() returns "g",
331// for which precision encodes the number of significant digits,
332// not the number of fractional digits
338template <typename T>
339struct Format
340{
341 char format[256];
342
349 Format(int fieldWidth = -1, int precision = -1)
350 {
351 char fieldWidthStr[16], precisionStr[16];
352 if (fieldWidth >= 0)
353 sprintf(fieldWidthStr, "%d", fieldWidth);
354 else
355 strcpy(fieldWidthStr, "");
356 if (precision >= 0)
357 sprintf(precisionStr, ".%d", precision);
358 else
359 strcpy(precisionStr, "");
361 // integer format, precision is ignored
362 sprintf(format, "%%%s%s", fieldWidthStr, TypeInfo<T>::format());
363 else
364 // float format, precision is used
365 sprintf(format, "%%%s%s%s", fieldWidthStr, precisionStr,
367 }
368};
369
370// a crude way to format SIMD* types as decimal number, can be used in
371// fprintf (use %s format specification)
377template <typename T>
379{
380 char str[256];
381
389 Decimal(T value, int fieldWidth = -1, int precision = -1)
390 {
391 sprintf(str, Format<T>(fieldWidth, precision).format, value);
392 }
393};
394
397// 07. Oct 23 (Jonas Keller): added dont_deduce
398
399namespace internal {
400template <typename T>
401struct dont_deduce
402{
403 using type = T;
404};
405} // namespace internal
406
415template <typename T>
416using dont_deduce = typename internal::dont_deduce<T>::type;
417
418// 22. Jan 23 (Jonas Keller): moved tag dispatching classes into internal
419// namespace
420
421namespace internal {
422// ===========================================================================
423// tag dispatching
424// ===========================================================================
425
426// int2type trick from
427// Andrei Alexandrescu: Modern C++ Design (Addison Wesley)
428
429// 08. Apr 23 (Jonas Keller): removed IsIntSize; it is no longer used
430// 24. Nov 23 (Jonas Keller): removed some more unused tag dispatching classes
431
432template <size_t N>
433struct Integer
434{};
435
436template <size_t N>
437struct Part
438{};
439
440template <size_t N>
441struct Elements
442{};
443
444template <size_t N>
445struct Bytes
446{};
447
448template <bool AT_LOWER_LIMIT, size_t LOWER_LIMIT_INCLUSIVE,
449 size_t UPPER_LIMIT_EXCLUSIVE>
450struct Range
451{};
452
453template <size_t IMM, size_t SIZE>
454struct SizeRange
455 : public Range<(IMM & (SIZE - 1)) == 0, // is IMM a multiple of SIZE?
456 IMM & ~(SIZE - 1), // previous multiple of SIZE
457 (IMM & ~(SIZE - 1)) + SIZE> // next multiple of SIZE
458{};
459
460template <size_t N>
461struct Compression
462{};
463
464template <typename T>
465struct OutputType
466{};
467} // namespace internal
468
469} // namespace simd
470
471#endif
float Float
Single-precision floating point number (32-bit)
Definition types.H:56
int16_t Short
Signed 16-bit integer.
Definition types.H:53
int32_t Int
Signed 32-bit integer.
Definition types.H:54
uint16_t Word
Unsigned 16-bit integer.
Definition types.H:52
int64_t Long
Signed 64-bit integer.
Definition types.H:55
uint8_t Byte
Unsigned 8-bit integer.
Definition types.H:50
double Double
Double-precision floating point number (64-bit)
Definition types.H:57
int8_t SignedByte
Signed 8-bit integer.
Definition types.H:51
SortSlope
Used to indicate the direction of a sort function.
Definition types.H:115
Namespace for T-SIMD.
Definition time_measurement.H:161
typename internal::dont_deduce< T >::type dont_deduce
Helper type to prevent template argument deduction.
Definition types.H:416
Class for formatting SIMD types as decimal numbers.
Definition types.H:379
Decimal(T value, int fieldWidth=-1, int precision=-1)
Constructor.
Definition types.H:389
char str[256]
The formatted string.
Definition types.H:380
Class for generating format strings for printf for SIMD types.
Definition types.H:340
char format[256]
The generated format string.
Definition types.H:341
Format(int fieldWidth=-1, int precision=-1)
Constructor.
Definition types.H:349
Type information for SIMD types.
Definition types.H:257
static constexpr bool isFloatingPoint
Whether the type is a floating point type.
Definition types.H:296
static constexpr T max()
Returns the maximum value of the type.
Definition types.H:309
static constexpr bool isSigned
Whether the type is signed.
Definition types.H:284
typename internal::types::TypeInfo< T >::NextLargerType NextLargerType
The next larger type (e.g. Word for Byte), or the same type if there is no larger type.
Definition types.H:317
static constexpr T trueval()
Returns a value where all bits are 1.
Definition types.H:311
static constexpr const char * format()
Returns the format string for printf (e.g. "d" for Int)
Definition types.H:264
typename internal::types::TypeInfo< T >::SignedType SignedType
The signed type (e.g. SignedByte for Byte), or the same type if there is no signed type.
Definition types.H:323
static constexpr const char * defaultFormat()
Returns the default format string for printf (e.g. "%d " for Int)
Definition types.H:270
static constexpr T min()
Returns the minimum value of the type.
Definition types.H:301
static constexpr const char * name()
Returns the name of the type (e.g. "Int" for Int)
Definition types.H:259
typename internal::types::TypeInfo< T >::UnsignedType UnsignedType
The unsigned type (e.g. Byte for SignedByte), or the same type if there is no unsigned type.
Definition types.H:320
static constexpr bool isInteger
Whether the type is an integer.
Definition types.H:290
static constexpr const char * hexFormat()
Returns the hex format string for printf (e.g. "%08x " for Int)
Definition types.H:275