From fa04e5606578786630f4862549b53c79e51bcb3e Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 1 Jan 2026 15:52:25 -0600 Subject: [PATCH] tweak variable precision --- src/base/base.cgh | 24 ++----- src/base/base_math.h | 2 +- src/base/base_string.c | 107 +++++++++++++++---------------- src/base/base_tweak.c | 17 +++-- src/base/base_tweak.h | 15 ++++- src/glyph_cache/glyph_cache.c | 6 +- src/gpu/gpu_dx12/gpu_dx12_core.c | 2 +- src/pp/pp_sim/pp_sim_core.c | 2 +- src/pp/pp_vis/pp_vis_core.c | 9 ++- src/ui/ui_core.c | 2 +- 10 files changed, 88 insertions(+), 98 deletions(-) diff --git a/src/base/base.cgh b/src/base/base.cgh index ad123d0e..bf5ce6f8 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -508,26 +508,12 @@ #define I32Min ((i32)0x80000000) #define I64Min ((i64)0x8000000000000000LL) -//- Float infinity / nan constants +//- Float infinity / nan #if IsLanguageC - Global const u32 _f32_infinity_u32 = 0x7f800000; - Global const f32 *_f32_infinity = (f32 *)&_f32_infinity_u32; - #define F32Infinity (*_f32_infinity) - - Global const u64 _f64_infinity_u64 = 0x7ff0000000000000ULL; - Global const f64 *_f64_infinity = (f64 *)&_f64_infinity_u64; - #define F64Infinity (*_f64_infinity) - - Global const u32 _f32_nan_u32 = 0x7f800001; - Global const f32 *_f32_nan = (f32 *)&_f32_nan_u32; - #define F32Nan (*_f32_nan) - - Global const u64 _f64_nan_u64 = 0x7ff8000000000001; - Global const f64 *_f64_nan = (f64 *)&_f64_nan_u64; - #define F64Nan (*_f64_nan) - - #define IsF32Nan(x) (x != x) - #define IsF64Nan(x) (x != x) + #define Inf INFINITY + #define Nan NAN + #define IsInf(x) isinf(x) + #define IsNan(x) isnan(x) #endif //////////////////////////////////////////////////////////// diff --git a/src/base/base_math.h b/src/base/base_math.h index f93cbc12..598a7860 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -242,7 +242,7 @@ f64 ClampF64(f64 v, f64 min, f64 max); //- Abs #define AbsF32(v) fabsf(v) -#define AbsF64(v) absf(v) +#define AbsF64(v) fabs(v) //////////////////////////////////////////////////////////// //~ Exponential ops diff --git a/src/base/base_string.c b/src/base/base_string.c index d635e5b5..c7268c64 100644 --- a/src/base/base_string.c +++ b/src/base/base_string.c @@ -101,73 +101,63 @@ String StringFromSints(Arena *arena, u64 sints_count, i64 *sints, u64 base, u64 String StringFromFloat(Arena *arena, f64 f, u32 precision) { String result = Zi; - result.text = ArenaNext(arena, u8); - TempArena scratch = BeginScratch(arena); + + if (IsNan(f)) { - if (IsF32Nan(f)) + result = PushString(arena, Lit("NaN")); + } + else if (IsInf(f)) + { + if (f >= 0) { - result.len += PushString(arena, Lit("NaN")).len; - } - else if (f == F64Infinity) - { - result.len += PushString(arena, Lit("inf")).len; - } - else if (f == -F64Infinity) - { - result.len += PushString(arena, Lit("-inf")).len; + result = PushString(arena, Lit("inf")); } else { - if (f < 0) + result = PushString(arena, Lit("-inf")); + } + } + else + { + result.text = ArenaNext(arena, u8); + + i32 sign = (f >= 0) - (f < 0); + u64 part_whole = 0; + u64 part_frac = 0; + if (precision > 0) + { + part_whole = f * sign; + part_frac = RoundF64(((f * sign) - part_whole) * PowU64(10, precision)); + } + else + { + part_whole = RoundF64(f * sign); + } + + + result.len += StringFromSint(arena, (i64)part_whole * sign, 10, 0).len; + if (part_frac != 0) + { + result.len += StringFromChar(arena, '.').len; + i64 frac_start_idx = result.len; + result.len += StringFromUint(arena, part_frac, 10, precision).len; + + // Remove trailing zeroes + for (i64 char_idx = result.len - 1; char_idx > frac_start_idx; --char_idx) { - StringFromChar(arena, '-'); - f = -f; - ++result.len; - } - - // Add one half of next precision level to round up - f += 0.5 / (f64)PowU64(10, (u8)precision); - - f64 part_whole = TruncF64(f); - f64 part_frac = f - part_whole; - - // Print whole part - { - // Build backwards text starting from least significant digit - u8 *backwards_text = ArenaNext(scratch.arena, u8); - u64 backwards_text_len = 0; - do + u8 c = result.text[char_idx]; + if (c == '0') { - u64 digit = RoundF64(ModF64(part_whole, 10.0)); - StringFromChar(scratch.arena, IntChars[digit % 10]); - ++backwards_text_len; - part_whole = TruncF64(part_whole / 10.0); - } while (part_whole > 0); - - // Reverse text into final string - PushStructsNoZero(arena, u8, backwards_text_len); - for (u64 i = backwards_text_len; i-- > 0;) - { - result.text[result.len++] = backwards_text[i]; + result.len -= 1; } - } - - // Print frac part - if (precision > 0) - { - StringFromChar(arena, '.'); - for (u64 i = 0; i < precision; ++i) + else { - part_frac *= 10.0; - u64 digit = (u64)part_frac; - part_frac -= digit; - StringFromChar(arena, IntChars[digit % 10]); + break; } - result.len += (u64)precision + 1; } } } - EndScratch(scratch); + return result; } @@ -299,7 +289,14 @@ f64 FloatFromString(String str) if (ok) { - result = ((f64)whole_part + ((f64)frac_part / PowU64(10, str.len - (frac_start_idx + 1)))) * sign; + if (frac_part != 0) + { + result = ((f64)whole_part + ((f64)frac_part / PowU64(10, str.len - (frac_start_idx + 1)))) * sign; + } + else + { + result = (f64)whole_part * sign; + } } else { diff --git a/src/base/base_tweak.c b/src/base/base_tweak.c index ad66190e..6f4d4aed 100644 --- a/src/base/base_tweak.c +++ b/src/base/base_tweak.c @@ -87,32 +87,31 @@ TweakVarArray GetAllTweakVars(Arena *arena) } //////////////////////////////////////////////////////////// -//~ Tweak var retrieval helpers +//~ Tweak utils -b32 TweakBool(String name, b32 default_value) +b32 TweakBool_(String name, b32 default_value) { b32 result = 0; TempArena scratch = BeginScratchNoConflict(); { TweakDesc desc = Zi; desc.kind = TweakKind_Bool; - String tweak_str = TweakEx(scratch.arena, name, desc, StringFromBool(scratch.arena, default_value), 0); + String default_value_str = StringFromBool(scratch.arena, default_value); + String tweak_str = TweakEx(scratch.arena, name, desc, default_value_str, 0); result = BoolFromString(tweak_str); } EndScratch(scratch); return result; } -f64 TweakFloat(String name, f64 default_value, f64 min, f64 max) +f64 TweakFloat_(String name, f64 default_value, TweakDesc desc) { f64 result = 0; + desc.kind = TweakKind_Float; TempArena scratch = BeginScratchNoConflict(); { - TweakDesc desc = Zi; - desc.kind = TweakKind_Float; - desc.range.min = min; - desc.range.max = max; - String tweak_str = TweakEx(scratch.arena, name, desc, StringFromFloat(scratch.arena, default_value, 6), 0); + String default_value_str = StringFromFloat(scratch.arena, default_value, desc.precision); + String tweak_str = TweakEx(scratch.arena, name, desc, default_value_str, 0); result = FloatFromString(tweak_str); } EndScratch(scratch); diff --git a/src/base/base_tweak.h b/src/base/base_tweak.h index 449b945a..2adaf809 100644 --- a/src/base/base_tweak.h +++ b/src/base/base_tweak.h @@ -11,6 +11,7 @@ Struct(TweakDesc) { TweakKind kind; RngF64 range; + i32 precision; }; Struct(TweakVar) @@ -70,7 +71,15 @@ String TweakEx(Arena *arena, String name, TweakDesc desc, String new_value, b32 TweakVarArray GetAllTweakVars(Arena *arena); //////////////////////////////////////////////////////////// -//~ Tweak var retrieval helpers +//~ Tweak utils -b32 TweakBool(String name, b32 default_value); -f64 TweakFloat(String name, f64 default_value, f64 min, f64 max); +b32 TweakBool_(String name, b32 default_value); +#define TweakBool(_name, _default_value) TweakBool_(Lit(_name), (_default_value)) + +f64 TweakFloat_(String name, f64 default_value, TweakDesc desc); +#define TweakFloat(_name, _default_value, _min, _max, ...) TweakFloat_(Lit(_name), (_default_value), (TweakDesc) { \ + .range.min = (_min), \ + .range.max = (_max), \ + .precision = 6, \ + __VA_ARGS__ \ +}) diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c index dd73d73f..d74ad92f 100644 --- a/src/glyph_cache/glyph_cache.c +++ b/src/glyph_cache/glyph_cache.c @@ -180,15 +180,15 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size GC_RunRect *rect = &result.rects[glyph_idx]; f32 advance = glyph->advance; - if (TweakBool(Lit("Ceil glyph advances"), 0)) + if (TweakBool("Ceil glyph advances", 0)) { advance = CeilF32(advance); } - if (TweakBool(Lit("Floor glyph advances"), 0)) + if (TweakBool("Floor glyph advances", 0)) { advance = FloorF32(advance); } - if (TweakBool(Lit("Round glyph advances"), 1)) + if (TweakBool("Round glyph advances", 1)) { advance = RoundF32(advance); } diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index 7cc80507..26de42a9 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -1351,7 +1351,7 @@ u32 G_PushRef(G_ArenaHandle arena_handle, G_ResourceHandle resource_handle, G_Re if (d3d_desc.AddressU == 0) d3d_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; if (d3d_desc.AddressV == 0) d3d_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; if (d3d_desc.AddressW == 0) d3d_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - if (d3d_desc.MaxLOD >= F32Infinity) + if (d3d_desc.MaxLOD >= Inf) { d3d_desc.MaxLOD = D3D12_FLOAT32_MAX; } diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 4edf5444..f421d4f8 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -154,7 +154,7 @@ S_Shape S_MulXformShape(Xform xf, S_Shape shape) Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir) { Vec2 result = Zi; - f32 max_dot = -F32Infinity; + f32 max_dot = -Inf; for (i32 i = 0; i < shape.points_count; ++i) { Vec2 p = shape.points[i]; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 12523280..61bc3089 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -83,7 +83,7 @@ V_WidgetTheme V_GetWidgetTheme(void) theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf"))); // theme.font_size = 14; - theme.font_size = TweakFloat(Lit("Font size"), 14, 6, 50); + theme.font_size = TweakFloat("Font size", 14, 6, 50, .precision = 0); theme.h1 = 2.00; theme.h2 = 1.50; theme.h3 = 1.17; @@ -93,7 +93,7 @@ V_WidgetTheme V_GetWidgetTheme(void) // theme.rounding = 0; // theme.rounding = 1; - theme.rounding = TweakFloat(Lit("Rounding"), 1, 0, 1); + theme.rounding = TweakFloat("Rounding", 1, 0, 1); theme.text_color = Rgb32(0xffdddee0); theme.text_padding_x = 5; @@ -1292,7 +1292,7 @@ void V_TickForever(WaveLaneCtx *lane) V_Palette *palette = &frame->palette; { - f32 palette_ease = TweakFloat(Lit("Command palette ease"), 30, 1, 100) * frame->dt; + f32 palette_ease = TweakFloat("Command palette ease", 30, 1, 100) * frame->dt; palette->show = LerpF32(palette->show, palette->pref_show, palette_ease); } if (palette->show > 0.001) @@ -1629,8 +1629,7 @@ void V_TickForever(WaveLaneCtx *lane) tweak_float = LerpF64(range_min, range_max, virtual_cursor_ratio); tweak_float = ClampF64(tweak_float, range_min, range_max); - f64 precision = 6; // FIXME: Remove this - new_tweak_str = StringFromFloat(frame->arena, tweak_float, precision); + new_tweak_str = StringFromFloat(frame->arena, tweak_float, tweak_desc.precision); } if (slider_reps.draw.is_hot) { diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 1365517b..e54abdc0 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -1127,7 +1127,7 @@ void UI_EndFrame(UI_Frame *frame) box->solved_scale = MulVec2Vec2(parent->solved_scale, box->solved_scale); } - f32 scale_snap = TweakFloat(Lit("UI scale snap"), 0.0050, 0, 0.01); + f32 scale_snap = TweakFloat("UI scale snap", 0.0050, 0, 0.01); if (AbsF32(1.0 - box->solved_scale.x) < scale_snap) { box->solved_scale.x = 1;