24using half_float::half;
28template<std::
floating_po
int F>
29constexpr F
pi = std::numbers::pi_v<F>;
34concept Arithmetic = std::is_arithmetic_v<T> || std::same_as<T, half>;
37[[nodiscard]]
constexpr T
remap(T value, T l1, T h1, T l2, T h2) {
38 return l2 + (value - l1) * (h2 - l2) / (h1 - l1);
42[[nodiscard]]
constexpr T
remap(T value, T h1, T h2) {
43 return value * h2 / h1;
46[[nodiscard]]
constexpr bool isPowerOf2(std::unsigned_integral
auto n) {
47 return n && !(n & (n - 1));
50template<std::
unsigned_
integral T>
55 auto bigger = std::bit_ceil(n);
56 auto smaller = std::bit_floor(n);
57 return (n - smaller) < (bigger - n) ? smaller : bigger;
60[[nodiscard]]
constexpr uint32_t
log2ceil(uint32_t value) {
61 return ((std::bit_cast<uint32_t>(
static_cast<float>(value)) >> 23) & 0xff) - 127;
65 if (
const auto rest = n % alignment; rest > 0) {
66 return alignment - rest;
71template<u
int8_t S_, Arithmetic P>
73 static constexpr uint8_t
S = S_;
74 static_assert(
S >= 2,
"Vectors must have at least two values!");
80 constexpr Vec() =
default;
83 template<std::convertible_to<P>... Vals>
84 requires (
sizeof...(Vals) ==
S)
85 constexpr Vec(Vals... vals)
86 :
values{
static_cast<P
>(vals)...} {}
88 [[nodiscard]]
constexpr const P*
data()
const {
92 [[nodiscard]]
constexpr P*
data() {
96 [[nodiscard]]
constexpr uint8_t
size()
const {
102 return this->values[index];
109 return this->values[index];
120 for (uint8_t i = 0; i <
S; i++) {
121 out[i] +=
static_cast<P
>(scalar);
126 template<u
int8_t SO, Arithmetic PO>
129 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
130 out[i] +=
static_cast<P
>(other[i]);
136 for (uint8_t i = 0; i <
S; i++) {
137 (*this)[i] +=
static_cast<P
>(scalar);
141 template<u
int8_t SO, Arithmetic PO>
143 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
144 (*this)[i] +=
static_cast<P
>(other[i]);
150 for (uint8_t i = 0; i <
S; i++) {
158 for (uint8_t i = 0; i <
S; i++) {
159 out[i] -=
static_cast<P
>(scalar);
164 template<u
int8_t SO, Arithmetic PO>
167 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
168 out[i] -=
static_cast<P
>(other[i]);
174 for (uint8_t i = 0; i <
S; i++) {
175 (*this)[i] -=
static_cast<P
>(scalar);
179 template<u
int8_t SO, Arithmetic PO>
181 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
182 (*this)[i] -=
static_cast<P
>(other[i]);
188 for (uint8_t i = 0; i <
S; i++) {
189 out[i] *=
static_cast<P
>(scalar);
195 for (uint8_t i = 0; i <
S; i++) {
196 (*this)[i] *=
static_cast<P
>(scalar);
202 for (uint8_t i = 0; i <
S; i++) {
203 out[i] /=
static_cast<P
>(scalar);
209 for (uint8_t i = 0; i <
S; i++) {
210 (*this)[i] /=
static_cast<P
>(scalar);
216 for (uint8_t i = 0; i <
S; i++) {
217 out[i] %=
static_cast<P
>(scalar);
223 for (uint8_t i = 0; i <
S; i++) {
224 (*this)[i] %=
static_cast<P
>(scalar);
228 template<u
int8_t SO, Arithmetic PO>
230 if constexpr (
S != SO) {
233 for (uint8_t i = 0; i <
S; i++) {
234 if ((*
this)[i] !=
static_cast<P
>(other[i])) {
242 template<u
int8_t SO, Arithmetic PO = P>
245 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
246 out[i] =
static_cast<PO
>((*this)[i]);
251 template<u
int8_t SO, Arithmetic PO>
254 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
255 out[i] *=
static_cast<P
>(other[i]);
260 template<u
int8_t SO, Arithmetic PO>
263 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
264 out[i] /=
static_cast<P
>(other[i]);
269 template<u
int8_t SO, Arithmetic PO>
272 for (uint8_t i = 0; i < (
S > SO ? SO :
S); i++) {
273 if constexpr ((std::floating_point<P> && std::floating_point<PO>) || std::floating_point<P>) {
274 out[i] = std::fmod(out[i],
static_cast<P
>(other[i]));
276 out[i] %=
static_cast<P
>(other[i]);
282 [[nodiscard]]
constexpr float magf()
const {
284 for (uint8_t i = 0; i <
S; i++) {
285 out += std::pow((*
this)[i], 2);
287 return std::sqrt(out);
290 [[nodiscard]]
constexpr double mag()
const {
292 for (uint8_t i = 0; i <
S; i++) {
293 out += std::pow((*
this)[i], 2);
295 return std::sqrt(out);
298 [[nodiscard]]
constexpr P
sum()
const {
300 for (uint8_t i = 0; i <
S; i++) {
306 template<Arithmetic PO>
309 for (uint8_t i = 0; i <
S; i++) {
310 out[i] = (*this)[i] *
static_cast<P
>(other[i]);
315 template<Arithmetic PO>
320 [[nodiscard]]
constexpr Vec abs()
const {
322 for (uint8_t i = 0; i <
S; i++) {
323 out[i] = std::abs(out[i]);
332 [[nodiscard]]
constexpr bool isZero()
const {
333 return *
this ==
zero();
336static_assert(std::is_trivially_copyable_v<Vec<2, float>>);
338#define SOURCEPP_VEC_DEFINE(S) \
339 template<Arithmetic P> \
340 using Vec##S = Vec<S, P>; \
341 using Vec##S##i8 = Vec##S<int8_t>; \
342 using Vec##S##i16 = Vec##S<int16_t>; \
343 using Vec##S##i32 = Vec##S<int32_t>; \
344 using Vec##S##i64 = Vec##S<int64_t>; \
345 using Vec##S##i = Vec##S##i32; \
346 using Vec##S##ui8 = Vec##S<uint8_t>; \
347 using Vec##S##ui16 = Vec##S<uint16_t>; \
348 using Vec##S##ui32 = Vec##S<uint32_t>; \
349 using Vec##S##ui64 = Vec##S<uint64_t>; \
350 using Vec##S##ui = Vec##S##ui32; \
351 using Vec##S##f16 = Vec##S<half>; \
352 using Vec##S##f32 = Vec##S<float>; \
353 using Vec##S##f64 = Vec##S<double>; \
354 using Vec##S##f = Vec##S##f32
360#undef SOURCEPP_VEC_DEFINE
375 const float fx = (
static_cast<float>(this->
x) / 32767.5f) - 1.f;
376 const float fy = (
static_cast<float>(this->
y) / 32767.5f) - 1.f;
377 const float fz = (
static_cast<float>(this->
z) / 16383.5f) - 1.f;
380 float fw = std::sqrt(1.f - fx * fx - fy * fy - fz * fz);
387 return {fx, fy, fz, fw};
390static_assert(std::is_trivially_copyable_v<QuatCompressed48>);
401 const double fx = (
static_cast<double>(this->
x) / 1048575.5) - 1.0f;
402 const double fy = (
static_cast<double>(this->
y) / 1048575.5) - 1.0f;
403 const double fz = (
static_cast<double>(this->
z) / 1048575.5) - 1.0f;
406 double fw = std::sqrt(1.0 - fx * fx - fy * fy - fz * fz);
413 return {
static_cast<float>(fx),
static_cast<float>(fy),
static_cast<float>(fz),
static_cast<float>(fw)};
416static_assert(std::is_trivially_copyable_v<QuatCompressed64>);
418template<u
int8_t M_, u
int8_t N_, Arithmetic P>
420 static constexpr uint8_t
M = M_;
421 static_assert(
M >= 2,
"Matrices must have at least two rows!");
422 static constexpr uint8_t
N = N_;
423 static_assert(
N >= 2,
"Matrices must have at least two columns!");
429 [[nodiscard]]
constexpr const P*
data()
const {
433 [[nodiscard]]
constexpr P*
data() {
437 [[nodiscard]]
constexpr uint8_t
rows()
const {
441 [[nodiscard]]
constexpr uint8_t
cols()
const {
445 [[nodiscard]] P*
operator[](uint8_t i) {
return this->values[i]; }
447 [[nodiscard]]
const P*
operator[](uint8_t i)
const {
return this->values[i]; }
449static_assert(std::is_trivially_copyable_v<Mat<2, 2, float>>);
451#define SOURCEPP_MAT_DEFINE(M, N) \
452 template<Arithmetic P> \
453 using Mat##M##x##N = Mat<M, N, P>; \
454 using Mat##M##x##N##i8 = Mat##M##x##N<int8_t>; \
455 using Mat##M##x##N##i16 = Mat##M##x##N<int16_t>; \
456 using Mat##M##x##N##i32 = Mat##M##x##N<int32_t>; \
457 using Mat##M##x##N##i64 = Mat##M##x##N<int64_t>; \
458 using Mat##M##x##N##i = Mat##M##x##N##i32; \
459 using Mat##M##x##N##ui8 = Mat##M##x##N<uint8_t>; \
460 using Mat##M##x##N##ui16 = Mat##M##x##N<uint16_t>; \
461 using Mat##M##x##N##ui32 = Mat##M##x##N<uint32_t>; \
462 using Mat##M##x##N##ui64 = Mat##M##x##N<uint64_t>; \
463 using Mat##M##x##N##ui = Mat##M##x##N##ui32; \
464 using Mat##M##x##N##f16 = Mat##M##x##N<half>; \
465 using Mat##M##x##N##f32 = Mat##M##x##N<float>; \
466 using Mat##M##x##N##f64 = Mat##M##x##N<double>; \
467 using Mat##M##x##N##f = Mat##M##x##N##f32
479#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 P dot(const Vec< S, PO > &other) const
constexpr Vec operator+(Arithmetic auto scalar) const
constexpr Vec(Vals... vals)
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 Vec operator-(Arithmetic auto scalar) const
constexpr void operator/=(Arithmetic auto scalar)
constexpr void operator-=(Arithmetic auto scalar) const
constexpr void operator+=(Arithmetic auto scalar) const
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)