[RELEASE] u22-v03
This version is submitted to U22 breau.
This commit is contained in:
16
util/math/CMakeLists.txt
Normal file
16
util/math/CMakeLists.txt
Normal 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
63
util/math/algorithm.h
Normal 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
88
util/math/algorithm.sos.c
Normal 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
8
util/math/constant.h
Normal 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
123
util/math/matrix.h
Normal 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
240
util/math/matrix.sos.c
Normal 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
110
util/math/rational.c
Normal 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
84
util/math/rational.h
Normal 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
111
util/math/test.c
Normal 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
275
util/math/vector.c
Normal 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
78
util/math/vector.h
Normal 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 */
|
Reference in New Issue
Block a user