21using half_float::half;
25template<std::
floating_po
int F>
26constexpr F
pi = std::numbers::pi_v<F>;
31concept Arithmetic = std::is_arithmetic_v<T> || std::same_as<T, half>;
34[[nodiscard]]
constexpr T
remap(T value, T l1, T h1, T l2, T h2) {
35 return l2 + (value - l1) * (h2 - l2) / (h1 - l1);
39[[nodiscard]]
constexpr T
remap(T value, T h1, T h2) {
40 return value * h2 / h1;
43[[nodiscard]]
constexpr bool isPowerOf2(std::unsigned_integral
auto n) {
44 return n && !(n & (n - 1));
47template<std::
unsigned_
integral T>
52 auto bigger = std::bit_ceil(n);
53 auto smaller = std::bit_floor(n);
54 return (n - smaller) < (bigger - n) ? smaller : bigger;
57[[nodiscard]]
constexpr uint32_t
log2ceil(uint32_t value) {
58 return ((std::bit_cast<uint32_t>(
static_cast<float>(value)) >> 23) & 0xff) - 127;
62 if (
const auto rest = n % alignment; rest > 0) {
63 return alignment - rest;
68template<u
int8_t S_, Arithmetic P>
70 static constexpr uint8_t
S = S_;
71 static_assert(
S >= 2,
"Vectors must have at least two values!");
77 constexpr Vec() =
default;
80 template<std::convertible_to<P>... Vals>
81 requires (
sizeof...(Vals) ==
S)
82 constexpr Vec(Vals... vals)
83 :
values{
static_cast<P
>(vals)...} {}
85 [[nodiscard]]
constexpr const P*
data()
const {
89 [[nodiscard]]
constexpr P*
data() {
93 [[nodiscard]]
constexpr uint8_t
size()
const {
99 return this->values[index];
106 return this->values[index];
115 template<u
int8_t SO, Arithmetic PO>
118 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
119 out[i] +=
static_cast<P
>(other[i]);
124 template<u
int8_t SO, Arithmetic PO>
126 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
127 (*this)[i] +=
static_cast<P
>(other[i]);
133 for (uint8_t i = 0; i <
S; i++) {
139 template<u
int8_t SO, Arithmetic PO>
142 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
143 out[i] -=
static_cast<P
>(other[i]);
148 template<u
int8_t SO, Arithmetic PO>
150 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
151 (*this)[i] -=
static_cast<P
>(other[i]);
157 for (uint8_t i = 0; i <
S; i++) {
158 out[i] *=
static_cast<P
>(scalar);
164 for (uint8_t i = 0; i <
S; i++) {
165 (*this)[i] *=
static_cast<P
>(scalar);
171 for (uint8_t i = 0; i <
S; i++) {
172 out[i] /=
static_cast<P
>(scalar);
178 for (uint8_t i = 0; i <
S; i++) {
179 (*this)[i] /=
static_cast<P
>(scalar);
185 for (uint8_t i = 0; i <
S; i++) {
186 out[i] %=
static_cast<P
>(scalar);
192 for (uint8_t i = 0; i <
S; i++) {
193 (*this)[i] %=
static_cast<P
>(scalar);
197 template<u
int8_t SO, Arithmetic PO>
199 if constexpr (
S != SO) {
202 for (uint8_t i = 0; i <
S; i++) {
203 if ((*
this)[i] !=
static_cast<P
>(other[i])) {
211 template<u
int8_t SO, Arithmetic PO = P>
214 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
215 out[i] =
static_cast<PO
>((*this)[i]);
220 template<u
int8_t SO, Arithmetic PO>
223 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
224 out[i] *=
static_cast<P
>(other[i]);
229 template<u
int8_t SO, Arithmetic PO>
232 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
233 out[i] /=
static_cast<P
>(other[i]);
238 template<u
int8_t SO, Arithmetic PO>
241 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
242 if constexpr ((std::floating_point<P> && std::floating_point<PO>) || std::floating_point<P>) {
243 out[i] = std::fmod(out[i],
static_cast<P
>(other[i]));
245 out[i] %=
static_cast<P
>(other[i]);
251 [[nodiscard]]
constexpr float magf()
const {
253 for (uint8_t i = 0; i <
S; i++) {
254 out += std::pow((*
this)[i], 2);
256 return std::sqrt(out);
259 [[nodiscard]]
constexpr double mag()
const {
261 for (uint8_t i = 0; i <
S; i++) {
262 out += std::pow((*
this)[i], 2);
264 return std::sqrt(out);
267 [[nodiscard]]
constexpr P
sum()
const {
269 for (uint8_t i = 0; i <
S; i++) {
275 template<Arithmetic PO>
278 for (uint8_t i = 0; i <
S; i++) {
279 out[i] = (*this)[i] *
static_cast<P
>(other[i]);
284 template<Arithmetic PO>
289 [[nodiscard]]
constexpr Vec abs()
const {
291 for (uint8_t i = 0; i <
S; i++) {
292 out[i] = std::abs(out[i]);
301 [[nodiscard]]
constexpr bool isZero()
const {
302 return *
this ==
zero();
305static_assert(std::is_trivially_copyable_v<Vec<2, float>>);
307#define SOURCEPP_VEC_DEFINE(S) \
308 template<Arithmetic P> \
309 using Vec##S = Vec<S, P>; \
310 using Vec##S##i8 = Vec##S<int8_t>; \
311 using Vec##S##i16 = Vec##S<int16_t>; \
312 using Vec##S##i32 = Vec##S<int32_t>; \
313 using Vec##S##i64 = Vec##S<int64_t>; \
314 using Vec##S##i = Vec##S##i32; \
315 using Vec##S##ui8 = Vec##S<uint8_t>; \
316 using Vec##S##ui16 = Vec##S<uint16_t>; \
317 using Vec##S##ui32 = Vec##S<uint32_t>; \
318 using Vec##S##ui64 = Vec##S<uint64_t>; \
319 using Vec##S##ui = Vec##S##ui32; \
320 using Vec##S##f16 = Vec##S<half>; \
321 using Vec##S##f32 = Vec##S<float>; \
322 using Vec##S##f64 = Vec##S<double>; \
323 using Vec##S##f = Vec##S##f32
329#undef SOURCEPP_VEC_DEFINE
344 const float fx = (
static_cast<float>(this->
x) / 32767.5f) - 1.f;
345 const float fy = (
static_cast<float>(this->
y) / 32767.5f) - 1.f;
346 const float fz = (
static_cast<float>(this->
z) / 16383.5f) - 1.f;
349 float fw = std::sqrt(1.f - fx * fx - fy * fy - fz * fz);
356 return {fx, fy, fz, fw};
359static_assert(std::is_trivially_copyable_v<QuatCompressed48>);
370 const double fx = (
static_cast<double>(this->
x) / 1048575.5) - 1.0f;
371 const double fy = (
static_cast<double>(this->
y) / 1048575.5) - 1.0f;
372 const double fz = (
static_cast<double>(this->
z) / 1048575.5) - 1.0f;
375 double fw = std::sqrt(1.0 - fx * fx - fy * fy - fz * fz);
382 return {
static_cast<float>(fx),
static_cast<float>(fy),
static_cast<float>(fz),
static_cast<float>(fw)};
385static_assert(std::is_trivially_copyable_v<QuatCompressed64>);
387template<u
int8_t M_, u
int8_t N_, Arithmetic P>
389 static constexpr uint8_t
M = M_;
390 static_assert(
M >= 2,
"Matrices must have at least two rows!");
391 static constexpr uint8_t
N = N_;
392 static_assert(
N >= 2,
"Matrices must have at least two columns!");
398 [[nodiscard]]
constexpr const P*
data()
const {
402 [[nodiscard]]
constexpr P*
data() {
406 [[nodiscard]]
constexpr uint8_t
rows()
const {
410 [[nodiscard]]
constexpr uint8_t
cols()
const {
414 [[nodiscard]] P*
operator[](uint8_t i) {
return this->values[i]; }
416 [[nodiscard]]
const P*
operator[](uint8_t i)
const {
return this->values[i]; }
418static_assert(std::is_trivially_copyable_v<Mat<2, 2, float>>);
420#define SOURCEPP_MAT_DEFINE(M, N) \
421 template<Arithmetic P> \
422 using Mat##M##x##N = Mat<M, N, P>; \
423 using Mat##M##x##N##i8 = Mat##M##x##N<int8_t>; \
424 using Mat##M##x##N##i16 = Mat##M##x##N<int16_t>; \
425 using Mat##M##x##N##i32 = Mat##M##x##N<int32_t>; \
426 using Mat##M##x##N##i64 = Mat##M##x##N<int64_t>; \
427 using Mat##M##x##N##i = Mat##M##x##N##i32; \
428 using Mat##M##x##N##ui8 = Mat##M##x##N<uint8_t>; \
429 using Mat##M##x##N##ui16 = Mat##M##x##N<uint16_t>; \
430 using Mat##M##x##N##ui32 = Mat##M##x##N<uint32_t>; \
431 using Mat##M##x##N##ui64 = Mat##M##x##N<uint64_t>; \
432 using Mat##M##x##N##ui = Mat##M##x##N##ui32; \
433 using Mat##M##x##N##f16 = Mat##M##x##N<half>; \
434 using Mat##M##x##N##f32 = Mat##M##x##N<float>; \
435 using Mat##M##x##N##f64 = Mat##M##x##N<double>; \
436 using Mat##M##x##N##f = Mat##M##x##N##f32
448#undef SOURCEPP_MAT_DEFINE
#define SOURCEPP_VEC_DEFINE(S)
#define SOURCEPP_MAT_DEFINE(M, N)
constexpr T nearestPowerOf2(T n)
constexpr bool isPowerOf2(std::unsigned_integral auto n)
constexpr uint16_t paddingForAlignment(uint16_t alignment, uint64_t n)
constexpr T remap(T value, T l1, T h1, T l2, T h2)
constexpr uint32_t log2ceil(uint32_t value)
constexpr uint8_t rows() const
constexpr const P * data() const
const P * operator[](uint8_t i) const
static constexpr uint8_t M
static constexpr uint8_t N
P * operator[](uint8_t i)
constexpr uint8_t cols() const
Lower precision Quat compressed to 6 bytes.
Lower precision Quat compressed to 8 bytes.
constexpr Vec mod(const Vec< SO, PO > &other) const
constexpr Vec(Vals... vals)
constexpr P dot(const Vec< S, PO > &other) const
constexpr Vec div(const Vec< SO, PO > &other) const
static constexpr Vec zero()
constexpr Vec operator-(const Vec< SO, PO > &other) const
constexpr Vec operator-() const
constexpr void operator/=(Arithmetic auto scalar)
constexpr Vec operator+() const
constexpr float magf() const
constexpr Vec operator*(Arithmetic auto scalar) const
constexpr Vec operator/(Arithmetic auto scalar) const
constexpr Vec scale(const Vec< S, PO > &other) const
constexpr Vec operator%(Arithmetic auto scalar) const
constexpr double mag() const
constexpr bool isZero() const
constexpr Vec< SO, PO > to() const
constexpr uint8_t size() const
constexpr Vec operator+(const Vec< SO, PO > &other) const
constexpr bool operator==(const Vec< SO, PO > &other) const
constexpr void operator-=(const Vec< SO, PO > &other)
constexpr void operator*=(Arithmetic auto scalar)
constexpr P operator[](uint8_t index) const
constexpr void operator%=(Arithmetic auto scalar)
constexpr Vec mul(const Vec< SO, PO > &other) const
constexpr P & operator[](uint8_t index)
static constexpr uint8_t S
constexpr Vec abs() const
constexpr const P * data() const
constexpr void operator+=(const Vec< SO, PO > &other)