12#include <promeki/config.h>
13#if PROMEKI_ENABLE_CORE
24PROMEKI_NAMESPACE_BEGIN
29#define PROMEKI_ASSERT(x) \
31 promekiErr("Assertion failed: " PROMEKI_STRINGIFY(x)); \
32 promekiLogStackTrace(Logger::Err); \
34 throw std::runtime_error(__FILE__ \
35 ":" PROMEKI_STRINGIFY(__LINE__) " Assertion failed: " PROMEKI_STRINGIFY(x)); \
39#define PROMEKI_STATIC_ASSERT(x) \
40 static_assert(x, __LINE__ ":" PROMEKI_STRINGIFY(__LINE__) " Assertion failed: " PROMEKI_STRINGIFY(x));
43#define PROMEKI_STRINGIFY_ARGS(...) #__VA_ARGS__
44#define PROMEKI_STRINGIFY_IMPL(value) #value
45#define PROMEKI_STRINGIFY(value) PROMEKI_STRINGIFY_IMPL(value)
46#define PROMEKI_CONCAT_IMPL(v1, v2) v1##v2
47#define PROMEKI_CONCAT(v1, v2) PROMEKI_CONCAT_IMPL(v1, v2)
50#define PROMEKI_UNIQUE_ID PROMEKI_CONCAT(__LINE__, __COUNTER__)
53#define PROMEKI_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
66#if defined(__has_feature)
67#if __has_feature(address_sanitizer)
68#define PROMEKI_ADDRESS_SANITIZER_ENABLED 1
71#if defined(__SANITIZE_ADDRESS__)
72#define PROMEKI_ADDRESS_SANITIZER_ENABLED 1
74#if defined(PROMEKI_ADDRESS_SANITIZER_ENABLED) && __has_include(<sanitizer/lsan_interface.h>)
75#include <sanitizer/lsan_interface.h>
76#define PROMEKI_INTENTIONAL_LEAK(ptr) __lsan_ignore_object(ptr)
78#define PROMEKI_INTENTIONAL_LEAK(ptr) ((void)(ptr))
82#define PROMEKI_ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
90#if defined(PROMEKI_COMPILER_GCC_COMPAT)
91#define PROMEKI_PRINTF_FUNC(m, n) __attribute__((format(printf, m, n)))
92#elif defined(PROMEKI_COMPILER_MSVC)
93#define PROMEKI_PRINTF_FUNC(m, n) _Printf_format_string_
95#define PROMEKI_PRINTF_FUNC(m, n)
116#if defined(PROMEKI_COMPILER_GCC_COMPAT)
117#define PROMEKI_PACKED_STRUCT_BEGIN
118#define PROMEKI_PACKED_STRUCT_END __attribute__((packed))
119#elif defined(PROMEKI_COMPILER_MSVC)
120#define PROMEKI_PACKED_STRUCT_BEGIN __pragma(pack(push, 1))
121#define PROMEKI_PACKED_STRUCT_END __pragma(pack(pop))
123#define PROMEKI_PACKED_STRUCT_BEGIN
124#define PROMEKI_PACKED_STRUCT_END
127StringList promekiStackTrace(
bool demangle =
true);
129template <
typename OutputType,
typename InputType>
130OutputType promekiConvert(
const InputType &input, Error *err =
nullptr) {
131 static_assert(std::is_integral<InputType>::value || std::is_floating_point<InputType>::value,
132 "InputType must be an integer or floating point type");
133 static_assert(std::is_integral<OutputType>::value || std::is_floating_point<OutputType>::value,
134 "OutputType must be an integer or floating point type");
150 if constexpr (std::is_same_v<InputType, bool> || std::is_same_v<OutputType, bool>) {
152 }
else if constexpr (std::is_integral_v<InputType> && std::is_integral_v<OutputType>) {
153 if (std::cmp_greater(input, std::numeric_limits<OutputType>::max()) ||
154 std::cmp_less(input, std::numeric_limits<OutputType>::lowest())) {
155 if (err !=
nullptr) *err = Error::Invalid;
159 if (input > std::numeric_limits<OutputType>::max() ||
160 input < std::numeric_limits<OutputType>::lowest()) {
161 if (err !=
nullptr) *err = Error::Invalid;
165 if (err !=
nullptr) *err = Error::Ok;
166 return static_cast<OutputType
>(input);
169template <
typename T>
inline T promekiLerp(
const T &a,
const T &b,
const double &t) {
170 return a + t * (b - a);
173template <
typename T> T promekiCatmullRom(
const Array<T, 4> &points, T t) {
176 T c1 = -0.5 * points[0] + 1.5 * points[1] - 1.5 * points[2] + 0.5 * points[3];
177 T c2 = points[0] - 2.5 * points[1] + 2 * points[2] - 0.5 * points[3];
178 T c3 = -0.5 * points[0] + 0.5 * points[2];
180 return c1 * t3 + c2 * t2 + c3 * t + c4;
183template <
typename T> T promekiBezier(
const Array<T, 4> &points, T t) {
193 return b0 * points[0] + b1 * points[1] + b2 * points[2] + b3 * points[3];
196template <
typename T> T promekiBicubic(
const Array<Array<T, 4>, 4> &points, T x, T y) {
198 for (
int i = 0; i < 4; ++i) {
200 for (
int j = 0; j < 4; ++j) {
201 row[j] = points[i][j];
203 arr[i] = cubic_lerp(row, y);
205 return cubic_lerp(arr, x);
208template <
typename T> T promekiCubic(
const Array<T, 4> &points, T t) {
209 T a = points[3] - points[2] - points[0] + points[1];
210 T b = points[0] - points[1] - a;
211 T c = points[2] - points[0];
213 return a * t * t * t + b * t * t + c * t + d;