T-SIMD v31.1.3
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 using IntegerType = SignedByte;
156};
157
158template <>
159struct TypeInfo<SignedByte>
160{
161 static constexpr SIMD_INLINE const char *name() { return "SignedByte"; }
162 static constexpr SIMD_INLINE const char *format() { return "d"; }
163 static constexpr SIMD_INLINE const char *defaultFormat() { return "%d "; }
164 static constexpr SIMD_INLINE const char *hexFormat() { return "%02x "; }
165 static constexpr SIMD_INLINE SignedByte trueval()
166 {
167 return SIMDSIGNEDBYTE_TRUE;
168 }
169 using NextLargerType = Short;
170 using UnsignedType = Byte;
171 using SignedType = SignedByte;
172 using IntegerType = SignedByte;
173};
174
175template <>
176struct TypeInfo<Word>
177{
178 static constexpr SIMD_INLINE const char *name() { return "Word"; }
179 static constexpr SIMD_INLINE const char *format() { return "u"; }
180 static constexpr SIMD_INLINE const char *defaultFormat() { return "%u "; }
181 static constexpr SIMD_INLINE const char *hexFormat() { return "%04x "; }
182 static constexpr SIMD_INLINE Word trueval() { return SIMDWORD_TRUE; }
183 using NextLargerType = Int; // no larger unsigned type, use Int
184 using UnsignedType = Word;
185 using SignedType = Short;
186 using IntegerType = Short;
187};
188
189template <>
190struct TypeInfo<Short>
191{
192 static constexpr SIMD_INLINE const char *name() { return "Short"; }
193 static constexpr SIMD_INLINE const char *format() { return "d"; }
194 static constexpr SIMD_INLINE const char *defaultFormat() { return "%d "; }
195 static constexpr SIMD_INLINE const char *hexFormat() { return "%04x "; }
196 static constexpr SIMD_INLINE Short trueval() { return SIMDSHORT_TRUE; }
197 using NextLargerType = Int;
198 using UnsignedType = Word;
199 using SignedType = Short;
200 using IntegerType = Short;
201};
202
203template <>
204struct TypeInfo<Int>
205{
206 static constexpr SIMD_INLINE const char *name() { return "Int"; }
207 static constexpr SIMD_INLINE const char *format() { return "d"; }
208 static constexpr SIMD_INLINE const char *defaultFormat() { return "%d "; }
209 static constexpr SIMD_INLINE const char *hexFormat() { return "%08x "; }
210 static constexpr SIMD_INLINE Int trueval() { return SIMDINT_TRUE; }
211 using NextLargerType = Long;
212 using UnsignedType = uint32_t; // not a SIMD type
213 using SignedType = Int;
214 using IntegerType = Int;
215};
216
217template <>
218struct TypeInfo<Long>
219{
220 static constexpr SIMD_INLINE const char *name() { return "Long"; }
221 static constexpr SIMD_INLINE const char *format() { return "ld"; }
222 static constexpr SIMD_INLINE const char *defaultFormat() { return "%ld "; }
223 static constexpr SIMD_INLINE const char *hexFormat() { return "%016lx "; }
224 static constexpr SIMD_INLINE Long trueval() { return SIMDLONG_TRUE; }
225 using NextLargerType = Long; // no larger integer type than Long
226 using UnsignedType = uint64_t; // not a SIMD type
227 using SignedType = Long;
228 using IntegerType = Long;
229};
230
231template <>
232struct TypeInfo<Float>
233{
234 static constexpr SIMD_INLINE const char *name() { return "Float"; }
235 static constexpr SIMD_INLINE const char *format() { return ".9g"; }
236 static constexpr SIMD_INLINE const char *defaultFormat() { return "%.9g "; }
237 static SIMD_INLINE Float trueval() { return SIMDFLOAT_TRUE; }
238 using NextLargerType = Double;
239 using UnsignedType = Float; // no unsigned float type
240 using SignedType = Float;
241 using IntegerType = Int;
242};
243
244template <>
245struct TypeInfo<Double>
246{
247 static constexpr SIMD_INLINE const char *name() { return "Double"; };
248 static constexpr SIMD_INLINE const char *format() { return ".17g"; };
249 static constexpr SIMD_INLINE const char *defaultFormat() { return "%.17g "; };
250 static SIMD_INLINE Double trueval() { return SIMDDOUBLE_TRUE; }
251 using NextLargerType = Double; // no larger double type than Double
252 using UnsignedType = Double; // no unsigned double type
253 using SignedType = Double;
254 using IntegerType = Long;
255};
256
257} // namespace types
258} // namespace internal
259
263template <typename T>
265{
267 static constexpr SIMD_INLINE const char *name()
268 {
269 return internal::types::TypeInfo<T>::name();
270 };
272 static constexpr SIMD_INLINE const char *format()
273 {
274 return internal::types::TypeInfo<T>::format();
275 };
278 static constexpr SIMD_INLINE const char *defaultFormat()
279 {
280 return internal::types::TypeInfo<T>::defaultFormat();
281 };
283 static constexpr SIMD_INLINE const char *hexFormat()
284 {
285 return internal::types::TypeInfo<T>::hexFormat();
286 }
292 static constexpr bool isSigned = std::is_signed<T>::value;
298 static constexpr bool isInteger = std::is_integral<T>::value;
304 static constexpr bool isFloatingPoint = std::is_floating_point<T>::value;
309 static constexpr SIMD_INLINE T min()
310 {
311 return std::numeric_limits<T>::lowest();
312 }
317 static constexpr SIMD_INLINE T max() { return std::numeric_limits<T>::max(); }
319 static constexpr SIMD_INLINE T trueval()
320 {
321 return internal::types::TypeInfo<T>::trueval();
322 }
325 using NextLargerType = typename internal::types::TypeInfo<T>::NextLargerType;
328 using UnsignedType = typename internal::types::TypeInfo<T>::UnsignedType;
331 using SignedType = typename internal::types::TypeInfo<T>::SignedType;
334 using IntegerType = typename internal::types::TypeInfo<T>::IntegerType;
335};
336
337// ===========================================================================
338// formatting
339// ===========================================================================
340
341// note that for T=Float, TypeInfo<T>::format() returns "g",
342// for which precision encodes the number of significant digits,
343// not the number of fractional digits
349template <typename T>
350struct Format
351{
352 char format[256];
353
360 Format(int fieldWidth = -1, int precision = -1)
361 {
362 char fieldWidthStr[16], precisionStr[16];
363 if (fieldWidth >= 0)
364 sprintf(fieldWidthStr, "%d", fieldWidth);
365 else
366 strcpy(fieldWidthStr, "");
367 if (precision >= 0)
368 sprintf(precisionStr, ".%d", precision);
369 else
370 strcpy(precisionStr, "");
372 // integer format, precision is ignored
373 sprintf(format, "%%%s%s", fieldWidthStr, TypeInfo<T>::format());
374 else
375 // float format, precision is used
376 sprintf(format, "%%%s%s%s", fieldWidthStr, precisionStr,
378 }
379};
380
381// a crude way to format SIMD* types as decimal number, can be used in
382// fprintf (use %s format specification)
388template <typename T>
390{
391 char str[256];
392
400 Decimal(T value, int fieldWidth = -1, int precision = -1)
401 {
402 sprintf(str, Format<T>(fieldWidth, precision).format, value);
403 }
404};
405
408// 07. Oct 23 (Jonas Keller): added dont_deduce
409
410namespace internal {
411template <typename T>
412struct dont_deduce
413{
414 using type = T;
415};
416} // namespace internal
417
426template <typename T>
427using dont_deduce = typename internal::dont_deduce<T>::type;
428
429// 22. Jan 23 (Jonas Keller): moved tag dispatching classes into internal
430// namespace
431
432namespace internal {
433// ===========================================================================
434// tag dispatching
435// ===========================================================================
436
437// int2type trick from
438// Andrei Alexandrescu: Modern C++ Design (Addison Wesley)
439
440// 08. Apr 23 (Jonas Keller): removed IsIntSize; it is no longer used
441// 24. Nov 23 (Jonas Keller): removed some more unused tag dispatching classes
442
443template <size_t N>
444struct Integer
445{};
446
447template <size_t N>
448struct Part
449{};
450
451template <size_t N>
452struct Elements
453{};
454
455template <size_t N>
456struct Bytes
457{};
458
459template <bool AT_LOWER_LIMIT, size_t LOWER_LIMIT_INCLUSIVE,
460 size_t UPPER_LIMIT_EXCLUSIVE>
461struct Range
462{};
463
464template <size_t IMM, size_t SIZE>
465struct SizeRange
466 : public Range<(IMM & (SIZE - 1)) == 0, // is IMM a multiple of SIZE?
467 IMM & ~(SIZE - 1), // previous multiple of SIZE
468 (IMM & ~(SIZE - 1)) + SIZE> // next multiple of SIZE
469{};
470
471template <size_t N>
472struct Compression
473{};
474
475template <typename T>
476struct OutputType
477{};
478} // namespace internal
479
480} // namespace simd
481
482#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:427
Class for formatting SIMD types as decimal numbers.
Definition types.H:390
Decimal(T value, int fieldWidth=-1, int precision=-1)
Constructor.
Definition types.H:400
char str[256]
The formatted string.
Definition types.H:391
Class for generating format strings for printf for SIMD types.
Definition types.H:351
char format[256]
The generated format string.
Definition types.H:352
Format(int fieldWidth=-1, int precision=-1)
Constructor.
Definition types.H:360
Type information for SIMD types.
Definition types.H:265
typename internal::types::TypeInfo< T >::IntegerType IntegerType
The signed integer type of the same size (e.g. SignedByte for Byte, Int for Float)
Definition types.H:334
static constexpr bool isFloatingPoint
Whether the type is a floating point type.
Definition types.H:304
static constexpr T max()
Returns the maximum value of the type.
Definition types.H:317
static constexpr bool isSigned
Whether the type is signed.
Definition types.H:292
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:325
static constexpr T trueval()
Returns a value where all bits are 1.
Definition types.H:319
static constexpr const char * format()
Returns the format string for printf (e.g. "d" for Int)
Definition types.H:272
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:331
static constexpr const char * defaultFormat()
Returns the default format string for printf (e.g. "%d " for Int)
Definition types.H:278
static constexpr T min()
Returns the minimum value of the type.
Definition types.H:309
static constexpr const char * name()
Returns the name of the type (e.g. "Int" for Int)
Definition types.H:267
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:328
static constexpr bool isInteger
Whether the type is an integer.
Definition types.H:298
static constexpr const char * hexFormat()
Returns the hex format string for printf (e.g. "%08x " for Int)
Definition types.H:283