Add exact arithmetic implementation and tests

- Introduced exact arithmetic with support for large integers and fractions in `exact.gd`, `big_integer.gd`, and `exact_value.gd`.
- Implemented a comprehensive test suite in `test_exact_math.gd` to validate arithmetic operations against expected results.
- Added a README in `math` directory to document the exact arithmetic system and its usage.
- Ensured that all arithmetic operations maintain precision without floating-point errors, using a custom representation for large numbers.
- Included methods for encoding and decoding exact values for serialization.
This commit is contained in:
Kirill
2026-09-30 08:08:27 +03:00
parent f2111a376a
commit fb8a3f5658
58 changed files with 5139 additions and 2162 deletions
+28 -27
View File
@@ -1,4 +1,5 @@
extends SceneTree
const E = preload("res://world/owniverse/math/exact.gd")
var checks: int = 0
var failures: int = 0
@@ -7,9 +8,9 @@ func _initialize() -> void:
call_deferred("run")
func check(value: bool, message: String) -> void:
checks += 1
if not value:
failures += 1
checks = E.add(checks, 1)
if (not value):
failures = E.add(failures, 1)
push_error(message)
func run() -> void:
@@ -21,48 +22,48 @@ func run() -> void:
await process_frame
await process_frame
var world = stage.owniverse
world.state.binds.RD = {"EON1": 10.0, "EON2": 4.0, "C0.0": 3.0}
world.state.amount.EON1 = 2.0
world.state.stats.total_amount.EON1 = 12.0
world.state.stats.total_amount.EON2 = 4.0
world.state.stats.total_amount["C0.0"] = 3.0
world.state.binds.RD = {"EON1": 10, "EON2": 4, "C0.0": 3}
world.state.amount.EON1 = 2
world.state.stats.total_amount.EON1 = 12
world.state.stats.total_amount.EON2 = 4
world.state.stats.total_amount["C0.0"] = 3
var before: Dictionary = world.state.duplicate(true)
stage._refresh_universe_ui()
var counts: Dictionary = world.presentation.amounts(world.state, world.catalog)
check(counts.EON1 == 12.0 and counts.EON2 == 4.0 and counts.LP == 16.0, "Individual eons and their total include bound planets")
check(counts["C0.0"] == 3.0 and counts.C0 == 3.0 and counts.Planet == 19.0, "Civilization detail does not double the planetary total")
check(world.presentation.amounts(world.state, world.catalog, true).EON1 == 12.0 and world.presentation.amounts(world.state, world.catalog, true).LP == 16.0, "Historical counts retain individual and aggregate values")
check(world.state == before, "Presentation does not modify simulation state")
check(((E.eq(counts.EON1, 12) and E.eq(counts.EON2, 4)) and E.eq(counts.LP, 16)), "Individual eons and their total include bound planets")
check(((E.eq(counts["C0.0"], 3) and E.eq(counts.C0, 3)) and E.eq(counts.Planet, 19)), "Civilization detail does not double the planetary total")
check((E.eq(world.presentation.amounts(world.state, world.catalog, true).EON1, 12) and E.eq(world.presentation.amounts(world.state, world.catalog, true).LP, 16)), "Historical counts retain individual and aggregate values")
check(E.eq(world.state, before), "Presentation does not modify simulation state")
var pending: Array = ["EON1", "EON2", "EON3", "C0.0"]
var pending_before: Array = pending.duplicate()
var decision: Dictionary = world.presentation.unlocks(world.state, world.catalog, pending)
check(decision.remaining == ["EON3"], "Only unmet requirements remain pending")
check(E.eq(decision.remaining, ["EON3"]), "Only unmet requirements remain pending")
for id in ["EON1", "EON2", "LP", "C0.0", "C0"]:
check(decision.visible.has(id), "Unlock projection includes detail and alias: " + id)
check(pending == pending_before and world.state == before, "Unlock evaluation leaves inputs untouched")
check(decision.visible.has(id), E.add("Unlock projection includes detail and alias: ", id))
check((E.eq(pending, pending_before) and E.eq(world.state, before)), "Unlock evaluation leaves inputs untouched")
var snapshot: Dictionary = world.presentation.pending_amounts.duplicate()
world.presentation.deferred_updates = true
world.state.amount.EON1 += 1.0
world.state.amount.EON1 = E.add(world.state.amount.EON1, 1)
world.presentation.refresh(world.state, world.catalog)
check(world.presentation.dirty and world.presentation.pending_amounts == snapshot, "Deferred refresh retains pending snapshot")
check((world.presentation.dirty and E.eq(world.presentation.pending_amounts, snapshot)), "Deferred refresh retains pending snapshot")
world.presentation.refresh(world.state, world.catalog, true)
check(not world.presentation.dirty and world.presentation.pending_amounts.EON1 == 13.0, "Forced refresh publishes latest amounts")
world.state.amount.EON1 -= 1.0
check(((not world.presentation.dirty) and E.eq(world.presentation.pending_amounts.EON1, 13)), "Forced refresh publishes latest amounts")
world.state.amount.EON1 = E.subtract(world.state.amount.EON1, 1)
world.presentation.deferred_updates = false
world.presentation.refresh(world.state, world.catalog)
for id in ["EON1", "EON2", "LP", "C0.0", "C0"]:
check(stage.owniverse_items[id].visible, "Unlock both levels: " + id)
check(stage.owniverse_items[id].description.text != "", "Populate the icon counter: " + id)
check(not stage.owniverse_items.EON3.visible, "Unreached eon remains locked")
check(stage.owniverse_items[id].visible, E.add("Unlock both levels: ", id))
check(E.ne(stage.owniverse_items[id].description.text, ""), E.add("Populate the icon counter: ", id))
check((not stage.owniverse_items.EON3.visible), "Unreached eon remains locked")
stage.item_activated(stage.owniverse_items.LP)
check(stage.owniverse_items.EON1.is_visible_in_tree(), "Selecting LP shows its unlocked eons")
stage.item_activated(stage.owniverse_items.C0)
check(stage.owniverse_items["C0.0"].is_visible_in_tree() and not stage.owniverse_items.EON1.is_visible_in_tree(), "Selecting C0 switches the detail panel")
world.state.binds.RD.EON2 = 0.0
check((stage.owniverse_items["C0.0"].is_visible_in_tree() and (not stage.owniverse_items.EON1.is_visible_in_tree())), "Selecting C0 switches the detail panel")
world.state.binds.RD.EON2 = 0
stage._refresh_universe_ui()
check(stage.owniverse_items.EON2.visible and stage.owniverse_items.EON2.description.text == "", "Previously reached stage stays unlocked after extinction with no stale count")
check((stage.owniverse_items.EON2.visible and E.eq(stage.owniverse_items.EON2.description.text, "")), "Previously reached stage stays unlocked after extinction with no stale count")
for entity in world.catalog.entities.values(): entity.free()
world.free()
scene.free()
print("Life icons: %d checks, %d failures" % [checks, failures])
quit(0 if failures == 0 else 1)
print(("Life icons: %d checks, %d failures" % [checks, failures]))
quit((0 if E.eq(failures, 0) else 1))