Author:ptrace
Comitter:ptrace
Date:2026-08-24 15:26:29 UTC
diff --git a/0x2_Math.jai b/0x2_Math.jai
index 7469a26..5b4c2c8 100644
--- a/0x2_Math.jai
+++ b/0x2_Math.jai
@@ -1,6 +1,25 @@
// TODO: Need module param for cringe xyz ordering
Rect_Origin :: enum_flags {
NONE;
/** XY */
MID;
/** X */
LEFT;
RIGHT;
/** Y */
TOP;
BOTTOM;
}
roundf :: inline (x: float) -> float {
return floor(x + 0.5);
}
@@ -9,11 +28,65 @@ round :: inline (x: float) -> int {
return xx floor(x + 0.5);
}
/** Assumes:
x = LEFT to RIGHT
y = TOP to BOTTOM
*/
rect_scale :: (rect: *$T/interface Rectangle, scale: Vector2, origin: Rect_Origin = .NONE) {
rect.* = rect_scale(rect.*, scale, origin);
}
/** Assumes:
x = LEFT to RIGHT
y = TOP to BOTTOM
*/
rect_scale :: (rect: $T/interface Rectangle, scale: Vector2, origin: Rect_Origin = .NONE) -> T {
using new: T;
if !origin || origin == .NONE then origin = .MID;
if origin & .LEFT {
width = rect.width * scale.x;
x = rect.x;
}
else if origin & .RIGHT {
width = rect.width * scale.x;
x = (rect.x + rect.width) - width;
}
else if origin & .MID {
width = rect.width * scale.x;
x = (rect.x + rect.width / 2.0) - width / 2.0;
}
if origin & .TOP {
height = rect.height * scale.y;
y = rect.y;
}
else if origin & .BOTTOM {
height = rect.height * scale.y;
y = (rect.y + rect.height) - height;
}
else if origin & .MID {
height = rect.height * scale.y;
y = (rect.y + rect.height / 2.0) - height / 2.0;
}
return new;
}
#scope_file
using, only(floor) Math :: #import "Math";
Rectangle :: struct {
x: float; /** top-left corner position x */
y: float; /** top-left corner position y */
width: float;
height: float;
}
using, only(floor, Vector2) Math :: #import "Math";
/*
diff --git a/tests/assertion.jai b/tests/assertion.jai
index b5b32e2..7f3c5de 100644
--- a/tests/assertion.jai
+++ b/tests/assertion.jai
@@ -17,20 +17,20 @@ ass :: (comp: bool, loc := #caller_location) #expand {
}
}
ass :: (a: $T, b: T, loc := #caller_location) #expand {
ass :: (a: $T, b: T, $code := ASS_CODE, loc := #caller_location) #expand {
if a != b {
#insert,scope() ASS_CODE;
#insert,scope() code;
}
}
/** Cannot use `[]$T, []T` here, because Jai cannot resolve the overloads then */
ass :: (a: []int, b: []int, loc := #caller_location) #expand {
ass :: (a: []int, b: []int, $code := ASS_CODE, loc := #caller_location) #expand {
if a.count != b.count {
#insert,scope() ASS_CODE;
#insert,scope() code;
}
for a if it != b[it_index] {
#insert,scope() ASS_CODE;
#insert,scope() code;
}
}
diff --git a/tests/math.jai b/tests/math.jai
new file mode 100644
index 0000000..96b8f57
--- /dev/null
+++ b/tests/math.jai
@@ -0,0 +1,81 @@
ROOT :: Rectangle.{
0.0,
0.0,
100.0,
100.0,
};
TESTS :: Test.[
{ "top left", ROOT, { 2.0, 2.0 }, .TOP | .LEFT, { 0.0, 0.0, 200.0, 200.0 } },
{ "top right", ROOT, { 2.0, 2.0 }, .TOP | .RIGHT, { -100.0, 0.0, 200.0, 200.0 } },
{ "top mid", ROOT, { 2.0, 2.0 }, .TOP | .MID, { -50.0, 0.0, 200.0, 200.0 } },
{ "mid left", ROOT, { 2.0, 2.0 }, .MID | .LEFT, { 0.0, -50.0, 200.0, 200.0 } },
{ "mid right", ROOT, { 2.0, 2.0 }, .MID | .RIGHT, { -100.0, -50.0, 200.0, 200.0 } },
{ "mid (none)", ROOT, { 2.0, 2.0 }, .NONE, { -50.0, -50.0, 200.0, 200.0 } },
{ "mid", ROOT, { 2.0, 2.0 }, .MID, { -50.0, -50.0, 200.0, 200.0 } },
{ "bot left", ROOT, { 2.0, 2.0 }, .BOTTOM | .LEFT, { 0.0, -100.0, 200.0, 200.0 } },
{ "bot right", ROOT, { 2.0, 2.0 }, .BOTTOM | .RIGHT, { -100.0, -100.0, 200.0, 200.0 } },
{ "bot mid", ROOT, { 2.0, 2.0 }, .BOTTOM | .MID, { -50.0, -100.0, 200.0, 200.0 } },
];
MY_ASS_CODE :: #code {
log_error("\n%: Test failed: '%'", loc, `it.label);
log_error("-------------------");
log_error(":Given\n%\n\n", a);
log_error(":Expected\n%\n\n", b);
`return false;
}
Rectangle :: struct {
x: float; /** top-left corner position x */
y: float; /** top-left corner position y */
width: float;
height: float;
}
Test :: struct {
label: string;
root: Rectangle;
scale: Vector2;
origin: Rect_Origin;
expected: Rectangle;
}
operator == :: (a: Rectangle, b: Rectangle) -> bool {
result := true;
result &= a.x == b.x;
result &= a.y == b.y;
result &= a.width == b.width;
result &= a.height == b.height;
return result;
}
run :: () -> bool {
for TESTS {
new := rect_scale(it.root, it.scale, it.origin);
#if false then log_vars(it.label, new);
ass(new, it.expected, MY_ASS_CODE);
}
/** Test with pointer */
root := ROOT;
test :: TESTS[TESTS.count-1];
rect_scale(*root, test.scale, test.origin);
ass(root == test.expected);
return true;
}
#import "Basic";
#import "Print_Vars";
#import "Math";
#import,file "../0x2_Math.jai";
#load "assertion.jai";
diff --git a/tests/run_tests.jai b/tests/run_tests.jai
index 6b55590..1287fab 100644
--- a/tests/run_tests.jai
+++ b/tests/run_tests.jai
@@ -46,6 +46,7 @@ main :: () {
ok &= df.run();
ok &= sp.run();
ok &= lx.run();
ok &= mt.run();
}
log("\n---------------------------------------------------------");
@@ -65,6 +66,7 @@ sp :: #import,file "string.jai";
lx :: #import,file "lexer.jai";
sc :: #import,file "seccomp.jai";
lk :: #import,file "landlock.jai";
mt :: #import,file "math.jai";
#import,file "../0x2_Qtrace.jai";
crash :: #import,file "../0x2_Crashed.jai";