[RELEASE] u22-v03

This version is submitted to U22 breau.
This commit is contained in:
2020-09-14 00:00:00 +00:00
parent 360595de37
commit 84c3a02b9a
357 changed files with 29223 additions and 0 deletions

16
util/math/CMakeLists.txt Normal file
View File

@@ -0,0 +1,16 @@
add_library(math
rational.c
vector.c
)
target_source_of_source(math
algorithm.sos.c
matrix.sos.c
)
target_link_libraries(math m)
if (BUILD_TESTING)
add_executable(math-test test.c)
target_link_libraries(math-test math)
add_test(math-test math-test)
endif()

63
util/math/algorithm.h Normal file
View File

@@ -0,0 +1,63 @@
#pragma once
#include <math.h>
#include <stdint.h>
#include "./constant.h"
#define MATH_ABS(a) ((a) > 0? (a): -(a))
#define MATH_MAX(a, b) ((a) > (b)? (a): (b))
#define MATH_MIN(a, b) ((a) < (b)? (a): (b))
#define MATH_DIFF(a, b) (MATH_MAX(a, b) - MATH_MIN(a, b))
#define MATH_CLAMP(x, min, max) ((x) < (min)? (min): (x) > (max)? (max): (x))
#define MATH_SIGN(a) (a < 0? -1: a > 0? 1: 0)
#define MATH_FLOAT_EQUAL(a, b) (MATH_ABS((a) - (b)) < MATH_EPSILON)
#define MATH_FLOAT_VALID(a) (!isnan(a) && !isinf(a))
#define decl_next_power2_(type) \
type##_t math_##type##_next_power2(type##_t x)
decl_next_power2_(int8);
decl_next_power2_(int16);
decl_next_power2_(int32);
decl_next_power2_(int64);
decl_next_power2_(uint8);
decl_next_power2_(uint16);
decl_next_power2_(uint32);
decl_next_power2_(uint64);
#undef decl_next_power2_
#define decl_gcd_(type) \
type##_t math_##type##_gcd(type##_t x, type##_t y)
decl_gcd_(int8);
decl_gcd_(int16);
decl_gcd_(int32);
decl_gcd_(int64);
decl_gcd_(uint8);
decl_gcd_(uint16);
decl_gcd_(uint32);
decl_gcd_(uint64);
#undef decl_gcd_
#define decl_lcm_(type) \
type##_t math_##type##_lcm(type##_t x, type##_t y)
decl_lcm_(int8);
decl_lcm_(int16);
decl_lcm_(int32);
decl_lcm_(int64);
decl_lcm_(uint8);
decl_lcm_(uint16);
decl_lcm_(uint32);
decl_lcm_(uint64);
#undef decl_lcm_

88
util/math/algorithm.sos.c Normal file
View File

