🤖 AI text below 🤖
Problem Statement
Follow up on #2542 by replacing derived floating-point phase tables in the structured benchmark generators with scalar runtime arithmetic. This issue tracks implementation; the inventory and feasibility analysis below did not change production code.
Baseline: #2542 at 65091673fdba9d2a1adbd728842358ec4cb06071, based on main 30d32c9aa9742ede8bca1f21b8e2f896b75679e8. Also inspected the shared modular-arithmetic implementation proposed in #2605 at ba5fd2212d21c6b35a639d02a5c4a519c358c153.
The current tables encode values derivable from the benchmark parameters, add tensor construction and indexing code, and make generated programs grow with those derived values. They also avoid repeated classical computation and preserve carefully bounded numerical calculations. A replacement must retain those numerical contracts.
Inventory of all registered families and related implementations
| Family or mode |
Current implementation |
Opportunity |
| QPE, standard and iterative |
controlledPhaseAngles creates one f64 per precision bit using exact modular doubling. |
Carry exact integer residues and compute bounded angles as needed. Standard QPE consumes powers in forward order; iterative QPE consumes them in reverse. |
| QFT adder, constant input |
phaseAngles creates one f64 per sum qubit. |
Compute theta = theta / 2 + pi * bit while consuming the classical addend from least significant bit upward; halve once more for carry. |
| Modular multiplier |
phaseData creates (n + 1)^2 angles, including the modulus row. |
Carry the residue a * 2^j mod N; derive each phase-addition row from that integer using the same bounded bit recurrence. Remove row strides and phase-table offsets. |
| QFT, standard and semiclassical; QFT adder, register input |
Already use phaseRotationLoop with repeated multiplication by 0.5. |
Keep the existing recurrence. General pow or transcendental calls would add work here. |
| Multiplexer |
Already carries and halves a scalar angle in its loop. |
Optionally reuse phaseRotationLoop to remove its duplicate loop builder. |
| W state |
#2542 computes angles inside the loop. |
Starting point for this follow-up. |
| BV |
Stores the user-supplied hidden bitstring as Boolean tensor data. |
No phase table to remove. Input data is distinct from derived angles. |
| GHZ, Grover, repeat-until-success, teleportation |
No phase tables. |
No change needed for this task. |
| Weak-measurement Grover, pending #2602 |
Computes one invariant 2 * asin(sqrt(strength)) angle during generation. |
Keep this scalar precomputation; moving the same calculation into each retry would add work without removing a table. |
| Magic-state distillation, pending #2543 |
Uses fixed decoder and correction-qubit arrays. |
These encode circuit topology, not phase tables; retain them. |
Pending #2605 adds Shor and moves modular arithmetic into a shared implementation. Shor stores both multiplier and inverse-multiplier phase blocks for every round: 2 * p * (n + 1)^2 doubles, with p = 2n. At its maximum supported n = 31, that is 126,976 doubles / 1,015,808 raw bytes, before serialization overhead or compression. Coordinate with that PR instead of maintaining two phase-addition implementations.
Source anchors: QPE, QFTAdder, ModularMultiplier, QFTUtils, Shor, shared modular arithmetic.
Proposed Solution
Also inspected weak-measurement Grover and magic-state distillation. Neither adds a phase-table migration.
Migrate the generators with bounded arithmetic
- Standard QPE: keep numerator and denominator as unsigned integers. Reuse the existing overflow-safe modular doubling rule:
r >= d - r ? r - (d - r) : r + r. Convert the reduced residue to an angle only when needed. Preserve the full uint64_t phase domain and the existing precision limit of 1,000,000. Do not compute 2^k as a floating-point value or repeatedly double an already rounded floating-point phase.
- Constant QFT addition: replace the angle tensor with the bit recurrence above. Preserve all 1,024 supported sum bits, including leading zeros and carry semantics. A single
i64 does not hold every supported addend, and an arbitrary-width MLIR integer is not automatically portable to jeff. Use a supported bit/chunk representation. The input bits still need storage; removing a derived phase table does not remove the information in an arbitrary addend. Do not replace the linear phase sweep with a quadratic gate expansion.
- Modular multiplication and Shor: compute phase rows from integer residues in the shared emitter. Current modular-multiplier inputs are at most 63 bits, so residues fit unsigned
i64; keep shifts, comparisons, division, and remainder unsigned. Preserve inverse rotations, modular reduction, work-qubit cleanup, and coherent controls. For Shor, initially retaining a compact list of exact powers and inverses is reasonable: replacing the large derived angle blocks is the useful simplification. Moving extended Euclid or repeated power reconstruction into every shot is not required merely to eliminate tables.
- Iterative QPE: explicitly design the descending-power path. Modular doubling is not generally invertible for even denominators; simply halving the last residue is incorrect. Compare exact scalar reconstruction with compact integer data before choosing. Avoid an accidental quadratic reconstruction cost at the million-bit precision limit. Preserve phase-bit order and adaptive corrections.
Use existing arith, math, and scf facilities and the existing phase-loop helper where appropriate. No new dialect or general phase-expression framework is needed.
Benefits and limits
- Remove host-side floating-point table builders, tensor constants and reads, flattened row bookkeeping, and tests tied to table layout.
- Reduce derived angle storage from
O(p) for QPE, O(n) for constant addition, O(n^2) for modular multiplication, and O(n^3) for Shor. Arbitrary input bits and any retained exact power data remain separate costs.
- Reduce generated MLIR/jeff payloads and QIR constant-array loads for these benchmarks. This should also reduce some parsing and serialization work; runtime and compilation speedups need measurement.
- Avoid OpenQASM phase-table dispatch.
emitTableLookup emits a switch for a runtime index and requires unrestricted multiway branching. Scalar arithmetic removes that requirement for these lookups, though the surrounding circuit still has its own target requirements.
- Runtime arithmetic adds work per execution and potentially per shot. Repeated modular additions may recompute values that the table currently shares. Prefer bounded recurrences over expensive
pow, and measure generation, payload size, compilation, and execution separately.
Audit compiler cleanup after migration
Candidates are the dense-f64 constant/read cases in DD interpretation, OpenQASM's table-to-dispatch expansion, and the constant-tensor bufferization path in QIRCommon.
These are candidates, not confirmed dead code. Dense rank-one f64 tensors are documented as supported DD inputs, and compiler tests cover imported tensor programs independently of benchmarks. User-provided arrays and the work tracked in #2109 and #2593 also matter. Keep general tensor/array support unless its remaining consumers and compatibility contract permit removal. Quantum qtensor bookkeeping is unrelated and remains necessary.
Validation and completion criteria
- Preserve parameters, manifests, case IDs, output-bit order, and analytic evaluators. Replace table-shape assertions with semantic checks; retain coherent-state/relative-phase checks, exhaustive small adders and multipliers, and sampled standard/iterative QPE checks.
- Exercise rational phases such as
1/3, dyadic phases, near-UINT64_MAX numerators/denominators, and selected powers beyond 1,024 without simulating huge registers. Preserve maximum-width generation checks and finite angles. Compare against exact integer/rational arithmetic and a high-precision numerical reference; document acceptable f64 rounding changes from the current long double precomputation.
- Validate each new operation and loop-carried value through QC/QCO, direct DD execution, jeff serialization/reload, OpenQASM export/re-import, Adaptive QIR serialization/execution, and the supported target-compilation route for Base QIR/static targets. Keep simulation tests at or below 1,024 qubits; prefer small semantic cases and generation-only boundary checks.
- Record payload-size and runtime tradeoffs before removing precomputation everywhere. Delete
test::angleTable and its table-only includes once the migrated benchmark tests no longer use it. Delete production compiler paths only after the separate consumer audit above.
Evidence from the analysis
Read-only generation probes on the #2542 head found:
| Example |
Derived angle entries |
Generated MLIR text bytes |
| QPE, precision 16, phase 1/3 |
16 |
2,352 |
| QPE, precision 1,024, phase 1/3 |
1,024 |
18,466 |
| Constant adder, alternating 16-bit input |
16 |
2,752 |
| Constant adder, alternating 1,024-bit input |
1,024 |
18,885 |
| Modular multiplier, 16-bit all-ones modulus, multiplier 1 |
289 |
13,058 |
| Modular multiplier, 63-bit all-ones modulus, multiplier 1 |
4,096 |
73,989 |
These are baseline sizes, not measured savings from an implemented replacement. A numerical probe shows why floating-point QPE doubling is unsafe: starting at float(1/3), repeated doubling modulo one reaches zero at power 54, while the exact phase is still 1/3.
The three-qubit W-state probe passed DD sampling, jeff round-trip sampling, Adaptive QIR bitcode serialization, and OpenQASM export. Direct Base QIR conversion still rejects retained scf.for; OpenQASM re-import rejects the generated computed qubit index because it cannot prove bounds. These limitations also reproduced with the earlier angle-table W implementation. Thus #2542 establishes useful runtime-math support, not universal support for every operation and target profile. Include these boundaries in the follow-up's tests rather than assuming them away.
Codex assisted this source audit, the small generation/numerical probes, and this issue description.
🤖 AI text below 🤖
Problem Statement
Follow up on #2542 by replacing derived floating-point phase tables in the structured benchmark generators with scalar runtime arithmetic. This issue tracks implementation; the inventory and feasibility analysis below did not change production code.
Baseline: #2542 at
65091673fdba9d2a1adbd728842358ec4cb06071, based on main30d32c9aa9742ede8bca1f21b8e2f896b75679e8. Also inspected the shared modular-arithmetic implementation proposed in #2605 atba5fd2212d21c6b35a639d02a5c4a519c358c153.The current tables encode values derivable from the benchmark parameters, add tensor construction and indexing code, and make generated programs grow with those derived values. They also avoid repeated classical computation and preserve carefully bounded numerical calculations. A replacement must retain those numerical contracts.
Inventory of all registered families and related implementations
controlledPhaseAnglescreates onef64per precision bit using exact modular doubling.phaseAnglescreates onef64per sum qubit.theta = theta / 2 + pi * bitwhile consuming the classical addend from least significant bit upward; halve once more for carry.phaseDatacreates(n + 1)^2angles, including the modulus row.a * 2^j mod N; derive each phase-addition row from that integer using the same bounded bit recurrence. Remove row strides and phase-table offsets.phaseRotationLoopwith repeated multiplication by0.5.powor transcendental calls would add work here.phaseRotationLoopto remove its duplicate loop builder.2 * asin(sqrt(strength))angle during generation.Pending #2605 adds Shor and moves modular arithmetic into a shared implementation. Shor stores both multiplier and inverse-multiplier phase blocks for every round:
2 * p * (n + 1)^2doubles, withp = 2n. At its maximum supportedn = 31, that is 126,976 doubles / 1,015,808 raw bytes, before serialization overhead or compression. Coordinate with that PR instead of maintaining two phase-addition implementations.Source anchors: QPE, QFTAdder, ModularMultiplier, QFTUtils, Shor, shared modular arithmetic.
Proposed Solution
Also inspected weak-measurement Grover and magic-state distillation. Neither adds a phase-table migration.
Migrate the generators with bounded arithmetic
r >= d - r ? r - (d - r) : r + r. Convert the reduced residue to an angle only when needed. Preserve the fulluint64_tphase domain and the existing precision limit of 1,000,000. Do not compute2^kas a floating-point value or repeatedly double an already rounded floating-point phase.i64does not hold every supported addend, and an arbitrary-width MLIR integer is not automatically portable to jeff. Use a supported bit/chunk representation. The input bits still need storage; removing a derived phase table does not remove the information in an arbitrary addend. Do not replace the linear phase sweep with a quadratic gate expansion.i64; keep shifts, comparisons, division, and remainder unsigned. Preserve inverse rotations, modular reduction, work-qubit cleanup, and coherent controls. For Shor, initially retaining a compact list of exact powers and inverses is reasonable: replacing the large derived angle blocks is the useful simplification. Moving extended Euclid or repeated power reconstruction into every shot is not required merely to eliminate tables.Use existing
arith,math, andscffacilities and the existing phase-loop helper where appropriate. No new dialect or general phase-expression framework is needed.Benefits and limits
O(p)for QPE,O(n)for constant addition,O(n^2)for modular multiplication, andO(n^3)for Shor. Arbitrary input bits and any retained exact power data remain separate costs.emitTableLookupemits aswitchfor a runtime index and requires unrestricted multiway branching. Scalar arithmetic removes that requirement for these lookups, though the surrounding circuit still has its own target requirements.pow, and measure generation, payload size, compilation, and execution separately.Audit compiler cleanup after migration
Candidates are the dense-
f64constant/read cases in DD interpretation, OpenQASM's table-to-dispatch expansion, and the constant-tensor bufferization path in QIRCommon.These are candidates, not confirmed dead code. Dense rank-one
f64tensors are documented as supported DD inputs, and compiler tests cover imported tensor programs independently of benchmarks. User-provided arrays and the work tracked in #2109 and #2593 also matter. Keep general tensor/array support unless its remaining consumers and compatibility contract permit removal. Quantumqtensorbookkeeping is unrelated and remains necessary.Validation and completion criteria
1/3, dyadic phases, near-UINT64_MAXnumerators/denominators, and selected powers beyond 1,024 without simulating huge registers. Preserve maximum-width generation checks and finite angles. Compare against exact integer/rational arithmetic and a high-precision numerical reference; document acceptablef64rounding changes from the currentlong doubleprecomputation.test::angleTableand its table-only includes once the migrated benchmark tests no longer use it. Delete production compiler paths only after the separate consumer audit above.Evidence from the analysis
Read-only generation probes on the #2542 head found:
These are baseline sizes, not measured savings from an implemented replacement. A numerical probe shows why floating-point QPE doubling is unsafe: starting at
float(1/3), repeated doubling modulo one reaches zero at power 54, while the exact phase is still1/3.The three-qubit W-state probe passed DD sampling, jeff round-trip sampling, Adaptive QIR bitcode serialization, and OpenQASM export. Direct Base QIR conversion still rejects retained
scf.for; OpenQASM re-import rejects the generated computed qubit index because it cannot prove bounds. These limitations also reproduced with the earlier angle-table W implementation. Thus #2542 establishes useful runtime-math support, not universal support for every operation and target profile. Include these boundaries in the follow-up's tests rather than assuming them away.Codex assisted this source audit, the small generation/numerical probes, and this issue description.