710 lines
24 KiB
Python
Executable File
710 lines
24 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Generate or verify the committed Macrostep 00 contract fixtures."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import math
|
|
import sys
|
|
from dataclasses import asdict
|
|
from pathlib import Path
|
|
from typing import Any, Mapping, Sequence
|
|
|
|
TOOLS_DIR = Path(__file__).resolve().parent
|
|
ROOT = TOOLS_DIR.parent
|
|
FIXTURE_DIR = ROOT / "tests" / "fixtures" / "contract"
|
|
if str(TOOLS_DIR) not in sys.path:
|
|
sys.path.insert(0, str(TOOLS_DIR))
|
|
|
|
from contract_oracle import ( # noqa: E402
|
|
ChaCha12,
|
|
Rule,
|
|
Scale,
|
|
ab3_startup,
|
|
circular_convolution,
|
|
delayed_boxes,
|
|
delayed_step,
|
|
euler_step,
|
|
f32,
|
|
f32_bits,
|
|
flat_index,
|
|
iter_coords,
|
|
legacy_butterfly_plan,
|
|
legacy_convolution,
|
|
legacy_sphere_map,
|
|
legacy_x_conversion_plan,
|
|
multiscale_step,
|
|
neighborhoods,
|
|
planar_splats,
|
|
product,
|
|
rising_curve,
|
|
rk4_relaxation,
|
|
rk4_step,
|
|
rule_target,
|
|
sampled_kernels,
|
|
signed_offset,
|
|
sphere_geometry,
|
|
sphere_overlays,
|
|
sphere_step,
|
|
unflatten_index,
|
|
window_curve,
|
|
)
|
|
|
|
FORMAT_VERSION = 1
|
|
|
|
|
|
def _render(value: Any) -> bytes:
|
|
return (
|
|
json.dumps(value, indent=2, ensure_ascii=False, allow_nan=False) + "\n"
|
|
).encode("utf-8")
|
|
|
|
|
|
def _f32_scalar(value: float) -> dict[str, Any]:
|
|
rounded = f32(value)
|
|
return {"decimal": rounded, "bits": f"0x{f32_bits(rounded):08x}"}
|
|
|
|
|
|
def _f32_series(values: Sequence[float]) -> dict[str, Any]:
|
|
rounded = [f32(value) for value in values]
|
|
return {
|
|
"decimal": rounded,
|
|
"bits": [f"0x{f32_bits(value):08x}" for value in rounded],
|
|
}
|
|
|
|
|
|
def _complex_f32_series(values: Sequence[tuple[float, float]]) -> dict[str, Any]:
|
|
rounded = [(f32(real), f32(imag)) for real, imag in values]
|
|
return {
|
|
"decimal": [[real, imag] for real, imag in rounded],
|
|
"bits": [
|
|
[f"0x{f32_bits(real):08x}", f"0x{f32_bits(imag):08x}"]
|
|
for real, imag in rounded
|
|
],
|
|
}
|
|
|
|
|
|
def _encode_plan(entries: Sequence[Mapping[str, Any]]) -> list[dict[str, Any]]:
|
|
return [
|
|
{
|
|
"output": entry["output"],
|
|
"source": entry["source"],
|
|
"twiddle": _f32_series(entry["twiddle"]),
|
|
}
|
|
for entry in entries
|
|
]
|
|
|
|
|
|
def _encode_stages(stages: Sequence[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
encoded: list[dict[str, Any]] = []
|
|
for stage in stages:
|
|
values = stage["values"]
|
|
if values and isinstance(values[0], tuple):
|
|
encoded_values = _complex_f32_series(values)
|
|
else:
|
|
encoded_values = _f32_series(values)
|
|
encoded.append({"name": stage["name"], "values": encoded_values})
|
|
return encoded
|
|
|
|
|
|
def indexing_fixture() -> dict[str, Any]:
|
|
shape_records = []
|
|
for shape in ((8,), (5, 3), (4, 3, 2)):
|
|
shape_records.append(
|
|
{
|
|
"shape": list(shape),
|
|
"x_fast_formula": "x + Nx*(y + Ny*z) (truncated to rank)",
|
|
"entries": [
|
|
{"coords": list(coords), "index": flat_index(coords, shape)}
|
|
for coords in iter_coords(shape)
|
|
],
|
|
"inverse": [
|
|
list(unflatten_index(index, shape))
|
|
for index in range(product(shape))
|
|
],
|
|
}
|
|
)
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Canonical x-fast indexing, inverse indexing, wrapping, and signed even offsets.",
|
|
"shapes": shape_records,
|
|
"signed_offsets": [
|
|
{
|
|
"extent": extent,
|
|
"values": [signed_offset(index, extent) for index in range(extent)],
|
|
}
|
|
for extent in (2, 4, 6, 8)
|
|
],
|
|
"wrap_examples": [
|
|
{"value": value, "extent": extent, "wrapped": value % extent}
|
|
for value, extent in ((-9, 8), (-1, 8), (8, 8), (17, 8), (-7, 6))
|
|
],
|
|
}
|
|
|
|
|
|
def curves_fixture() -> dict[str, Any]:
|
|
center = 0.5
|
|
width = 0.2
|
|
epsilon = 1e-12
|
|
rising_x = [
|
|
center - width,
|
|
center - width / 2.0 - epsilon,
|
|
center - width / 2.0,
|
|
center,
|
|
center + width / 2.0,
|
|
center + width / 2.0 + epsilon,
|
|
center + width,
|
|
]
|
|
window_x = [0.249999999999, 0.25, 0.3, 0.5, 0.7, 0.75, 0.750000000001]
|
|
overshoot_points = [0.096, 0.364, 0.5, 0.636, 0.904]
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Boundary samples for every scalar curve and explicit overshoot samples.",
|
|
"rising": {
|
|
"center": center,
|
|
"width": width,
|
|
"x": rising_x,
|
|
"curves": [
|
|
{
|
|
"type": curve_type,
|
|
"values": [
|
|
rising_curve(curve_type, x, center, width) for x in rising_x
|
|
],
|
|
}
|
|
for curve_type in range(8)
|
|
],
|
|
},
|
|
"windows": {
|
|
"a": 0.3,
|
|
"b": 0.7,
|
|
"width": 0.1,
|
|
"x": window_x,
|
|
"curves": [
|
|
{
|
|
"type": curve_type,
|
|
"values": [
|
|
window_curve(curve_type, x, 0.3, 0.7, 0.1) for x in window_x
|
|
],
|
|
}
|
|
for curve_type in range(10)
|
|
],
|
|
},
|
|
"overshoot": [
|
|
{
|
|
"type": curve_type,
|
|
"samples": [
|
|
{"x": x, "value": rising_curve(curve_type, x, center, width)}
|
|
for x in overshoot_points
|
|
],
|
|
}
|
|
for curve_type in (6, 7)
|
|
],
|
|
"hard_window_exact_interval": {
|
|
"a": 0.3,
|
|
"b": 0.7,
|
|
"at_a": window_curve(0, 0.3, 0.3, 0.7, 0.1),
|
|
"below_b": window_curve(0, math.nextafter(0.7, -math.inf), 0.3, 0.7, 0.1),
|
|
"at_b": window_curve(0, 0.7, 0.3, 0.7, 0.1),
|
|
},
|
|
}
|
|
|
|
|
|
def rule_surface_fixture() -> dict[str, Any]:
|
|
m_axis = [0.2, 0.5, 0.8]
|
|
n_axis = [0.2, 0.5, 0.8]
|
|
base = Rule()
|
|
values = []
|
|
for sigmode in range(1, 5):
|
|
by_sigtype = []
|
|
for sigtype in range(10):
|
|
by_mixtype = []
|
|
for mixtype in range(8):
|
|
rule = Rule(
|
|
b1=base.b1,
|
|
b2=base.b2,
|
|
d1=base.d1,
|
|
d2=base.d2,
|
|
sn=base.sn,
|
|
sm=base.sm,
|
|
sigmode=sigmode,
|
|
sigtype=sigtype,
|
|
mixtype=mixtype,
|
|
)
|
|
by_mixtype.append(
|
|
[[rule_target(n, m, rule) for n in n_axis] for m in m_axis]
|
|
)
|
|
by_sigtype.append(by_mixtype)
|
|
values.append(by_sigtype)
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Rule surface [sigmode][sigtype][mixtype][M][N], including all 320 enum triples.",
|
|
"rule_parameters": {
|
|
key: value
|
|
for key, value in asdict(base).items()
|
|
if key not in ("sigmode", "sigtype", "mixtype")
|
|
},
|
|
"axes": {
|
|
"sigmode": list(range(1, 5)),
|
|
"sigtype": list(range(10)),
|
|
"mixtype": list(range(8)),
|
|
"M": m_axis,
|
|
"N": n_axis,
|
|
},
|
|
"enum_combination_count": 4 * 10 * 8,
|
|
"values": values,
|
|
}
|
|
|
|
|
|
def planar_fields_fixture() -> dict[str, Any]:
|
|
cases = [
|
|
((8,), [0.0, 0.17, 0.91, 0.26, 0.73, 0.42, 0.08, 0.64]),
|
|
((5, 4), [((index * 11 + 3) % 29) / 28.0 for index in range(20)]),
|
|
((4, 3, 2), [((index * 13 + 5) % 37) / 36.0 for index in range(24)]),
|
|
]
|
|
encoded_cases = []
|
|
for shape, field in cases:
|
|
m, n, kernels = neighborhoods(field, shape, 1.45, 3.0, 5.0)
|
|
encoded_cases.append(
|
|
{
|
|
"rank": len(shape),
|
|
"shape": list(shape),
|
|
"field": field,
|
|
"kernel": kernels,
|
|
"direct_disk_convolution_raw": circular_convolution(
|
|
field, kernels["raw_disk"], shape
|
|
),
|
|
"direct_ring_convolution_raw": circular_convolution(
|
|
field, kernels["raw_ring"], shape
|
|
),
|
|
"M_disk_normalized": m,
|
|
"N_ring_normalized": n,
|
|
}
|
|
)
|
|
known = sampled_kernels((64, 64), 10.0, 3.0, 10.0)
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Asymmetric f64 fields with complete sampled kernels and direct circular convolutions.",
|
|
"convolution_sign": "out[x] = sum_offset field[x-offset] * kernel[offset] with every axis periodic",
|
|
"cases": encoded_cases,
|
|
"known_2d_check": {
|
|
"shape": [64, 64],
|
|
"ra": 10.0,
|
|
"rr": 3.0,
|
|
"rb": 10.0,
|
|
"ring_sum": known["ring_sum"],
|
|
"disk_sum": known["disk_sum"],
|
|
},
|
|
}
|
|
|
|
|
|
def _fft_case(
|
|
shape: tuple[int, ...], field: list[float], kernel: list[float]
|
|
) -> dict[str, Any]:
|
|
result = legacy_convolution(field, kernel, shape, capture_stages=True)
|
|
nx = shape[0]
|
|
plans: dict[str, Any] = {
|
|
"x_forward_butterflies": [
|
|
{
|
|
"stage": stage,
|
|
"entries": _encode_plan(legacy_butterfly_plan(nx // 2, stage, -1)),
|
|
}
|
|
for stage in range(1, (nx // 2).bit_length())
|
|
],
|
|
"x_forward_real_conversion": _encode_plan(legacy_x_conversion_plan(nx, -1)),
|
|
"x_inverse_real_conversion": _encode_plan(legacy_x_conversion_plan(nx, 1)),
|
|
"x_inverse_butterflies": [
|
|
{
|
|
"stage": stage,
|
|
"entries": _encode_plan(legacy_butterfly_plan(nx // 2, stage, 1)),
|
|
}
|
|
for stage in range(1, (nx // 2).bit_length())
|
|
],
|
|
}
|
|
for axis, name in enumerate("yz", start=1):
|
|
if axis < len(shape):
|
|
plans[f"{name}_forward_butterflies"] = [
|
|
{
|
|
"stage": stage,
|
|
"entries": _encode_plan(
|
|
legacy_butterfly_plan(shape[axis], stage, -1)
|
|
),
|
|
}
|
|
for stage in range(1, shape[axis].bit_length())
|
|
]
|
|
plans[f"{name}_inverse_butterflies"] = [
|
|
{
|
|
"stage": stage,
|
|
"entries": _encode_plan(
|
|
legacy_butterfly_plan(shape[axis], stage, 1)
|
|
),
|
|
}
|
|
for stage in range(1, shape[axis].bit_length())
|
|
]
|
|
return {
|
|
"shape": list(shape),
|
|
"packed_shape": [nx // 2 + 1, *shape[1:]],
|
|
"input_f32": _f32_series(field),
|
|
"kernel_f32": _f32_series(kernel),
|
|
"kernel_sum_f64": sum(kernel),
|
|
"scales_f32": {
|
|
"unitary_butterfly": _f32_scalar(1.0 / math.sqrt(2.0)),
|
|
"forward_real_conversion": _f32_scalar(0.5 / math.sqrt(2.0)),
|
|
"inverse_real_conversion": _f32_scalar(0.5 * math.sqrt(2.0)),
|
|
"spectral_correction": _f32_scalar(result["correction"]),
|
|
},
|
|
"plans": plans,
|
|
"forward_field_stages": _encode_stages(result["field_stages"]),
|
|
"field_spectrum": _complex_f32_series(result["field_spectrum"]),
|
|
"kernel_spectrum": _complex_f32_series(result["kernel_spectrum"]),
|
|
"spectral_product": _complex_f32_series(result["spectral_product"]),
|
|
"inverse_product_stages": _encode_stages(result["inverse_stages"]),
|
|
"convolution_f32": _f32_series(result["output"]),
|
|
"direct_normalized_f64": result["direct_normalized"],
|
|
"max_abs_error_to_direct": max(
|
|
abs(actual - expected)
|
|
for actual, expected in zip(
|
|
result["output"], result["direct_normalized"], strict=True
|
|
)
|
|
),
|
|
}
|
|
|
|
|
|
def packed_fft_fixture() -> dict[str, Any]:
|
|
definitions = []
|
|
for shape in ((8,), (4, 4), (4, 2, 2)):
|
|
count = product(shape)
|
|
field = [((index * 7 + 1) % 19) / 18.0 for index in range(count)]
|
|
kernel = [0.2 + ((index * 5 + 2) % 11) / 13.0 for index in range(count)]
|
|
definitions.append(_fft_case(shape, field, kernel))
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Legacy adjacent-real packed unitary 1D/2D/3D FFT with operation-ordered IEEE-f32 stages.",
|
|
"operation_order": {
|
|
"butterfly_real": "f32(f32(f32(a.r + f32(cos*b.r)) - f32(sin*b.i)) * f32(1/sqrt(2)))",
|
|
"butterfly_imag": "f32(f32(f32(a.i + f32(cos*b.i)) + f32(sin*b.r)) * f32(1/sqrt(2)))",
|
|
"complex_multiply": "real=f32(f32(ar*br)-f32(ai*bi)); imag=f32(f32(ar*bi)+f32(ai*br))",
|
|
"kernel_scaling": "scale each kernel spectrum component first by f32(sqrt(sample_count)/kernel_sum)",
|
|
},
|
|
"layout": "adjacent x samples become real/imag; spectrum x extent is Nx/2+1; x remains fastest",
|
|
"cases": definitions,
|
|
}
|
|
|
|
|
|
def integration_fixture() -> dict[str, Any]:
|
|
initial = [0.02, 0.37, 0.81, 0.98]
|
|
time = 0.25
|
|
dt = 0.4
|
|
|
|
def derivative(state: Sequence[float], current_time: float) -> list[float]:
|
|
return [
|
|
0.34 - 0.45 * value + (index + 1) * 0.08 * current_time
|
|
for index, value in enumerate(state)
|
|
]
|
|
|
|
def target(state: Sequence[float]) -> list[float]:
|
|
return [
|
|
0.1
|
|
+ 0.65 * state[(index - 1) % len(state)]
|
|
+ 0.2 * state[(index + 1) % len(state)]
|
|
for index in range(len(state))
|
|
]
|
|
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Clamp-at-commit Euler/AB and clamp-every-stage RK4, including both relaxation references.",
|
|
"initial": initial,
|
|
"time": time,
|
|
"dt": dt,
|
|
"synthetic_derivative": "k_i(A,t)=0.34-0.45*A_i+(i+1)*0.08*t",
|
|
"euler": euler_step(initial, time, dt, derivative),
|
|
"ab3_startup": ab3_startup(initial, time, dt, derivative),
|
|
"rk4": rk4_step(initial, time, dt, derivative),
|
|
"relaxation_target": "S_i(A)=0.1+0.65*A_(i-1)+0.2*A_(i+1), periodic",
|
|
"rk4_relaxation_stage_state": rk4_relaxation(
|
|
initial, dt, target, "stage_state"
|
|
),
|
|
"rk4_relaxation_step_origin": rk4_relaxation(
|
|
initial, dt, target, "step_origin"
|
|
),
|
|
}
|
|
|
|
|
|
def multiscale_fixture() -> dict[str, Any]:
|
|
shape = (5, 4)
|
|
field = [((index * 17 + 4) % 31) / 30.0 for index in range(product(shape))]
|
|
scales = [
|
|
Scale(1.65, 3.0, 6.0, 0.18, Rule(sigmode=2, sigtype=4, mixtype=3)),
|
|
Scale(1.25, 3.0, 6.0, 0.11, Rule(sigmode=3, sigtype=2, mixtype=5)),
|
|
Scale(0.95, 3.0, 6.0, 0.07, Rule(sigmode=4, sigtype=7, mixtype=1)),
|
|
]
|
|
cases = []
|
|
for dynamics in ("growth", "relaxation"):
|
|
for interpretation in ("independent", "chained"):
|
|
for composition in ("sequential", "ordered_clamped_sum", "mean_increment"):
|
|
cases.append(
|
|
multiscale_step(
|
|
field, shape, scales, interpretation, composition, dynamics
|
|
)
|
|
)
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "All 2 interpretations x 3 compositions for growth and corrected relaxation.",
|
|
"shape": list(shape),
|
|
"field": field,
|
|
"scales": [
|
|
{
|
|
"ra": scale.ra,
|
|
"rr": scale.rr,
|
|
"rb": scale.rb,
|
|
"dt": scale.dt,
|
|
"rule": asdict(scale.rule),
|
|
}
|
|
for scale in scales
|
|
],
|
|
"chained_inputs": [
|
|
["ring_0", "ring_1"],
|
|
["ring_1", "ring_2"],
|
|
["ring_2", "disk_2"],
|
|
],
|
|
"case_count": len(cases),
|
|
"cases": cases,
|
|
}
|
|
|
|
|
|
def sphere_fixture() -> dict[str, Any]:
|
|
k = 4
|
|
ra = 1.4
|
|
rule = Rule(sigmode=2, sigtype=4, mixtype=4)
|
|
geometry = sphere_geometry(k)
|
|
field = [((index * 19 + 7) % 43) / 42.0 for index in range(6 * k * k)]
|
|
constant_value = 0.375
|
|
probes = [
|
|
{"label": "face0_center", "face": 0, "x": 1, "y": 1},
|
|
{"label": "face1_center", "face": 1, "x": 2, "y": 2},
|
|
{"label": "face0_left_edge", "face": 0, "x": 0, "y": 1},
|
|
{"label": "face2_top_edge", "face": 2, "x": 2, "y": 3},
|
|
{"label": "face0_bottom_left_corner", "face": 0, "x": 0, "y": 0},
|
|
{"label": "face4_top_right_corner", "face": 4, "x": 3, "y": 3},
|
|
]
|
|
models = {}
|
|
for model in ("corrected", "legacy"):
|
|
result = sphere_step(field, k, ra, rule, model)
|
|
constant = sphere_step([constant_value] * (6 * k * k), k, ra, rule, model)
|
|
probe_values = []
|
|
for probe in probes:
|
|
index = probe["face"] * k * k + probe["y"] * k + probe["x"]
|
|
probe_values.append(
|
|
{
|
|
**probe,
|
|
"index": index,
|
|
"M": result["m"][index],
|
|
"N": result["n"][index],
|
|
"S": result["s"][index],
|
|
"next_discrete": result["next_discrete"][index],
|
|
"next_smooth": result["next_smooth"][index],
|
|
}
|
|
)
|
|
models[model] = {**result, "constant_field": constant, "probes": probe_values}
|
|
legacy_map = []
|
|
for face in range(6):
|
|
for label, x, y in (
|
|
("left", -1, 1),
|
|
("right", k, 1),
|
|
("bottom", 1, -1),
|
|
("top", 1, k),
|
|
("masked_bottom_left_diagonal", -1, -1),
|
|
("masked_top_right_diagonal", k, k),
|
|
):
|
|
mapped = legacy_sphere_map(face, x, y, k)
|
|
legacy_map.append(
|
|
{
|
|
"face": face,
|
|
"region": label,
|
|
"query": [x, y],
|
|
"mapped": list(mapped) if mapped is not None else None,
|
|
}
|
|
)
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Compact even-K corrected global enumeration and deterministic legacy side-gutter sphere goldens.",
|
|
"k": k,
|
|
"radius": k / 2.0,
|
|
"ra_planar": ra,
|
|
"rule": asdict(rule),
|
|
"field": field,
|
|
"geometry": geometry,
|
|
"probe_definitions": probes,
|
|
"legacy_side_and_mask_map": legacy_map,
|
|
"models": models,
|
|
}
|
|
|
|
|
|
def delayed_time_fixture() -> dict[str, Any]:
|
|
shape = (5, 4)
|
|
depth = 16
|
|
head = 5
|
|
history = [[layer / 15.0] * product(shape) for layer in range(depth)]
|
|
rule = Rule(sigmode=2, sigtype=4, mixtype=4)
|
|
result = delayed_step(history, shape, head, 2.2, rule)
|
|
shells: dict[int, list[list[int]]] = {}
|
|
for entry in result["stencil"]["entries"]:
|
|
shells.setdefault(entry["delay"], []).append([entry["dx"], entry["dy"]])
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Layer-coded causal radial shells; head is next overwrite; both direct and fixed smooth updates.",
|
|
"shape": list(shape),
|
|
"depth": depth,
|
|
"history": history,
|
|
"head": head,
|
|
"latest": (head - 1) % depth,
|
|
"rule": asdict(rule),
|
|
"shell_offsets_by_rounded_age": [
|
|
{
|
|
"age": age,
|
|
"offsets": offsets,
|
|
"selected_layer": ((head - 1) - age) % depth,
|
|
}
|
|
for age, offsets in sorted(shells.items())
|
|
],
|
|
"evaluation": result,
|
|
}
|
|
|
|
|
|
def initializers_fixture() -> dict[str, Any]:
|
|
zero_rng = ChaCha12(0)
|
|
seed_one_rng = ChaCha12(1)
|
|
seed_one_u64_rng = ChaCha12(1)
|
|
seed_one_float_rng = ChaCha12(1)
|
|
return {
|
|
"format_version": FORMAT_VERSION,
|
|
"description": "Exact topology-native seeded f64 initializer arrays; arrays, not hashes, are authoritative.",
|
|
"prng": {
|
|
"algorithm": "ChaCha12, 256-bit key = LE seed u64 + 24 zero bytes, original 64-bit counter and 64-bit stream both zero",
|
|
"u64_order": "low u32 then high u32",
|
|
"float": "top 53 bits of u64 multiplied by 2^-53",
|
|
"integer": "reject u64 values at or above 2^64-(2^64 mod span), then modulo span",
|
|
"seed_0_first_16_u32_hex": [f"0x{zero_rng.u32():08x}" for _ in range(16)],
|
|
"seed_1_first_16_u32_hex": [
|
|
f"0x{seed_one_rng.u32():08x}" for _ in range(16)
|
|
],
|
|
"seed_1_first_8_u64_hex": [
|
|
f"0x{seed_one_u64_rng.u64():016x}" for _ in range(8)
|
|
],
|
|
"seed_1_first_8_float53": [seed_one_float_rng.float53() for _ in range(8)],
|
|
},
|
|
"planar_periodic_splats": [
|
|
planar_splats((12,), 3.0, 1),
|
|
planar_splats((8, 6), 2.0, 1),
|
|
planar_splats((6, 5, 4), 1.6, 1),
|
|
],
|
|
"sphere_geodesic_overlays": sphere_overlays(6, 1, 1000),
|
|
"delayed_time_periodic_boxes": delayed_boxes((17, 16), 1, 16, 1000),
|
|
}
|
|
|
|
|
|
DESCRIPTIONS = {
|
|
"indexing.json": "Indexing and signed offsets",
|
|
"curves.json": "Scalar curves and boundaries",
|
|
"rule_surface.json": "Complete rule enum surface",
|
|
"planar_fields.json": "Sampled kernels and direct convolution",
|
|
"legacy_packed_fft.json": "Packed-unitary f32 FFT oracle",
|
|
"integration.json": "Euler, AB startup, RK4 references",
|
|
"multiscale.json": "All multiscale policies",
|
|
"sphere.json": "Corrected and legacy sphere",
|
|
"delayed_time.json": "Causal delayed-time shells",
|
|
"initializers.json": "ChaCha12 and exact seeded arrays",
|
|
}
|
|
|
|
|
|
def build_payloads() -> dict[str, Any]:
|
|
return {
|
|
"indexing.json": indexing_fixture(),
|
|
"curves.json": curves_fixture(),
|
|
"rule_surface.json": rule_surface_fixture(),
|
|
"planar_fields.json": planar_fields_fixture(),
|
|
"legacy_packed_fft.json": packed_fft_fixture(),
|
|
"integration.json": integration_fixture(),
|
|
"multiscale.json": multiscale_fixture(),
|
|
"sphere.json": sphere_fixture(),
|
|
"delayed_time.json": delayed_time_fixture(),
|
|
"initializers.json": initializers_fixture(),
|
|
}
|
|
|
|
|
|
def expected_files() -> dict[str, bytes]:
|
|
payloads = build_payloads()
|
|
rendered = {name: _render(payload) for name, payload in payloads.items()}
|
|
manifest = {
|
|
"format_version": FORMAT_VERSION,
|
|
"contract": "Macrostep 00 deterministic oracle fixtures",
|
|
"generator": "tools/generate_contract_fixtures.py",
|
|
"oracle": "tools/contract_oracle.py",
|
|
"standard_library_only": True,
|
|
"semantic_float": "IEEE-754 binary64 represented as JSON numbers",
|
|
"packed_fft_float": "IEEE-754 binary32 after every operation, with decimal values and hexadecimal bit patterns",
|
|
"determinism": "No timestamp, locale, platform RNG, external source tree, or runtime dependency is used.",
|
|
"files": [
|
|
{
|
|
"path": name,
|
|
"description": DESCRIPTIONS[name],
|
|
"bytes": len(rendered[name]),
|
|
"sha256": hashlib.sha256(rendered[name]).hexdigest(),
|
|
}
|
|
for name in payloads
|
|
],
|
|
}
|
|
rendered["manifest.json"] = _render(manifest)
|
|
return rendered
|
|
|
|
|
|
def write_files(files: dict[str, bytes]) -> None:
|
|
FIXTURE_DIR.mkdir(parents=True, exist_ok=True)
|
|
for name, content in files.items():
|
|
(FIXTURE_DIR / name).write_bytes(content)
|
|
|
|
|
|
def check_files(files: dict[str, bytes]) -> int:
|
|
failures: list[str] = []
|
|
for name, expected in files.items():
|
|
path = FIXTURE_DIR / name
|
|
if not path.exists():
|
|
failures.append(f"missing: {path.relative_to(ROOT)}")
|
|
elif path.read_bytes() != expected:
|
|
failures.append(f"stale: {path.relative_to(ROOT)}")
|
|
if FIXTURE_DIR.exists():
|
|
extras = sorted(
|
|
path.name for path in FIXTURE_DIR.glob("*.json") if path.name not in files
|
|
)
|
|
failures.extend(
|
|
f"unexpected: {(FIXTURE_DIR / name).relative_to(ROOT)}" for name in extras
|
|
)
|
|
if failures:
|
|
sys.stderr.write("contract fixtures are not current:\n")
|
|
for failure in failures:
|
|
sys.stderr.write(f" {failure}\n")
|
|
return 1
|
|
sys.stdout.write(f"verified {len(files)} contract fixture files\n")
|
|
return 0
|
|
|
|
|
|
def main(argv: Sequence[str] | None = None) -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument(
|
|
"--check", action="store_true", help="verify committed bytes without writing"
|
|
)
|
|
args = parser.parse_args(argv)
|
|
files = expected_files()
|
|
if args.check:
|
|
return check_files(files)
|
|
write_files(files)
|
|
sys.stdout.write(
|
|
f"wrote {len(files)} contract fixture files under "
|
|
f"{FIXTURE_DIR.relative_to(ROOT)}\n"
|
|
)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|