Saving... I was in the process of writing my physics sim when I noticed that Ozon delivered my new headphones. Which would also imply that I am already too late

This commit is contained in:
Андреев Григорий 2026-02-01 03:01:01 +03:00
parent 7277f606f4
commit 0c41f3dd3e
12 changed files with 294 additions and 92 deletions

View File

@ -14,6 +14,7 @@
#include "margaret/png_pixel_masses.h"
#include "lucy.h"
#include "alice.h"
#include "precise_integers.h"
int main() {
mkdir_nofail("l1");
@ -31,6 +32,7 @@ int main() {
generate_margaret_png_pixel_masses_header();
generate_l1_lucy_headers();
generate_code_for_alice_on_l1();
generate_l1_header_for_precise_integers();
finish_layer(cstr("l1"));
return 0;
}

View File

@ -2,6 +2,8 @@
#include "../codegen/codegen.h"
// todo: rewrite all of this
SpanU8 vec_field_name(int ci) {
assert(0 <= ci && ci < 4);
return ci == 0 ? cstr("x") : (ci == 1 ? cstr("y") : (ci == 2 ? cstr("z") : cstr("w")));
@ -312,34 +314,93 @@ NODISCARD VecU8 generate_xmatnm_transpose_method(SpanU8 xmat, SpanU8 xvec, SpanU
return res;
}
NODISCARD VecU8 generate_square_xmatn_methods(SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int n) {
VecU8 g_xmatn = codegen_name_xmatnm(xmat, n, n);
SpanU8 xmatn = VecU8_to_span(&g_xmatn);
NODISCARD VecU8 generate_xmat234_det_method(SpanU8 xmat, SpanU8 xvec, SpanU8 memb){
VecU8 res = VecU8_new();
VecU8_append_vec(&res, VecU8_fmt(
"%s %s2_det(%s2 a){\n"
SPACE "return a.x.x * a.y.y - a.x.y * a.y.x;\n"
"}\n\n", memb, xmat, xmat));
VecU8_append_vec(&res, VecU8_fmt(
"%s %s3_det(%s3 a){\n"
SPACE "return", memb, xmat, xmat));
for (int i = 0; i < 3; i++) {
if (i)
VecU8_append_span(&res, cstr("\n" SPACE SPACE));
for (int j = 0; j < 3; j++) {
if (j == i)
continue;
int k = 3 - i - j;
assert(k != i && k != j);
bool minused = ((i > j) + (j > k) + (i > k)) % 2;
VecU8_append_vec(&res, VecU8_fmt(" %c a.x.%s * a.y.%s * a.z.%s",
minused ? '-' : '+', vec_field_name(i), vec_field_name(j), vec_field_name(k)));
}
}
VecU8_append_span(&res, cstr(";\n}\n\n"));
VecU8_append_vec(&res, VecU8_fmt(
"%s %s4_det(%s4 a){\n"
SPACE "return", memb, xmat, xmat));
for (int i = 0; i < 4; i++) {
if (i)
VecU8_append_span(&res, cstr("\n" SPACE SPACE));
for (int j = 0; j < 4; j++) {
if (j == i)
continue;
for (int k = 0; k < 4; k++) {
if (i == k || j == k)
continue;
int u = 6 - i - j - k;
assert(u != i && u != j && u != k);
bool minused = ((i > j) + (j > k) + (i > k) + (i > u) + (j > u) + (k > u)) % 2;
VecU8_append_vec(&res, VecU8_fmt(" %c a.x.%s * a.y.%s * a.z.%s * a.w.%s",
minused ? '-' : '+', vec_field_name(i), vec_field_name(j), vec_field_name(k), vec_field_name(u)));
}
}
}
VecU8_append_span(&res, cstr(";\n}\n\n"));
return res;
}
void codegen_append_square_xmatn_methods(VecU8* res, SpanU8 xmat, SpanU8 xvec, SpanU8 memb, int n) {
VecU8 g_xmatn = codegen_name_xmatnm(xmat, n, n);
SpanU8 xmatn = VecU8_to_span(&g_xmatn);
VecU8 g_xvecn = codegen_name_xvecn(xvec, n);
SpanU8 xvecn = VecU8_to_span(&g_xvecn);
VecU8_append_vec(res, VecU8_fmt(
"const %s %s_E = { ", xmatn, xmatn));
for (int x = 0; x < n; x++) {
if (x)
VecU8_append_span(&res, cstr(", "));
VecU8_append_vec(&res, VecU8_fmt(".%s = {", vec_field_name(x)));
VecU8_append_span(res, cstr(", "));
VecU8_append_vec(res, VecU8_fmt(".%s = {", vec_field_name(x)));
for (int y = 0; y < n; y++) {
if (y)
VecU8_append_span(&res, cstr(", "));
VecU8_append(&res, '0' + (x == y));
VecU8_append_span(res, cstr(", "));
VecU8_append(res, '0' + (x == y));
}
VecU8_append_span(&res, cstr(" }"));
VecU8_append_span(res, cstr(" }"));
}
VecU8_append_span(&res, cstr(" };\n\n"));
// VecU8_append_vec(&res, VecU8_fmt(
// "%s %s_det(%s a){\n"
// SPACE "return ", memb, xmatn, xmatn));
//
// VecU8_append_span(&res, cstr(";\n}\n\n"));
VecU8_append_span(res, cstr(" };\n\n"));
VecU8_append_vec(res, VecU8_fmt(
"%s %s_new_for_proj(%s v){\n" /* xmatn, xmatn, xvecn */
SPACE "return (%s){ ", /* xmatn */
xmatn, xmatn, xvecn, xmatn));
for (int x = 0; x < n; x++) {
VecU8_append_span(res, cstr("\n" SPACE SPACE));
VecU8_append_vec(res, VecU8_fmt(".%s={", vec_field_name(x)));
for (int y = 0; y < n; y++) {
if (y)
VecU8_append_span(res, cstr(", "));
VecU8_append_vec(res, VecU8_fmt("v.%s * v.%s", vec_field_name(x), vec_field_name(y)));
}
VecU8_append_span(res, cstr("},"));
}
VecU8_append_span(res, cstr("};\n}\n\n"));
VecU8_drop(g_xmatn);
return res;
VecU8_drop(g_xvecn);
}
NODISCARD VecU8 generate_xmat_inverse_methods(SpanU8 xmat, SpanU8 xvec, SpanU8 memb){
@ -485,7 +546,7 @@ NODISCARD VecU8 generate_xmat234x234_structs_and_base_methods(SpanU8 xmat, SpanU
}
}
for (int n = 2; n <= 4; n++) {
VecU8_append_vec(&res, generate_square_xmatn_methods(xmat, xvec, memb, n));
codegen_append_square_xmatn_methods(&res, xmat, xvec, memb, n);
}
for (int n = 2; n <= 4; n++) {
for (int m = 2; m <= 4; m++) {
@ -494,6 +555,7 @@ NODISCARD VecU8 generate_xmat234x234_structs_and_base_methods(SpanU8 xmat, SpanU
}
}
}
VecU8_append_vec(&res, generate_xmat234_det_method(xmat, xvec, memb));
return res;
}
@ -520,6 +582,7 @@ void generate_geom_header() {
VecU8_append_vec(&res.result, generate_xvec234_structs_and_cool_methods(cstr("vec"), cstr("float"), cstr("sqrtf")));
VecU8_append_vec(&res.result, generate_xvec234_structs_and_cool_methods(cstr("dvec"), cstr("double"), cstr("sqrt")));
// todo: remove padding from matrix structure. VERY IMPORTANT!!! Add padding on the fly when transferring to vulkan
VecU8_append_vec(&res.result, generate_xmat234x234_structs_and_cool_methods(cstr("mat"), cstr("vec"), cstr("float"), sizeof(float)));
VecU8_append_vec(&res.result, generate_xmat234x234_structs_and_base_methods(cstr("s64mat"), cstr("s64vec"), cstr("S64"), sizeof(S64)));

View File

@ -0,0 +1,20 @@
#pragma once
// todo: write something here after I close КТ-1
#include "../codegen/codegen.h"
void generate_precise_addition_func(VecU8* res, U64 liA, U64 liB){
assert(liA < 1000 && liB < 1000);
assert(liA >= liB);
VecU8_append_vec(res, VecU8_fmt(
"void S%u_add_S%u(S%u* a, S%u b){\n", liA * 64, liB * 64, liA * 64, liB * 64));
// for (size_t i = 10; )
VecU8_append_span(res, cstr("}\n\n"));
}
void generate_l1_header_for_precise_integers(){
GeneratedHeader h = begin_header(cstr("l1/precise_integers.h"));
VecU8_append_span(&h.result, cstr("#include \"../../src/l1/core/int_primitives.h\"\n"));
finish_header(h);
}

View File

@ -40,6 +40,7 @@ void VecU8_print(VecU8 self){
VecU8_drop(self);
}
/* Wrapper around vsnprintf */
NODISCARD VecU8 VecU8_format(const char *fmt, ...) {
assert(fmt);
@ -152,17 +153,10 @@ VecU8 U64_stringification(U64 x){
return res;
}
/* %s - SpanU8
* %v - VecU8
* %u - U64
* %c - int (one byte character)
* %i - S64
*/
NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
assert(fmt);
NODISCARD VecU8 VecU8_fmt_va_list(const char* fmt, va_list args){
size_t k = 0;
va_list args;
va_start(args, fmt);
va_list repeat;
va_copy(repeat, args);
for (const char *ch = fmt; *ch; ) {
if (*ch == '%') {
ch++;
@ -175,7 +169,7 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
va_arg(args, int);
k++;
} else if (*ch == 'v') {
/* We had not taken ownership of YET (will take it the next iteration) */
/* We had not taken ownership of it YET (will take it the next iteration) */
VecU8 vs = va_arg(args, VecU8);
k += vs.len;
} else if (*ch == 'i') {
@ -184,6 +178,9 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
} else if (*ch == 'u') {
U64 x = va_arg(args, U64);
k += U64_stringification_get_length(x);
} else if (*ch == 'r') {
VecU8 vs = va_arg(args, VecU8);
k += vs.len;
} else
abortf("Format syntax error at pos %lu! Watch out, be careful", (size_t)(ch - fmt));
} else {
@ -191,29 +188,31 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
}
ch++;
}
va_end(args);
VecU8 res = VecU8_new_reserved(k);
va_start(args, fmt);
for (const char *ch = fmt; *ch;) {
if (*ch == '%') {
ch++;
if (*ch == '%') {
VecU8_append(&res, '%');
} else if (*ch == 's') {
SpanU8 s = va_arg(args, SpanU8);
SpanU8 s = va_arg(repeat, SpanU8);
VecU8_append_span(&res, s);
} else if (*ch == 'c') {
int byte = va_arg(args, int);
int byte = va_arg(repeat, int);
VecU8_append(&res, (U8)byte);
} else if (*ch == 'v') {
VecU8 vs = va_arg(args, VecU8);
VecU8 vs = va_arg(repeat, VecU8);
VecU8_append_vec(&res, vs); /* Moved ownership of vs argument */
} else if (*ch == 'i') {
S64 x = va_arg(args, S64);
S64 x = va_arg(repeat, S64);
S64_stringification_into_buf(x, &res);
} else if (*ch == 'u') {
U64 x = va_arg(args, U64);
U64 x = va_arg(repeat, U64);
U64_stringification_into_buf(x, &res);
} else if (*ch == 'r') {
VecU8 vs = va_arg(repeat, VecU8);
VecU8_append_span(&res, VecU8_to_span(&vs));
/* But we won't deallocate `vs` because never took ownership of it */
} else
assert(false);
} else {
@ -221,10 +220,40 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
}
ch++;
}
va_end(repeat);
return res;
}
/* %s - SpanU8
* %v - VecU8
* %u - U64
* %c - int (one byte character)
* %i - S64
* %r - VecU8 (but taken by reference, it won't be deallocated)
* Yes, I am breaking the dumb ownership-syntax-crutch convention I set up myself
*/
NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
assert(fmt);
va_list args;
va_start(args, fmt);
VecU8 res = VecU8_fmt_va_list(fmt, args);
va_end(args);
return res;
}
void VecU8_append_cstr(VecU8* res, const char* lit){
VecU8_append_span(res, SpanU8_from_cstr(lit));
}
// todo: add VecX_resize method. I really REALLY need to refactor this awful code
void VecU8_append_fmt(VecU8* res, const char* fmt, ...){
va_list args;
va_start(args, fmt);
VecU8 t = VecU8_fmt_va_list(fmt, args);
VecU8_append_vec(res, t);
va_end(args);
}
// todo: generate a special span method to check equality of contents
bool SpanU8_cont_equal(SpanU8 a, SpanU8 b) {
if (a.len != b.len)

View File

@ -36,60 +36,6 @@ bool marie_same_dir3(float A0, float A1, float A2, float B) {
return A0 == 0 || A1 == 0 || A2 == 0 || (diff & 0x80000000u) == 0;
}
// This function uses floating point arithmetic, which is very bad
/* cross product (vi - u) x (vj - u). If {vi, vj, vu} are points of CCW triangle, this will be it's positive surface */
float marie_surface(vec2 vi, vec2 vj, vec2 u) {
return u.x * (vi.y - vj.y) + u.y * (vj.x - vi.x) + (vi.x * vj.y - vj.x * vi.y);
}
typedef vec4 MarieVertAttr;
typedef struct {
vec2 pos;
MarieVertAttr attr;
} MariePlaneVertAttr;
typedef struct {
vec2 v0;
vec2 v1;
vec2 v2;
} MarieTriangle;
MarieTriangle MarieTriangle_mat3x2_mul_pos(MarieTriangle self, mat3x2 trop) {
return (MarieTriangle){
.v0 = mat3x2_mul_vec3(trop, vec2_and_one(self.v0)),
.v1 = mat3x2_mul_vec3(trop, vec2_and_one(self.v1)),
.v2 = mat3x2_mul_vec3(trop, vec2_and_one(self.v2))};
}
#include "../../../gen/l1/eve/marie/VecMarieTriangle.h"
typedef struct {
MariePlaneVertAttr v0;
MariePlaneVertAttr v1;
MariePlaneVertAttr v2;
} MarieTriangleAttr;
MarieTriangleAttr MarieTriangle_goto_nat_cords_pres_par(MarieTriangle self, mat3x2 trop) {
return (MarieTriangleAttr){
{mat3x2_mul_vec3(trop, vec2_and_one(self.v0)), {self.v0.x, self.v0.y, 0, 0}},
{mat3x2_mul_vec3(trop, vec2_and_one(self.v1)), {self.v1.x, self.v1.y, 0, 0}},
{mat3x2_mul_vec3(trop, vec2_and_one(self.v2)), {self.v2.x, self.v2.y, 0, 0}},
};
}
#include "../../../gen/l1/eve/marie/VecMarieTriangleAttr.h"
vec2 marie_intersect_lines(vec2 A1, vec2 B1, vec2 A2, vec2 B2) {
vec2 alpha = vec2_minus_vec2(B1, A1);
vec2 beta = vec2_minus_vec2(A2, B2);
vec2 gamma = vec2_minus_vec2(A2, A1);
float det_alpha_beta = alpha.x * beta.y - alpha.y * beta.x;
float det_gamma_beta = gamma.x * beta.y - gamma.y * beta.x;
float t1 = det_gamma_beta / det_alpha_beta;
return vec2_add_vec2(A1, vec2_mul_scal(alpha, t1));
}
float marie_clamp_float(float a, float l, float r) {
return (a < l) ? l : ((a <= r) ? a : r);
}

View File

@ -1,4 +1,59 @@
#pragma once
#include "../../../gen/l1/geom.h"
#include "../marie/geom_util.h"
#include "math.h"
typedef vec4 quaternion_t;
vec4 quaternion_fl_mul_vec4(vec4 A, vec4 B){
return (vec4){
A.x * B.x - A.y * B.y - A.z * B.z - A.w * B.w,
A.x * B.y + A.y * B.x + A.z * B.w - A.w * B.z,
A.x * B.z - A.y * B.w + A.z * B.x + A.w * B.y,
A.x * B.w + A.y * B.z - A.z * B.y + A.w * B.x,
};
}
/* Assumes abs(a) is 1 */
vec4 unit_quaternion_fl_inverse(vec4 a){
return (vec4){a.x, -a.y, -a.z, -a.w};
}
vec4 quaternion_fl_inverse(vec4 a){
float m = vec4_length(a);
m = 1 / (m * m);
return (vec4){a.x * m, -a.y * m, -a.z * m, -a.w * m};
}
mat3 quaternion_fl_to_rot3d_mat3(vec4 q){
float a = q.x;
float Rx = q.y;
float Ry = q.z;
float Rz = q.w;
return mat3_add_mat3(mat3_add_mat3(
mat3_mul_scal(mat3_E, 2*a*a - 1),
mat3_mul_scal(mat3_for_cross_product((vec3){Rx, Ry, Rz}), 2 * a)), mat3_E);
}
/* This thing requires some MATH */
vec4 unit_quaternion_fl_power(vec4 q, float t){
float qva = vec3_length((vec3){q.y, q.z, q.w});
float fi = atan2f(qva, q.x);
const float rub = 0.001f;
float e_x = cosf(t * fi);
float e_vc;
// float t_to_3 = t*t*t;
// float t_to_5 = t_to_3*t*t;
// float fi_to_2 = fi * fi;
// float fi_to_4 = fi_to_2 * fi_to_2;
// Remember, qva = sin(fi)
if (qva < rub) {
/* I have a feeling this is an overkill... Well, only time __and 100 hours of testing__ will show ;) */
// e_vc = t + (-t_to_3+t) / 6 * fi_to_2 + (3 * t_to_5 - 10 * t_to_3 + 7 * t) / 360 * fi_to_4;
e_vc = t + (-t*t*t+t) / 6 * fi * fi ;
} else {
e_vc = sinf(t *fi) / qva;
}
return (vec4){e_x, e_vc * q.y, e_vc * q.z, e_vc * q.w};
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "../../../gen/l1/geom.h"
mat3 mat3_for_cross_product(vec3 r){
return (mat3){.x = {0, -r.z, r.y}, .y = {r.z, 0, -r.x}, .z = {-r.y, r.x, 0}};
}

View File

@ -2,6 +2,46 @@
#include "../../../gen/l1/geom.h"
/* cross product (vi - u) x (vj - u). If {vi, vj, vu} are points of CCW triangle, this will be it's positive surface */
float marie_surface(vec2 vi, vec2 vj, vec2 u) {
return u.x * (vi.y - vj.y) + u.y * (vj.x - vi.x) + (vi.x * vj.y - vj.x * vi.y);
}
/* 2 lines on a plane (of float type). Assumes lines are intersecting */
vec2 marie_intersect_lines(vec2 A1, vec2 B1, vec2 A2, vec2 B2) {
vec2 alpha = vec2_minus_vec2(B1, A1);
vec2 beta = vec2_minus_vec2(A2, B2);
vec2 gamma = vec2_minus_vec2(A2, A1);
float det_alpha_beta = alpha.x * beta.y - alpha.y * beta.x;
float det_gamma_beta = gamma.x * beta.y - gamma.y * beta.x;
float t1 = det_gamma_beta / det_alpha_beta;
return vec2_add_vec2(A1, vec2_mul_scal(alpha, t1));
}
/* Triangle (ABC) and a ray (from origin P to point Q) in 3d space (of float type). Returns bool: do they intersect */
bool marie_intersect_triangle_and_ray(vec3 A, vec3 B, vec3 C, vec3 P, vec3 Q, vec3* ret){
vec3 alpha = vec3_minus_vec3(A, C);
vec3 beta = vec3_minus_vec3(B, C);
vec3 gamma = vec3_minus_vec3(P, Q);
vec3 delta = vec3_minus_vec3(P, C);
float det_alpha_beta_gamma = mat3_det((mat3){.x = alpha, .y = beta, .z = gamma});
float det_delta_beta_gamma = mat3_det((mat3){.x = delta, .y = beta, .z = gamma});
float det_alpha_delta_gamma = mat3_det((mat3){.x = alpha, .y = delta, .z = gamma});
float det_alpha_beta_delta = mat3_det((mat3){.x = alpha, .y = beta, .z = delta});
if (det_alpha_beta_gamma < 0.0001)
return false;
float b_0 = det_delta_beta_gamma / det_alpha_beta_gamma;
float b_1 = det_delta_beta_gamma / det_alpha_beta_gamma;
float t = det_delta_beta_gamma / det_alpha_beta_gamma;
if (b_0 < 0 || b_0 > 1 || b_1 < 0 || b_1 > 1 || t < 0)
return false;
*ret = vec3_add_vec3(P, vec3_mul_scal(gamma, -t));
return true;
}
/* any inv exp q => any abs bitness a =>
* vec2#(a)#.(q) -> vec2#(a)#.(q) -> vec2#(a)#.(q) -> vec2#(2a+3)#.(2q) */
S64 marie_precise_surface(s64vec2 vi, s64vec2 vj, s64vec2 u){

View File

@ -1,6 +1,6 @@
#pragma once
#include "../marie/graphics_geom.h"
#include "../../l1_5/marie/graphics_geom.h"
#include "../../../gen/l1/VecAndSpan_U32.h"
#include "../../../gen/l1/VecAndSpan_U8.h"

View File

@ -2,6 +2,46 @@
#include "../../../gen/l1/geom.h"
#include "../../l1/marie/geom_alg_utils.h"
#include "../../l1_5/marie/prim_shape_geom.h"
typedef vec4 MarieVertAttr;
typedef struct {
vec2 pos;
MarieVertAttr attr;
} MariePlaneVertAttr;
typedef struct {
vec2 v0;
vec2 v1;
vec2 v2;
} MarieTriangle;
MarieTriangle MarieTriangle_mat3x2_mul_pos(MarieTriangle self, mat3x2 trop) {
return (MarieTriangle){
.v0 = mat3x2_mul_vec3(trop, vec2_and_one(self.v0)),
.v1 = mat3x2_mul_vec3(trop, vec2_and_one(self.v1)),
.v2 = mat3x2_mul_vec3(trop, vec2_and_one(self.v2))};
}
#include "../../../gen/l1/eve/marie/VecMarieTriangle.h"
typedef struct {
MariePlaneVertAttr v0;
MariePlaneVertAttr v1;
MariePlaneVertAttr v2;
} MarieTriangleAttr;
MarieTriangleAttr MarieTriangle_goto_nat_cords_pres_par(MarieTriangle self, mat3x2 trop) {
return (MarieTriangleAttr){
{mat3x2_mul_vec3(trop, vec2_and_one(self.v0)), {self.v0.x, self.v0.y, 0, 0}},
{mat3x2_mul_vec3(trop, vec2_and_one(self.v1)), {self.v1.x, self.v1.y, 0, 0}},
{mat3x2_mul_vec3(trop, vec2_and_one(self.v2)), {self.v2.x, self.v2.y, 0, 0}},
};
}
#include "../../../gen/l1/eve/marie/VecMarieTriangleAttr.h"
typedef struct {
/* guest, x, y, attribute (custom) */

View File

@ -5,7 +5,7 @@
#include <stdio.h>
#include "../../../l1/system/pthread.h"
#include "../../margaret/time_utils.h"
#include "../../marie/graphics_geom.h"
#include "../../../l1_5/marie/graphics_geom.h"
#include "../../marie/rasterization.h"
#include <fcntl.h>