@@ -0,0 +1,88 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static void next_power2(const char* type, size_t N) {
assert(N > 0);
/* https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
printf("%s%zu_t math_%s%zu_next_power2(%s%zu_t x) {", type, N, type, N, type, N);
printf("--x;");
for (size_t i = 1; i < N; i*=2) {
printf("x |= x >> %zu;", i);
}
printf("return ++x;");
printf("}\n");
}
static void gcd(const char* type, size_t N) {
assert(N > 0);
printf("%s%zu_t math_%s%zu_gcd(%s%zu_t x, %s%zu_t y) {", type, N, type, N, type, N, type, N);
printf("assert(x > 0);");
printf("assert(y > 0);");
printf("if (x < y) return math_%s%zu_gcd(y, x);", type, N);
printf("%s%zu_t z;", type, N);
printf("while (y) {");
printf("z = x%%y;");
printf("x = y;");
printf("y = z;");
printf("}");
printf("return x;}\n");
}
static void lcm(const char* type, size_t N) {
assert(N > 0);
printf("%s%zu_t math_%s%zu_lcm(%s%zu_t x, %s%zu_t y) {", type, N, type, N, type, N, type, N);
printf("assert(x > 0);");
printf("assert(y > 0);");
printf("return x / math_%s%zu_gcd(x, y) * y;}\n", type, N);
}
int main(int argc, char** argv) {
(void) argc, (void) argv;
printf("#include \"./algorithm.h\"\n");
printf("#include <assert.h>\n");
printf("#include <stdint.h>\n");
next_power2("int", 8);
next_power2("int", 16);
next_power2("int", 32);
next_power2("int", 64);
next_power2("uint", 8);
next_power2("uint", 16);
next_power2("uint", 32);
next_power2("uint", 64);
gcd("int", 8);
gcd("int", 16);
gcd("int", 32);
gcd("int", 64);
gcd("uint", 8);
gcd("uint", 16);
gcd("uint", 32);
gcd("uint", 64);
lcm("int", 8);
lcm("int", 16);
lcm("int", 32);
lcm("int", 64);
lcm("uint", 8);
lcm("uint", 16);
lcm("uint", 32);
lcm("uint", 64);
return EXIT_SUCCESS;
}

8
util/math/constant.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include <math.h>
#include <float.h>
#define MATH_EPSILON FLT_EPSILON
#define MATH_INF 1e+10
#define MATH_PI M_PI

123
util/math/matrix.h Normal file
View File

@@ -0,0 +1,123 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include "./vector.h"
typedef union {
vec2_t col[2];
float elm[2][2];
float ptr[4];
} mat2_t;
typedef union {
vec3_t col[3];
float elm[3][3];
float ptr[9];
} mat3_t;
typedef union {
vec4_t col[4];
float elm[4][4];
float ptr[16];
} mat4_t;
#define mat3_identity() (mat3_t) {{ \
vec3(1, 0, 0), \
vec3(0, 1, 0), \
vec3(0, 0, 1), \
}}
#define mat4_identity() (mat4_t) {{ \
vec4(1, 0, 0, 0), \
vec4(0, 1, 0, 0), \
vec4(0, 0, 1, 0), \
vec4(0, 0, 0, 1), \
}}
#define mat3_translation(x, y) (mat3_t) {{ \
vec3(1, 0, 0), \
vec3(0, 1, 0), \
vec3(x, y, 1), \
}}
#define mat4_translation(x, y, z) (mat4_t) {{ \
vec4(1, 0, 0, 0), \
vec4(0, 1, 0, 0), \
vec4(0, 0, 1, 0), \
vec4(x, y, z, 1), \
}}
#define mat3_scale(x, y) (mat3_t) {{ \
vec3(x, 0, 0), \
vec3(0, y, 0), \
vec3(0, 0, 1), \
}}
#define mat4_scale(x, y, z) (mat4_t) {{ \
vec4(x, 0, 0, 0), \
vec4(0, y, 0, 0), \
vec4(0, 0, z, 0), \
vec4(0, 0, 0, 1), \
}}
#define mat3_rotation_z(sin_theta, cos_theta) (mat3_t) {{ \
vec3( cos_theta, sin_theta, 0), \
vec3(-(sin_theta), cos_theta, 0), \
vec3( 0, 0, 1), \
}}
#define mat4_rotation_x(sin_theta, cos_theta) (mat4_t) {{ \
vec4(1, 0, 0, 0), \
vec4(0, cos_theta, sin_theta, 0), \
vec4(0, -(sin_theta), cos_theta, 0), \
vec4(0, 0, 0, 1), \
}}
#define mat4_rotation_y(sin_theta, cos_theta) (mat4_t) {{ \
vec4(cos_theta, 0, -(sin_theta), 0), \
vec4( 0, 1, 0, 0), \
vec4(sin_theta, 0, cos_theta, 0), \
vec4( 0, 0, 0, 1), \
}}
#define mat4_rotation_z(sin_theta, cos_theta) (mat4_t) {{ \
vec4( cos_theta, sin_theta, 0, 0), \
vec4(-(sin_theta), cos_theta, 0, 0), \
vec4( 0, 0, 1, 0), \
vec4( 0, 0, 0, 1), \
}}
bool mat2_valid(const mat2_t* x);
bool mat3_valid(const mat3_t* x);
bool mat4_valid(const mat4_t* x);
void mat2_add(mat2_t* x, const mat2_t* l, const mat2_t* r);
void mat3_add(mat3_t* x, const mat3_t* l, const mat3_t* r);
void mat4_add(mat4_t* x, const mat4_t* l, const mat4_t* r);
void mat2_addeq(mat2_t* x, const mat2_t* r);
void mat3_addeq(mat3_t* x, const mat3_t* r);
void mat4_addeq(mat4_t* x, const mat4_t* r);
void mat2_sub(mat2_t* x, const mat2_t* l, const mat2_t* r);
void mat3_sub(mat3_t* x, const mat3_t* l, const mat3_t* r);
void mat4_sub(mat4_t* x, const mat4_t* l, const mat4_t* r);
void mat2_subeq(mat2_t* x, const mat2_t* r);
void mat3_subeq(mat3_t* x, const mat3_t* r);
void mat4_subeq(mat4_t* x, const mat4_t* r);
void mat2_mul(mat2_t* x, const mat2_t* l, const mat2_t* r);
void mat3_mul(mat3_t* x, const mat3_t* l, const mat3_t* r);
void mat4_mul(mat4_t* x, const mat4_t* l, const mat4_t* r);
void mat2_mul_vec2(vec2_t* x, const mat2_t* l, const vec2_t* r);
void mat3_mul_vec3(vec3_t* x, const mat3_t* l, const vec3_t* r);
void mat4_mul_vec4(vec4_t* x, const mat4_t* l, const vec4_t* r);
float mat2_det(const mat2_t* x);
float mat3_det(const mat3_t* x);
float mat4_det(const mat4_t* x);
void mat3_cofactor(mat2_t* x, const mat3_t* r, size_t row, size_t col);
void mat4_cofactor(mat3_t* x, const mat4_t* r, size_t row, size_t col);
bool mat3_inv(mat3_t* x, const mat3_t* r);
bool mat4_inv(mat4_t* x, const mat4_t* r);

240
util/math/matrix.sos.c Normal file
View File

@@ -0,0 +1,240 @@
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#define SWAP(a, b) do { \
typeof(a) macro_SWAP_temp_ = a; \
a = b; \
b = macro_SWAP_temp_; \
} while (0)
static void next_permutation(size_t* p, size_t* c, size_t len) {
assert(p != NULL);
assert(c != NULL);
size_t i = 0;
while (i < len) {
if (c[i] < i) {
if (i%2 == 0) {
SWAP(p[0], p[i]);
} else {
SWAP(p[c[i]], p[i]);
}
++c[i];
return;
}
c[i] = 0;
++i;
}
}
static void valid(size_t dim) {
assert(dim >= 2);
printf("bool mat%zu_valid(const mat%zu_t* m) {", dim, dim);
printf("return m != NULL && MATH_FLOAT_VALID(m->ptr[0])");
for (size_t i = 1; i < dim*dim; ++i) {
printf("&& MATH_FLOAT_VALID(m->ptr[%zu])", i);
}
printf(";}\n");
}
static void each(size_t dim, const char* name, char op) {
assert(dim >= 2);
printf("void mat%zu_%s(mat%zu_t* x, const mat%zu_t* l, const mat%zu_t* r) {", dim, name, dim, dim, dim);
printf("assert(x != NULL);");
printf("assert(mat%zu_valid(l));", dim);
printf("assert(mat%zu_valid(r));", dim);
for (size_t i = 0; i < dim*dim; ++i) {
printf("x->ptr[%zu] = l->ptr[%zu] %c r->ptr[%zu];", i, i, op, i);
}
printf("}\n");
}
static void eacheq(size_t dim, const char* name, char op) {
assert(dim >= 2);
printf("void mat%zu_%s(mat%zu_t* x, const mat%zu_t* r) {", dim, name, dim, dim);
printf("assert(mat%zu_valid(x));", dim);
printf("assert(mat%zu_valid(r));", dim);
for (size_t i = 0; i < dim*dim; ++i) {
printf("x->ptr[%zu] %c= r->ptr[%zu];", i, op, i);
}
printf("}\n");
}
static void mul(size_t dim) {
assert(dim >= 2);
printf("void mat%zu_mul(mat%zu_t* x, const mat%zu_t* l, const mat%zu_t* r) {", dim, dim, dim, dim);
printf("assert(x != NULL);");
printf("assert(mat%zu_valid(l));", dim);
printf("assert(mat%zu_valid(r));", dim);
for (size_t i = 0; i < dim; ++i) {
for (size_t j = 0; j < dim; ++j) {
printf("x->elm[%zu][%zu] = 0", j, i);
for (size_t k = 0; k < dim; ++k) {
printf("+ l->elm[%zu][%zu] * r->elm[%zu][%zu]", k, i, j, k);
}
printf(";");
}
}
printf("}\n");
}
static void mul_vec(size_t dim) {
assert(dim >= 2);
printf("void mat%zu_mul_vec%zu(vec%zu_t* x, const mat%zu_t* l, const vec%zu_t* r) {", dim, dim, dim, dim, dim);
printf("assert(x != NULL);");
printf("assert(mat%zu_valid(l));", dim);
printf("assert(vec%zu_valid(r));", dim);
for (size_t i = 0; i < dim; ++i) {
printf("x->ptr[%zu] = 0", i);
for (size_t j = 0; j < dim; ++j) {
printf("+ l->elm[%zu][%zu] * r->ptr[%zu]", j, i, j);
}
printf(";");
}
printf("}\n");
}
static void det(size_t dim) {
assert(dim >= 2);
size_t p[dim];
for (size_t i = 0; i < dim; ++i) p[i] = i;
size_t c[dim];
for (size_t i = 0; i < dim; ++i) c[i] = 0;
printf("float mat%zu_det(const mat%zu_t* x) {", dim, dim);
printf("assert(mat%zu_valid(x));", dim);
size_t f = 1;
for (size_t i = 1; i <= dim; ++i) f *= i;
printf("return 0");
bool positive = true;
for (size_t i = 0; i < f; ++i) {
printf("%c1", positive? '+': '-');
for (size_t j = 0; j < dim; ++j) {
printf("*x->elm[%zu][%zu]", p[j], j);
}
next_permutation(p, c, dim);
positive = !positive;
}
printf(";}\n");
}
static void cofactor(size_t dim) {
assert(dim >= 3);
printf("void mat%zu_cofactor(mat%zu_t* x, const mat%zu_t* r, size_t row, size_t col) {", dim, dim-1, dim);
printf("assert(x != NULL);");
printf("assert(mat%zu_valid(r));", dim);
printf("assert(row < %zu);", dim);
printf("assert(col < %zu);", dim);
for (size_t row = 0; row < dim; ++row) {
for (size_t col = 0; col < dim; ++col) {
printf("if (row == %zu && col == %zu) {", row, col);
for (size_t xi = 0; xi < dim-1; ++xi) {
const size_t ri = xi >= row? xi+1: xi;
for (size_t xj = 0; xj < dim-1; ++xj) {
const size_t rj = xj >= col? xj+1: xj;
printf("x->elm[%zu][%zu] = %s r->elm[%zu][%zu];", xj, xi, (xj+xi)%2 == 0? "": "-", rj, ri);
}
}
printf("return;}");
}
}
printf("}\n");
}
static void inv(size_t dim) {
assert(dim >= 3);
printf("bool mat%zu_inv(mat%zu_t* x, const mat%zu_t* r) {", dim, dim, dim);
printf("assert(x != NULL);");
printf("assert(mat%zu_valid(r));", dim);
printf("const float d = mat%zu_det(r);", dim);
printf("if (d == 0) return false;");
printf("mat%zu_t co;", dim-1);
for (size_t i = 0; i < dim; ++i) {
for (size_t j = 0; j < dim; ++j) {
printf("mat%zu_cofactor(&co, r, %zu, %zu);", dim, i, j);
printf("x->elm[%zu][%zu] = mat%zu_det(&co) / d;", j, i, dim-1);
}
}
printf("return true;");
printf("}\n");
}
int main(int argc, char** argv) {
(void) argc, (void) argv;
printf("#include \"./matrix.h\"\n");
printf("#include <assert.h>\n");
printf("#include <stdbool.h>\n");
printf("#include <stddef.h>\n");
printf("#include \"./algorithm.h\"\n");
printf("#include \"./vector.h\"\n");
valid(2);
valid(3);
valid(4);
each(2, "add", '+');
each(3, "add", '+');
each(4, "add", '+');
eacheq(2, "addeq", '+');
eacheq(3, "addeq", '+');
eacheq(4, "addeq", '+');
each(2, "sub", '-');
each(3, "sub", '-');
each(4, "sub", '-');
eacheq(2, "subeq", '-');
eacheq(3, "subeq", '-');
eacheq(4, "subeq", '-');
mul(2);
mul(3);
mul(4);
mul_vec(2);
mul_vec(3);
mul_vec(4);
det(2);
det(3);
det(4);
cofactor(3);
cofactor(4);
inv(3);
inv(4);
}

110
util/math/rational.c Normal file
View File

@@ -0,0 +1,110 @@
#include "./rational.h"
#include <assert.h>
#include <stddef.h>
#include "./algorithm.h"
bool rational_valid(const rational_t* x) {
return x != NULL && x->den != 0;
}
void rational_add(rational_t* x, const rational_t* a, const rational_t* b) {
assert(x != NULL);
assert(rational_valid(a));
assert(rational_valid(b));
const int64_t d = math_int64_lcm(a->den, b->den);
*x = (typeof(*x)) {
.num = a->num*(d/a->den) + b->num*(d/b->den),
.den = d,
};
}
void rational_addeq(rational_t* x, const rational_t* a) {
assert(rational_valid(x));
assert(rational_valid(a));
const int64_t d = math_int64_lcm(x->den, a->den);
x->num = x->num*(d/x->den) + a->num*(d/a->den);
x->den = d;
}
void rational_sub(rational_t* x, const rational_t* a, const rational_t* b) {
assert(x != NULL);
assert(rational_valid(a));
assert(rational_valid(b));
rational_t c = *b;
c.num *= -1;
rational_add(x, a, &c);
}
void rational_subeq(rational_t* x, const rational_t* a) {
assert(rational_valid(x));
assert(rational_valid(a));
rational_t c = *a;
c.num *= -1;
rational_addeq(x, &c);
}
void rational_mul(rational_t* x, const rational_t* a, const rational_t* b) {
assert(x != NULL);
assert(rational_valid(a));
assert(rational_valid(b));
*x = (typeof(*x)) {
.num = a->num*b->num,
.den = a->den*b->den,
};
}
void rational_muleq(rational_t* x, const rational_t* a) {
assert(rational_valid(x));
assert(rational_valid(a));
x->num *= a->num;
x->den *= a->den;
}
void rational_div(rational_t* x, const rational_t* a, const rational_t* b) {
assert(x != NULL);
assert(rational_valid(a));
assert(rational_valid(b));
assert(b->num != 0);
*x = (typeof(*x)) {
.num = a->num*b->den,
.den = a->den*b->num,
};
}
void rational_diveq(rational_t* x, const rational_t* a) {
assert(rational_valid(x));
assert(rational_valid(a));
assert(a->num != 0);
x->num *= a->den;
x->den *= a->num;
}
void rational_simplify(rational_t* x) {
assert(rational_valid(x));
const int64_t d =
x->num != 0? math_int64_gcd(MATH_ABS(x->num), MATH_ABS(x->den)): x->den;
x->num /= d;
x->den /= d;
}
void rational_normalize(rational_t* x, int64_t den) {
assert(rational_valid(x));
assert(den != 0);
x->num = x->num * den / x->den;
x->den = den;
}
float rational_calculate(const rational_t* x) {
assert(rational_valid(x));
return x->num*1.0f / x->den;
}

84
util/math/rational.h Normal file
View File

@@ -0,0 +1,84 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
typedef struct {
int64_t num;
int64_t den;
} rational_t;
#define rational(n, d) ((rational_t) { \
.num = n, \
.den = d, \
})
bool
rational_valid(
const rational_t* x
);
void
rational_add(
rational_t* x,
const rational_t* a,
const rational_t* b
);
void
rational_addeq(
rational_t* x,
const rational_t* a
);
void
rational_sub(
rational_t* x,
const rational_t* a,
const rational_t* b
);
void
rational_subeq(
rational_t* x,
const rational_t* a
);
void
rational_mul(
rational_t* x,
const rational_t* a,
const rational_t* b
);
void
rational_muleq(
rational_t* x,
const rational_t* a
);
void
rational_div(
rational_t* x,
const rational_t* a,
const rational_t* b
);
void
rational_diveq(
rational_t* x,
const rational_t* a
);
void
rational_simplify(
rational_t* x
);
/* Don't forget that this operation may cause a discrepancy. */
void
rational_normalize(
rational_t* x,
int64_t den
);
float
rational_calculate(
const rational_t* x
);

111
util/math/test.c Normal file
View File

@@ -0,0 +1,111 @@
#undef NDEBUG
#include <assert.h>
#include <math.h>
#include <float.h>
#include <stdbool.h>
#include <stdio.h>
#include "./algorithm.h"
#include "./matrix.h"
#include "./rational.h"
#include "./vector.h"
static bool vec4_is_equal(vec4_t v1, vec4_t v2) {
return
MATH_FLOAT_EQUAL(v1.x, v2.x) &&
MATH_FLOAT_EQUAL(v1.y, v2.y) &&
MATH_FLOAT_EQUAL(v1.z, v2.z) &&
MATH_FLOAT_EQUAL(v1.w, v2.w);
}
static void test_matrix() {
vec4_t v1, v2;
mat4_t m1, m2, m3;
v1 = vec4(1, 1, 1, 1);
m1 = mat4_identity();
mat4_mul_vec4(&v2, &m1, &v1);
assert(vec4_is_equal(v2, v1));
v1 = vec4(1, 1, 1, 1);
m1 = mat4_translation(1, 1, 1);
mat4_mul_vec4(&v2, &m1, &v1);
assert(vec4_is_equal(v2, vec4(2, 2, 2, 1)));
v1 = vec4(1, 1, 1, 1);
m1 = mat4_scale(.5f, 2, 1);
mat4_mul_vec4(&v2, &m1, &v1);
assert(vec4_is_equal(v2, vec4(.5f, 2, 1, 1)));
v1 = vec4(0, 1, 0, 1);
m1 = mat4_rotation_x(-1 /* = sin -PI/2 */, 0 /* = cos -PI/2 */);
mat4_mul_vec4(&v2, &m1, &v1);
assert(vec4_is_equal(v2, vec4(0, 0, -1, 1)));
v1 = vec4(1, 0, 0, 1);
m1 = mat4_rotation_y(1 /* = sin PI/2 */, 0 /* = cos PI/2 */);
mat4_mul_vec4(&v2, &m1, &v1);
assert(vec4_is_equal(v2, vec4(0, 0, -1, 1)));
v1 = vec4(0, 0, -1, 1);
m1 = mat4_rotation_z(1 /* = sin PI/2 */, 0 /* = cos PI/2 */);
mat4_mul_vec4(&v2, &m1, &v1);
assert(vec4_is_equal(v2, vec4(0, 0, -1, 1)));
v1 = vec4(-1, 1, 0, 1);
m1 = mat4_rotation_z(1 /* = sin PI/2 */, 0 /* = cos PI/2 */);
m2 = mat4_scale(.5f, .5f, .5f);
mat4_mul(&m3, &m2, &m1);
m1 = mat4_translation(1, 1, 0);
mat4_mul(&m2, &m1, &m3);
mat4_mul_vec4(&v2, &m2, &v1);
assert(vec4_is_equal(v2, vec4(.5f, .5f, 0, 1)));
}
static void test_algorithm(void) {
assert(math_int32_next_power2(8) == 8);
assert(math_int32_next_power2(20) == 32);
assert(math_int32_next_power2(200) == 256);
assert(math_int32_gcd(10, 5) == 5);
assert(math_int32_gcd(12, 6) == 6);
assert(math_int32_gcd(12, 9) == 3);
assert(math_int32_gcd(12, 11) == 1);
assert(math_int32_lcm(10, 5) == 10);
assert(math_int32_lcm(12, 10) == 60);
assert(math_int32_lcm(7, 8) == 56);
}
static void test_rational(void) {
rational_t x, y;
x = rational(1, 2);
y = rational(1, 4);
rational_addeq(&x, &y);
assert(x.num == 3 && x.den == 4);
x = rational(1, 2);
y = rational(1, 3);
rational_muleq(&x, &y);
assert(x.num == 1 && x.den == 6);
x = rational(10, 20);
rational_simplify(&x);
assert(x.num == 1 && x.den == 2);
x = rational(1, 2);
rational_normalize(&x, 100);
assert(x.num == 50 && x.den == 100);
x = rational(1, 2);
assert(rational_calculate(&x) == 1.0f/2.0f);
}
int main(void) {
test_matrix();
test_algorithm();
test_rational();
return 0;
}

275
util/math/vector.c Normal file
View File

@@ -0,0 +1,275 @@
#include "./vector.h"
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include "./algorithm.h"
bool vec2_valid(const vec2_t* x) {
return x != NULL &&
MATH_FLOAT_VALID(x->ptr[0]) &&
MATH_FLOAT_VALID(x->ptr[1]);
}
bool vec3_valid(const vec3_t* x) {
return x != NULL &&
MATH_FLOAT_VALID(x->ptr[0]) &&
MATH_FLOAT_VALID(x->ptr[1]) &&
MATH_FLOAT_VALID(x->ptr[2]);
}
bool vec4_valid(const vec4_t* x) {
return x != NULL &&
MATH_FLOAT_VALID(x->ptr[0]) &&
MATH_FLOAT_VALID(x->ptr[1]) &&
MATH_FLOAT_VALID(x->ptr[2]) &&
MATH_FLOAT_VALID(x->ptr[3]);
}
void vec2_add(vec2_t* x, const vec2_t* l, const vec2_t* r) {
assert(x != NULL);
assert(l != NULL);
assert(r != NULL);
x->x = l->x + r->x;
x->y = l->y + r->y;
}
void vec3_add(vec3_t* x, const vec3_t* l, const vec3_t* r) {
assert(x != NULL);
assert(l != NULL);
assert(r != NULL);
x->x = l->x + r->x;
x->y = l->y + r->y;
x->z = l->z + r->z;
}
void vec4_add(vec4_t* x, const vec4_t* l, const vec4_t* r) {
assert(x != NULL);
assert(l != NULL);
assert(r != NULL);
x->x = l->x + r->x;
x->y = l->y + r->y;
x->z = l->z + r->z;
x->w = l->w + r->w;
}
void vec2_addeq(vec2_t* x, const vec2_t* r) {
assert(x != NULL);
assert(r != NULL);
x->x += r->x;
x->y += r->y;
}
void vec3_addeq(vec3_t* x, const vec3_t* r) {
assert(x != NULL);
assert(r != NULL);
x->x += r->x;
x->y += r->y;
x->z += r->z;
}
void vec4_addeq(vec4_t* x, const vec4_t* r) {
assert(x != NULL);
assert(r != NULL);
x->x += r->x;
x->y += r->y;
x->z += r->z;
x->w += r->w;
}
void vec2_sub(vec2_t* x, const vec2_t* l, const vec2_t* r) {
assert(x != NULL);
assert(l != NULL);
assert(r != NULL);
x->x = l->x - r->x;
x->y = l->y - r->y;
}
void vec3_sub(vec3_t* x, const vec3_t* l, const vec3_t* r) {
assert(x != NULL);
assert(l != NULL);
assert(r != NULL);
x->x = l->x - r->x;
x->y = l->y - r->y;
x->z = l->z - r->z;
}
void vec4_sub(vec4_t* x, const vec4_t* l, const vec4_t* r) {
assert(x != NULL);
assert(l != NULL);
assert(r != NULL);
x->x = l->x - r->x;
x->y = l->y - r->y;
x->z = l->z - r->z;
x->w = l->w - r->w;
}
void vec2_subeq(vec2_t* x, const vec2_t* r) {
assert(x != NULL);
assert(r != NULL);
x->x -= r->x;
x->y -= r->y;
}
void vec3_subeq(vec3_t* x, const vec3_t* r) {
assert(x != NULL);
assert(r != NULL);
x->x -= r->x;
x->y -= r->y;
x->z -= r->z;
}
void vec4_subeq(vec4_t* x, const vec4_t* r) {
assert(x != NULL);
assert(r != NULL);
x->x -= r->x;
x->y -= r->y;
x->z -= r->z;
x->w -= r->w;
}
void vec2_mul(vec2_t* x, const vec2_t* l, float r) {
assert(x != NULL);
assert(l != NULL);
x->x = l->x * r;
x->y = l->y * r;
}
void vec3_mul(vec3_t* x, const vec3_t* l, float r) {
assert(x != NULL);
assert(l != NULL);
x->x = l->x * r;
x->y = l->y * r;
x->z = l->z * r;
}
void vec4_mul(vec4_t* x, const vec4_t* l, float r) {
assert(x != NULL);
assert(l != NULL);
x->x = l->x * r;
x->y = l->y * r;
x->z = l->z * r;
x->w = l->w * r;
}
void vec2_muleq(vec2_t* x, float r) {
assert(x != NULL);
x->x *= r;
x->y *= r;
}
void vec3_muleq(vec3_t* x, float r) {
assert(x != NULL);
x->x *= r;
x->y *= r;
x->z *= r;
}
void vec4_muleq(vec4_t* x, float r) {
assert(x != NULL);
x->x *= r;
x->y *= r;
x->z *= r;
x->w *= r;
}
void vec2_div(vec2_t* x, const vec2_t* l, float r) {
assert(x != NULL);
assert(l != NULL);
x->x = l->x / r;
x->y = l->y / r;
}
void vec3_div(vec3_t* x, const vec3_t* l, float r) {
assert(x != NULL);
assert(l != NULL);
x->x = l->x / r;
x->y = l->y / r;
x->z = l->z / r;
}
void vec4_div(vec4_t* x, const vec4_t* l, float r) {
assert(x != NULL);
assert(l != NULL);
x->x = l->x / r;
x->y = l->y / r;
x->z = l->z / r;
x->w = l->w / r;
}
void vec2_diveq(vec2_t* x, float r) {
assert(x != NULL);
x->x /= r;
x->y /= r;
}
void vec3_diveq(vec3_t* x, float r) {
assert(x != NULL);
x->x /= r;
x->y /= r;
x->z /= r;
}
void vec4_diveq(vec4_t* x, float r) {
assert(x != NULL);
x->x /= r;
x->y /= r;
x->z /= r;
x->w /= r;
}
float vec2_pow_length(const vec2_t* x) {
assert(x != NULL);
return x->x*x->x + x->y*x->y;
}
float vec3_pow_length(const vec3_t* x) {
assert(x != NULL);
return x->x*x->x + x->y*x->y + x->z*x->z;
}
float vec4_pow_length(const vec4_t* x) {
assert(x != NULL);
return x->x*x->x + x->y*x->y + x->z*x->z + x->w*x->w;
}
float vec2_length(const vec2_t* x) {
assert(x != NULL);
return sqrtf(vec2_pow_length(x));
}
float vec3_length(const vec3_t* x) {
assert(x != NULL);
return sqrtf(vec3_pow_length(x));
}
float vec4_length(const vec4_t* x) {
assert(x != NULL);
return sqrtf(vec4_pow_length(x));
}
float vec2_dot(const vec2_t* l, const vec2_t* r) {
assert(l != NULL);
assert(r != NULL);
return l->x*r->x + l->y*r->y;
}
float vec3_dot(const vec3_t* l, const vec3_t* r) {
assert(l != NULL);
assert(r != NULL);
return l->x*r->x + l->y*r->y + l->z*r->z;
}
float vec4_dot(const vec4_t* l, const vec4_t* r) {
assert(l != NULL);
assert(r != NULL);
return l->x*r->x + l->y*r->y + l->z*r->z + l->w*r->w;
}
float vec2_cross(const vec2_t* l, const vec2_t* r) {
assert(l != NULL);
assert(r != NULL);
return l->x*r->y - l->y*r->x;
}

78
util/math/vector.h Normal file
View File

@@ -0,0 +1,78 @@
#pragma once
#include <stdbool.h>
typedef union {
struct { float x, y; };
float ptr[2];
} vec2_t;
typedef union {
struct { float x, y, z; };
float ptr[3];
vec2_t xy;
} vec3_t;
typedef union {
struct { float x, y, z, w; };
float ptr[4];
vec2_t xy;
vec3_t xyz;
} vec4_t;
#define vec2(x, y) (vec2_t) {{x, y}}
#define vec3(x, y, z) (vec3_t) {{x, y, z}}
#define vec4(x, y, z, w) (vec4_t) {{x, y, z, w}}
bool vec2_valid(const vec2_t* x);
bool vec3_valid(const vec3_t* x);
bool vec4_valid(const vec4_t* x);
void vec2_add(vec2_t* x, const vec2_t* l, const vec2_t* r);
void vec3_add(vec3_t* x, const vec3_t* l, const vec3_t* r);
void vec4_add(vec4_t* x, const vec4_t* l, const vec4_t* r);
void vec2_addeq(vec2_t* x, const vec2_t* r);
void vec3_addeq(vec3_t* x, const vec3_t* r);
void vec4_addeq(vec4_t* x, const vec4_t* r);
void vec2_sub(vec2_t* x, const vec2_t* l, const vec2_t* r);
void vec3_sub(vec3_t* x, const vec3_t* l, const vec3_t* r);
void vec4_sub(vec4_t* x, const vec4_t* l, const vec4_t* r);
void vec2_subeq(vec2_t* x, const vec2_t* r);
void vec3_subeq(vec3_t* x, const vec3_t* r);
void vec4_subeq(vec4_t* x, const vec4_t* r);
void vec2_mul(vec2_t* x, const vec2_t* l, float r);
void vec3_mul(vec3_t* x, const vec3_t* l, float r);
void vec4_mul(vec4_t* x, const vec4_t* l, float r);
void vec2_muleq(vec2_t* x, float r);
void vec3_muleq(vec3_t* x, float r);
void vec4_muleq(vec4_t* x, float r);
void vec2_div(vec2_t* x, const vec2_t* l, float r);
void vec3_div(vec3_t* x, const vec3_t* l, float r);
void vec4_div(vec4_t* x, const vec4_t* l, float r);
void vec2_diveq(vec2_t* x, float r);
void vec3_diveq(vec3_t* x, float r);
void vec4_diveq(vec4_t* x, float r);
float vec2_pow_length(const vec2_t* x);
float vec3_pow_length(const vec3_t* x);
float vec4_pow_length(const vec4_t* x);
float vec2_length(const vec2_t* x);
float vec3_length(const vec3_t* x);
float vec4_length(const vec4_t* x);
float vec2_dot(const vec2_t* l, const vec2_t* r);
float vec3_dot(const vec3_t* l, const vec3_t* r);
float vec4_dot(const vec4_t* l, const vec4_t* r);
float vec2_cross(const vec2_t* l, const vec2_t* r);
/* TODO(catfoot): add vec3_cross function */