From 18bcbbef8df734e4b8d4a52ece1a123e88a4338e Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 28 Jan 2025 13:35:45 +0100 Subject: [PATCH] fix scroller inf divide, safe ratio, safe cast --- src/core/core.h | 24 ++++++++++++++++++++++++ src/core/core_intrin.c | 24 +++++++++++++++++++++++- src/core/core_math.gen.c | 20 ++++++++++++++++++++ src/core/core_math_gen.py | 15 +++++++++++++++ src/ui/ui.c | 31 ++++++++++++++++++++----------- src/ui/ui_inc.c | 1 - todo.txt | 1 + 7 files changed, 103 insertions(+), 13 deletions(-) diff --git a/src/core/core.h b/src/core/core.h index 98bcc3f..468a269 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -18,6 +18,30 @@ typedef int8_t b8; typedef float f32; typedef double f64; +#define f32_max FLT_MAX +#define f32_min FLT_MIN +#define f64_max DBL_MAX +#define f64_min DBL_MIN + +#define i8_max INT8_MAX +#define i8_min INT8_MIN +#define i16_max INT16_MAX +#define i16_min INT16_MIN +#define i32_max INT32_MAX +#define i32_min INT32_MIN +#define i64_max INT64_MAX +#define i64_min INT64_MIN + +#define u8_max UINT8_MAX +#define u8_min 0 +#define u16_max UINT16_MAX +#define u16_min 0 +#define u32_max UINT32_MAX +#define u32_min 0 +#define u64_max UINT64_MAX +#define u64_min 0 + + #ifndef true #define true 1 #endif diff --git a/src/core/core_intrin.c b/src/core/core_intrin.c index 2e87ab0..5fcc6a4 100644 --- a/src/core/core_intrin.c +++ b/src/core/core_intrin.c @@ -181,7 +181,7 @@ fn f32 f32_pow(f32 x, f32 y) { * is preserved. * ==================================================== **/ -f32 f32_round(f32 x) { +fn f32 f32_round(f32 x) { u32 w = F32_TO_U32(x); /* Most significant word, least significant word. */ int exponent_less_127; @@ -214,3 +214,25 @@ f32 f32_round(f32 x) { x = U32_TO_F32(w); return x; } + +/////////////////////////////// +// other +fn u32 u32_cast(u64 v) { + assert(v <= u32_max); + return (u32)v; +} + +fn u16 u16_cast(u64 v) { + assert(v <= u16_max); + return (u16)v; +} + +fn u8 u8_cast(u64 v) { + assert(v <= u8_max); + return (u8)v; +} + +fn i32 i32_cast(i64 v) { + assert(v >= i32_min && v <= i32_max); + return (i32)v; +} diff --git a/src/core/core_math.gen.c b/src/core/core_math.gen.c index 34edc1d..d697889 100644 --- a/src/core/core_math.gen.c +++ b/src/core/core_math.gen.c @@ -875,3 +875,23 @@ fn_inline r2i64_t r2i64_add_v2i64(r2i64_t a, v2i64_t b) { return (r2i64_t){ v2i6 fn_inline r2i64_t r2i64_sub_v2i64(r2i64_t a, v2i64_t b) { return (r2i64_t){ v2i64_sub(a.min, b), v2i64_sub(a.max, b) }; } fn_inline r2i64_t r2i64_mul_v2i64(r2i64_t a, v2i64_t b) { return (r2i64_t){ v2i64_mul(a.min, b), v2i64_mul(a.max, b) }; } fn_inline r2i64_t r2i64_div_v2i64(r2i64_t a, v2i64_t b) { return (r2i64_t){ v2i64_div(a.min, b), v2i64_div(a.max, b) }; } +fn f32 f32_safe_ratio(f32 a, f32 b, f32 if0) { + f32 result = if0; + if (b != 0.0) { + result = a / b; + } + return result; +} + +fn_inline f32 f32_safe_ratio0(f32 a, f32 b) { return f32_safe_ratio(a, b, 0); } +fn_inline f32 f32_safe_ratio1(f32 a, f32 b) { return f32_safe_ratio(a, b, 0); } +fn f64 f64_safe_ratio(f64 a, f64 b, f64 if0) { + f64 result = if0; + if (b != 0.0) { + result = a / b; + } + return result; +} + +fn_inline f64 f64_safe_ratio0(f64 a, f64 b) { return f64_safe_ratio(a, b, 0); } +fn_inline f64 f64_safe_ratio1(f64 a, f64 b) { return f64_safe_ratio(a, b, 0); } diff --git a/src/core/core_math_gen.py b/src/core/core_math_gen.py index 775f425..98b810a 100644 --- a/src/core/core_math_gen.py +++ b/src/core/core_math_gen.py @@ -374,3 +374,18 @@ fn_inline r2f64_t r2f64_sub_v2f64(r2f64_t a, v2f64_t b) { return (r2f64_t){ v2f6 print(s) +for bt in ["f32", "f64"]: + s = """ +fn f64 f64_safe_ratio(f64 a, f64 b, f64 if0) { + f64 result = if0; + if (b != 0.0) { + result = a / b; + } + return result; +} + +fn_inline f64 f64_safe_ratio0(f64 a, f64 b) { return f64_safe_ratio(a, b, 0); } +fn_inline f64 f64_safe_ratio1(f64 a, f64 b) { return f64_safe_ratio(a, b, 0); } + """.strip() + s = s.replace("f64", bt) + print(s) \ No newline at end of file diff --git a/src/ui/ui.c b/src/ui/ui.c index 9ebd7dd..ce252b9 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -163,11 +163,23 @@ fn r2f32_t ui_next_rect(ui_lop_t op, r2f32_t *rect, v2f32_t required_size) { return (r2f32_t){0}; } -fn void ui_offset_box(ui_box_t *box, v2f32_t offset) { +fn void ui_offset_one_box(ui_box_t *box, v2f32_t offset) { box->full_rect = r2f32_sub_v2f32(box->full_rect, offset); box->rect = r2f32_sub_v2f32(box->rect, offset); } +fn void ui_offset_children(ui_box_t *box, v2f32_t offset) { + for (ui_box_t *it = box->first; it; it = it->next) { + ui_offset_one_box(it, offset); + ui_offset_children(it, offset); + } +} + +fn void ui_offset_box(ui_box_t *box, v2f32_t offset) { + ui_offset_one_box(box, offset); + ui_offset_children(box, offset); +} + fn ui_box_t *ui_build_box_from_id(ui_code_loc_t loc, ui_box_flags_t flags, ui_id_t id) { ui_box_t *box = ui_find_box(id); if (box) { @@ -1052,7 +1064,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co ui_signal_t upper_box_signal = ui_signal_from_box(upper_box); ui_signal_t down_box_signal = ui_signal_from_box(down_box); f32 drag = ev->mouse_delta.y; - f32 coef = (all_items_size / item_box_size) / scrollable_space; + f32 coef = f32_safe_ratio0(all_items_size / item_box_size, scrollable_space); if (signal.dragging) { scroller_value += drag * coef; } @@ -1063,6 +1075,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co if (ev->kind == app_event_kind_mouse_wheel) { scroller_value -= ev->mouse_wheel_delta.y; } + scroller_value = CLAMP(scroller_value, 0, all_items_size); } @@ -1090,7 +1103,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co ui_signal_t signal = ui_signal_from_box(slider_box); ui_signal_t right_box_sig = ui_signal_from_box(down_box); - f32 coef = (max_size / scroller_rect_pixels) / scrollable_space; + f32 coef = f32_safe_ratio0(max_size / scroller_rect_pixels, scrollable_space); if (signal.dragging) { bottom_scroller_value += ev->mouse_delta.x * coef; @@ -1106,9 +1119,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co bottom_scroller_value = CLAMP(bottom_scroller_value, 0, max_size); } - for (ui_box_t *it = item_box->first; it; it = it->next) { - ui_offset_box(it, v2f32(bottom_scroller_value, scroller_value)); - } + ui_offset_children(item_box, v2f32(bottom_scroller_value, scroller_value)); } /////////////////////////////// @@ -1289,7 +1300,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co ui_signal_t upper_box_signal = ui_signal_from_box(upper_box); ui_signal_t down_box_signal = ui_signal_from_box(down_box); f32 drag = ev->mouse_delta.y; - f32 coef = (all_items_size / item_box_pixels) / scrollable_space; + f32 coef = f32_safe_ratio0((all_items_size / item_box_pixels), scrollable_space); if (signal.dragging) { right_scroller_value += drag * coef; } @@ -1326,7 +1337,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co ui_signal_t signal = ui_signal_from_box(slider_box); ui_signal_t right_box_sig = ui_signal_from_box(down_box); - f32 coef = (max_size / scroller_rect_pixels) / scrollable_space; + f32 coef = f32_safe_ratio0((max_size / scroller_rect_pixels), scrollable_space); if (signal.dragging) { bottom_scroller_value += ev->mouse_delta.x * coef; @@ -1343,9 +1354,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co } - for (ui_box_t *it = item_box->first; it; it = it->next) { - ui_offset_box(it, v2f32(bottom_scroller_value, right_scroller_value)); - } + ui_offset_children(item_box, v2f32(bottom_scroller_value, right_scroller_value)); } /////////////////////////////// diff --git a/src/ui/ui_inc.c b/src/ui/ui_inc.c index 610a96a..2d5fc93 100644 --- a/src/ui/ui_inc.c +++ b/src/ui/ui_inc.c @@ -1,3 +1,2 @@ -#include "ui_iter.c" #include "ui.gen.c" #include "ui.c" \ No newline at end of file diff --git a/todo.txt b/todo.txt index 6f0c6da..c3aa758 100644 --- a/todo.txt +++ b/todo.txt @@ -56,6 +56,7 @@ [ ] draw image in box ui [ ] core + [x] safe cast [ ] ast [ ] move to core layer at some point as the abstract format for different types of serialization [ ] use bit fields instead of ast_flag