libpromeki main
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
util.h
Go to the documentation of this file.
1
9#pragma once
10
11#include <array>
12#include <stdexcept>
13#include <cstdint>
14#include <limits>
15#include <type_traits>
18#include <promeki/core/error.h>
19
21
22class StringList;
23
24// Runtime time assert
25#define PROMEKI_ASSERT(x) if(!(x)) { \
26 promekiErr("Assertion failed: " PROMEKI_STRINGIFY(x)); \
27 promekiLogStackTrace(Logger::Err); \
28 promekiLogSync(); \
29 throw std::runtime_error(__FILE__ ":" PROMEKI_STRINGIFY(__LINE__) " Assertion failed: " PROMEKI_STRINGIFY(x)); \
30}
31
32// Compile time assert
33#define PROMEKI_STATIC_ASSERT(x) static_assert(x, __LINE__ ":" PROMEKI_STRINGIFY(__LINE__) " Assertion failed: " PROMEKI_STRINGIFY(x));
34
35// Macro string conversion and concatination
36#define PROMEKI_STRINGIFY_ARGS(...) #__VA_ARGS__
37#define PROMEKI_STRINGIFY_IMPL(value) #value
38#define PROMEKI_STRINGIFY(value) PROMEKI_STRINGIFY_IMPL(value)
39#define PROMEKI_CONCAT_IMPL(v1, v2) v1##v2
40#define PROMEKI_CONCAT(v1, v2) PROMEKI_CONCAT_IMPL(v1, v2)
41
42// Returns a unique ID that can be used to make unique macro items
43#define PROMEKI_UNIQUE_ID PROMEKI_CONCAT(__LINE__, __COUNTER__)
44
45// Returns the number of elements in a statically defined simple array.
46#define PROMEKI_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
47
48// Some useful alignment macros
49#define PROMEKI_ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
50
51// Use the PROMEKI_PRINTF_FUNC to hint to the compiler a particular variadic function
52// uses printf() symantics. This will allow the compiler to check that the variable
53// arguments match up with the format.
54// The m argument should be the index that contains the format
55// The n argument should be the index of the start of the variadic
56// Index starts at 1
57#if defined(PROMEKI_COMPILER_GCC_COMPAT)
58# define PROMEKI_PRINTF_FUNC(m, n) __attribute__((format(printf, m, n)))
59#elif defined(PROMEKI_COMPILER_MSVC)
60# define PROMEKI_PRINTF_FUNC(m, n) _Printf_format_string_
61#else
62# define PROMEKI_PRINTF_FUNC(m, n)
63#endif
64
65// If you'd like the compiler to implement the structure as
66// a packed data structure (i.e. no platform alignment)
67// surround the declaration with PROMEKI_PACKED_STRUCT_BEGIN
68// and PROMEKI_PACKED_STRUCT_END
69//
70// Ex:
71//
72// PROMEKI_PACKED_STRUCT_BEGIN
73// struct MyStruct {
74// int8_t value1;
75// int32_t value2;
76// int16_t value3;
77// }
78// PROMEKI_PACKED_STRUCT_END
79//
80// You can validate the packed-ness of the structure as it should
81// now show a sizeof(MyStruct) == to the exact size of all the data
82// in the structure.
83#if defined(PROMEKI_COMPILER_GCC_COMPAT)
84# define PROMEKI_PACKED_STRUCT_BEGIN
85# define PROMEKI_PACKED_STRUCT_END __attribute__((packed))
86#elif defined(PROMEKI_COMPILER_MSVC)
87# define PROMEKI_PACKED_STRUCT_BEGIN __pragma(pack(push, 1))
88# define PROMEKI_PACKED_STRUCT_END __pragma(pack(pop))
89#else
90# define PROMEKI_PACKED_STRUCT_BEGIN
91# define PROMEKI_PACKED_STRUCT_END
92#endif
93
94StringList promekiStackTrace(bool demangle = true);
95
96template <typename OutputType, typename InputType>
97OutputType promekiConvert(const InputType &input, Error *err = nullptr) {
98 static_assert(std::is_integral<InputType>::value || std::is_floating_point<InputType>::value,
99 "InputType must be an integer or floating point type");
100 static_assert(std::is_integral<OutputType>::value || std::is_floating_point<OutputType>::value,
101 "OutputType must be an integer or floating point type");
102 if (input > std::numeric_limits<OutputType>::max() || input < std::numeric_limits<OutputType>::lowest()) {
103 if(err != nullptr) *err = Error::Invalid;
104 return OutputType();
105 }
106 if(err != nullptr) *err = Error::Ok;
107 return static_cast<OutputType>(input);
108}
109
110template<typename T>
111inline T promekiLerp(const T& a, const T& b, const double& t) {
112 return a + t * (b - a);
113}
114
115template<typename T>
116T promekiCatmullRom(const std::array<T, 4>& points, T t) {
117 T t2 = t * t;
118 T t3 = t * t2;
119 T c1 = -0.5 * points[0] + 1.5 * points[1] - 1.5 * points[2] + 0.5 * points[3];
120 T c2 = points[0] - 2.5 * points[1] + 2 * points[2] - 0.5 * points[3];
121 T c3 = -0.5 * points[0] + 0.5 * points[2];
122 T c4 = points[1];
123 return c1 * t3 + c2 * t2 + c3 * t + c4;
124}
125
126template<typename T>
127T promekiBezier(const std::array<T, 4>& points, T t) {
128 T u = 1 - t;
129 T t2 = t * t;
130 T u2 = u * u;
131 T t3 = t2 * t;
132 T u3 = u2 * u;
133 T b0 = u3;
134 T b1 = 3 * u2 * t;
135 T b2 = 3 * u * t2;
136 T b3 = t3;
137 return b0 * points[0] + b1 * points[1] + b2 * points[2] + b3 * points[3];
138}
139
140template<typename T>
141T promekiBicubic(const std::array<std::array<T, 4>, 4>& points, T x, T y) {
142 std::array<T, 4> arr;
143 for (int i = 0; i < 4; ++i) {
144 std::array<T, 4> row;
145 for (int j = 0; j < 4; ++j) {
146 row[j] = points[i][j];
147 }
148 arr[i] = cubic_lerp(row, y);
149 }
150 return cubic_lerp(arr, x);
151}
152
153template<typename T>
154T promekiCubic(const std::array<T, 4>& points, T t) {
155 T a = points[3] - points[2] - points[0] + points[1];
156 T b = points[0] - points[1] - a;
157 T c = points[2] - points[0];
158 T d = points[1];
159 return a * t * t * t + b * t * t + c * t + d;
160}
161
163
Lightweight error code wrapper for the promeki library.
Definition error.h:39
@ Ok
No error.
Definition error.h:51
@ Invalid
Invalid value or argument (EINVAL).
Definition error.h:66
Dynamic array container wrapping std::vector.
Definition list.h:40
Manages a list of strings.
Definition stringlist.h:21
List()=default
Default constructor. Creates an empty list.
#define PROMEKI_NAMESPACE_BEGIN
Starts a promeki namespace block.
Definition namespace.h:14
#define PROMEKI_NAMESPACE_END
Ends a promeki namespace block.
Definition namespace.h:19