refactor, libc made optional
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
#include "../std.h"
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <tgmath.h>
|
||||
|
||||
void *com_std_realloc(void *ptr, size_t size) { return realloc(ptr, size); }
|
||||
void com_std_free(void *ptr) { free(ptr); }
|
||||
void com_std_assert(bool holds) { assert(holds); }
|
||||
void com_std_printf(char const *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
double com_std_sqrt(double v) { return sqrt(v); }
|
||||
double com_std_fabs(double v) { return fabs(v); }
|
||||
double com_std_sin(double v) { return sin(v); }
|
||||
double com_std_cos(double v) { return cos(v); }
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "../std.h"
|
||||
|
||||
void *com_std_realloc(void *ptr, size_t size) { return NULL; }
|
||||
void com_std_free(void *ptr) {}
|
||||
void com_std_assert(bool holds) {}
|
||||
void com_std_printf(char const *fmt, ...) {}
|
||||
double com_std_sqrt(double v) { return 0; }
|
||||
double com_std_fabs(double v) { return 0; }
|
||||
double com_std_sin(double v) { return 0; }
|
||||
double com_std_cos(double v) { return 0; }
|
||||
@@ -1,11 +1,9 @@
|
||||
#include "../std.h"
|
||||
#include "timer.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#define __USE_POSIX199309 1
|
||||
#include <time.h>
|
||||
|
||||
/* TODO: Rename to posix.c */
|
||||
|
||||
uint64_t com_timer_count_ns(void) {
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
@@ -15,5 +13,5 @@ uint64_t com_timer_count_ns(void) {
|
||||
void com_timer_profile(uint64_t starttime, const char *what) {
|
||||
uint64_t const endtime = com_timer_count_ns();
|
||||
uint64_t const diff = endtime - starttime;
|
||||
printf("profile \"%s\" took %fms\n", what, (double)diff / 1000000);
|
||||
com_std_printf("profile \"%s\" took %fms\n", what, (double)diff / 1000000);
|
||||
}
|
||||
+4
-13
@@ -10,17 +10,15 @@
|
||||
#define COM_DEF_COMPILE_MODERN 1
|
||||
#endif
|
||||
|
||||
#define COM_DEF_TARGET_NATIVE 0
|
||||
#define COM_DEF_TARGET_LINUX 0
|
||||
#define COM_DEF_TARGET_WASM 1
|
||||
|
||||
#if defined(__wasm__)
|
||||
#define COM_DEF_NOSTD 1
|
||||
#define COM_DEF_TARGET COM_DEF_TARGET_WASM
|
||||
/* TODO: Move to std.h instead, forbid stdlib on any platform. */
|
||||
#define assert(m_t) (m_t)
|
||||
#define printf(...) ((void)0)
|
||||
#define com_def_export_sym(m_s) __attribute__((export_name(m_s)))
|
||||
#else
|
||||
#define COM_DEF_TARGET COM_DEF_TARGET_NATIVE
|
||||
#define COM_DEF_TARGET COM_DEF_TARGET_LINUX
|
||||
#define com_def_export_sym(m_s) __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
/* TODO: uppercase? */
|
||||
@@ -33,13 +31,6 @@
|
||||
#define com_def_vector(v_t, v_v, v_n) v_t v_v[v_n]
|
||||
#endif
|
||||
|
||||
#define COM_DEF_VECTOR_NONE 0
|
||||
#define COM_DEF_VECTOR_SSE2 1
|
||||
|
||||
#ifdef COM_DEF_COMPILE_MODERN
|
||||
#define COM_DEF_VECTOR_IMPL COM_DEF_VECTOR_SSE2
|
||||
#endif
|
||||
|
||||
// #define COM_DEF_PROFILE_VAR volatile /* Sadly, doesn't work in some cases */
|
||||
#define COM_DEF_PROFILE_SINK(m_v) __asm__ volatile("" ::"r"(m_v) : "memory")
|
||||
|
||||
|
||||
+21
-23
@@ -6,15 +6,10 @@
|
||||
#include "fix.h"
|
||||
#include "Timer/timer.h"
|
||||
#include "def.h"
|
||||
#include "std.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef COM_DEF_NOSTD
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <tgmath.h>
|
||||
#endif
|
||||
|
||||
// 4-bit LUT (16 entries) for the normalized range [0.5, 2.0)
|
||||
// It stores the initial guess scaled to Q16.16.
|
||||
static const uint32_t com_fix_sqrt_lut[16] = {
|
||||
@@ -40,7 +35,7 @@ const uint16_t com_fix_sin_lut[128] = {
|
||||
|
||||
com_fix_t com_fix_sqrt(com_fix_t a) {
|
||||
// 1. Handle sign and edge cases
|
||||
assert(a >= 0);
|
||||
com_std_assert(a >= 0);
|
||||
if (a == 0)
|
||||
return 0;
|
||||
|
||||
@@ -86,7 +81,7 @@ com_fix_t com_fix_sqrt(com_fix_t a) {
|
||||
|
||||
void com_fix_print(com_fix_t a) {
|
||||
if (a < 0) {
|
||||
printf("-");
|
||||
com_std_printf("-");
|
||||
a = -a;
|
||||
}
|
||||
int32_t int_part = a >> 16;
|
||||
@@ -95,7 +90,7 @@ void com_fix_print(com_fix_t a) {
|
||||
// Convert fractional 16-bit part to a decimal value (up to 4 decimal places)
|
||||
uint32_t decimal_val = (frac_part * 10000) >> 16;
|
||||
|
||||
printf("%d.%04u\n", int_part, decimal_val);
|
||||
com_std_printf("%d.%04u\n", int_part, decimal_val);
|
||||
}
|
||||
|
||||
void com_fix_run_bench(void) {
|
||||
@@ -133,7 +128,6 @@ void com_fix_run_bench(void) {
|
||||
}
|
||||
|
||||
void com_fix_run_tests(void) {
|
||||
#ifndef COM_DEF_NOSTD
|
||||
{
|
||||
double max_sqrt_deviation = 0.0f;
|
||||
com_fix_t sqrt_accumulator = 0;
|
||||
@@ -141,12 +135,13 @@ void com_fix_run_tests(void) {
|
||||
for (int i = 0; i < COM_FIX_FRACUNIT << 1; ++i) {
|
||||
com_fix_t sqrt = com_fix_sqrt(sqrt_accumulator);
|
||||
double const deviation =
|
||||
sqrt(com_fix_as_float(sqrt_accumulator)) - com_fix_as_float(sqrt);
|
||||
com_std_sqrt(com_fix_as_float(sqrt_accumulator)) -
|
||||
com_fix_as_float(sqrt);
|
||||
if (deviation > max_sqrt_deviation)
|
||||
max_sqrt_deviation = deviation;
|
||||
sqrt_accumulator += sqrt_test_step;
|
||||
}
|
||||
printf("max sqrt deviation: %f\n", max_sqrt_deviation);
|
||||
com_std_printf("max sqrt deviation: %f\n", max_sqrt_deviation);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -156,12 +151,13 @@ void com_fix_run_tests(void) {
|
||||
for (int i = 0; i < 1024 * 32; ++i) {
|
||||
com_fix_t sin = com_fix_sin(sin_accumulator);
|
||||
double const deviation =
|
||||
fabs(sin(com_fix_as_float(sin_accumulator)) - com_fix_as_float(sin));
|
||||
com_std_fabs(com_std_sin(com_fix_as_float(sin_accumulator)) -
|
||||
com_fix_as_float(sin));
|
||||
if (deviation > max_sin_deviation)
|
||||
max_sin_deviation = deviation;
|
||||
sin_accumulator += sin_test_step;
|
||||
}
|
||||
printf("max sin deviation: %f\n", max_sin_deviation);
|
||||
com_std_printf("max sin deviation: %f\n", max_sin_deviation);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -171,12 +167,13 @@ void com_fix_run_tests(void) {
|
||||
for (int i = 0; i < 1024 * 32; ++i) {
|
||||
com_fix_t cos = com_fix_cos(cos_accumulator);
|
||||
double const deviation =
|
||||
fabs(cos(com_fix_as_float(cos_accumulator)) - com_fix_as_float(cos));
|
||||
com_std_fabs(com_std_cos(com_fix_as_float(cos_accumulator)) -
|
||||
com_fix_as_float(cos));
|
||||
if (deviation > max_cos_deviation)
|
||||
max_cos_deviation = deviation;
|
||||
cos_accumulator += cos_test_step;
|
||||
}
|
||||
printf("max cos deviation: %f\n", max_cos_deviation);
|
||||
com_std_printf("max cos deviation: %f\n", max_cos_deviation);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -187,18 +184,19 @@ void com_fix_run_tests(void) {
|
||||
for (int i = 0; i < 1024 * 32; ++i) {
|
||||
com_fix_t sin, cos;
|
||||
com_fix_sincos(sincos_accumulator, &sin, &cos);
|
||||
double const sin_deviation = fabs(
|
||||
sin(com_fix_as_float(sincos_accumulator)) - com_fix_as_float(sin));
|
||||
double const cos_deviation = fabs(
|
||||
cos(com_fix_as_float(sincos_accumulator)) - com_fix_as_float(cos));
|
||||
double const sin_deviation =
|
||||
com_std_fabs(com_std_sin(com_fix_as_float(sincos_accumulator)) -
|
||||
com_fix_as_float(sin));
|
||||
double const cos_deviation =
|
||||
com_std_fabs(com_std_cos(com_fix_as_float(sincos_accumulator)) -
|
||||
com_fix_as_float(cos));
|
||||
if (sin_deviation > max_sin_deviation)
|
||||
max_sin_deviation = sin_deviation;
|
||||
if (cos_deviation > max_cos_deviation)
|
||||
max_cos_deviation = cos_deviation;
|
||||
sincos_accumulator += sincos_test_step;
|
||||
}
|
||||
printf("max sincos deviations: %f %f\n", max_sin_deviation,
|
||||
max_cos_deviation);
|
||||
com_std_printf("max sincos deviations: %f %f\n", max_sin_deviation,
|
||||
max_cos_deviation);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+15
-15
@@ -22,9 +22,9 @@ static inline com_vec_t com_gem_vec_project_clip(com_mat_t a, com_vec_t b) {
|
||||
com_vec_t result;
|
||||
|
||||
#define CASE(m_c, m_n) \
|
||||
result.a[m_c] = (((int64_t)a.a[m_n * 4 + 0] * b.s.x) + \
|
||||
((int64_t)a.a[m_n * 4 + 1] * b.s.y) + \
|
||||
((int64_t)a.a[m_n * 4 + 2] * b.s.z) + a.a[m_n * 4 + 3]) >> \
|
||||
result.a[m_c] = (((int64_t)a.a[m_n * 4 + 0] * b.a[0]) + \
|
||||
((int64_t)a.a[m_n * 4 + 1] * b.a[1]) + \
|
||||
((int64_t)a.a[m_n * 4 + 2] * b.a[2]) + a.a[m_n * 4 + 3]) >> \
|
||||
COM_FIX_FRACBITS;
|
||||
|
||||
CASE(0, 0);
|
||||
@@ -51,9 +51,9 @@ static inline com_vec_t com_gem_vec_project_clip(com_mat_t a, com_vec_t b) {
|
||||
* determining new view-lying clipped triangles. */
|
||||
static inline uint8_t com_gem_clip_vis_project(com_vec_t a, com_pnt_t *out) {
|
||||
uint8_t mask = 0;
|
||||
if (a.s.x < -a.s.z || a.s.x > a.s.z)
|
||||
if (a.a[0] < -a.a[2] || a.a[0] > a.a[2])
|
||||
mask ^= COM_GEM_VERTEX_CLIPPED_X;
|
||||
if (a.s.y < -a.s.z || a.s.y > a.s.z)
|
||||
if (a.a[1] < -a.a[2] || a.a[1] > a.a[2])
|
||||
mask ^= COM_GEM_VERTEX_CLIPPED_Y;
|
||||
out->a[0] = com_fix_div(a.a[0], a.a[2]) / 480 + 240;
|
||||
out->a[1] = com_fix_div(a.a[1], a.a[2]) / 640 + 320;
|
||||
@@ -62,14 +62,14 @@ static inline uint8_t com_gem_clip_vis_project(com_vec_t a, com_pnt_t *out) {
|
||||
|
||||
static inline void com_gem_draw_triangle(com_pnt_t v0, com_pnt_t v1,
|
||||
com_pnt_t v2, uint8_t *out) {
|
||||
int minX = com_vec_min(com_vec_from(v0.s.x, v1.s.x, v2.s.x));
|
||||
int minY = com_vec_min(com_vec_from(v0.s.y, v1.s.y, v2.s.y));
|
||||
int maxX = com_vec_max(com_vec_from(v0.s.x, v1.s.x, v2.s.x));
|
||||
int maxY = com_vec_max(com_vec_from(v0.s.y, v1.s.y, v2.s.y));
|
||||
int minX = com_vec_min(com_vec_from(v0.a[0], v1.a[0], v2.a[0]));
|
||||
int minY = com_vec_min(com_vec_from(v0.a[1], v1.a[1], v2.a[1]));
|
||||
int maxX = com_vec_max(com_vec_from(v0.a[0], v1.a[0], v2.a[0]));
|
||||
int maxY = com_vec_max(com_vec_from(v0.a[1], v1.a[1], v2.a[1]));
|
||||
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
com_pnt_t p = {.s = {x, y}};
|
||||
com_pnt_t p = {.a = {x, y}};
|
||||
|
||||
// Test the pixel center against all 3 edges
|
||||
com_vec_t ws = com_pnt_edge_weight(v0, v1, v2, p);
|
||||
@@ -89,16 +89,16 @@ static inline void com_gem_draw_triangle_textured(com_pnt_t v0, com_pnt_t v1,
|
||||
com_pnt_t v2, uint8_t *out,
|
||||
com_pnt_t uv0, com_pnt_t uv1,
|
||||
com_pnt_t uv2, uint8_t *tex) {
|
||||
int minX = com_vec_min(com_vec_from(v0.s.x, v1.s.x, v2.s.x));
|
||||
int minY = com_vec_min(com_vec_from(v0.s.y, v1.s.y, v2.s.y));
|
||||
int maxX = com_vec_max(com_vec_from(v0.s.x, v1.s.x, v2.s.x));
|
||||
int maxY = com_vec_max(com_vec_from(v0.s.y, v1.s.y, v2.s.y));
|
||||
int minX = com_vec_min(com_vec_from(v0.a[0], v1.a[0], v2.a[0]));
|
||||
int minY = com_vec_min(com_vec_from(v0.a[1], v1.a[1], v2.a[1]));
|
||||
int maxX = com_vec_max(com_vec_from(v0.a[0], v1.a[0], v2.a[0]));
|
||||
int maxY = com_vec_max(com_vec_from(v0.a[1], v1.a[1], v2.a[1]));
|
||||
|
||||
com_fix_t const area = com_pnt_area(v0, v1, v2);
|
||||
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
com_pnt_t p = {.s = {x, y}};
|
||||
com_pnt_t p = {.a = {x, y}};
|
||||
|
||||
/* TODO: Move to a separate weighting function over vec. */
|
||||
// Test the pixel center against all 3 edges
|
||||
|
||||
+13
-17
@@ -5,17 +5,11 @@
|
||||
|
||||
#include "lzw.h"
|
||||
#include "bits.h"
|
||||
#include "std.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef COM_DEF_NOSTD
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include "std.h"
|
||||
#endif
|
||||
|
||||
/* References: */
|
||||
/* https://www.w3.org/Graphics/GIF/spec-gif89a.txt */
|
||||
/* https://www.daubnet.com/en/file-format-gif */
|
||||
@@ -50,8 +44,9 @@ struct com_lzw_table com_lzw_infer_table(const char *datain, uint32_t sizein) {
|
||||
if (!code_found) {
|
||||
if (table_size >= table_cap) {
|
||||
/* TODO: Ref to prev table gets missed, memory leak scenario */
|
||||
if (!(table = realloc(table, sizeof(struct com_lzw_table_entry) *
|
||||
(table_cap + COM_LZW_TABLE_CAP_GROW))))
|
||||
if (!(table = com_std_realloc(
|
||||
table, sizeof(struct com_lzw_table_entry) *
|
||||
(table_cap + COM_LZW_TABLE_CAP_GROW))))
|
||||
goto ERR_ALLOC_INIT_TABLE;
|
||||
|
||||
table_cap += COM_LZW_TABLE_CAP_GROW;
|
||||
@@ -73,14 +68,14 @@ struct com_lzw_table com_lzw_infer_table(const char *datain, uint32_t sizein) {
|
||||
|
||||
ERR_ALLOC_INIT_TABLE:
|
||||
if (table_cap > 0)
|
||||
free(table);
|
||||
com_std_free(table);
|
||||
return (struct com_lzw_table){0};
|
||||
}
|
||||
|
||||
void com_lzw_free_table(struct com_lzw_table *table) {
|
||||
if (!table->table)
|
||||
return;
|
||||
free(table->table);
|
||||
com_std_free(table->table);
|
||||
table->size = 0;
|
||||
table->cap = 0;
|
||||
table->init_size = 0;
|
||||
@@ -89,14 +84,14 @@ void com_lzw_free_table(struct com_lzw_table *table) {
|
||||
/* For GIFs, color should already be collapsed to indices at this point */
|
||||
bool com_lzw_compress(const struct com_lzw_table *table, const char *datain,
|
||||
uint32_t sizein, char **dataout, uint32_t *sizeout) {
|
||||
assert(datain && dataout && sizeout && sizein > 0);
|
||||
assert(*dataout == NULL && *sizeout == 0);
|
||||
com_std_assert(datain && dataout && sizeout && sizein > 0);
|
||||
com_std_assert(*dataout == NULL && *sizeout == 0);
|
||||
|
||||
/* TODO: Make sure the table is cleared */
|
||||
|
||||
/* Encode step */
|
||||
uint8_t codesize = com_bits_needed(table->init_size) + 1;
|
||||
assert(codesize < COM_TABLE_BIT_WIDTH_LIMIT);
|
||||
com_std_assert(codesize < COM_TABLE_BIT_WIDTH_LIMIT);
|
||||
|
||||
uint32_t cur_table_idx =
|
||||
0; /* Head table in which vector we should be looking into */
|
||||
@@ -131,12 +126,13 @@ bool com_lzw_compress(const struct com_lzw_table *table, const char *datain,
|
||||
// }
|
||||
|
||||
/* Emit output, drop the string */
|
||||
assert(cur_table_idx < (1 << codesize));
|
||||
assert(cur_table_idx < table->size);
|
||||
com_std_assert(cur_table_idx < (1 << codesize));
|
||||
com_std_assert(cur_table_idx < table->size);
|
||||
|
||||
if (output_size == output_cap && output_bitshift + codesize > 8) {
|
||||
/* TODO: catch alloc failure */
|
||||
output = realloc(output, output_cap + COM_LZW_OUTPUT_CAP_GROWTH);
|
||||
output =
|
||||
com_std_realloc(output, output_cap + COM_LZW_OUTPUT_CAP_GROWTH);
|
||||
output_cap += COM_LZW_OUTPUT_CAP_GROWTH;
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -21,7 +21,7 @@
|
||||
#include "vec.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union {
|
||||
typedef struct {
|
||||
com_def_alignedas(64) com_def_vector(com_fix_t, a, 4 * 4);
|
||||
} com_mat_t;
|
||||
|
||||
@@ -130,17 +130,17 @@ static inline com_mat_t com_mat_look_at(com_vec_t pos, com_vec_t up,
|
||||
|
||||
com_mat_t result;
|
||||
|
||||
result.a[0] = r.s.x;
|
||||
result.a[1] = u.s.x;
|
||||
result.a[2] = -target.s.x;
|
||||
result.a[0] = r.a[0];
|
||||
result.a[1] = u.a[0];
|
||||
result.a[2] = -target.a[0];
|
||||
result.a[3] = 0;
|
||||
result.a[4] = r.s.y;
|
||||
result.a[5] = u.s.y;
|
||||
result.a[6] = -target.s.y;
|
||||
result.a[4] = r.a[1];
|
||||
result.a[5] = u.a[1];
|
||||
result.a[6] = -target.a[1];
|
||||
result.a[7] = 0;
|
||||
result.a[8] = r.s.z;
|
||||
result.a[9] = u.s.z;
|
||||
result.a[10] = -target.s.z;
|
||||
result.a[8] = r.a[2];
|
||||
result.a[9] = u.a[2];
|
||||
result.a[10] = -target.a[2];
|
||||
result.a[11] = 0;
|
||||
result.a[12] = -com_vec_dot(r, pos);
|
||||
result.a[13] = -com_vec_dot(u, pos);
|
||||
|
||||
+16
-21
@@ -10,54 +10,49 @@
|
||||
#include "vec.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union {
|
||||
typedef struct {
|
||||
com_def_alignedas(16) com_def_vector(com_fix_t, a, 2);
|
||||
com_def_alignedas(16) struct {
|
||||
com_fix_t x;
|
||||
com_fix_t y;
|
||||
} s;
|
||||
} com_pnt_t;
|
||||
|
||||
static inline com_pnt_t com_pnt_from(com_fix_t x, com_fix_t y) {
|
||||
return (com_pnt_t){.s = {.x = x, .y = y}};
|
||||
return (com_pnt_t){.a = {x, y}};
|
||||
}
|
||||
|
||||
static inline com_pnt_t com_pnt_from_vec(com_vec_t a) {
|
||||
return (com_pnt_t){.s = {.x = a.a[0], .y = a.a[1]}};
|
||||
return (com_pnt_t){.a = {a.a[0], a.a[1]}};
|
||||
}
|
||||
|
||||
static inline com_pnt_t com_pnt_identity(void) {
|
||||
return (com_pnt_t){.s = {
|
||||
.x = COM_FIX_FRACUNIT,
|
||||
.y = COM_FIX_FRACUNIT,
|
||||
return (com_pnt_t){.a = {
|
||||
COM_FIX_FRACUNIT,
|
||||
COM_FIX_FRACUNIT,
|
||||
}};
|
||||
}
|
||||
|
||||
static inline com_pnt_t com_pnt_add(com_pnt_t a, com_pnt_t b) {
|
||||
return (com_pnt_t){
|
||||
.s = {.x = com_fix_add(a.s.x, b.s.x), .y = com_fix_add(a.s.y, b.s.y)}};
|
||||
.a = {com_fix_add(a.a[0], b.a[0]), com_fix_add(a.a[1], b.a[1])}};
|
||||
}
|
||||
|
||||
static inline com_pnt_t com_pnt_sub(com_pnt_t a, com_pnt_t b) {
|
||||
return (com_pnt_t){
|
||||
.s = {.x = com_fix_sub(a.s.x, b.s.x), .y = com_fix_sub(a.s.y, b.s.y)}};
|
||||
.a = {com_fix_sub(a.a[0], b.a[0]), com_fix_sub(a.a[1], b.a[1])}};
|
||||
}
|
||||
|
||||
static inline com_pnt_t com_pnt_mul(com_pnt_t a, com_pnt_t b) {
|
||||
return (com_pnt_t){
|
||||
.s = {.x = com_fix_mul(a.s.x, b.s.x), .y = com_fix_mul(a.s.y, b.s.y)}};
|
||||
.a = {com_fix_mul(a.a[0], b.a[0]), com_fix_mul(a.a[1], b.a[1])}};
|
||||
}
|
||||
|
||||
/* Note: this does not clamp for over/underflow cases */
|
||||
static inline com_pnt_t com_pnt_div(com_pnt_t a, com_pnt_t b) {
|
||||
return (com_pnt_t){
|
||||
.s = {.x = com_fix_div(a.s.x, b.s.x), .y = com_fix_div(a.s.y, b.s.y)}};
|
||||
.a = {com_fix_div(a.a[0], b.a[0]), com_fix_div(a.a[1], b.a[1])}};
|
||||
}
|
||||
|
||||
/* Scale pnttor by a fixed point number */
|
||||
static inline com_pnt_t com_pnt_scl(com_pnt_t a, com_fix_t b) {
|
||||
return (com_pnt_t){
|
||||
.s = {.x = com_fix_mul(a.s.x, b), .y = com_fix_mul(a.s.y, b)}};
|
||||
return (com_pnt_t){.a = {com_fix_mul(a.a[0], b), com_fix_mul(a.a[1], b)}};
|
||||
}
|
||||
|
||||
static inline com_fix_t com_pnt_min(com_pnt_t a) {
|
||||
@@ -75,17 +70,17 @@ static inline com_fix_t com_pnt_max(com_pnt_t a) {
|
||||
This also produces area of a triangle! */
|
||||
static inline com_fix_t com_pnt_edge_orient(com_pnt_t l0, com_pnt_t l1,
|
||||
com_pnt_t p) {
|
||||
return (l0.s.x - l1.s.x) * (p.s.y - l1.s.y) -
|
||||
(l0.s.y - l1.s.y) * (p.s.x - l1.s.x);
|
||||
return (l0.a[0] - l1.a[0]) * (p.a[1] - l1.a[1]) -
|
||||
(l0.a[1] - l1.a[1]) * (p.a[0] - l1.a[0]);
|
||||
}
|
||||
|
||||
#define com_pnt_area(m_p0, m_p1, m_p2) (com_pnt_edge_orient(m_p0, m_p1, m_p2))
|
||||
|
||||
static inline com_vec_t com_pnt_edge_weight(com_pnt_t v0, com_pnt_t v1,
|
||||
com_pnt_t v2, com_pnt_t p) {
|
||||
return (com_vec_t){.s = {.x = com_pnt_edge_orient(v1, v2, p),
|
||||
.y = com_pnt_edge_orient(v2, v0, p),
|
||||
.z = com_pnt_edge_orient(v0, v1, p)}};
|
||||
return (com_vec_t){.a = {com_pnt_edge_orient(v1, v2, p),
|
||||
com_pnt_edge_orient(v2, v0, p),
|
||||
com_pnt_edge_orient(v0, v1, p)}};
|
||||
}
|
||||
|
||||
static inline void com_pnt_print(com_pnt_t a) {
|
||||
|
||||
+19
-3
@@ -1,4 +1,20 @@
|
||||
/*
|
||||
Minimal subset of stdlib, none of which have to be actually implemented,
|
||||
even memory mnagement.
|
||||
*/
|
||||
|
||||
/* TODO: Actually implement. */
|
||||
#define realloc(m_p, m_b) (NULL)
|
||||
#define free(m_p) ((void)0)
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern void *com_std_realloc(void *ptr, size_t size);
|
||||
extern void com_std_free(void *ptr);
|
||||
|
||||
/* Note: Functions listed below are only available for test builds. */
|
||||
/* Trigonometry functions are for reference testing of our own fixed point
|
||||
* implementations. Do not use otherwise. */
|
||||
extern void com_std_assert(bool holds);
|
||||
extern void com_std_printf(char const *fmt, ...);
|
||||
extern double com_std_sqrt(double v);
|
||||
extern double com_std_fabs(double v);
|
||||
extern double com_std_sin(double v);
|
||||
extern double com_std_cos(double v);
|
||||
|
||||
+29
-37
@@ -11,79 +11,72 @@
|
||||
#include "fix.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union {
|
||||
typedef struct {
|
||||
com_def_alignedas(16) com_def_vector(com_fix_t, a, 3);
|
||||
com_def_alignedas(16) struct {
|
||||
com_fix_t x;
|
||||
com_fix_t y;
|
||||
com_fix_t z;
|
||||
} s;
|
||||
} com_vec_t;
|
||||
|
||||
static inline com_vec_t com_vec_from(com_fix_t x, com_fix_t y, com_fix_t z) {
|
||||
return (com_vec_t){.s = {.x = x, .y = y, .z = z}};
|
||||
return (com_vec_t){.a = {x, y, z}};
|
||||
}
|
||||
|
||||
static inline com_vec_t com_vec_scalar(com_fix_t s) {
|
||||
return (com_vec_t){.s = {.x = s, .y = s, .z = s}};
|
||||
return (com_vec_t){.a = {s, s, s}};
|
||||
}
|
||||
|
||||
static inline com_vec_t com_vec_identity(void) {
|
||||
return (com_vec_t){.s = {.x = COM_FIX_FRACUNIT,
|
||||
.y = COM_FIX_FRACUNIT,
|
||||
.z = COM_FIX_FRACUNIT}};
|
||||
return (com_vec_t){
|
||||
.a = {COM_FIX_FRACUNIT, COM_FIX_FRACUNIT, COM_FIX_FRACUNIT}};
|
||||
}
|
||||
|
||||
static inline com_vec_t com_vec_add(com_vec_t a, com_vec_t b) {
|
||||
return (com_vec_t){.s = {.x = com_fix_add(a.s.x, b.s.x),
|
||||
.y = com_fix_add(a.s.y, b.s.y),
|
||||
.z = com_fix_add(a.s.z, b.s.z)}};
|
||||
return (com_vec_t){.a = {com_fix_add(a.a[0], b.a[0]),
|
||||
com_fix_add(a.a[1], b.a[1]),
|
||||
com_fix_add(a.a[2], b.a[2])}};
|
||||
}
|
||||
|
||||
static inline com_vec_t com_vec_sub(com_vec_t a, com_vec_t b) {
|
||||
return (com_vec_t){.s = {.x = com_fix_sub(a.s.x, b.s.x),
|
||||
.y = com_fix_sub(a.s.y, b.s.y),
|
||||
.z = com_fix_sub(a.s.z, b.s.z)}};
|
||||
return (com_vec_t){.a = {com_fix_sub(a.a[0], b.a[0]),
|
||||
com_fix_sub(a.a[1], b.a[1]),
|
||||
com_fix_sub(a.a[2], b.a[2])}};
|
||||
}
|
||||
|
||||
static inline com_vec_t com_vec_mul(com_vec_t a, com_vec_t b) {
|
||||
return (com_vec_t){.s = {.x = com_fix_mul(a.s.x, b.s.x),
|
||||
.y = com_fix_mul(a.s.y, b.s.y),
|
||||
.z = com_fix_mul(a.s.z, b.s.z)}};
|
||||
return (com_vec_t){.a = {com_fix_mul(a.a[0], b.a[0]),
|
||||
com_fix_mul(a.a[1], b.a[1]),
|
||||
com_fix_mul(a.a[2], b.a[2])}};
|
||||
}
|
||||
|
||||
/* Note: this does not clamp for over/underflow cases */
|
||||
static inline com_vec_t com_vec_div(com_vec_t a, com_vec_t b) {
|
||||
return (com_vec_t){.s = {.x = com_fix_div(a.s.x, b.s.x),
|
||||
.y = com_fix_div(a.s.y, b.s.y),
|
||||
.z = com_fix_div(a.s.z, b.s.z)}};
|
||||
return (com_vec_t){.a = {com_fix_div(a.a[0], b.a[0]),
|
||||
com_fix_div(a.a[1], b.a[1]),
|
||||
com_fix_div(a.a[2], b.a[2])}};
|
||||
}
|
||||
|
||||
/* Scale vector by a fixed point number */
|
||||
static inline com_vec_t com_vec_scl(com_vec_t a, com_fix_t b) {
|
||||
return (com_vec_t){.s = {.x = com_fix_mul(a.s.x, b),
|
||||
.y = com_fix_mul(a.s.y, b),
|
||||
.z = com_fix_mul(a.s.z, b)}};
|
||||
return (com_vec_t){.a = {com_fix_mul(a.a[0], b), com_fix_mul(a.a[1], b),
|
||||
com_fix_mul(a.a[2], b)}};
|
||||
}
|
||||
|
||||
/* Shows how much given vectors are correlated in direction to each other */
|
||||
/* Resulted range depends on input, it's in -1 to 1 for normalized
|
||||
* input and otherwise is -ab to +ab */
|
||||
static inline com_fix_t com_vec_dot(com_vec_t a, com_vec_t b) {
|
||||
return (((int64_t)a.s.x * b.s.x) + ((int64_t)a.s.y * b.s.y) +
|
||||
((int64_t)a.s.z * b.s.z)) >>
|
||||
return (((int64_t)a.a[0] * b.a[0]) + ((int64_t)a.a[1] * b.a[1]) +
|
||||
((int64_t)a.a[2] * b.a[2])) >>
|
||||
COM_FIX_FRACBITS;
|
||||
}
|
||||
|
||||
/* Cross product produces a perpendicular for normalized vectors, or 0 for
|
||||
* parallel vectors */
|
||||
static inline com_vec_t com_vec_crs(com_vec_t a, com_vec_t b) {
|
||||
int64_t const cx = ((int64_t)a.s.y * b.s.z) - ((int64_t)a.s.z - b.s.y);
|
||||
int64_t const cy = ((int64_t)a.s.z * b.s.x) - ((int64_t)a.s.x - b.s.z);
|
||||
int64_t const cz = ((int64_t)a.s.x * b.s.y) - ((int64_t)a.s.y - b.s.x);
|
||||
return (com_vec_t){.s = {.x = (com_fix_t)(cx >> COM_FIX_FRACBITS),
|
||||
.y = (com_fix_t)(cy >> COM_FIX_FRACBITS),
|
||||
.z = (com_fix_t)(cz >> COM_FIX_FRACBITS)}};
|
||||
int64_t const cx = ((int64_t)a.a[1] * b.a[2]) - ((int64_t)a.a[2] - b.a[1]);
|
||||
int64_t const cy = ((int64_t)a.a[2] * b.a[0]) - ((int64_t)a.a[0] - b.a[2]);
|
||||
int64_t const cz = ((int64_t)a.a[0] * b.a[1]) - ((int64_t)a.a[1] - b.a[0]);
|
||||
return (com_vec_t){.a = {(com_fix_t)(cx >> COM_FIX_FRACBITS),
|
||||
(com_fix_t)(cy >> COM_FIX_FRACBITS),
|
||||
(com_fix_t)(cz >> COM_FIX_FRACBITS)}};
|
||||
}
|
||||
|
||||
/* Normalize vector, making it a unit one (of length 1). */
|
||||
@@ -91,9 +84,8 @@ static inline com_vec_t com_vec_crs(com_vec_t a, com_vec_t b) {
|
||||
static inline com_vec_t com_vec_nrm(com_vec_t a) {
|
||||
com_fix_t const n = com_fix_sqrt(com_vec_dot(a, a));
|
||||
// return com_vec_scl(a, com_fix_div(COM_FIX_FRACUNIT, n));
|
||||
return (com_vec_t){.s = {.x = com_fix_div(a.s.x, n),
|
||||
.y = com_fix_div(a.s.y, n),
|
||||
.z = com_fix_div(a.s.z, n)}};
|
||||
return (com_vec_t){.a = {com_fix_div(a.a[0], n), com_fix_div(a.a[1], n),
|
||||
com_fix_div(a.a[2], n)}};
|
||||
}
|
||||
|
||||
static inline com_fix_t com_vec_min(com_vec_t a) {
|
||||
|
||||
Reference in New Issue
Block a user