gb.hpp - Cache friendly Transform and String fixes

This commit is contained in:
gingerBill 2015-11-09 10:34:46 +00:00
parent d4a4a0770a
commit 915845b0dc
2 changed files with 220 additions and 456 deletions

View File

@ -6,7 +6,7 @@ library | latest version | category | languages | description
----------------|----------------|----------|-----------|------------- ----------------|----------------|----------|-----------|-------------
**gb_string.h** | 0.93 | strings | C, C++ | A better string library for C & C++ **gb_string.h** | 0.93 | strings | C, C++ | A better string library for C & C++
**gb_ini.h** | 0.91 | misc | C, C++ | A simple ini file loader library for C & C++ **gb_ini.h** | 0.91 | misc | C, C++ | A simple ini file loader library for C & C++
**gb.hpp** | 0.18 | misc | C++11 | (Experimental) A C++11 helper library without STL geared towards game development **gb.hpp** | 0.19 | misc | C++11 | (Experimental) A C++11 helper library without STL geared towards game development
## FAQ ## FAQ

658
gb.hpp
View File

@ -1,8 +1,9 @@
// gb.hpp - v0.18 - public domain C++11 helper library - no warranty implied; use at your own risk // gb.hpp - v0.19 - public domain C++11 helper library - no warranty implied; use at your own risk
// (Experimental) A C++11 helper library without STL geared towards game development // (Experimental) A C++11 helper library without STL geared towards game development
/* /*
Version History: Version History:
0.19 - Cache friendly Transform and String fixes
0.18 - Hash_Table bug fixes 0.18 - Hash_Table bug fixes
0.17 - Death to OOP 0.17 - Death to OOP
0.16 - All References are const convention 0.16 - All References are const convention
@ -210,7 +211,7 @@ Context:
#include <windows.h> #include <windows.h>
#include <mmsystem.h> // Time functions #include <mmsystem.h> // Time functions
// #include <ntsecapi.h> // Random generation functions #include <wincrypt.h>
#undef NOMINMAX #undef NOMINMAX
#undef VC_EXTRALEAN #undef VC_EXTRALEAN
@ -234,13 +235,9 @@ Context:
#endif #endif
extern "C" inline void #define GB_DISABLE_COPY(Type) \
gb__abort(void) Type(const Type&) = delete; \
{ Type& operator=(const Type&) = delete
// TODO(bill): Get a better way to abort
*(int*)0 = 0;
// raise(SIGABRT);
}
/// Helper function used as a better alternative to assert which allows for /// Helper function used as a better alternative to assert which allows for
/// optional printf style error messages /// optional printf style error messages
@ -263,7 +260,8 @@ gb__assert_handler(bool condition, const char* condition_str,
va_end(args); va_end(args);
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
gb__abort(); // TODO(bill): Get a better way to abort
*(int*)0 = 0;
} }
//////////////////////////////// ////////////////////////////////
@ -526,6 +524,20 @@ template <typename T> struct Remove_Reference_Def<T&> { using Type = T; };
template <typename T> struct Remove_Reference_Def<T&&> { using Type = T; }; template <typename T> struct Remove_Reference_Def<T&&> { using Type = T; };
template <typename T> using Remove_Reference = typename Remove_Reference_Def<T>::Type; template <typename T> using Remove_Reference = typename Remove_Reference_Def<T>::Type;
template <typename T, T v> struct Integral_Constant { global const T VALUE = v; using Value_Type = T; using Type = Integral_Constant; };
template <typename T, usize N = 0> struct Extent : Integral_Constant<usize, 0> {};
template <typename T> struct Extent<T[], 0> : Integral_Constant<usize, 0> {};
template <typename T, usize N> struct Extent<T[], N> : Integral_Constant<usize, Extent<T, N-1>::VALUE> {};
template <typename T, usize N> struct Extent<T[N], 0> : Integral_Constant<usize, N> {};
template <typename T, usize I, usize N> struct Extent<T[I], N> : Integral_Constant<usize, Extent<T, N-1>::VALUE> {};
template <typename T> struct Remove_Extend_Def { using Type = T; };
template <typename T> struct Remove_Extend_Def<T[]> { using Type = T; };
template <typename T, usize N> struct Remove_Extend_Def<T[N]> { using Type = T; };
// TODO NOTE(bill): Do I _need_ all of these template traits?
//////////////////////////////// ////////////////////////////////
/// /// /// ///
/// C++11 Move Semantics /// /// C++11 Move Semantics ///
@ -569,7 +581,7 @@ struct Defer
}; };
template <typename Func> template <typename Func>
Defer<Func> inline Defer<Func>
defer_func(Func&& f) { return Defer<Func>(forward<Func>(f)); } defer_func(Func&& f) { return Defer<Func>(forward<Func>(f)); }
} // namespace impl } // namespace impl
__GB_NAMESPACE_END __GB_NAMESPACE_END
@ -742,9 +754,7 @@ struct Allocator
/// If the allocator does not track memory, the function will return -1 /// If the allocator does not track memory, the function will return -1
virtual s64 total_allocated() = 0; virtual s64 total_allocated() = 0;
// Delete copying GB_DISABLE_COPY(Allocator);
Allocator(const Allocator&) = delete;
Allocator& operator=(const Allocator&) = delete;
}; };
/// An allocator that used the malloc(). Allocations are padded with the size of /// An allocator that used the malloc(). Allocations are padded with the size of
@ -988,7 +998,6 @@ equals(const void* a, const void* b, usize bytes)
{ {
return (memcmp(a, b, bytes) == 0); return (memcmp(a, b, bytes) == 0);
} }
} // namespace memory } // namespace memory
//////////////////////////////// ////////////////////////////////
@ -1027,6 +1036,7 @@ Size available_space(const String str);
void clear(String str); void clear(String str);
void append(String* str, char c);
void append(String* str, const String other); void append(String* str, const String other);
void append_cstring(String* str, const char* other); void append_cstring(String* str, const char* other);
void append(String* str, const void* other, Size len); void append(String* str, const void* other, Size len);
@ -1038,6 +1048,7 @@ bool equals(const String lhs, const String rhs);
int compare(const String lhs, const String rhs); // NOTE(bill): three-way comparison int compare(const String lhs, const String rhs); // NOTE(bill): three-way comparison
void trim(String* str, const char* cut_set); void trim(String* str, const char* cut_set);
void trim_space(String* str);
} // namespace string } // namespace string
// TODO(bill): string libraries // TODO(bill): string libraries
@ -2062,17 +2073,19 @@ struct Transform
{ {
Vector3 position; Vector3 position;
Quaternion orientation; Quaternion orientation;
Vector3 scale; f32 scale;
// NOTE(bill): Scale is only f32 to make sizeof(Transform) == 32 bytes
}; };
struct Aabb struct Aabb
{ {
Vector3 center, half_size; Vector3 center;
Vector3 half_size;
}; };
struct Oobb struct Oobb
{ {
Matrix4 tm; Matrix4 transform;
Aabb aabb; Aabb aabb;
}; };
@ -2296,10 +2309,10 @@ f32 sin(f32 radians);
f32 cos(f32 radians); f32 cos(f32 radians);
f32 tan(f32 radians); f32 tan(f32 radians);
f32 asin(f32 x); f32 arcsin(f32 x);
f32 acos(f32 x); f32 arccos(f32 x);
f32 atan(f32 x); f32 arctan(f32 x);
f32 atan2(f32 y, f32 x); f32 arctan2(f32 y, f32 x);
f32 radians(f32 degrees); f32 radians(f32 degrees);
f32 degrees(f32 radians); f32 degrees(f32 radians);
@ -2309,9 +2322,9 @@ f32 sinh(f32 x);
f32 cosh(f32 x); f32 cosh(f32 x);
f32 tanh(f32 x); f32 tanh(f32 x);
f32 asinh(f32 x); f32 arsinh(f32 x);
f32 acosh(f32 x); f32 arcosh(f32 x);
f32 atanh(f32 x); f32 artanh(f32 x);
// Rounding // Rounding
f32 ceil(f32 x); f32 ceil(f32 x);
@ -2369,6 +2382,8 @@ Vector2 normalize(const Vector2& a);
Vector2 hadamard(const Vector2& a, const Vector2& b); Vector2 hadamard(const Vector2& a, const Vector2& b);
f32 aspect_ratio(const Vector2& a);
// Vector3 functions // Vector3 functions
f32 dot(const Vector3& a, const Vector3& b); f32 dot(const Vector3& a, const Vector3& b);
Vector3 cross(const Vector3& a, const Vector3& b); Vector3 cross(const Vector3& a, const Vector3& b);
@ -2524,239 +2539,37 @@ bool intersection3(const Plane& p1, const Plane& p2, const Plane& p3, Vector3* i
namespace random namespace random
{ {
enum Generator_Type struct Random // NOTE(bill): Mt19937_64
{
MERSENNE_TWISTER_32,
MERSENNE_TWISTER_64,
RANDOM_DEVICE,
};
// NOTE(bill): Basic Definition of a Random Number Generator
// NOTE(bill): C++(17)?? Concepts might be useful here
// NOTE(bill): A vtable could be used but would not have good performance
// NOTE(bill): Just overload functions like mad?
/*
struct Generator
// concept Generator<typename T, typename U>
{
using Result_Type = T;
using Seed_Type = U;
Generator_Type type;
u32 entropy();
Result_Type next();
u32 next_u32();
s32 next_s32();
u64 next_u64();
s64 next_s64();
f32 next_f32();
f64 next_f64();
};
*/
template <typename T, typename U>
struct Generator_Base
{
using Result_Type = T;
using Seed_Type = U;
Seed_Type seed;
Generator_Type type;
};
struct Mt19937_32 : Generator_Base<s32, s32>
{
u32 index;
s32 mt[624];
u32 entropy();
Result_Type next();
u32 next_u32();
s32 next_s32();
u64 next_u64();
s64 next_s64();
f32 next_f32();
f64 next_f64();
};
struct Mt19937_64 : Generator_Base<s64, s64>
{ {
s64 seed;
u32 index; u32 index;
s64 mt[312]; s64 mt[312];
u32 entropy();
Result_Type next();
u32 next_u32();
s32 next_s32();
u64 next_u64();
s64 next_s64();
f32 next_f32();
f64 next_f64();
}; };
struct Random_Device : Generator_Base<u32, u32> Random make(s64 seed);
{
u32 entropy();
Result_Type next(); void set_seed(Random* r, s64 seed);
u32 next_u32();
s32 next_s32();
u64 next_u64();
s64 next_s64();
f32 next_f32();
f64 next_f64();
};
// Makers for Generators s64 next(Random* r);
Mt19937_32 make_mt19937_32(Mt19937_32::Seed_Type seed);
Mt19937_64 make_mt19937_64(Mt19937_64::Seed_Type seed);
Random_Device make_random_device();
void set_seed(Mt19937_32* gen, Mt19937_32::Seed_Type seed); void next_from_device(void* buffer, u32 length_in_bytes);
void set_seed(Mt19937_64* gen, Mt19937_64::Seed_Type seed);
template <typename Generator> typename Generator::Result_Type next(Generator* gen); s32 next_s32(Random* r);
u32 next_u32(Random* r);
f32 next_f32(Random* r);
s64 next_s64(Random* r);
u64 next_u64(Random* r);
f64 next_f64(Random* r);
template <typename Generator> s32 uniform_s32_distribution(Generator* gen, s32 min_inc, s32 max_inc); s32 uniform_s32(Random* r, s32 min_inc, s32 max_inc);
template <typename Generator> s64 uniform_s64_distribution(Generator* gen, s64 min_inc, s64 max_inc); u32 uniform_u32(Random* r, u32 min_inc, u32 max_inc);
template <typename Generator> u32 uniform_u32_distribution(Generator* gen, u32 min_inc, u32 max_inc); f32 uniform_f32(Random* r, f32 min_inc, f32 max_inc);
template <typename Generator> u64 uniform_u64_distribution(Generator* gen, u64 min_inc, u64 max_inc); s64 uniform_s64(Random* r, s64 min_inc, s64 max_inc);
template <typename Generator> f32 uniform_f32_distribution(Generator* gen, f32 min_inc, f32 max_inc); u64 uniform_u64(Random* r, u64 min_inc, u64 max_inc);
template <typename Generator> f64 uniform_f64_distribution(Generator* gen, f64 min_inc, f64 max_inc); f64 uniform_f64(Random* r, f64 min_inc, f64 max_inc);
template <typename Generator> ssize uniform_ssize_distribution(Generator* gen, ssize min_inc, ssize max_inc);
template <typename Generator> usize uniform_usize_distribution(Generator* gen, usize min_inc, usize max_inc);
inline Mt19937_32
make_mt19937_32(Mt19937_32::Seed_Type seed)
{
Mt19937_32 gen = {};
gen.type = MERSENNE_TWISTER_32;
set_seed(&gen, seed);
return gen;
}
inline Mt19937_64
make_mt19937_64(Mt19937_64::Seed_Type seed)
{
Mt19937_64 gen = {};
gen.type = MERSENNE_TWISTER_64;
set_seed(&gen, seed);
return gen;
}
inline Random_Device
make_random_device()
{
Random_Device gen = {};
gen.type = RANDOM_DEVICE;
return gen;
}
inline void
set_seed(Mt19937_32* gen, Mt19937_32::Seed_Type seed)
{
gen->seed = seed;
gen->mt[0] = seed;
for (u32 i = 1; i < 624; i++)
gen->mt[i] = 1812433253 * (gen->mt[i-1] ^ gen->mt[i-1] >> 30) + i;
}
inline void
set_seed(Mt19937_64* gen, Mt19937_64::Seed_Type seed)
{
gen->seed = seed;
gen->mt[0] = seed;
for (u32 i = 1; i < 312; i++)
gen->mt[i] = 6364136223846793005ull * (gen->mt[i-1] ^ gen->mt[i-1] >> 62) + i;
}
template <typename Generator>
inline typename Generator::Result_Type
next(Generator* gen)
{
return gen->next();
}
template <typename Generator>
inline s32
uniform_s32_distribution(Generator* gen, s32 min_inc, s32 max_inc)
{
return (gen->next_s32() % (max_inc - min_inc + 1)) + min_inc;
}
template <typename Generator>
inline s64
uniform_s64_distribution(Generator* gen, s64 min_inc, s64 max_inc)
{
return (gen->next_s64() % (max_inc - min_inc + 1)) + min_inc;
}
template <typename Generator>
inline u32
uniform_u32_distribution(Generator* gen, u32 min_inc, u32 max_inc)
{
return (gen->next_u64() % (max_inc - min_inc + 1)) + min_inc;
}
template <typename Generator>
inline u64
uniform_u64_distribution(Generator* gen, u64 min_inc, u64 max_inc)
{
return (gen->next_u64() % (max_inc - min_inc + 1)) + min_inc;
}
template <typename Generator>
inline f32
uniform_f32_distribution(Generator* gen, f32 min_inc, f32 max_inc)
{
f64 n = (gen->next_s64() >> 11) * (1.0/4503599627370495.0);
return static_cast<f32>(n * (max_inc - min_inc + 1.0) + min_inc);
}
template <typename Generator>
inline f64
uniform_f64_distribution(Generator* gen, f64 min_inc, f64 max_inc)
{
f64 n = (gen->next_s64() >> 11) * (1.0/4503599627370495.0);
return n * (max_inc - min_inc + 1.0) + min_inc;
}
template <typename Generator>
inline ssize
uniform_ssize_distribution(Generator* gen, ssize min_inc, ssize max_inc)
{
#if GB_ARCH_32_BIT
return (gen->next_s32() % (max_inc - min_inc + 1)) + min_inc;
#elif GB_ARCH_64_BIT
return (gen->next_s64() % (max_inc - min_inc + 1)) + min_inc;
#else
#error Bit size not supported
#endif
}
template <typename Generator>
inline usize
uniform_usize_distribution(Generator* gen, usize min_inc, usize max_inc)
{
#if GB_ARCH_32_BIT
return (gen->next_u32() % (max_inc - min_inc + 1)) + min_inc;
#elif GB_ARCH_64_BIT
return (gen->next_u64() % (max_inc - min_inc + 1)) + min_inc;
#else
#error Bit size not supported
#endif
}
} // namespace random } // namespace random
__GB_NAMESPACE_END __GB_NAMESPACE_END
@ -3457,6 +3270,19 @@ void clear(String str)
str[0] = '\0'; str[0] = '\0';
} }
void append(String* str, char c)
{
Size curr_len = string::length(*str);
string::make_space_for(str, 1);
if (str == nullptr)
return;
(*str)[curr_len] = c;
(*str)[curr_len + 1] = '\0';
string::header(*str)->len = curr_len + 1;
}
void append(String* str, const String other) void append(String* str, const String other)
{ {
string::append(str, other, string::length(other)); string::append(str, other, string::length(other));
@ -3475,8 +3301,8 @@ void append(String* str, const void* other, Size other_len)
if (str == nullptr) if (str == nullptr)
return; return;
memory::copy(str + curr_len, other, other_len); memory::copy((*str) + curr_len, other, other_len);
str[curr_len + other_len] = '\0'; (*str)[curr_len + other_len] = '\0';
string::header(*str)->len = curr_len + other_len; string::header(*str)->len = curr_len + other_len;
} }
@ -3517,7 +3343,7 @@ make_space_for(String* str, Size add_len)
if (available >= add_len) // Return if there is enough space left if (available >= add_len) // Return if there is enough space left
return; return;
void* ptr = reinterpret_cast<string::Header*>(str) - 1; void* ptr = reinterpret_cast<string::Header*>(*str) - 1;
usize old_size = sizeof(string::Header) + string::length(*str) + 1; usize old_size = sizeof(string::Header) + string::length(*str) + 1;
usize new_size = sizeof(string::Header) + new_len + 1; usize new_size = sizeof(string::Header) + new_len + 1;
@ -3598,6 +3424,11 @@ trim(String* str, const char* cut_set)
string::header(*str)->len = len; string::header(*str)->len = len;
} }
inline void
trim_space(String* str)
{
trim(str, " \n\r\t\v\f");
}
} // namespace string } // namespace string
@ -4460,22 +4291,22 @@ close(File* file)
/// /// /// ///
//////////////////////////////// ////////////////////////////////
const Vector2 VECTOR2_ZERO = {0, 0}; const Vector2 VECTOR2_ZERO = Vector2{0, 0};
const Vector3 VECTOR3_ZERO = {0, 0, 0}; const Vector3 VECTOR3_ZERO = Vector3{0, 0, 0};
const Vector4 VECTOR4_ZERO = {0, 0, 0, 0}; const Vector4 VECTOR4_ZERO = Vector4{0, 0, 0, 0};
const Complex COMPLEX_ZERO = {0, 0}; const Complex COMPLEX_ZERO = Complex{0, 0};
const Quaternion QUATERNION_IDENTITY = {0, 0, 0, 1}; const Quaternion QUATERNION_IDENTITY = Quaternion{0, 0, 0, 1};
const Matrix2 MATRIX2_IDENTITY = {1, 0, const Matrix2 MATRIX2_IDENTITY = Matrix2{1, 0,
0, 1}; 0, 1};
const Matrix3 MATRIX3_IDENTITY = {1, 0, 0, const Matrix3 MATRIX3_IDENTITY = Matrix3{1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1}; 0, 0, 1};
const Matrix4 MATRIX4_IDENTITY = {1, 0, 0, 0, const Matrix4 MATRIX4_IDENTITY = Matrix4{1, 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1}; 0, 0, 0, 1};
const Euler_Angles EULER_ANGLES_ZERO = {0, 0, 0}; const Euler_Angles EULER_ANGLES_ZERO = Euler_Angles{0, 0, 0};
const Transform TRANSFORM_IDENTITY = Transform{}; const Transform TRANSFORM_IDENTITY = Transform{VECTOR3_ZERO, QUATERNION_IDENTITY, 1};
//////////////////////////////// ////////////////////////////////
/// Math Type Op Overloads /// /// Math Type Op Overloads ///
@ -5145,7 +4976,8 @@ Transform operator*(const Transform& ps, const Transform& ls)
ws.position = ps.position + ps.orientation * (ps.scale * ls.position); ws.position = ps.position + ps.orientation * (ps.scale * ls.position);
ws.orientation = ps.orientation * ls.orientation; ws.orientation = ps.orientation * ls.orientation;
ws.scale = ps.scale * (ps.orientation * ls.scale); // ws.scale = ps.scale * (ps.orientation * ls.scale); // Vector3 scale
ws.scale = ps.scale * ls.scale;
return ws; return ws;
} }
@ -5164,7 +4996,8 @@ Transform operator/(const Transform& ws, const Transform& ps)
ls.position = (ps_conjugate * (ws.position - ps.position)) / ps.scale; ls.position = (ps_conjugate * (ws.position - ps.position)) / ps.scale;
ls.orientation = ps_conjugate * ws.orientation; ls.orientation = ps_conjugate * ws.orientation;
ls.scale = ps_conjugate * (ws.scale / ps.scale); // ls.scale = ps_conjugate * (ws.scale / ps.scale); // Vector3 scale
ls.scale = ws.scale / ps.scale;
return ls; return ls;
} }
@ -5201,8 +5034,8 @@ const f32 F32_PRECISION = 1.0e-7f;
// Power // Power
inline f32 sqrt(f32 x) { return ::sqrtf(x); } inline f32 sqrt(f32 x) { return ::sqrtf(x); }
inline f32 pow(f32 x, f32 y) { return (f32)::powf(x, y); } inline f32 pow(f32 x, f32 y) { return static_cast<f32>(::powf(x, y)); }
inline f32 cbrt(f32 x) { return (f32)::cbrtf(x); } inline f32 cbrt(f32 x) { return static_cast<f32>(::cbrtf(x)); }
inline f32 inline f32
fast_inv_sqrt(f32 x) fast_inv_sqrt(f32 x)
@ -5226,10 +5059,10 @@ inline f32 sin(f32 radians) { return ::sinf(radians); }
inline f32 cos(f32 radians) { return ::cosf(radians); } inline f32 cos(f32 radians) { return ::cosf(radians); }
inline f32 tan(f32 radians) { return ::tanf(radians); } inline f32 tan(f32 radians) { return ::tanf(radians); }
inline f32 asin(f32 x) { return ::asinf(x); } inline f32 arcsin(f32 x) { return ::asinf(x); }
inline f32 acos(f32 x) { return ::acosf(x); } inline f32 arccos(f32 x) { return ::acosf(x); }
inline f32 atan(f32 x) { return ::atanf(x); } inline f32 arctan(f32 x) { return ::atanf(x); }
inline f32 atan2(f32 y, f32 x) { return ::atan2f(y, x); } inline f32 arctan2(f32 y, f32 x) { return ::atan2f(y, x); }
inline f32 radians(f32 degrees) { return TAU * degrees / 360.0f; } inline f32 radians(f32 degrees) { return TAU * degrees / 360.0f; }
inline f32 degrees(f32 radians) { return 360.0f * radians / TAU; } inline f32 degrees(f32 radians) { return 360.0f * radians / TAU; }
@ -5239,9 +5072,9 @@ inline f32 sinh(f32 x) { return ::sinhf(x); }
inline f32 cosh(f32 x) { return ::coshf(x); } inline f32 cosh(f32 x) { return ::coshf(x); }
inline f32 tanh(f32 x) { return ::tanhf(x); } inline f32 tanh(f32 x) { return ::tanhf(x); }
inline f32 asinh(f32 x) { return ::asinhf(x); } inline f32 arsinh(f32 x) { return ::asinhf(x); }
inline f32 acosh(f32 x) { return ::acoshf(x); } inline f32 arcosh(f32 x) { return ::acoshf(x); }
inline f32 atanh(f32 x) { return ::atanhf(x); } inline f32 artanh(f32 x) { return ::atanhf(x); }
// Rounding // Rounding
inline f32 ceil(f32 x) { return ::ceilf(x); } inline f32 ceil(f32 x) { return ::ceilf(x); }
@ -5409,6 +5242,13 @@ hadamard(const Vector2& a, const Vector2& b)
return {a.x * b.x, a.y * b.y}; return {a.x * b.x, a.y * b.y};
} }
inline f32
aspect_ratio(const Vector2& a)
{
return a.x / a.y;
}
inline Matrix4 inline Matrix4
matrix2_to_matrix4(const Matrix2& m) matrix2_to_matrix4(const Matrix2& m)
{ {
@ -5612,7 +5452,7 @@ inverse(const Quaternion& a)
inline f32 inline f32
quaternion_angle(const Quaternion& a) quaternion_angle(const Quaternion& a)
{ {
return 2.0f * math::acos(a.w); return 2.0f * math::arccos(a.w);
} }
inline Vector3 inline Vector3
@ -5644,21 +5484,21 @@ axis_angle(const Vector3& axis, f32 radians)
inline f32 inline f32
quaternion_roll(const Quaternion& a) quaternion_roll(const Quaternion& a)
{ {
return math::atan2(2.0f * a.x * a.y + a.z * a.w, return math::arctan2(2.0f * a.x * a.y + a.z * a.w,
a.x * a.x + a.w * a.w - a.y * a.y - a.z * a.z); a.x * a.x + a.w * a.w - a.y * a.y - a.z * a.z);
} }
inline f32 inline f32
quaternion_pitch(const Quaternion& a) quaternion_pitch(const Quaternion& a)
{ {
return math::atan2(2.0f * a.y * a.z + a.w * a.x, return math::arctan2(2.0f * a.y * a.z + a.w * a.x,
a.w * a.w - a.x * a.x - a.y * a.y + a.z * a.z); a.w * a.w - a.x * a.x - a.y * a.y + a.z * a.z);
} }
inline f32 inline f32
quaternion_yaw(const Quaternion& a) quaternion_yaw(const Quaternion& a)
{ {
return math::asin(-2.0f * (a.x * a.z - a.w * a.y)); return math::arcsin(-2.0f * (a.x * a.z - a.w * a.y));
} }
@ -5704,7 +5544,7 @@ slerp(const Quaternion& x, const Quaternion& y, f32 t)
lerp(x.w, y.w, t)}; lerp(x.w, y.w, t)};
} }
f32 angle = math::acos(cos_theta); f32 angle = math::arccos(cos_theta);
Quaternion result = math::sin(1.0f - (t * angle)) * x + math::sin(t * angle) * z; Quaternion result = math::sin(1.0f - (t * angle)) * x + math::sin(t * angle) * z;
return result * (1.0f / math::sin(angle)); return result * (1.0f / math::sin(angle));
@ -6259,7 +6099,8 @@ inverse(const Transform& t)
inv_transform.position = (inv_orientation * -t.position) / t.scale; inv_transform.position = (inv_orientation * -t.position) / t.scale;
inv_transform.orientation = inv_orientation; inv_transform.orientation = inv_orientation;
inv_transform.scale = inv_orientation * (Vector3{1, 1, 1} / t.scale); // inv_transform.scale = inv_orientation * (Vector3{1, 1, 1} / t.scale); // Vector3 scale
inv_transform.scale = 1.0f / t.scale;
return inv_transform; return inv_transform;
} }
@ -6267,9 +6108,9 @@ inverse(const Transform& t)
inline Matrix4 inline Matrix4
transform_to_matrix4(const Transform& t) transform_to_matrix4(const Transform& t)
{ {
return math::translate(t.position) * // return math::translate(t.position) *
math::quaternion_to_matrix4(t.orientation) * // math::quaternion_to_matrix4(t.orientation) *
math::scale(t.scale); // math::scale({t.scale, t.scale, t.scale});
} }
@ -6526,8 +6367,7 @@ namespace sphere
inline Sphere inline Sphere
calculate_min_bounding(const void* vertices, usize num_vertices, usize stride, usize offset, f32 step) calculate_min_bounding(const void* vertices, usize num_vertices, usize stride, usize offset, f32 step)
{ {
auto ran_gen = random::make_random_device(); auto gen = random::make(0);
auto gen = random::make_mt19937_64(random::next(&ran_gen));
const u8* vertex = reinterpret_cast<const u8*>(vertices); const u8* vertex = reinterpret_cast<const u8*>(vertices);
vertex += offset; vertex += offset;
@ -6545,7 +6385,7 @@ calculate_min_bounding(const void* vertices, usize num_vertices, usize stride, u
do do
{ {
done = true; done = true;
for (usize i = 0, index = random::uniform_usize_distribution(&gen, 0, num_vertices-1); for (u32 i = 0, index = random::uniform_u32(&gen, 0, num_vertices-1);
i < num_vertices; i < num_vertices;
i++, index = (index + 1)%num_vertices) i++, index = (index + 1)%num_vertices)
{ {
@ -6685,110 +6525,49 @@ intersection3(const Plane& p1, const Plane& p2, const Plane& p3, Vector3* ip)
namespace random namespace random
{ {
inline Mt19937_32::Result_Type inline Random
Mt19937_32::next() make(s64 seed)
{ {
if (index >= 624) Random r = {};
{ set_seed(&r, seed);
for (u32 i = 0; i < 624; i++) return r;
{
s32 y = ((mt[i] & 0x80000000) + (mt[(i + 1) % 624] & 0x7fffffff)) & 0xffffffff;
mt[i] = mt[(i + 397) % 624] ^ y >> 1;
if (y % 2 != 0)
mt[i] = mt[i] ^ 0x9908b0df;
}
index = 0;
}
s32 y = mt[index];
y ^= (y >> 11);
y ^= (y << 7) & 2636928640;
y ^= (y << 15) & 4022730752;
y ^= (y >> 18);
index++;
return y;
} }
inline u32 Mt19937_32::entropy() { return 32; } void
set_seed(Random* r, s64 seed)
inline u32
Mt19937_32::next_u32()
{ {
s32 n = next(); r->seed = seed;
return bit_cast<u32>(n); r->mt[0] = seed;
for (u64 i = 1; i < 312; i++)
r->mt[i] = 6364136223846793005ull * (r->mt[i-1] ^ r->mt[i-1] >> 62) + i;
} }
inline s32 s64
Mt19937_32::next_s32() next(Random* r)
{ {
return next(); const u64 MAG01[2] = {0ull, 0xb5026f5aa96619e9ull};
}
inline u64
Mt19937_32::next_u64()
{
s32 n = next();
u64 a = n;
a = static_cast<u64>(a << 32) | static_cast<u64>(next());
return a;
}
inline s64
Mt19937_32::next_s64()
{
s32 n = next();
u64 a = n;
a = static_cast<u64>(a << 32) | static_cast<u64>(next());
return bit_cast<s64>(a);
}
inline f32
Mt19937_32::next_f32()
{
s32 n = next();
return bit_cast<f32>(n);
}
inline f64
Mt19937_32::next_f64()
{
s32 n = next();
u64 a = n;
a = static_cast<u64>(a << 32) | static_cast<u64>(next());
return bit_cast<f64>(a);
}
inline Mt19937_64::Result_Type
Mt19937_64::next()
{
const u64 MAG01[2] = {0ull, 0xB5026F5AA96619E9ull};
u64 x; u64 x;
if (index > 312) if (r->index > 312)
{ {
u32 i = 0; u32 i = 0;
for (; i < 312-156; i++) for (; i < 312-156; i++)
{ {
x = (mt[i] & 0xffffffff80000000ull) | (mt[i+1] & 0x7fffffffull); x = (r->mt[i] & 0xffffffff80000000ull) | (r->mt[i+1] & 0x7fffffffull);
mt[i] = mt[i+156] ^ (x>>1) ^ MAG01[(u32)(x & 1ull)]; r->mt[i] = r->mt[i+156] ^ (x>>1) ^ MAG01[(u32)(x & 1ull)];
} }
for (; i < 312-1; i++) for (; i < 312-1; i++)
{ {
x = (mt[i] & 0xffffffff80000000ull) | (mt[i+1] & 0x7fffffffull); x = (r->mt[i] & 0xffffffff80000000ull) | (r->mt[i+1] & 0x7fffffffull);
mt[i] = mt[i + (312-156)] ^ (x >> 1) ^ MAG01[(u32)(x & 1ull)]; r->mt[i] = r->mt[i + (312-156)] ^ (x >> 1) ^ MAG01[(u32)(x & 1ull)];
} }
x = (mt[312-1] & 0xffffffff80000000ull) | (mt[0] & 0x7fffffffull); x = (r->mt[312-1] & 0xffffffff80000000ull) | (r->mt[0] & 0x7fffffffull);
mt[312-1] = mt[156-1] ^ (x>>1) ^ MAG01[(u32)(x & 1ull)]; r->mt[312-1] = r->mt[156-1] ^ (x>>1) ^ MAG01[(u32)(x & 1ull)];
index = 0; r->index = 0;
} }
x = mt[index++]; x = r->mt[r->index++];
x ^= (x >> 29) & 0x5555555555555555ull; x ^= (x >> 29) & 0x5555555555555555ull;
x ^= (x << 17) & 0x71d67fffeda60000ull; x ^= (x << 17) & 0x71d67fffeda60000ull;
@ -6798,112 +6577,97 @@ Mt19937_64::next()
return x; return x;
} }
inline u32 Mt19937_64::entropy() { return 64; } void
next_from_device(void* buffer, u32 length_in_bytes)
inline u32
Mt19937_64::next_u32()
{ {
s64 n = next();
return bit_cast<u32>(n);
}
inline s32
Mt19937_64::next_s32()
{
s64 n = next();
return bit_cast<s32>(n);
}
inline u64
Mt19937_64::next_u64()
{
s64 n = next();
return bit_cast<u64>(n);
}
inline s64
Mt19937_64::next_s64()
{
s64 n = next();
return n;
}
inline f32
Mt19937_64::next_f32()
{
s64 n = next();
return bit_cast<f32>(n);
}
inline f64
Mt19937_64::next_f64()
{
s64 n = next();
return bit_cast<f64>(n);
}
inline Random_Device::Result_Type
Random_Device::next()
{
u32 result = 0;
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
// rand_s(&result); // TODO(bill): fix this HCRYPTPROV prov;
bool ok = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
GB_ASSERT(ok, "CryptAcquireContext");
ok = CryptGenRandom(prov, length_in_bytes, reinterpret_cast<u8*>(&buffer));
GB_ASSERT(ok, "CryptGenRandom");
CryptReleaseContext(prov, 0);
#else #else
#error Implement Random_Device::next() for this platform #error Implement random::next_from_device()
#endif #endif
// IMPORTANT TODO(bill): Implenent Random_Device::next()
return result;
} }
inline u32 Random_Device::entropy() { return 32; } s32
next_s32(Random* r)
inline u32
Random_Device::next_u32()
{ {
s32 n = next(); return bit_cast<s32>(random::next(r));
return bit_cast<u32>(n);
} }
inline s32 u32
Random_Device::next_s32() next_u32(Random* r)
{ {
return next(); return bit_cast<u32>(random::next(r));
} }
inline u64 f32
Random_Device::next_u64() next_f32(Random* r)
{ {
s32 n = next(); return bit_cast<f32>(random::next(r));
u64 a = n;
a = static_cast<u64>(a << 32) | static_cast<u64>(next());
return a;
} }
inline s64 s64
Random_Device::next_s64() next_s64(Random* r)
{ {
s32 n = next(); return random::next(r);
u64 a = n;
a = static_cast<u64>(a << 32) | static_cast<u64>(next());
return bit_cast<s64>(a);
} }
inline f32 u64
Random_Device::next_f32() next_u64(Random* r)
{ {
s32 n = next(); return bit_cast<u64>(random::next(r));
return bit_cast<f32>(n);
} }
inline f64 f64
Random_Device::next_f64() next_f64(Random* r)
{ {
s32 n = next(); return bit_cast<f64>(random::next(r));
u64 a = n;
a = static_cast<u64>(a << 32) | static_cast<u64>(next());
return bit_cast<f64>(a);
} }
s32
uniform_s32(Random* r, s32 min_inc, s32 max_inc)
{
return (random::next_s32(r) & (max_inc - min_inc + 1)) + min_inc;
}
u32
uniform_u32(Random* r, u32 min_inc, u32 max_inc)
{
return (random::next_u32(r) & (max_inc - min_inc + 1)) + min_inc;
}
f32
uniform_f32(Random* r, f32 min_inc, f32 max_inc)
{
f64 n = (random::next_s64(r) >> 11) * (1.0/4503599627370495.0);
return static_cast<f32>(n * (max_inc - min_inc + 1.0) + min_inc);
}
s64
uniform_s64(Random* r, s64 min_inc, s64 max_inc)
{
return (random::next_s32(r) & (max_inc - min_inc + 1)) + min_inc;
}
u64
uniform_u64(Random* r, u64 min_inc, u64 max_inc)
{
return (random::next_u64(r) & (max_inc - min_inc + 1)) + min_inc;
}
f64
uniform_f64(Random* r, f64 min_inc, f64 max_inc)
{
f64 n = (random::next_s64(r) >> 11) * (1.0/4503599627370495.0);
return (n * (max_inc - min_inc + 1.0) + min_inc);
}
} // namespace random } // namespace random
__GB_NAMESPACE_END __GB_NAMESPACE_END