aboutsummaryrefslogtreecommitdiffstats
path: root/gb_math.h
diff options
context:
space:
mode:
authorGravatar gingerBill 2016-03-03 11:37:48 +0000
committerGravatar gingerBill 2016-03-03 11:37:48 +0000
commitde04cbcee732ba43c9645cc02e48f8323c2bbf07 (patch)
treeda2e9bbd820d51045b6a4baf36e8b0d000a9c8ea /gb_math.h
parentExplicit Everything! (diff)
New Libraries
Diffstat (limited to 'gb_math.h')
-rw-r--r--gb_math.h798
1 files changed, 798 insertions, 0 deletions
diff --git a/gb_math.h b/gb_math.h
new file mode 100644
index 0000000..9158181
--- /dev/null
+++ b/gb_math.h
@@ -0,0 +1,798 @@
+// gb_math.h - v0.03 - public domain C math library - no warranty implied; use at your own risk
+// A C math library geared towards game development
+
+/*
+Version History:
+ 0.03 - Complete Replacement
+ 0.01 - Initial Version
+
+LICENSE
+ This software is in the public domain. Where that dedication is not
+ recognized, you are granted a perpetual, irrevocable license to copy,
+ distribute, and modify this file as you see fit.
+
+WARNING
+ - This library is _slightly_ experimental and features may not work as expected.
+ - This also means that many functions are not documented.
+
+CONTENTS
+ - Common Macros
+ - Types
+ - Vec(2,3,4)
+ - Mat(2,3,4)
+ - Float(2,3,4)
+ - Rect(2,3)
+ - Aabb(2,3)
+ - Operations
+ - Functions
+ - Type Functions
+ - Random
+
+TODO
+ - Complex
+ - Quaternion
+ - More Math Functions
+*/
+
+#ifndef GB_MATH_INCLUDE_GB_MATH_H
+#define GB_MATH_INCLUDE_GB_MATH_H
+
+#include <stddef.h>
+
+#ifdef GB_MATH_STATIC
+#define GB_MATH_DEF static
+#else
+#define GB_MATH_DEF extern
+#endif
+
+typedef union Vec2
+{
+ struct { float x, y; };
+ float e[2];
+} Vec2;
+
+typedef union Vec3
+{
+ struct { float x, y, z; };
+ struct { float r, g, b; };
+
+ Vec2 xy;
+ float e[2];
+} Vec3;
+
+typedef union Vec4
+{
+ struct { float x, y, z, w; };
+ struct { float r, g, b, a; };
+ struct { Vec2 xy, zw; };
+ Vec3 xyz;
+ Vec3 rgb;
+ float e[4];
+} Vec4;
+
+
+
+typedef union Mat2
+{
+ struct { Vec2 x, y; };
+ Vec4 col[2];
+ float e[4];
+} Mat2;
+
+typedef union Mat3
+{
+ struct { Vec3 x, y, z; };
+ Vec4 col[3];
+ float e[9];
+} Mat3;
+
+typedef union Mat4
+{
+ struct { Vec4 x, y, z, w; };
+ Vec4 col[4];
+ float e[16];
+} Mat4;
+
+
+
+
+typedef float Float2[2];
+typedef float Float3[3];
+typedef float Float4[4];
+
+
+typedef struct Rect2 { Vec2 pos, dim; } Rect2;
+typedef struct Rect3 { Vec3 pos, dim; } Rect3;
+
+typedef struct Aabb2 { Vec2 center, half_size; } Aabb2;
+typedef struct Aabb3 { Vec3 center, half_size; } Aabb3;
+
+#if defined(_MSC_VER)
+ typedef unsigned __int8 gb_math_u8;
+ typedef unsigned __int32 gb_math_u32;
+ typedef unsigned __int64 gb_math_u64;
+#else
+ #include <stdint.h>
+ typedef uint8_t gb_math_u8;
+ typedef uint32_t gb_math_u32;
+ typedef uint64_t gb_math_u64;
+#endif
+
+// Constants
+#define MATH_TAU 6.28318530718f
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+// Vector
+
+GB_MATH_DEF Vec2 vec2_zero(void);
+GB_MATH_DEF Vec2 vec2(float x, float y);
+GB_MATH_DEF Vec2 vec2v(float x[2]);
+
+GB_MATH_DEF Vec3 vec3_zero(void);
+GB_MATH_DEF Vec3 vec3(float x, float y, float z);
+GB_MATH_DEF Vec3 vec3v(float x[3]);
+
+GB_MATH_DEF Vec4 vec4_zero(void);
+GB_MATH_DEF Vec4 vec4(float x, float y, float z, float w);
+GB_MATH_DEF Vec4 vec4v(float x[4]);
+
+GB_MATH_DEF void vec2_add(Vec2 *d, Vec2 v0, Vec2 v1);
+GB_MATH_DEF void vec2_sub(Vec2 *d, Vec2 v0, Vec2 v1);
+GB_MATH_DEF void vec2_mul(Vec2 *d, Vec2 v, float s);
+GB_MATH_DEF void vec2_div(Vec2 *d, Vec2 v, float s);
+
+GB_MATH_DEF void vec3_add(Vec3 *d, Vec3 v0, Vec3 v1);
+GB_MATH_DEF void vec3_sub(Vec3 *d, Vec3 v0, Vec3 v1);
+GB_MATH_DEF void vec3_mul(Vec3 *d, Vec3 v, float s);
+GB_MATH_DEF void vec3_div(Vec3 *d, Vec3 v, float s);
+
+GB_MATH_DEF void vec4_add(Vec4 *d, Vec4 v0, Vec4 v1);
+GB_MATH_DEF void vec4_sub(Vec4 *d, Vec4 v0, Vec4 v1);
+GB_MATH_DEF void vec4_mul(Vec4 *d, Vec4 v, float s);
+GB_MATH_DEF void vec4_div(Vec4 *d, Vec4 v, float s);
+
+GB_MATH_DEF void vec2_addeq(Vec2 *d, Vec2 v);
+GB_MATH_DEF void vec2_subeq(Vec2 *d, Vec2 v);
+GB_MATH_DEF void vec2_muleq(Vec2 *d, float s);
+GB_MATH_DEF void vec2_diveq(Vec2 *d, float s);
+
+GB_MATH_DEF void vec3_addeq(Vec3 *d, Vec3 v);
+GB_MATH_DEF void vec3_subeq(Vec3 *d, Vec3 v);
+GB_MATH_DEF void vec3_muleq(Vec3 *d, float s);
+GB_MATH_DEF void vec3_diveq(Vec3 *d, float s);
+
+GB_MATH_DEF void vec4_addeq(Vec4 *d, Vec4 v);
+GB_MATH_DEF void vec4_subeq(Vec4 *d, Vec4 v);
+GB_MATH_DEF void vec4_muleq(Vec4 *d, float s);
+GB_MATH_DEF void vec4_diveq(Vec4 *d, float s);
+
+GB_MATH_DEF float vec2_dot(Vec2 v0, Vec2 v1);
+GB_MATH_DEF float vec3_dot(Vec3 v0, Vec3 v1);
+GB_MATH_DEF float vec4_dot(Vec4 v0, Vec4 v1);
+
+GB_MATH_DEF void vec2_cross(float *d, Vec2 v0, Vec2 v1);
+GB_MATH_DEF void vec3_cross(Vec3 *d, Vec3 v0, Vec3 v1);
+
+GB_MATH_DEF float vec2_mag2(Vec2 v);
+GB_MATH_DEF float vec3_mag2(Vec3 v);
+GB_MATH_DEF float vec4_mag2(Vec4 v);
+
+GB_MATH_DEF float vec2_mag(Vec2 v);
+GB_MATH_DEF float vec3_mag(Vec3 v);
+GB_MATH_DEF float vec4_mag(Vec4 v);
+
+GB_MATH_DEF void vec2_norm(Vec2 *d, Vec2 v);
+GB_MATH_DEF void vec3_norm(Vec3 *d, Vec3 v);
+GB_MATH_DEF void vec4_norm(Vec4 *d, Vec4 v);
+
+GB_MATH_DEF float vec2_aspect(Vec2 v);
+
+// Matrix
+
+GB_MATH_DEF void mat2_identity(Mat2 *m);
+GB_MATH_DEF void float22_identity(float m[2][2]);
+
+GB_MATH_DEF void mat2_transpose(Mat2 *m);
+GB_MATH_DEF void mat2_mul(Mat2 *out, Mat2 *m1, Mat2 *m2);
+GB_MATH_DEF void mat2_mul_vec2(Vec2 *out, Mat2 *m, Vec2 in);
+
+GB_MATH_DEF Mat2 *mat2_v(Vec2 m[2]);
+GB_MATH_DEF Mat2 *mat2_f(float m[2][2]);
+GB_MATH_DEF Float2 *float22_m(Mat2 *m);
+GB_MATH_DEF Float2 *float22_v(Vec2 m[2]);
+GB_MATH_DEF Float2 *float22_4(float m[4]);
+
+GB_MATH_DEF void float22_transpose(float (*vec)[2]);
+GB_MATH_DEF void float22_mul(float (*out)[2], float (*mat1)[2], float (*mat2)[2]);
+GB_MATH_DEF void float22_mul_vec2(Vec2 *out, float m[2][2], Vec2 in);
+
+
+GB_MATH_DEF void mat3_identity(Mat3 *m);
+GB_MATH_DEF void float33_identity(float m[3][3]);
+
+GB_MATH_DEF void mat3_transpose(Mat3 *m);
+GB_MATH_DEF void mat3_mul(Mat3 *out, Mat3 *m1, Mat3 *m2);
+GB_MATH_DEF void mat3_mul_vec3(Vec3 *out, Mat3 *m, Vec3 in);
+
+GB_MATH_DEF Mat3 *mat3_v(Vec3 m[3]);
+GB_MATH_DEF Mat3 *mat3_f(float m[3][3]);
+GB_MATH_DEF Float3 *float33_m(Mat3 *m);
+GB_MATH_DEF Float3 *float33_v(Vec3 m[3]);
+GB_MATH_DEF Float3 *float33_9(float m[9]);
+
+GB_MATH_DEF void float33_transpose(float (*vec)[3]);
+GB_MATH_DEF void float33_mul(float (*out)[3], float (*mat1)[3], float (*mat2)[3]);
+GB_MATH_DEF void float33_mul_vec3(Vec3 *out, float m[3][3], Vec3 in);
+
+
+GB_MATH_DEF void mat4_identity(Mat4 *m);
+GB_MATH_DEF void float44_identity(float m[4][4]);
+
+GB_MATH_DEF void mat4_transpose(Mat4 *m);
+GB_MATH_DEF void mat4_mul(Mat4 *out, Mat4 *m1, Mat4 *m2);
+GB_MATH_DEF void mat4_mul_vec4(Vec4 *out, Mat4 *m, Vec4 in);
+
+GB_MATH_DEF Mat4 *mat4_v(Vec4 m[4]);
+GB_MATH_DEF Mat4 *mat4_f(float m[4][4]);
+GB_MATH_DEF Float4 *float44_m(Mat4 *m);
+GB_MATH_DEF Float4 *float44_v(Vec4 m[4]);
+GB_MATH_DEF Float4 *float44_16(float m[16]);
+
+GB_MATH_DEF void float44_transpose(float (*vec)[4]);
+GB_MATH_DEF void float44_mul(float (*out)[4], float (*mat1)[4], float (*mat2)[4]);
+GB_MATH_DEF void float44_mul_vec4(Vec4 *out, float m[4][4], Vec4 in);
+
+
+// Hermite Interpolations
+GB_MATH_DEF float lerp(float a, float b, float t);
+GB_MATH_DEF float smooth_step(float a, float b, float t);
+GB_MATH_DEF float smoother_step(float a, float b, float t);
+
+GB_MATH_DEF void vec2_lerp(Vec2 *d, Vec2 a, Vec2 b, float t);
+GB_MATH_DEF void vec3_lerp(Vec3 *d, Vec3 a, Vec3 b, float t);
+GB_MATH_DEF void vec4_lerp(Vec4 *d, Vec4 a, Vec4 b, float t);
+
+
+// Angles
+GB_MATH_DEF float to_radians(float degrees);
+GB_MATH_DEF float to_degrees(float radians);
+
+// Projections
+// NOTE(bill): Uses OpenGL Projection Conventions (-1 to 1)
+// NOTE(bill): If Direct3D is needed, use custom projection to shift-z to (0 to 1)
+GB_MATH_DEF void mat4_ortho2d(Mat4 *out, float left, float right, float bottom, float top);
+GB_MATH_DEF void mat4_ortho3d(Mat4 *out, float left, float right, float bottom, float top, float z_near, float z_far);
+
+#ifndef MURMUR64_SEED
+#define MURMUR64_SEED 0x9747b28c
+#endif
+// Hashing
+GB_MATH_DEF gb_math_u64 hash_murmur64(void const *key, size_t num_bytes);
+
+// Random
+// TODO(bill): Use a generator for the random numbers
+GB_MATH_DEF float random_range_float(float min_inc, float max_inc);
+GB_MATH_DEF int random_range_int(int min_inc, int max_inc);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif // GB_MATH_INCLUDE_GB_MATH_H
+
+////////////////////
+// //
+// Implementation //
+// //
+////////////////////
+
+#if defined(GB_MATH_IMPLEMENTATION)
+
+#include <math.h>
+
+#define VEC2_2OP(a,c,post) \
+ a->x = c.x post; \
+ a->y = c.y post;
+
+#define VEC2_3OP(a,b,op,c,post) \
+ a->x = b.x op c.x post; \
+ a->y = b.y op c.y post;
+
+#define VEC3_2OP(a,c,post) \
+ a->x = c.x post; \
+ a->y = c.y post; \
+ a->z = c.z post;
+
+#define VEC3_3OP(a,b,op,c,post) \
+ a->x = b.x op c.x post; \
+ a->y = b.y op c.y post; \
+ a->z = b.z op c.z post;
+
+#define VEC4_2OP(a,c,post) \
+ a->x = c.x post; \
+ a->y = c.y post; \
+ a->z = c.z post; \
+ a->w = c.w post;
+
+#define VEC4_3OP(a,b,op,c,post) \
+ a->x = b.x op c.x post; \
+ a->y = b.y op c.y post; \
+ a->z = b.z op c.z post; \
+ a->w = b.w op c.w post;
+
+
+Vec2 vec2_zero(void) { Vec2 v = {0, 0}; return v; }
+Vec2 vec2(float x, float y) { Vec2 v = {x, y}; return v; }
+Vec2 vec2v(float x[2]) { Vec2 v = {x[0], x[1]}; return v; }
+
+Vec3 vec3_zero(void) { Vec3 v = {0, 0, 0}; return v; }
+Vec3 vec3(float x, float y, float z) { Vec3 v = {x, y, z}; return v; }
+Vec3 vec3v(float x[3]) { Vec3 v = {x[0], x[1], x[2]}; return v; }
+
+Vec4 vec4_zero(void) { Vec4 v = {0, 0, 0, 0}; return v; }
+Vec4 vec4(float x, float y, float z, float w) { Vec4 v = {x, y, z, w}; return v; }
+Vec4 vec4v(float x[4]) { Vec4 v = {x[0], x[1], x[2], x[3]}; return v; }
+
+
+void vec2_add(Vec2 *d, Vec2 v0, Vec2 v1) { VEC2_3OP(d,v0,+,v1,+0); }
+void vec2_sub(Vec2 *d, Vec2 v0, Vec2 v1) { VEC2_3OP(d,v0,-,v1,+0); }
+void vec2_mul(Vec2 *d, Vec2 v, float s) { VEC2_2OP(d,v,* s); }
+void vec2_div(Vec2 *d, Vec2 v, float s) { VEC2_2OP(d,v,/ s); }
+
+void vec3_add(Vec3 *d, Vec3 v0, Vec3 v1) { VEC3_3OP(d,v0,+,v1,+0); }
+void vec3_sub(Vec3 *d, Vec3 v0, Vec3 v1) { VEC3_3OP(d,v0,-,v1,+0); }
+void vec3_mul(Vec3 *d, Vec3 v, float s) { VEC3_2OP(d,v,* s); }
+void vec3_div(Vec3 *d, Vec3 v, float s) { VEC3_2OP(d,v,/ s); }
+
+void vec4_add(Vec4 *d, Vec4 v0, Vec4 v1) { VEC4_3OP(d,v0,+,v1,+0); }
+void vec4_sub(Vec4 *d, Vec4 v0, Vec4 v1) { VEC4_3OP(d,v0,-,v1,+0); }
+void vec4_mul(Vec4 *d, Vec4 v, float s) { VEC4_2OP(d,v,* s); }
+void vec4_div(Vec4 *d, Vec4 v, float s) { VEC4_2OP(d,v,/ s); }
+
+
+void vec2_addeq(Vec2 *d, Vec2 v) { VEC2_3OP(d,(*d),+,v,+0); }
+void vec2_subeq(Vec2 *d, Vec2 v) { VEC2_3OP(d,(*d),-,v,+0); }
+void vec2_muleq(Vec2 *d, float s) { VEC2_2OP(d,(*d),* s); }
+void vec2_diveq(Vec2 *d, float s) { VEC2_2OP(d,(*d),/ s); }
+
+void vec3_addeq(Vec3 *d, Vec3 v) { VEC3_3OP(d,(*d),+,v,+0); }
+void vec3_subeq(Vec3 *d, Vec3 v) { VEC3_3OP(d,(*d),-,v,+0); }
+void vec3_muleq(Vec3 *d, float s) { VEC3_2OP(d,(*d),* s); }
+void vec3_diveq(Vec3 *d, float s) { VEC3_2OP(d,(*d),/ s); }
+
+void vec4_addeq(Vec4 *d, Vec4 v) { VEC4_3OP(d,(*d),+,v,+0); }
+void vec4_subeq(Vec4 *d, Vec4 v) { VEC4_3OP(d,(*d),-,v,+0); }
+void vec4_muleq(Vec4 *d, float s) { VEC4_2OP(d,(*d),* s); }
+void vec4_diveq(Vec4 *d, float s) { VEC4_2OP(d,(*d),/ s); }
+
+
+float vec2_dot(Vec2 v0, Vec2 v1) { return v0.x*v1.x + v0.y*v1.y; }
+float vec3_dot(Vec3 v0, Vec3 v1) { return v0.x*v1.x + v0.y*v1.y + v0.z*v1.z; }
+float vec4_dot(Vec4 v0, Vec4 v1) { return v0.x*v1.x + v0.y*v1.y + v0.z*v1.z + v0.w*v1.w; }
+
+void vec2_cross(float *d, Vec2 v0, Vec2 v1) { *d = v0.x*v1.y - v1.x*v0.y; }
+void vec3_cross(Vec3 *d, Vec3 v0, Vec3 v1) { d->x = v0.y*v1.z - v0.z*v1.y;
+ d->y = v0.z*v1.x - v0.x*v1.z;
+ d->z = v0.x*v1.y - v0.y*v1.x; }
+
+float vec2_mag2(Vec2 v) { return vec2_dot(v, v); }
+float vec3_mag2(Vec3 v) { return vec3_dot(v, v); }
+float vec4_mag2(Vec4 v) { return vec4_dot(v, v); }
+
+// TODO(bill): Create custom sqrt function
+float vec2_mag(Vec2 v) { return sqrtf(vec2_dot(v, v)); }
+float vec3_mag(Vec3 v) { return sqrtf(vec3_dot(v, v)); }
+float vec4_mag(Vec4 v) { return sqrtf(vec4_dot(v, v)); }
+
+// TODO(bill): Should I calculate inv_sqrt directly?
+void vec2_norm(Vec2 *d, Vec2 v) { vec2_div(d, v, vec2_mag(v)); }
+void vec3_norm(Vec3 *d, Vec3 v) { vec3_div(d, v, vec3_mag(v)); }
+void vec4_norm(Vec4 *d, Vec4 v) { vec4_div(d, v, vec4_mag(v)); }
+
+float vec2_aspect(Vec2 v)
+{
+ if (v.y < 0.0001f)
+ return 0.0f;
+ return v.x/v.y;
+}
+
+
+
+
+
+void mat2_transpose(Mat2 *m) { float22_transpose(float22_m(m)); }
+void mat2_identity(Mat2 *m) { float22_identity(float22_m(m)); }
+void mat2_mul(Mat2 *out, Mat2 *m1, Mat2 *m2) { float22_mul(float22_m(out), float22_m(m1), float22_m(m2)); }
+
+void
+float22_identity(float m[2][2])
+{
+ m[0][0] = 1; m[0][1] = 0;
+ m[1][0] = 0; m[1][1] = 1;
+}
+
+void
+mat2_mul_vec2(Vec2 *out, Mat2 *m, Vec2 in)
+{
+ float22_mul_vec2(out, float22_m(m), in);
+}
+
+Mat2 *mat2_v(Vec2 m[2]) { return (Mat2 *)m; }
+Mat2 *mat2_f(float m[2][2]) { return (Mat2 *)m; }
+
+Float2 *float22_m(Mat2 *m) { return (Float2 *)m; }
+Float2 *float22_v(Vec2 m[2]) { return (Float2 *)m; }
+Float2 *float22_4(float m[4]) { return (Float2 *)m; }
+
+void
+float22_transpose(float (*vec)[2])
+{
+ int i, j;
+ for (j = 0; j < 2; j++) {
+ for (i = j + 1; i < 2; i++) {
+ float t = vec[i][j];
+ vec[i][j] = vec[j][i];
+ vec[j][i] = t;
+ }
+ }
+}
+
+void
+float22_mul(float (*out)[2], float (*mat1)[2], float (*mat2)[2])
+{
+ int i, j;
+ float temp1[2][2], temp2[2][2];
+ if (mat1 == out) { memcpy(temp1, mat1, sizeof(temp1)); mat1 = temp1; }
+ if (mat2 == out) { memcpy(temp2, mat2, sizeof(temp2)); mat2 = temp2; }
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < 2; i++) {
+ out[j][i] = mat1[0][i]*mat2[j][0]
+ + mat1[1][i]*mat2[j][1];
+ }
+ }
+}
+
+void
+float22_mul_vec2(Vec2 *out, float m[2][2], Vec2 v)
+{
+ out->x = m[0][0] * v.x + m[0][1] * v.y;
+ out->y = m[1][0] * v.x + m[1][1] * v.y;
+}
+
+
+
+
+
+
+void mat3_transpose(Mat3 *m) { float33_transpose(float33_m(m)); }
+void mat3_identity(Mat3 *m) { float33_identity(float33_m(m)); }
+void mat3_mul(Mat3 *out, Mat3 *m1, Mat3 *m2) { float33_mul(float33_m(out), float33_m(m1), float33_m(m2)); }
+
+void
+float33_identity(float m[3][3])
+{
+ m[0][0] = 1; m[0][1] = 0; m[0][2] = 0;
+ m[1][0] = 0; m[1][1] = 1; m[1][2] = 0;
+ m[2][0] = 0; m[2][1] = 0; m[2][2] = 1;
+}
+
+void
+mat3_mul_vec3(Vec3 *out, Mat3 *m, Vec3 in)
+{
+ float33_mul_vec3(out, float33_m(m), in);
+}
+
+Mat3 *mat3_v(Vec3 m[3]) { return (Mat3 *)m; }
+Mat3 *mat3_f(float m[3][3]) { return (Mat3 *)m; }
+
+Float3 *float33_m(Mat3 *m) { return (Float3 *)m; }
+Float3 *float33_v(Vec3 m[3]) { return (Float3 *)m; }
+Float3 *float33_16(float m[9]) { return (Float3 *)m; }
+
+void
+float33_transpose(float (*vec)[3])
+{
+ int i, j;
+ for (j = 0; j < 3; j++) {
+ for (i = j + 1; i < 3; i++) {
+ float t = vec[i][j];
+ vec[i][j] = vec[j][i];
+ vec[j][i] = t;
+ }
+ }
+}
+
+void
+float33_mul(float (*out)[3], float (*mat1)[3], float (*mat2)[3])
+{
+ int i, j;
+ float temp1[3][3], temp2[3][3];
+ if (mat1 == out) { memcpy(temp1, mat1, sizeof(temp1)); mat1 = temp1; }
+ if (mat2 == out) { memcpy(temp2, mat2, sizeof(temp2)); mat2 = temp2; }
+ for (j = 0; j < 3; j++) {
+ for (i = 0; i < 3; i++) {
+ out[j][i] = mat1[0][i]*mat2[j][0]
+ + mat1[1][i]*mat2[j][1]
+ + mat1[2][i]*mat2[j][2];
+ }
+ }
+}
+
+void
+float33_mul_vec3(Vec3 *out, float m[3][3], Vec3 v)
+{
+ out->x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z;
+ out->y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z;
+ out->z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z;
+}
+
+
+
+
+
+
+
+
+
+void mat4_transpose(Mat4 *m) { float44_transpose(float44_m(m)); }
+void mat4_identity(Mat4 *m) { float44_identity(float44_m(m)); }
+void mat4_mul(Mat4 *out, Mat4 *m1, Mat4 *m2) { float44_mul(float44_m(out), float44_m(m1), float44_m(m2)); }
+
+void
+float44_identity(float m[4][4])
+{
+ m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
+ m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0;
+ m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0;
+ m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
+}
+
+void
+mat4_mul_vec4(Vec4 *out, Mat4 *m, Vec4 in)
+{
+ float44_mul_vec4(out, float44_m(m), in);
+}
+
+Mat4 *mat4_v(Vec4 m[4]) { return (Mat4 *)m; }
+Mat4 *mat4_f(float m[4][4]) { return (Mat4 *)m; }
+
+Float4 *float44_m(Mat4 *m) { return (Float4 *)m; }
+Float4 *float44_v(Vec4 m[4]) { return (Float4 *)m; }
+Float4 *float44_16(float m[16]) { return (Float4 *)m; }
+
+void
+float44_transpose(float (*vec)[4])
+{
+ int i, j;
+ for (j = 0; j < 4; j++) {
+ for (i = j + 1; i < 4; i++) {
+ float t = vec[i][j];
+ vec[i][j] = vec[j][i];
+ vec[j][i] = t;
+ }
+ }
+}
+
+void
+float44_mul(float (*out)[4], float (*mat1)[4], float (*mat2)[4])
+{
+ int i, j;
+ float temp1[4][4], temp2[4][4];
+ if (mat1 == out) { memcpy(temp1, mat1, sizeof(temp1)); mat1 = temp1; }
+ if (mat2 == out) { memcpy(temp2, mat2, sizeof(temp2)); mat2 = temp2; }
+ for (j = 0; j < 4; j++) {
+ for (i = 0; i < 4; i++) {
+ out[j][i] = mat1[0][i]*mat2[j][0]
+ + mat1[1][i]*mat2[j][1]
+ + mat1[2][i]*mat2[j][2]
+ + mat1[3][i]*mat2[j][3];
+ }
+ }
+}
+
+void
+float44_mul_vec4(Vec4 *out, float m[4][4], Vec4 v)
+{
+ out->x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w;
+ out->y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w;
+ out->z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w;
+ out->w = m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w;
+}
+
+
+
+
+float lerp(float a, float b, float t) { return a*(1.0f-t) + b*t; }
+float smooth_step(float a, float b, float t) { float x = (t - a)/(b - a); return x*x*(3.0f - 2.0f*x); }
+float smoother_step(float a, float b, float t) { float x = (t - a)/(b - a); return x*x*x*(x*(6.0f*x - 15.0f) + 10.0f); }
+
+#define VEC_LERPN(N, d, a, b, t) Vec##N db; vec##N##_mul(&db, b, t); vec##N##_add(d, a, db)
+void vec2_lerp(Vec2 *d, Vec2 a, Vec2 b, float t) { VEC_LERPN(2, d, a, b, t); }
+void vec3_lerp(Vec3 *d, Vec3 a, Vec3 b, float t) { VEC_LERPN(3, d, a, b, t); }
+void vec4_lerp(Vec4 *d, Vec4 a, Vec4 b, float t) { VEC_LERPN(4, d, a, b, t); }
+
+
+
+
+
+float to_radians(float degrees) { return degrees * MATH_TAU / 360.0f; }
+float to_degrees(float radians) { return radians * 360.0f / MATH_TAU; }
+
+
+
+
+
+
+void
+mat4_ortho2d(Mat4 *out, float left, float right, float bottom, float top)
+{
+ Float4 *m;
+ mat4_identity(out);
+ m = float44_m(out);
+
+ m[0][0] = 2.0f / (right - left);
+ m[1][1] = 2.0f / (top - bottom);
+ m[2][2] = -1.0f;
+ m[3][0] = -(right + left) / (right - left);
+ m[3][1] = -(top + bottom) / (top - bottom);
+}
+
+void
+mat4_ortho3d(Mat4 *out, float left, float right, float bottom, float top, float z_near, float z_far)
+{
+ Float4 *m;
+ mat4_identity(out);
+ m = float44_m(out);
+
+ m[0][0] = +2.0f / (right - left);
+ m[1][1] = +2.0f / (top - bottom);
+ m[2][2] = -2.0f / (z_far - z_near);
+ m[3][0] = -(right + left) / (right - left);
+ m[3][1] = -(top + bottom) / (top - bottom);
+ m[3][2] = -(z_far + z_near) / (z_far - z_near);
+}
+
+
+#if defined(__x86_64__) || defined(__ppc64__)
+
+ u64
+ hash_murmur64(void const *key, size_t num_bytes)
+ {
+ u64 const m = 0xc6a4a7935bd1e995ULL;
+ int const r = 47;
+
+ u64 h = MURMUR64_SEED ^ (num_bytes * m);
+
+ u64 *data = (u64 *)(key);
+ u64 *end = data + (num_bytes / 8);
+ u8 *data2;
+
+ while (data != end) {
+ u64 k = *data++;
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+ h ^= k;
+ h *= m;
+ }
+
+ data2 = (u8 *)data;
+
+ switch (num_bytes & 7) {
+ case 7: h ^= (u64)data2[6] << 48;
+ case 6: h ^= (u64)data2[5] << 40;
+ case 5: h ^= (u64)data2[4] << 32;
+ case 4: h ^= (u64)data2[3] << 24;
+ case 3: h ^= (u64)data2[2] << 16;
+ case 2: h ^= (u64)data2[1] << 8;
+ case 1: h ^= (u64)data2[0];
+ h *= m;
+ };
+
+ h ^= h >> r;
+ h *= m;
+ h ^= h >> r;
+
+ return h;
+ }
+#else
+ gb_math_u64
+ hash_murmur64(void const *key, size_t num_bytes)
+ {
+ gb_math_u32 const m = 0x5bd1e995;
+ gb_math_u32 const r = 24;
+
+ gb_math_u64 h = 0;
+ gb_math_u32 h1 = (gb_math_u32)MURMUR64_SEED ^ (gb_math_u32)num_bytes;
+ gb_math_u32 h2 = (gb_math_u32)((gb_math_u64)MURMUR64_SEED >> 32);
+
+ gb_math_u32 *data = (gb_math_u32 *)key;
+
+
+ while (num_bytes >= 8) {
+ gb_math_u32 k1, k2;
+ k1 = *data++;
+ k1 *= m;
+ k1 ^= k1 >> r;
+ k1 *= m;
+ h1 *= m;
+ h1 ^= k1;
+ num_bytes -= 4;
+
+ k2 = *data++;
+ k2 *= m;
+ k2 ^= k2 >> r;
+ k2 *= m;
+ h2 *= m;
+ h2 ^= k2;
+ num_bytes -= 4;
+ }
+
+ if (num_bytes >= 4) {
+ gb_math_u32 k1 = *data++;
+ k1 *= m;
+ k1 ^= k1 >> r;
+ k1 *= m;
+ h1 *= m;
+ h1 ^= k1;
+ num_bytes -= 4;
+ }
+
+ switch (num_bytes) {
+ case 3: h2 ^= (gb_math_u32)((gb_math_u8 *)(data)[2]) << 16;
+ case 2: h2 ^= (gb_math_u32)((gb_math_u8 *)(data)[1]) << 8;
+ case 1: h2 ^= (gb_math_u32)((gb_math_u8 *)(data)[0]) << 0;
+ h2 *= m;
+ };
+
+ h1 ^= h2 >> 18;
+ h1 *= m;
+ h2 ^= h1 >> 22;
+ h2 *= m;
+ h1 ^= h2 >> 17;
+ h1 *= m;
+ h2 ^= h1 >> 19;
+ h2 *= m;
+
+ h = (gb_math_u64)(h << 32) | (gb_math_u64)h2;
+
+ return h;
+ }
+#endif
+
+
+// TODO(bill): Make better random number generators
+float
+random_range_float(float min_inc, float max_inc)
+{
+ static int random_value = 0xdeadbeef; // Random Value
+ float result;
+ random_value = random_value * 2147001325 + 715136305; // BCPL generator
+ result = *(float *)&random_value; // bits
+ result /= 4294967295.0f;
+ result *= (max_inc - min_inc);
+ result += min_inc;
+
+ return result;
+}
+
+int
+random_range_int(int min_inc, int max_inc)
+{
+ static int random_value = 0xdeadbeef; // Random Value
+ int diff, result;
+ random_value = random_value * 2147001325 + 715136305; // BCPL generator
+ diff = max_inc - min_inc + 1;
+ result = random_value % diff;
+ result += min_inc;
+
+ return result;
+}
+
+
+#endif // GB_MATH_IMPLEMENTATION