extends SceneTree const E = preload("res://world/owniverse/math/exact.gd") const Q = preload("res://world/owniverse/quantity_math.gd") const Clock = preload("res://world/owniverse/simulation_time.gd") var checks: int = 0 var failures: int = 0 func _initialize(): call_deferred("run") func check(actual, expected: String, label: String): checks += 1 if str(actual) != expected: failures += 1 push_error(label + ": " + str(actual) + " != " + expected) func run(): # Expected strings were generated independently with Python fractions.Fraction. var cases = JSON.parse_string(FileAccess.get_file_as_string("res://tests/fixtures/exact_oracle.json")) for row in cases: var a = E.of(row[0]) var b = E.of(row[1]) check(E.add(a, b), row[2], "sum") check(E.subtract(a, b), row[3], "difference") check(E.multiply(a, b), row[4], "product") check(E.divide(a, b), row[5], "quotient") check(E.floor_value(E.divide(a, b)), row[6], "floor") for text in ["9223372036854775807", "-9223372036854775808", "9007199254740993", "1000000000000000000000000001", "-1/10000000000000"]: var value = E.of(text) check(E.decode(JSON.parse_string(JSON.stringify(E.encode(value)))), text, "JSON round trip") check(E.add(E.of("9223372036854775807"), 1), "9223372036854775808", "int64 overflow promoted") check(E.subtract(E.of("-9223372036854775808"), 1), "-9223372036854775809", "int64 underflow promoted") check(Q.production_step([E.of("1e27")]), "1", "large integral recipe") check(Q.production_step([E.of("1e-13")]), "10000000000000", "tiny fractional recipe") var count = E.of("1000000000000000000000000001") var allocation = Q.allocate_whole({"a": count, "b": count, "c": count}, count) check(Q.sum(allocation), str(count), "allocation conserves every unit") check(allocation.a, "333333333333333333333333334", "deterministic remainder") var clock = Clock.advance({"datetime": E.of("1e27")}, 0.000000001, 1) check(E.subtract(clock.datetime, E.of("1e27")), "1/1000000000", "single tick at huge age") var world = load("res://world/owniverse/owniverse.gd").new() world.catalog.load_definitions(root.get_node("Global").OwniverseEntities) for id in world.catalog.entities: world.state.amount[id] = 0 world.state.stats.total_amount[id] = 0 var group: String = world.catalog.entities[id].group_as if group != "": world.state.amount[group] = 0 world.state.stats.total_amount[group] = 0 world.production.produce_hs("H", 1) check(world.state.energy, "999999999999999999999999999", "spend one energy") var life = world.life.life_products(world.state, world.catalog.entities.EON5, count) check(Q.sum(life), str(count), "life conservation at 1e27") var precise = E.divide(count, E.of("100000000000000000000000000000000000003")) var bounded = E.bounded(precise) check(E.lt(E.absolute(E.subtract(precise, bounded)), E.of("1e-36")), "true", "bounded fractional error") check(E.bounded(count), str(count), "integer counts never quantized") world.state.amount.S = E.of("1e24") world.state.amount.H = E.of("1e24") world.state.amount.RD = 1234567 world.state.amount.YD = 765432 world.state.amount.STN = 654321 world.speed = 6 var started: int = Time.get_ticks_msec() for i in 100: world.state.amount.RD = E.add(world.state.amount.RD, i + 1) world.evolute(0.1) check(str(world.state.auto_star_deficits).length() < 500, "true", "fraction storage stays bounded") print("100 changing-composition cycles: %d ms" % (Time.get_ticks_msec() - started)) var saves = root.get_node("SaveManager") check(saves.validate_data({"format_version": 3, "app_version": "", "ui": {"current_page": 0}, "state": world.state}), "", "long-running state saves") for entity in world.catalog.entities.values(): entity.free() world.free() print("Exact math: %d checks, %d failures" % [checks, failures]) quit(0 if failures == 0 else 1)