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;
58 if (
const auto rest = n % alignment; rest > 0) {
59 return alignment - rest;
64template<u
int8_t S, Arithmetic P>
66 static_assert(S >= 2,
"Vectors must have at least two values!");
72 constexpr Vec() =
default;
74 template<std::convertible_to<P>... Vals>
75 requires (
sizeof...(Vals) == S)
76 constexpr Vec(Vals... vals)
77 :
values{static_cast<P>(vals)...} {}
82 [[nodiscard]]
constexpr const P*
data()
const {
86 [[nodiscard]]
constexpr P*
data() {
90 [[nodiscard]]
constexpr uint8_t
size()
const {
96 return this->values[index];
103 return this->values[index];
112 template<u
int8_t SO, Arithmetic PO>
115 for (uint8_t i = 0; i < (S > SO ? SO : S); i++) {
116 out[i] +=
static_cast<P
>(other[i]);
121 template<u
int8_t SO, Arithmetic PO>
123 for (uint8_t i = 0; i < (S > SO ? SO : S); i++) {
124 (*this)[i] +=
static_cast<P
>(other[i]);
130 for (uint8_t i = 0; i < S; i++) {
136 template<u
int8_t SO, Arithmetic PO>
139 for (uint8_t i = 0; i < (S > SO ? SO : S); i++) {
140 out[i] -=
static_cast<P
>(other[i]);
145 template<u
int8_t SO, Arithmetic PO>
147 for (uint8_t i = 0; i < (S > SO ? SO : S); i++) {
148 (*this)[i] -=
static_cast<P
>(other[i]);
154 for (uint8_t i = 0; i < S; i++) {
155 out[i] *=
static_cast<P
>(scalar);
161 for (uint8_t i = 0; i < S; i++) {
162 (*this)[i] *=
static_cast<P
>(scalar);
168 for (uint8_t i = 0; i < S; i++) {
169 out[i] /=
static_cast<P
>(scalar);
175 for (uint8_t i = 0; i < S; i++) {
176 (*this)[i] /=
static_cast<P
>(scalar);
182 for (uint8_t i = 0; i < S; i++) {
183 out[i] %=
static_cast<P
>(scalar);
189 for (uint8_t i = 0; i < S; i++) {
190 (*this)[i] %=
static_cast<P
>(scalar);
194 template<u
int8_t SO, Arithmetic PO>
196 if constexpr (S != SO) {
199 for (uint8_t i = 0; i < S; i++) {
200 if ((*
this)[i] !=
static_cast<P
>(other[i])) {
208 template<u
int8_t SO, Arithmetic PO = P>
211 for (uint8_t i = 0; i < (S > SO ? SO : S); i++) {
212 out[i] =
static_cast<PO
>((*this)[i]);
217 template<u
int8_t SO, Arithmetic PO>
220 for (uint8_t i = 0; i < (S > SO ? SO : S); i++) {
221 out[i] *=
static_cast<P
>(other[i]);
226 template<u
int8_t SO, Arithmetic PO>
229 for (uint8_t i = 0; i < (S > SO ? SO : S); i++) {
230 out[i] /=
static_cast<P
>(other[i]);
235 template<u
int8_t SO, Arithmetic PO>
238 for (uint8_t i = 0; i < (S > SO ? SO : S); i++) {
239 if constexpr ((std::floating_point<P> && std::floating_point<PO>) || std::floating_point<P>) {
240 out[i] = std::fmod(out[i],
static_cast<P
>(other[i]));
242 out[i] %=
static_cast<P
>(other[i]);
248 [[nodiscard]]
constexpr float magf()
const {
250 for (uint8_t i = 0; i < S; i++) {
251 out += std::pow((*
this)[i], 2);
253 return std::sqrt(out);
256 [[nodiscard]]
constexpr double mag()
const {
258 for (uint8_t i = 0; i < S; i++) {
259 out += std::pow((*
this)[i], 2);
261 return std::sqrt(out);
264 [[nodiscard]]
constexpr P
sum()
const {
266 for (uint8_t i = 0; i < S; i++) {
272 template<Arithmetic PO>
275 for (uint8_t i = 0; i < S; i++) {
276 out[i] = (*this)[i] *
static_cast<P
>(other[i]);
281 template<Arithmetic PO>
286 [[nodiscard]]
constexpr Vec abs()
const {
288 for (uint8_t i = 0; i < S; i++) {
289 out[i] = std::abs(out[i]);
298 [[nodiscard]]
constexpr bool isZero()
const {
299 return *
this ==
zero();
302static_assert(std::is_trivially_copyable_v<Vec<2, float>>);
304#define SOURCEPP_VEC_DEFINE(S) \
305 template<Arithmetic P> \
306 using Vec##S = Vec<S, P>; \
307 using Vec##S##i8 = Vec##S<int8_t>; \
308 using Vec##S##i16 = Vec##S<int16_t>; \
309 using Vec##S##i32 = Vec##S<int32_t>; \
310 using Vec##S##i64 = Vec##S<int64_t>; \
311 using Vec##S##i = Vec##S##i32; \
312 using Vec##S##ui8 = Vec##S<uint8_t>; \
313 using Vec##S##ui16 = Vec##S<uint16_t>; \
314 using Vec##S##ui32 = Vec##S<uint32_t>; \
315 using Vec##S##ui64 = Vec##S<uint64_t>; \
316 using Vec##S##ui = Vec##S##ui32; \
317 using Vec##S##f16 = Vec##S<half>; \
318 using Vec##S##f32 = Vec##S<float>; \
319 using Vec##S##f64 = Vec##S<double>; \
320 using Vec##S##f = Vec##S##f32
326#undef SOURCEPP_VEC_DEFINE
341 const float fx = (
static_cast<float>(this->
x) / 32767.5f) - 1.f;
342 const float fy = (
static_cast<float>(this->
y) / 32767.5f) - 1.f;
343 const float fz = (
static_cast<float>(this->
z) / 16383.5f) - 1.f;
346 float fw = std::sqrt(1.f - fx * fx - fy * fy - fz * fz);
353 return {fx, fy, fz, fw};
356static_assert(std::is_trivially_copyable_v<QuatCompressed48>);
367 const double fx = (
static_cast<double>(this->
x) / 1048575.5) - 1.0f;
368 const double fy = (
static_cast<double>(this->
y) / 1048575.5) - 1.0f;
369 const double fz = (
static_cast<double>(this->
z) / 1048575.5) - 1.0f;
372 double fw = std::sqrt(1.0 - fx * fx - fy * fy - fz * fz);
379 return {
static_cast<float>(fx),
static_cast<float>(fy),
static_cast<float>(fz),
static_cast<float>(fw)};
382static_assert(std::is_trivially_copyable_v<QuatCompressed64>);
384template<u
int8_t M, u
int8_t N, Arithmetic P>
386 static_assert(M >= 2,
"Matrices must have at least two rows!");
387 static_assert(N >= 2,
"Matrices must have at least two columns!");
390 [[nodiscard]] P*
operator[](uint8_t i) {
return this->data[i]; }
392 [[nodiscard]]
const P*
operator[](uint8_t i)
const {
return this->data[i]; }
397static_assert(std::is_trivially_copyable_v<Mat<2, 2, float>>);
399#define SOURCEPP_MAT_DEFINE(M, N) \
400 template<Arithmetic P> \
401 using Mat##M##x##N = Mat<M, N, P>; \
402 using Mat##M##x##N##i8 = Mat##M##x##N<int8_t>; \
403 using Mat##M##x##N##i16 = Mat##M##x##N<int16_t>; \
404 using Mat##M##x##N##i32 = Mat##M##x##N<int32_t>; \
405 using Mat##M##x##N##i64 = Mat##M##x##N<int64_t>; \
406 using Mat##M##x##N##i = Mat##M##x##N##i32; \
407 using Mat##M##x##N##ui8 = Mat##M##x##N<uint8_t>; \
408 using Mat##M##x##N##ui16 = Mat##M##x##N<uint16_t>; \
409 using Mat##M##x##N##ui32 = Mat##M##x##N<uint32_t>; \
410 using Mat##M##x##N##ui64 = Mat##M##x##N<uint64_t>; \
411 using Mat##M##x##N##ui = Mat##M##x##N##ui32; \
412 using Mat##M##x##N##f16 = Mat##M##x##N<half>; \
413 using Mat##M##x##N##f32 = Mat##M##x##N<float>; \
414 using Mat##M##x##N##f64 = Mat##M##x##N<double>; \
415 using Mat##M##x##N##f = Mat##M##x##N##f32
427#undef SOURCEPP_MAT_DEFINE
#define SOURCEPP_VEC_DEFINE(S)
#define SOURCEPP_MAT_DEFINE(M, N)
P * operator[](uint8_t i)
const P * operator[](uint8_t i) const
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)
Lower precision Quat compressed to 6 bytes.
Lower precision Quat compressed to 8 bytes.
constexpr float magf() const
constexpr Vec< SO, PO > to() const
constexpr Vec operator-(const Vec< SO, PO > &other) const
constexpr Vec operator%(Arithmetic auto scalar) const
constexpr void operator/=(Arithmetic auto scalar)
constexpr Vec operator+(const Vec< SO, PO > &other) const
constexpr P operator[](uint8_t index) const
constexpr const P * data() const
constexpr bool isZero() const
constexpr void operator-=(const Vec< SO, PO > &other)
constexpr P & operator[](uint8_t index)
constexpr P dot(const Vec< S, PO > &other) const
constexpr Vec scale(const Vec< S, PO > &other) const
constexpr void operator*=(Arithmetic auto scalar)
constexpr void operator%=(Arithmetic auto scalar)
constexpr Vec operator-() const
constexpr bool operator==(const Vec< SO, PO > &other) const
static constexpr Vec zero()
constexpr Vec mod(const Vec< SO, PO > &other) const
constexpr Vec operator/(Arithmetic auto scalar) const
constexpr Vec abs() const
constexpr double mag() const
constexpr Vec div(const Vec< SO, PO > &other) const
constexpr Vec operator*(Arithmetic auto scalar) const
constexpr uint8_t size() const
constexpr void operator+=(const Vec< SO, PO > &other)
constexpr Vec(Vals... vals)
constexpr Vec operator+() const
constexpr Vec mul(const Vec< SO, PO > &other) const