tweak variable precision

This commit is contained in:
jacob 2026-01-01 15:52:25 -06:00
parent 31b277d8f7
commit fa04e56065
10 changed files with 88 additions and 98 deletions

View File

@ -508,26 +508,12 @@
#define I32Min ((i32)0x80000000) #define I32Min ((i32)0x80000000)
#define I64Min ((i64)0x8000000000000000LL) #define I64Min ((i64)0x8000000000000000LL)
//- Float infinity / nan constants //- Float infinity / nan
#if IsLanguageC #if IsLanguageC
Global const u32 _f32_infinity_u32 = 0x7f800000; #define Inf INFINITY
Global const f32 *_f32_infinity = (f32 *)&_f32_infinity_u32; #define Nan NAN
#define F32Infinity (*_f32_infinity) #define IsInf(x) isinf(x)
#define IsNan(x) isnan(x)
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)
#endif #endif
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -242,7 +242,7 @@ f64 ClampF64(f64 v, f64 min, f64 max);
//- Abs //- Abs
#define AbsF32(v) fabsf(v) #define AbsF32(v) fabsf(v)
#define AbsF64(v) absf(v) #define AbsF64(v) fabs(v)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Exponential ops //~ Exponential ops

View File

@ -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 StringFromFloat(Arena *arena, f64 f, u32 precision)
{ {
String result = Zi; 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; result = PushString(arena, Lit("inf"));
}
else if (f == F64Infinity)
{
result.len += PushString(arena, Lit("inf")).len;
}
else if (f == -F64Infinity)
{
result.len += PushString(arena, Lit("-inf")).len;
} }
else 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, '-'); u8 c = result.text[char_idx];
f = -f; if (c == '0')
++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
{ {
u64 digit = RoundF64(ModF64(part_whole, 10.0)); result.len -= 1;
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];
} }
} else
// Print frac part
if (precision > 0)
{
StringFromChar(arena, '.');
for (u64 i = 0; i < precision; ++i)
{ {
part_frac *= 10.0; break;
u64 digit = (u64)part_frac;
part_frac -= digit;
StringFromChar(arena, IntChars[digit % 10]);
} }
result.len += (u64)precision + 1;
} }
} }
} }
EndScratch(scratch);
return result; return result;
} }
@ -299,7 +289,14 @@ f64 FloatFromString(String str)
if (ok) 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 else
{ {

View File

@ -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; b32 result = 0;
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
{ {
TweakDesc desc = Zi; TweakDesc desc = Zi;
desc.kind = TweakKind_Bool; 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); result = BoolFromString(tweak_str);
} }
EndScratch(scratch); EndScratch(scratch);
return result; 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; f64 result = 0;
desc.kind = TweakKind_Float;
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
{ {
TweakDesc desc = Zi; String default_value_str = StringFromFloat(scratch.arena, default_value, desc.precision);
desc.kind = TweakKind_Float; String tweak_str = TweakEx(scratch.arena, name, desc, default_value_str, 0);
desc.range.min = min;
desc.range.max = max;
String tweak_str = TweakEx(scratch.arena, name, desc, StringFromFloat(scratch.arena, default_value, 6), 0);
result = FloatFromString(tweak_str); result = FloatFromString(tweak_str);
} }
EndScratch(scratch); EndScratch(scratch);

View File

@ -11,6 +11,7 @@ Struct(TweakDesc)
{ {
TweakKind kind; TweakKind kind;
RngF64 range; RngF64 range;
i32 precision;
}; };
Struct(TweakVar) Struct(TweakVar)
@ -70,7 +71,15 @@ String TweakEx(Arena *arena, String name, TweakDesc desc, String new_value, b32
TweakVarArray GetAllTweakVars(Arena *arena); TweakVarArray GetAllTweakVars(Arena *arena);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Tweak var retrieval helpers //~ Tweak utils
b32 TweakBool(String name, b32 default_value); b32 TweakBool_(String name, b32 default_value);
f64 TweakFloat(String name, f64 default_value, f64 min, f64 max); #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__ \
})

View File

@ -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]; GC_RunRect *rect = &result.rects[glyph_idx];
f32 advance = glyph->advance; f32 advance = glyph->advance;
if (TweakBool(Lit("Ceil glyph advances"), 0)) if (TweakBool("Ceil glyph advances", 0))
{ {
advance = CeilF32(advance); advance = CeilF32(advance);
} }
if (TweakBool(Lit("Floor glyph advances"), 0)) if (TweakBool("Floor glyph advances", 0))
{ {
advance = FloorF32(advance); advance = FloorF32(advance);
} }
if (TweakBool(Lit("Round glyph advances"), 1)) if (TweakBool("Round glyph advances", 1))
{ {
advance = RoundF32(advance); advance = RoundF32(advance);
} }

View File

@ -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.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.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.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; d3d_desc.MaxLOD = D3D12_FLOAT32_MAX;
} }

View File

@ -154,7 +154,7 @@ S_Shape S_MulXformShape(Xform xf, S_Shape shape)
Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir) Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir)
{ {
Vec2 result = Zi; Vec2 result = Zi;
f32 max_dot = -F32Infinity; f32 max_dot = -Inf;
for (i32 i = 0; i < shape.points_count; ++i) for (i32 i = 0; i < shape.points_count; ++i)
{ {
Vec2 p = shape.points[i]; Vec2 p = shape.points[i];

View File

@ -83,7 +83,7 @@ V_WidgetTheme V_GetWidgetTheme(void)
theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf"))); theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf")));
// theme.font_size = 14; // 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.h1 = 2.00;
theme.h2 = 1.50; theme.h2 = 1.50;
theme.h3 = 1.17; theme.h3 = 1.17;
@ -93,7 +93,7 @@ V_WidgetTheme V_GetWidgetTheme(void)
// theme.rounding = 0; // theme.rounding = 0;
// theme.rounding = 1; // 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_color = Rgb32(0xffdddee0);
theme.text_padding_x = 5; theme.text_padding_x = 5;
@ -1292,7 +1292,7 @@ void V_TickForever(WaveLaneCtx *lane)
V_Palette *palette = &frame->palette; 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); palette->show = LerpF32(palette->show, palette->pref_show, palette_ease);
} }
if (palette->show > 0.001) 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 = LerpF64(range_min, range_max, virtual_cursor_ratio);
tweak_float = ClampF64(tweak_float, range_min, range_max); tweak_float = ClampF64(tweak_float, range_min, range_max);
f64 precision = 6; // FIXME: Remove this new_tweak_str = StringFromFloat(frame->arena, tweak_float, tweak_desc.precision);
new_tweak_str = StringFromFloat(frame->arena, tweak_float, precision);
} }
if (slider_reps.draw.is_hot) if (slider_reps.draw.is_hot)
{ {

View File

@ -1127,7 +1127,7 @@ void UI_EndFrame(UI_Frame *frame)
box->solved_scale = MulVec2Vec2(parent->solved_scale, box->solved_scale); 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) if (AbsF32(1.0 - box->solved_scale.x) < scale_snap)
{ {
box->solved_scale.x = 1; box->solved_scale.x = 1;